# HG changeset patch # User jmasa # Date 1360013164 28800 # Node ID f2f0cf0f5444f484c1add9058b50b6c006989e84 # Parent 256d3f43c177c95ff8aa5170b2d9d6ff2db24d16# Parent 80518f4ecf325b8ada740322b772db1d887076a9 Merge diff -r 256d3f43c177 -r f2f0cf0f5444 .hgtags --- a/.hgtags Thu Jan 31 10:45:09 2013 -0800 +++ b/.hgtags Mon Feb 04 13:26:04 2013 -0800 @@ -309,3 +309,5 @@ 1e129851479e4f5df439109fca2c7be1f1613522 hs25-b15 11619f33cd683c2f1d6ef72f1c6ff3dacf5a9f1c jdk8-b73 70c89bd6b895a10d25ca70e08093c09ff2005fda hs25-b16 +1a3e54283c54aaa8b3437813e8507fbdc966e5b6 jdk8-b74 +b4391649e91ea8d37f66317a03d6d2573a93d10d hs25-b17 diff -r 256d3f43c177 -r f2f0cf0f5444 agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Thu Jan 31 10:45:09 2013 -0800 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Mon Feb 04 13:26:04 2013 -0800 @@ -53,6 +53,7 @@ private static int HIGH_OFFSET; private static int FIELD_SLOTS; private static short FIELDINFO_TAG_SIZE; + private static short FIELDINFO_TAG_MASK; private static short FIELDINFO_TAG_OFFSET; // ClassState constants @@ -102,6 +103,7 @@ HIGH_OFFSET = db.lookupIntConstant("FieldInfo::high_packed_offset").intValue(); FIELD_SLOTS = db.lookupIntConstant("FieldInfo::field_slots").intValue(); FIELDINFO_TAG_SIZE = db.lookupIntConstant("FIELDINFO_TAG_SIZE").shortValue(); + FIELDINFO_TAG_MASK = db.lookupIntConstant("FIELDINFO_TAG_MASK").shortValue(); FIELDINFO_TAG_OFFSET = db.lookupIntConstant("FIELDINFO_TAG_OFFSET").shortValue(); // read ClassState constants @@ -321,7 +323,7 @@ U2Array fields = getFields(); short lo = fields.at(index * FIELD_SLOTS + LOW_OFFSET); short hi = fields.at(index * FIELD_SLOTS + HIGH_OFFSET); - if ((lo & FIELDINFO_TAG_SIZE) == FIELDINFO_TAG_OFFSET) { + if ((lo & FIELDINFO_TAG_MASK) == FIELDINFO_TAG_OFFSET) { return VM.getVM().buildIntFromShorts(lo, hi) >> FIELDINFO_TAG_SIZE; } throw new RuntimeException("should not reach here"); diff -r 256d3f43c177 -r f2f0cf0f5444 make/bsd/makefiles/mapfile-vers-debug --- a/make/bsd/makefiles/mapfile-vers-debug Thu Jan 31 10:45:09 2013 -0800 +++ b/make/bsd/makefiles/mapfile-vers-debug Mon Feb 04 13:26:04 2013 -0800 @@ -3,7 +3,7 @@ # # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -205,7 +205,6 @@ JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff -r 256d3f43c177 -r f2f0cf0f5444 make/bsd/makefiles/mapfile-vers-product --- a/make/bsd/makefiles/mapfile-vers-product Thu Jan 31 10:45:09 2013 -0800 +++ b/make/bsd/makefiles/mapfile-vers-product Mon Feb 04 13:26:04 2013 -0800 @@ -3,7 +3,7 @@ # # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -205,7 +205,6 @@ JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff -r 256d3f43c177 -r f2f0cf0f5444 make/hotspot_version --- a/make/hotspot_version Thu Jan 31 10:45:09 2013 -0800 +++ b/make/hotspot_version Mon Feb 04 13:26:04 2013 -0800 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=17 +HS_BUILD_NUMBER=18 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r 256d3f43c177 -r f2f0cf0f5444 make/linux/makefiles/mapfile-vers-debug --- a/make/linux/makefiles/mapfile-vers-debug Thu Jan 31 10:45:09 2013 -0800 +++ b/make/linux/makefiles/mapfile-vers-debug Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -201,7 +201,6 @@ JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff -r 256d3f43c177 -r f2f0cf0f5444 make/linux/makefiles/mapfile-vers-product --- a/make/linux/makefiles/mapfile-vers-product Thu Jan 31 10:45:09 2013 -0800 +++ b/make/linux/makefiles/mapfile-vers-product Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -201,7 +201,6 @@ JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff -r 256d3f43c177 -r f2f0cf0f5444 make/solaris/makefiles/mapfile-vers --- a/make/solaris/makefiles/mapfile-vers Thu Jan 31 10:45:09 2013 -0800 +++ b/make/solaris/makefiles/mapfile-vers Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 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 @@ -201,7 +201,6 @@ JVM_NewMultiArray; JVM_OnExit; JVM_Open; - JVM_PrintStackTrace; JVM_RaiseSignal; JVM_RawMonitorCreate; JVM_RawMonitorDestroy; diff -r 256d3f43c177 -r f2f0cf0f5444 src/cpu/x86/vm/assembler_x86.cpp --- a/src/cpu/x86/vm/assembler_x86.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/cpu/x86/vm/assembler_x86.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -2263,6 +2263,18 @@ emit_simd_arith(0x67, dst, src, VEX_SIMD_66); } +void Assembler::vpackuswb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { + assert(VM_Version::supports_avx() && !vector256 || VM_Version::supports_avx2(), "256 bit integer vectors requires AVX2"); + emit_vex_arith(0x67, dst, nds, src, VEX_SIMD_66, vector256); +} + +void Assembler::vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256) { + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, true, vector256); + emit_int8(0x00); + emit_int8(0xC0 | encode); + emit_int8(imm8); +} + void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) { assert(VM_Version::supports_sse4_2(), ""); InstructionMark im(this); @@ -2475,7 +2487,7 @@ assert(dst != xnoreg, "sanity"); int dst_enc = dst->encoding(); // swap src<->dst for encoding - vex_prefix(src, dst_enc, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector256); + vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector256); emit_int8(0x17); emit_operand(dst, src); } diff -r 256d3f43c177 -r f2f0cf0f5444 src/cpu/x86/vm/assembler_x86.hpp --- a/src/cpu/x86/vm/assembler_x86.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/cpu/x86/vm/assembler_x86.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -1395,6 +1395,10 @@ // Pack with unsigned saturation void packuswb(XMMRegister dst, XMMRegister src); void packuswb(XMMRegister dst, Address src); + void vpackuswb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256); + + // Pemutation of 64bit words + void vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256); // SSE4.2 string instructions void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8); diff -r 256d3f43c177 -r f2f0cf0f5444 src/cpu/x86/vm/jni_x86.h --- a/src/cpu/x86/vm/jni_x86.h Thu Jan 31 10:45:09 2013 -0800 +++ b/src/cpu/x86/vm/jni_x86.h Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,14 +38,9 @@ #define JNICALL typedef int jint; -#if defined(_LP64) && !defined(__APPLE__) +#if defined(_LP64) typedef long jlong; #else - /* - * On _LP64 __APPLE__ "long" and "long long" are both 64 bits, - * but we use the "long long" typedef to avoid complaints from - * the __APPLE__ compiler about fprintf formats. - */ typedef long long jlong; #endif diff -r 256d3f43c177 -r f2f0cf0f5444 src/cpu/x86/vm/macroAssembler_x86.cpp --- a/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/cpu/x86/vm/macroAssembler_x86.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -6209,6 +6209,128 @@ } BIND(L_exit); } + +// encode char[] to byte[] in ISO_8859_1 +void MacroAssembler::encode_iso_array(Register src, Register dst, Register len, + XMMRegister tmp1Reg, XMMRegister tmp2Reg, + XMMRegister tmp3Reg, XMMRegister tmp4Reg, + Register tmp5, Register result) { + // rsi: src + // rdi: dst + // rdx: len + // rcx: tmp5 + // rax: result + ShortBranchVerifier sbv(this); + assert_different_registers(src, dst, len, tmp5, result); + Label L_done, L_copy_1_char, L_copy_1_char_exit; + + // set result + xorl(result, result); + // check for zero length + testl(len, len); + jcc(Assembler::zero, L_done); + movl(result, len); + + // Setup pointers + lea(src, Address(src, len, Address::times_2)); // char[] + lea(dst, Address(dst, len, Address::times_1)); // byte[] + negptr(len); + + if (UseSSE42Intrinsics || UseAVX >= 2) { + Label L_chars_8_check, L_copy_8_chars, L_copy_8_chars_exit; + Label L_chars_16_check, L_copy_16_chars, L_copy_16_chars_exit; + + if (UseAVX >= 2) { + Label L_chars_32_check, L_copy_32_chars, L_copy_32_chars_exit; + movl(tmp5, 0xff00ff00); // create mask to test for Unicode chars in vector + movdl(tmp1Reg, tmp5); + vpbroadcastd(tmp1Reg, tmp1Reg); + jmpb(L_chars_32_check); + + bind(L_copy_32_chars); + vmovdqu(tmp3Reg, Address(src, len, Address::times_2, -64)); + vmovdqu(tmp4Reg, Address(src, len, Address::times_2, -32)); + vpor(tmp2Reg, tmp3Reg, tmp4Reg, /* vector256 */ true); + vptest(tmp2Reg, tmp1Reg); // check for Unicode chars in vector + jccb(Assembler::notZero, L_copy_32_chars_exit); + vpackuswb(tmp3Reg, tmp3Reg, tmp4Reg, /* vector256 */ true); + vpermq(tmp4Reg, tmp3Reg, 0xD8, /* vector256 */ true); + vmovdqu(Address(dst, len, Address::times_1, -32), tmp4Reg); + + bind(L_chars_32_check); + addptr(len, 32); + jccb(Assembler::lessEqual, L_copy_32_chars); + + bind(L_copy_32_chars_exit); + subptr(len, 16); + jccb(Assembler::greater, L_copy_16_chars_exit); + + } else if (UseSSE42Intrinsics) { + movl(tmp5, 0xff00ff00); // create mask to test for Unicode chars in vector + movdl(tmp1Reg, tmp5); + pshufd(tmp1Reg, tmp1Reg, 0); + jmpb(L_chars_16_check); + } + + bind(L_copy_16_chars); + if (UseAVX >= 2) { + vmovdqu(tmp2Reg, Address(src, len, Address::times_2, -32)); + vptest(tmp2Reg, tmp1Reg); + jccb(Assembler::notZero, L_copy_16_chars_exit); + vpackuswb(tmp2Reg, tmp2Reg, tmp1Reg, /* vector256 */ true); + vpermq(tmp3Reg, tmp2Reg, 0xD8, /* vector256 */ true); + } else { + if (UseAVX > 0) { + movdqu(tmp3Reg, Address(src, len, Address::times_2, -32)); + movdqu(tmp4Reg, Address(src, len, Address::times_2, -16)); + vpor(tmp2Reg, tmp3Reg, tmp4Reg, /* vector256 */ false); + } else { + movdqu(tmp3Reg, Address(src, len, Address::times_2, -32)); + por(tmp2Reg, tmp3Reg); + movdqu(tmp4Reg, Address(src, len, Address::times_2, -16)); + por(tmp2Reg, tmp4Reg); + } + ptest(tmp2Reg, tmp1Reg); // check for Unicode chars in vector + jccb(Assembler::notZero, L_copy_16_chars_exit); + packuswb(tmp3Reg, tmp4Reg); + } + movdqu(Address(dst, len, Address::times_1, -16), tmp3Reg); + + bind(L_chars_16_check); + addptr(len, 16); + jccb(Assembler::lessEqual, L_copy_16_chars); + + bind(L_copy_16_chars_exit); + subptr(len, 8); + jccb(Assembler::greater, L_copy_8_chars_exit); + + bind(L_copy_8_chars); + movdqu(tmp3Reg, Address(src, len, Address::times_2, -16)); + ptest(tmp3Reg, tmp1Reg); + jccb(Assembler::notZero, L_copy_8_chars_exit); + packuswb(tmp3Reg, tmp1Reg); + movq(Address(dst, len, Address::times_1, -8), tmp3Reg); + addptr(len, 8); + jccb(Assembler::lessEqual, L_copy_8_chars); + + bind(L_copy_8_chars_exit); + subptr(len, 8); + jccb(Assembler::zero, L_done); + } + + bind(L_copy_1_char); + load_unsigned_short(tmp5, Address(src, len, Address::times_2, 0)); + testl(tmp5, 0xff00); // check if Unicode char + jccb(Assembler::notZero, L_copy_1_char_exit); + movb(Address(dst, len, Address::times_1, 0), tmp5); + addptr(len, 1); + jccb(Assembler::less, L_copy_1_char); + + bind(L_copy_1_char_exit); + addptr(result, len); // len is negative count of not processed elements + bind(L_done); +} + #undef BIND #undef BLOCK_COMMENT diff -r 256d3f43c177 -r f2f0cf0f5444 src/cpu/x86/vm/macroAssembler_x86.hpp --- a/src/cpu/x86/vm/macroAssembler_x86.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/cpu/x86/vm/macroAssembler_x86.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -1135,6 +1135,10 @@ Register to, Register value, Register count, Register rtmp, XMMRegister xtmp); + void encode_iso_array(Register src, Register dst, Register len, + XMMRegister tmp1, XMMRegister tmp2, XMMRegister tmp3, + XMMRegister tmp4, Register tmp5, Register result); + #undef VIRTUAL }; diff -r 256d3f43c177 -r f2f0cf0f5444 src/cpu/x86/vm/vm_version_x86.cpp --- a/src/cpu/x86/vm/vm_version_x86.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/cpu/x86/vm/vm_version_x86.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -661,6 +661,14 @@ } } } +#if defined(COMPILER2) && defined(_ALLBSD_SOURCE) + if (MaxVectorSize > 16) { + // Limit vectors size to 16 bytes on BSD until it fixes + // restoring upper 128bit of YMM registers on return + // from signal handler. + FLAG_SET_DEFAULT(MaxVectorSize, 16); + } +#endif // COMPILER2 // Use population count instruction if available. if (supports_popcnt()) { diff -r 256d3f43c177 -r f2f0cf0f5444 src/cpu/x86/vm/x86_32.ad --- a/src/cpu/x86/vm/x86_32.ad Thu Jan 31 10:45:09 2013 -0800 +++ b/src/cpu/x86/vm/x86_32.ad Mon Feb 04 13:26:04 2013 -0800 @@ -11687,6 +11687,23 @@ ins_pipe( pipe_slow ); %} +// encode char[] to byte[] in ISO_8859_1 +instruct encode_iso_array(eSIRegP src, eDIRegP dst, eDXRegI len, + regD tmp1, regD tmp2, regD tmp3, regD tmp4, + eCXRegI tmp5, eAXRegI result, eFlagsReg cr) %{ + match(Set result (EncodeISOArray src (Binary dst len))); + effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr); + + format %{ "Encode array $src,$dst,$len -> $result // KILL ECX, EDX, $tmp1, $tmp2, $tmp3, $tmp4, ESI, EDI " %} + ins_encode %{ + __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister, + $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register); + %} + ins_pipe( pipe_slow ); +%} + + //----------Control Flow Instructions------------------------------------------ // Signed compare Instructions instruct compI_eReg(eFlagsReg cr, rRegI op1, rRegI op2) %{ diff -r 256d3f43c177 -r f2f0cf0f5444 src/cpu/x86/vm/x86_64.ad --- a/src/cpu/x86/vm/x86_64.ad Thu Jan 31 10:45:09 2013 -0800 +++ b/src/cpu/x86/vm/x86_64.ad Mon Feb 04 13:26:04 2013 -0800 @@ -10495,6 +10495,23 @@ ins_pipe( pipe_slow ); %} +// encode char[] to byte[] in ISO_8859_1 +instruct encode_iso_array(rsi_RegP src, rdi_RegP dst, rdx_RegI len, + regD tmp1, regD tmp2, regD tmp3, regD tmp4, + rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{ + match(Set result (EncodeISOArray src (Binary dst len))); + effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr); + + format %{ "Encode array $src,$dst,$len -> $result // KILL RCX, RDX, $tmp1, $tmp2, $tmp3, $tmp4, RSI, RDI " %} + ins_encode %{ + __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register, + $tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister, + $tmp4$$XMMRegister, $tmp5$$Register, $result$$Register); + %} + ins_pipe( pipe_slow ); +%} + + //----------Control Flow Instructions------------------------------------------ // Signed compare Instructions diff -r 256d3f43c177 -r f2f0cf0f5444 src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/os/bsd/vm/os_bsd.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,29 +243,32 @@ int mib[2]; size_t len; int cpu_val; - u_long mem_val; + julong mem_val; /* get processors count via hw.ncpus sysctl */ mib[0] = CTL_HW; mib[1] = HW_NCPU; len = sizeof(cpu_val); if (sysctl(mib, 2, &cpu_val, &len, NULL, 0) != -1 && cpu_val >= 1) { + assert(len == sizeof(cpu_val), "unexpected data size"); set_processor_count(cpu_val); } else { set_processor_count(1); // fallback } - /* get physical memory via hw.usermem sysctl (hw.usermem is used - * instead of hw.physmem because we need size of allocatable memory + /* get physical memory via hw.memsize sysctl (hw.memsize is used + * since it returns a 64 bit value) */ mib[0] = CTL_HW; - mib[1] = HW_USERMEM; + mib[1] = HW_MEMSIZE; len = sizeof(mem_val); - if (sysctl(mib, 2, &mem_val, &len, NULL, 0) != -1) + if (sysctl(mib, 2, &mem_val, &len, NULL, 0) != -1) { + assert(len == sizeof(mem_val), "unexpected data size"); _physical_memory = mem_val; - else + } else { _physical_memory = 256*1024*1024; // fallback (XXXBSD?) + } #ifdef __OpenBSD__ { @@ -4091,11 +4094,12 @@ } -- _nParked ; - // In theory we could move the ST of 0 into _Event past the unlock(), - // but then we'd need a MEMBAR after the ST. _Event = 0 ; status = pthread_mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock"); + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other. + OrderAccess::fence(); } guarantee (_Event >= 0, "invariant") ; } @@ -4158,40 +4162,44 @@ status = pthread_mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock"); assert (_nParked == 0, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other. + OrderAccess::fence(); return ret; } void os::PlatformEvent::unpark() { - int v, AnyWaiters ; - for (;;) { - v = _Event ; - if (v > 0) { - // The LD of _Event could have reordered or be satisfied - // by a read-aside from this processor's write buffer. - // To avoid problems execute a barrier and then - // ratify the value. - OrderAccess::fence() ; - if (_Event == v) return ; - continue ; - } - if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; + // Transitions for _Event: + // 0 :=> 1 + // 1 :=> 1 + // -1 :=> either 0 or 1; must signal target thread + // That is, we can safely transition _Event from -1 to either + // 0 or 1. Forcing 1 is slightly more efficient for back-to-back + // unpark() calls. + // See also: "Semaphores in Plan 9" by Mullender & Cox + // + // Note: Forcing a transition from "-1" to "1" on an unpark() means + // that it will take two back-to-back park() calls for the owning + // thread to block. This has the benefit of forcing a spurious return + // from the first park() call after an unpark() call which will help + // shake out uses of park() and unpark() without condition variables. + + if (Atomic::xchg(1, &_Event) >= 0) return; + + // Wait for the thread associated with the event to vacate + int status = pthread_mutex_lock(_mutex); + assert_status(status == 0, status, "mutex_lock"); + int AnyWaiters = _nParked; + assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant"); + if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { + AnyWaiters = 0; + pthread_cond_signal(_cond); } - if (v < 0) { - // Wait for the thread associated with the event to vacate - int status = pthread_mutex_lock(_mutex); - assert_status(status == 0, status, "mutex_lock"); - AnyWaiters = _nParked ; - assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; - if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { - AnyWaiters = 0 ; - pthread_cond_signal (_cond); - } - status = pthread_mutex_unlock(_mutex); - assert_status(status == 0, status, "mutex_unlock"); - if (AnyWaiters != 0) { - status = pthread_cond_signal(_cond); - assert_status(status == 0, status, "cond_signal"); - } + status = pthread_mutex_unlock(_mutex); + assert_status(status == 0, status, "mutex_unlock"); + if (AnyWaiters != 0) { + status = pthread_cond_signal(_cond); + assert_status(status == 0, status, "cond_signal"); } // Note that we signal() _after dropping the lock for "immortal" Events. @@ -4277,13 +4285,14 @@ } void Parker::park(bool isAbsolute, jlong time) { + // Ideally we'd do something useful while spinning, such + // as calling unpackTime(). + // Optional fast-path check: // Return immediately if a permit is available. - if (_counter > 0) { - _counter = 0 ; - OrderAccess::fence(); - return ; - } + // We depend on Atomic::xchg() having full barrier semantics + // since we are doing a lock-free update to _counter. + if (Atomic::xchg(0, &_counter) > 0) return; Thread* thread = Thread::current(); assert(thread->is_Java_thread(), "Must be JavaThread"); @@ -4324,6 +4333,8 @@ _counter = 0; status = pthread_mutex_unlock(_mutex); assert (status == 0, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other and Java-level accesses. OrderAccess::fence(); return; } @@ -4360,12 +4371,14 @@ _counter = 0 ; status = pthread_mutex_unlock(_mutex) ; assert_status(status == 0, status, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other and Java-level accesses. + OrderAccess::fence(); + // If externally suspended while waiting, re-suspend if (jt->handle_special_suspend_equivalent_condition()) { jt->java_suspend_self(); } - - OrderAccess::fence(); } void Parker::unpark() { diff -r 256d3f43c177 -r f2f0cf0f5444 src/os/bsd/vm/os_bsd.inline.hpp --- a/src/os/bsd/vm/os_bsd.inline.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/os/bsd/vm/os_bsd.inline.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,14 +59,6 @@ return ":"; } -inline const char* os::jlong_format_specifier() { - return "%lld"; -} - -inline const char* os::julong_format_specifier() { - return "%llu"; -} - // File names are case-sensitive on windows only inline int os::file_name_strcmp(const char* s1, const char* s2) { return strcmp(s1, s2); diff -r 256d3f43c177 -r f2f0cf0f5444 src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/os/linux/vm/os_linux.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -5001,11 +5001,12 @@ } -- _nParked ; - // In theory we could move the ST of 0 into _Event past the unlock(), - // but then we'd need a MEMBAR after the ST. _Event = 0 ; status = pthread_mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock"); + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other. + OrderAccess::fence(); } guarantee (_Event >= 0, "invariant") ; } @@ -5068,40 +5069,44 @@ status = pthread_mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock"); assert (_nParked == 0, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other. + OrderAccess::fence(); return ret; } void os::PlatformEvent::unpark() { - int v, AnyWaiters ; - for (;;) { - v = _Event ; - if (v > 0) { - // The LD of _Event could have reordered or be satisfied - // by a read-aside from this processor's write buffer. - // To avoid problems execute a barrier and then - // ratify the value. - OrderAccess::fence() ; - if (_Event == v) return ; - continue ; - } - if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; - } - if (v < 0) { - // Wait for the thread associated with the event to vacate - int status = pthread_mutex_lock(_mutex); - assert_status(status == 0, status, "mutex_lock"); - AnyWaiters = _nParked ; - assert (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; - if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { - AnyWaiters = 0 ; - pthread_cond_signal (_cond); - } - status = pthread_mutex_unlock(_mutex); - assert_status(status == 0, status, "mutex_unlock"); - if (AnyWaiters != 0) { - status = pthread_cond_signal(_cond); - assert_status(status == 0, status, "cond_signal"); - } + // Transitions for _Event: + // 0 :=> 1 + // 1 :=> 1 + // -1 :=> either 0 or 1; must signal target thread + // That is, we can safely transition _Event from -1 to either + // 0 or 1. Forcing 1 is slightly more efficient for back-to-back + // unpark() calls. + // See also: "Semaphores in Plan 9" by Mullender & Cox + // + // Note: Forcing a transition from "-1" to "1" on an unpark() means + // that it will take two back-to-back park() calls for the owning + // thread to block. This has the benefit of forcing a spurious return + // from the first park() call after an unpark() call which will help + // shake out uses of park() and unpark() without condition variables. + + if (Atomic::xchg(1, &_Event) >= 0) return; + + // Wait for the thread associated with the event to vacate + int status = pthread_mutex_lock(_mutex); + assert_status(status == 0, status, "mutex_lock"); + int AnyWaiters = _nParked; + assert(AnyWaiters == 0 || AnyWaiters == 1, "invariant"); + if (AnyWaiters != 0 && WorkAroundNPTLTimedWaitHang) { + AnyWaiters = 0; + pthread_cond_signal(_cond); + } + status = pthread_mutex_unlock(_mutex); + assert_status(status == 0, status, "mutex_unlock"); + if (AnyWaiters != 0) { + status = pthread_cond_signal(_cond); + assert_status(status == 0, status, "cond_signal"); } // Note that we signal() _after dropping the lock for "immortal" Events. @@ -5187,13 +5192,14 @@ } void Parker::park(bool isAbsolute, jlong time) { + // Ideally we'd do something useful while spinning, such + // as calling unpackTime(). + // Optional fast-path check: // Return immediately if a permit is available. - if (_counter > 0) { - _counter = 0 ; - OrderAccess::fence(); - return ; - } + // We depend on Atomic::xchg() having full barrier semantics + // since we are doing a lock-free update to _counter. + if (Atomic::xchg(0, &_counter) > 0) return; Thread* thread = Thread::current(); assert(thread->is_Java_thread(), "Must be JavaThread"); @@ -5234,6 +5240,8 @@ _counter = 0; status = pthread_mutex_unlock(_mutex); assert (status == 0, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other and Java-level accesses. OrderAccess::fence(); return; } @@ -5270,12 +5278,14 @@ _counter = 0 ; status = pthread_mutex_unlock(_mutex) ; assert_status(status == 0, status, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other and Java-level accesses. + OrderAccess::fence(); + // If externally suspended while waiting, re-suspend if (jt->handle_special_suspend_equivalent_condition()) { jt->java_suspend_self(); } - - OrderAccess::fence(); } void Parker::unpark() { diff -r 256d3f43c177 -r f2f0cf0f5444 src/os/linux/vm/os_linux.inline.hpp --- a/src/os/linux/vm/os_linux.inline.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/os/linux/vm/os_linux.inline.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,14 +68,6 @@ return ":"; } -inline const char* os::jlong_format_specifier() { - return "%lld"; -} - -inline const char* os::julong_format_specifier() { - return "%llu"; -} - // File names are case-sensitive on windows only inline int os::file_name_strcmp(const char* s1, const char* s2) { return strcmp(s1, s2); diff -r 256d3f43c177 -r f2f0cf0f5444 src/os/posix/launcher/java_md.c --- a/src/os/posix/launcher/java_md.c Thu Jan 31 10:45:09 2013 -0800 +++ b/src/os/posix/launcher/java_md.c Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1876,11 +1876,6 @@ } } -const char * -jlong_format_specifier() { - return "%lld"; -} - /* * Block current thread and continue execution in a new thread */ diff -r 256d3f43c177 -r f2f0cf0f5444 src/os/posix/launcher/java_md.h --- a/src/os/posix/launcher/java_md.h Thu Jan 31 10:45:09 2013 -0800 +++ b/src/os/posix/launcher/java_md.h Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,6 +64,12 @@ #define Counter2Micros(counts) (1) #endif /* HAVE_GETHRTIME */ +#ifdef _LP64 +#define JLONG_FORMAT "%ld" +#else +#define JLONG_FORMAT "%lld" +#endif + /* * Function prototypes. */ diff -r 256d3f43c177 -r f2f0cf0f5444 src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/os/solaris/vm/os_solaris.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -6014,6 +6014,9 @@ _Event = 0 ; status = os::Solaris::mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock"); + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other. + OrderAccess::fence(); } } @@ -6055,51 +6058,43 @@ _Event = 0 ; status = os::Solaris::mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock"); + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other. + OrderAccess::fence(); return ret; } void os::PlatformEvent::unpark() { - int v, AnyWaiters; - - // Increment _Event. - // Another acceptable implementation would be to simply swap 1 - // into _Event: - // if (Swap (&_Event, 1) < 0) { - // mutex_lock (_mutex) ; AnyWaiters = nParked; mutex_unlock (_mutex) ; - // if (AnyWaiters) cond_signal (_cond) ; - // } - - for (;;) { - v = _Event ; - if (v > 0) { - // The LD of _Event could have reordered or be satisfied - // by a read-aside from this processor's write buffer. - // To avoid problems execute a barrier and then - // ratify the value. A degenerate CAS() would also work. - // Viz., CAS (v+0, &_Event, v) == v). - OrderAccess::fence() ; - if (_Event == v) return ; - continue ; - } - if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; - } + // Transitions for _Event: + // 0 :=> 1 + // 1 :=> 1 + // -1 :=> either 0 or 1; must signal target thread + // That is, we can safely transition _Event from -1 to either + // 0 or 1. Forcing 1 is slightly more efficient for back-to-back + // unpark() calls. + // See also: "Semaphores in Plan 9" by Mullender & Cox + // + // Note: Forcing a transition from "-1" to "1" on an unpark() means + // that it will take two back-to-back park() calls for the owning + // thread to block. This has the benefit of forcing a spurious return + // from the first park() call after an unpark() call which will help + // shake out uses of park() and unpark() without condition variables. + + if (Atomic::xchg(1, &_Event) >= 0) return; // If the thread associated with the event was parked, wake it. - if (v < 0) { - int status ; - // Wait for the thread assoc with the PlatformEvent to vacate. - status = os::Solaris::mutex_lock(_mutex); - assert_status(status == 0, status, "mutex_lock"); - AnyWaiters = _nParked ; - status = os::Solaris::mutex_unlock(_mutex); - assert_status(status == 0, status, "mutex_unlock"); - guarantee (AnyWaiters == 0 || AnyWaiters == 1, "invariant") ; - if (AnyWaiters != 0) { - // We intentional signal *after* dropping the lock - // to avoid a common class of futile wakeups. - status = os::Solaris::cond_signal(_cond); - assert_status(status == 0, status, "cond_signal"); - } + // Wait for the thread assoc with the PlatformEvent to vacate. + int status = os::Solaris::mutex_lock(_mutex); + assert_status(status == 0, status, "mutex_lock"); + int AnyWaiters = _nParked; + status = os::Solaris::mutex_unlock(_mutex); + assert_status(status == 0, status, "mutex_unlock"); + guarantee(AnyWaiters == 0 || AnyWaiters == 1, "invariant"); + if (AnyWaiters != 0) { + // We intentional signal *after* dropping the lock + // to avoid a common class of futile wakeups. + status = os::Solaris::cond_signal(_cond); + assert_status(status == 0, status, "cond_signal"); } } @@ -6177,14 +6172,14 @@ } void Parker::park(bool isAbsolute, jlong time) { + // Ideally we'd do something useful while spinning, such + // as calling unpackTime(). // Optional fast-path check: // Return immediately if a permit is available. - if (_counter > 0) { - _counter = 0 ; - OrderAccess::fence(); - return ; - } + // We depend on Atomic::xchg() having full barrier semantics + // since we are doing a lock-free update to _counter. + if (Atomic::xchg(0, &_counter) > 0) return; // Optional fast-exit: Check interrupt before trying to wait Thread* thread = Thread::current(); @@ -6226,6 +6221,8 @@ _counter = 0; status = os::Solaris::mutex_unlock(_mutex); assert (status == 0, "invariant") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other and Java-level accesses. OrderAccess::fence(); return; } @@ -6267,12 +6264,14 @@ _counter = 0 ; status = os::Solaris::mutex_unlock(_mutex); assert_status(status == 0, status, "mutex_unlock") ; + // Paranoia to ensure our locked and lock-free paths interact + // correctly with each other and Java-level accesses. + OrderAccess::fence(); // If externally suspended while waiting, re-suspend if (jt->handle_special_suspend_equivalent_condition()) { jt->java_suspend_self(); } - OrderAccess::fence(); } void Parker::unpark() { diff -r 256d3f43c177 -r f2f0cf0f5444 src/os/solaris/vm/os_solaris.inline.hpp --- a/src/os/solaris/vm/os_solaris.inline.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/os/solaris/vm/os_solaris.inline.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,9 +50,6 @@ inline const char* os::line_separator() { return "\n"; } inline const char* os::path_separator() { return ":"; } -inline const char* os::jlong_format_specifier() { return "%lld"; } -inline const char* os::julong_format_specifier() { return "%llu"; } - // File names are case-sensitive on windows only inline int os::file_name_strcmp(const char* s1, const char* s2) { return strcmp(s1, s2); diff -r 256d3f43c177 -r f2f0cf0f5444 src/os/windows/launcher/java_md.c --- a/src/os/windows/launcher/java_md.c Thu Jan 31 10:45:09 2013 -0800 +++ b/src/os/windows/launcher/java_md.c Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1323,11 +1323,6 @@ } } -const char * -jlong_format_specifier() { - return "%I64d"; -} - /* * Block current thread and continue execution in a new thread */ diff -r 256d3f43c177 -r f2f0cf0f5444 src/os/windows/launcher/java_md.h --- a/src/os/windows/launcher/java_md.h Thu Jan 31 10:45:09 2013 -0800 +++ b/src/os/windows/launcher/java_md.h Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,6 +69,8 @@ extern int _main(int argc, char **argv); #endif +#define JLONG_FORMAT "%I64d" + /* * Function prototypes. */ diff -r 256d3f43c177 -r f2f0cf0f5444 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/os/windows/vm/os_windows.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1874,8 +1874,22 @@ } return TRUE; break; + case CTRL_LOGOFF_EVENT: { + // Don't terminate JVM if it is running in a non-interactive session, + // such as a service process. + USEROBJECTFLAGS flags; + HANDLE handle = GetProcessWindowStation(); + if (handle != NULL && + GetUserObjectInformation(handle, UOI_FLAGS, &flags, + sizeof( USEROBJECTFLAGS), NULL)) { + // If it is a non-interactive session, let next handler to deal + // with it. + if ((flags.dwFlags & WSF_VISIBLE) == 0) { + return FALSE; + } + } + } case CTRL_CLOSE_EVENT: - case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: os::signal_raise(SIGTERM); return TRUE; @@ -2946,7 +2960,7 @@ } if( Verbose && PrintMiscellaneous ) { reserveTimer.stop(); - tty->print_cr("reserve_memory of %Ix bytes took %ld ms (%ld ticks)", bytes, + tty->print_cr("reserve_memory of %Ix bytes took " JLONG_FORMAT " ms (" JLONG_FORMAT " ticks)", bytes, reserveTimer.milliseconds(), reserveTimer.ticks()); } } @@ -4305,7 +4319,7 @@ if (hFile == NULL) { if (PrintMiscellaneous && Verbose) { DWORD err = GetLastError(); - tty->print_cr("CreateFile() failed: GetLastError->%ld."); + tty->print_cr("CreateFile() failed: GetLastError->%ld.", err); } return NULL; } @@ -4355,7 +4369,7 @@ if (hMap == NULL) { if (PrintMiscellaneous && Verbose) { DWORD err = GetLastError(); - tty->print_cr("CreateFileMapping() failed: GetLastError->%ld."); + tty->print_cr("CreateFileMapping() failed: GetLastError->%ld.", err); } CloseHandle(hFile); return NULL; @@ -4565,6 +4579,7 @@ } v = _Event ; _Event = 0 ; + // see comment at end of os::PlatformEvent::park() below: OrderAccess::fence() ; // If we encounter a nearly simultanous timeout expiry and unpark() // we return OS_OK indicating we awoke via unpark(). @@ -4602,25 +4617,25 @@ void os::PlatformEvent::unpark() { guarantee (_ParkHandle != NULL, "Invariant") ; - int v ; - for (;;) { - v = _Event ; // Increment _Event if it's < 1. - if (v > 0) { - // If it's already signaled just return. - // The LD of _Event could have reordered or be satisfied - // by a read-aside from this processor's write buffer. - // To avoid problems execute a barrier and then - // ratify the value. A degenerate CAS() would also work. - // Viz., CAS (v+0, &_Event, v) == v). - OrderAccess::fence() ; - if (_Event == v) return ; - continue ; - } - if (Atomic::cmpxchg (v+1, &_Event, v) == v) break ; - } - if (v < 0) { - ::SetEvent (_ParkHandle) ; - } + + // Transitions for _Event: + // 0 :=> 1 + // 1 :=> 1 + // -1 :=> either 0 or 1; must signal target thread + // That is, we can safely transition _Event from -1 to either + // 0 or 1. Forcing 1 is slightly more efficient for back-to-back + // unpark() calls. + // See also: "Semaphores in Plan 9" by Mullender & Cox + // + // Note: Forcing a transition from "-1" to "1" on an unpark() means + // that it will take two back-to-back park() calls for the owning + // thread to block. This has the benefit of forcing a spurious return + // from the first park() call after an unpark() call which will help + // shake out uses of park() and unpark() without condition variables. + + if (Atomic::xchg(1, &_Event) >= 0) return; + + ::SetEvent(_ParkHandle); } diff -r 256d3f43c177 -r f2f0cf0f5444 src/os/windows/vm/os_windows.inline.hpp --- a/src/os/windows/vm/os_windows.inline.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/os/windows/vm/os_windows.inline.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,9 +38,6 @@ inline const char* os::path_separator() { return ";"; } inline const char* os::dll_file_extension() { return ".dll"; } -inline const char* os::jlong_format_specifier() { return "%I64d"; } -inline const char* os::julong_format_specifier() { return "%I64u"; } - inline const int os::default_file_open_flags() { return O_BINARY | O_NOINHERIT;} // File names are case-insensitive on windows only diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/tools/launcher/java.c --- a/src/share/tools/launcher/java.c Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/tools/launcher/java.c Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -808,7 +808,7 @@ static int parse_stack_size(const char *s, jlong *result) { jlong n = 0; - int args_read = sscanf(s, jlong_format_specifier(), &n); + int args_read = sscanf(s, JLONG_FORMAT, &n); if (args_read != 1) { return 0; } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/tools/launcher/java.h --- a/src/share/tools/launcher/java.h Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/tools/launcher/java.h Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,7 +86,6 @@ jboolean RemovableMachineDependentOption(char * option); void PrintMachineDependentOptions(); -const char *jlong_format_specifier(); /* * Block current thread and continue execution in new thread */ diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/adlc/formssel.cpp --- a/src/share/vm/adlc/formssel.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/adlc/formssel.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -862,8 +862,10 @@ ( strcmp(_matrule->_rChild->_opType,"AryEq" )==0 || strcmp(_matrule->_rChild->_opType,"StrComp" )==0 || strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 || - strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 )) { + strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 || + strcmp(_matrule->_rChild->_opType,"EncodeISOArray")==0)) { // String.(compareTo/equals/indexOf) and Arrays.equals + // and sun.nio.cs.iso8859_1$Encoder.EncodeISOArray // take 1 control and 1 memory edges. return 2; } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/c1/c1_InstructionPrinter.cpp --- a/src/share/vm/c1/c1_InstructionPrinter.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/c1/c1_InstructionPrinter.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -360,7 +360,7 @@ ValueType* t = x->type(); switch (t->tag()) { case intTag : output()->print("%d" , t->as_IntConstant ()->value()); break; - case longTag : output()->print(os::jlong_format_specifier(), t->as_LongConstant()->value()); output()->print("L"); break; + case longTag : output()->print(JLONG_FORMAT, t->as_LongConstant()->value()); output()->print("L"); break; case floatTag : output()->print("%g" , t->as_FloatConstant ()->value()); break; case doubleTag : output()->print("%gD" , t->as_DoubleConstant()->value()); break; case objectTag : print_object(x); break; diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/c1/c1_LIR.cpp --- a/src/share/vm/c1/c1_LIR.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/c1/c1_LIR.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -1563,7 +1563,7 @@ switch (type()) { case T_ADDRESS:out->print("address:%d",as_jint()); break; case T_INT: out->print("int:%d", as_jint()); break; - case T_LONG: out->print("lng:%lld", as_jlong()); break; + case T_LONG: out->print("lng:" JLONG_FORMAT, as_jlong()); break; case T_FLOAT: out->print("flt:%f", as_jfloat()); break; case T_DOUBLE: out->print("dbl:%f", as_jdouble()); break; case T_OBJECT: out->print("obj:0x%x", as_jobject()); break; diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/ci/ciReplay.cpp --- a/src/share/vm/ci/ciReplay.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/ci/ciReplay.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +/* 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 @@ -645,7 +645,7 @@ java_mirror->bool_field_put(fd.offset(), value); } else if (strcmp(field_signature, "J") == 0) { jlong value; - if (sscanf(string_value, INT64_FORMAT, &value) != 1) { + if (sscanf(string_value, JLONG_FORMAT, &value) != 1) { fprintf(stderr, "Error parsing long: %s\n", string_value); return; } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/classfile/classFileParser.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1802,11 +1802,9 @@ ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_data, Symbol* name) { vmSymbols::SID sid = vmSymbols::find_sid(name); - bool privileged = false; - if (loader_data->is_the_null_class_loader_data()) { - // Privileged code can use all annotations. Other code silently drops some. - privileged = true; - } + // Privileged code can use all annotations. Other code silently drops some. + bool privileged = loader_data->is_the_null_class_loader_data() || + loader_data->is_anonymous(); switch (sid) { case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_ForceInline_signature): if (_location != _in_method) break; // only allow for methods diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/classfile/javaClasses.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -911,7 +911,6 @@ // Write the thread status value to threadStatus field in java.lang.Thread java class. void java_lang_Thread::set_thread_status(oop java_thread, java_lang_Thread::ThreadStatus status) { - assert(JavaThread::current()->thread_state() == _thread_in_vm, "Java Thread is not running in vm"); // The threadStatus is only present starting in 1.5 if (_thread_status_offset > 0) { java_thread->int_field_put(_thread_status_offset, status); @@ -1145,179 +1144,43 @@ } } -// Print stack trace element to resource allocated buffer -char* java_lang_Throwable::print_stack_element_to_buffer(Method* method, int bci) { - // Get strings and string lengths - InstanceKlass* klass = method->method_holder(); - const char* klass_name = klass->external_name(); - int buf_len = (int)strlen(klass_name); - char* source_file_name; - if (klass->source_file_name() == NULL) { - source_file_name = NULL; +// After this many redefines, the stack trace is unreliable. +const int MAX_VERSION = USHRT_MAX; + +// Helper backtrace functions to store bci|version together. +static inline int merge_bci_and_version(int bci, int version) { + // only store u2 for version, checking for overflow. + if (version > USHRT_MAX || version < 0) version = MAX_VERSION; + assert((jushort)bci == bci, "bci should be short"); + return build_int_from_shorts(version, bci); +} + +static inline int bci_at(unsigned int merged) { + return extract_high_short_from_int(merged); +} +static inline int version_at(unsigned int merged) { + return extract_low_short_from_int(merged); +} + +static inline bool version_matches(Method* method, int version) { + return (method->constants()->version() == version && version < MAX_VERSION); +} + +static inline int get_line_number(Method* method, int bci) { + int line_number = 0; + if (method->is_native()) { + // Negative value different from -1 below, enabling Java code in + // class java.lang.StackTraceElement to distinguish "native" from + // "no LineNumberTable". JDK tests for -2. + line_number = -2; } else { - source_file_name = klass->source_file_name()->as_C_string(); - buf_len += (int)strlen(source_file_name); - } - char* method_name = method->name()->as_C_string(); - buf_len += (int)strlen(method_name); - - // Allocate temporary buffer with extra space for formatting and line number - char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); - - // Print stack trace line in buffer - sprintf(buf, "\tat %s.%s", klass_name, method_name); - if (method->is_native()) { - strcat(buf, "(Native Method)"); - } else { - int line_number = method->line_number_from_bci(bci); - if (source_file_name != NULL && (line_number != -1)) { - // Sourcename and linenumber - sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number); - } else if (source_file_name != NULL) { - // Just sourcename - sprintf(buf + (int)strlen(buf), "(%s)", source_file_name); - } else { - // Neither soucename and linenumber - sprintf(buf + (int)strlen(buf), "(Unknown Source)"); - } - nmethod* nm = method->code(); - if (WizardMode && nm != NULL) { - sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); + // Returns -1 if no LineNumberTable, and otherwise actual line number + line_number = method->line_number_from_bci(bci); + if (line_number == -1 && ShowHiddenFrames) { + line_number = bci + 1000000; } } - - return buf; -} - - -void java_lang_Throwable::print_stack_element(Handle stream, Method* method, int bci) { - ResourceMark rm; - char* buf = print_stack_element_to_buffer(method, bci); - print_to_stream(stream, buf); -} - -void java_lang_Throwable::print_stack_element(outputStream *st, Method* method, int bci) { - ResourceMark rm; - char* buf = print_stack_element_to_buffer(method, bci); - st->print_cr("%s", buf); -} - -void java_lang_Throwable::print_to_stream(Handle stream, const char* str) { - if (stream.is_null()) { - tty->print_cr("%s", str); - } else { - EXCEPTION_MARK; - JavaValue result(T_VOID); - Handle arg (THREAD, oopFactory::new_charArray(str, THREAD)); - if (!HAS_PENDING_EXCEPTION) { - JavaCalls::call_virtual(&result, - stream, - KlassHandle(THREAD, stream->klass()), - vmSymbols::println_name(), - vmSymbols::char_array_void_signature(), - arg, - THREAD); - } - // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. - if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION; - } - -} - - -const char* java_lang_Throwable::no_stack_trace_message() { - return "\t<>"; -} - - -// Currently used only for exceptions occurring during startup -void java_lang_Throwable::print_stack_trace(oop throwable, outputStream* st) { - Thread *THREAD = Thread::current(); - Handle h_throwable(THREAD, throwable); - while (h_throwable.not_null()) { - objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable()))); - if (result.is_null()) { - st->print_cr(no_stack_trace_message()); - return; - } - - while (result.not_null()) { - typeArrayHandle methods (THREAD, - typeArrayOop(result->obj_at(trace_methods_offset))); - typeArrayHandle bcis (THREAD, - typeArrayOop(result->obj_at(trace_bcis_offset))); - - if (methods.is_null() || bcis.is_null()) { - st->print_cr(no_stack_trace_message()); - return; - } - - int length = methods()->length(); - for (int index = 0; index < length; index++) { - Method* method = ((Method*)methods()->metadata_at(index)); - if (method == NULL) goto handle_cause; - int bci = bcis->ushort_at(index); - print_stack_element(st, method, bci); - } - result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); - } - handle_cause: - { - EXCEPTION_MARK; - JavaValue result(T_OBJECT); - JavaCalls::call_virtual(&result, - h_throwable, - KlassHandle(THREAD, h_throwable->klass()), - vmSymbols::getCause_name(), - vmSymbols::void_throwable_signature(), - THREAD); - // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - h_throwable = Handle(); - } else { - h_throwable = Handle(THREAD, (oop) result.get_jobject()); - if (h_throwable.not_null()) { - st->print("Caused by: "); - print(h_throwable, st); - st->cr(); - } - } - } - } -} - - -void java_lang_Throwable::print_stack_trace(oop throwable, oop print_stream) { - // Note: this is no longer used in Merlin, but we support it for compatibility. - Thread *thread = Thread::current(); - Handle stream(thread, print_stream); - objArrayHandle result (thread, objArrayOop(backtrace(throwable))); - if (result.is_null()) { - print_to_stream(stream, no_stack_trace_message()); - return; - } - - while (result.not_null()) { - typeArrayHandle methods(thread, - typeArrayOop(result->obj_at(trace_methods_offset))); - typeArrayHandle bcis (thread, - typeArrayOop(result->obj_at(trace_bcis_offset))); - - if (methods.is_null() || bcis.is_null()) { - print_to_stream(stream, no_stack_trace_message()); - return; - } - - int length = methods()->length(); - for (int index = 0; index < length; index++) { - Method* method = ((Method*)methods()->metadata_at(index)); - if (method == NULL) return; - int bci = bcis->ushort_at(index); - print_stack_element(stream, method, bci); - } - result = objArrayHandle(thread, objArrayOop(result->obj_at(trace_next_offset))); - } + return line_number; } // This class provides a simple wrapper over the internal structure of @@ -1337,13 +1200,30 @@ enum { trace_methods_offset = java_lang_Throwable::trace_methods_offset, - trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, + trace_bcis_offset = java_lang_Throwable::trace_bcis_offset, trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset, trace_next_offset = java_lang_Throwable::trace_next_offset, trace_size = java_lang_Throwable::trace_size, trace_chunk_size = java_lang_Throwable::trace_chunk_size }; + // get info out of chunks + static typeArrayOop get_methods(objArrayHandle chunk) { + typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset)); + assert(methods != NULL, "method array should be initialized in backtrace"); + return methods; + } + static typeArrayOop get_bcis(objArrayHandle chunk) { + typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset)); + assert(bcis != NULL, "bci array should be initialized in backtrace"); + return bcis; + } + static objArrayOop get_mirrors(objArrayHandle chunk) { + objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset)); + assert(mirrors != NULL, "mirror array should be initialized in backtrace"); + return mirrors; + } + // constructor for new backtrace BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL) { expand(CHECK); @@ -1351,6 +1231,19 @@ _index = 0; } + BacktraceBuilder(objArrayHandle backtrace) { + _methods = get_methods(backtrace); + _bcis = get_bcis(backtrace); + _mirrors = get_mirrors(backtrace); + assert(_methods->length() == _bcis->length() && + _methods->length() == _mirrors->length(), + "method and source information arrays should match"); + + // head is the preallocated backtrace + _backtrace = _head = backtrace(); + _index = 0; + } + void expand(TRAPS) { objArrayHandle old_head(THREAD, _head); Pause_No_Safepoint_Verifier pnsv(&_nsv); @@ -1358,10 +1251,10 @@ objArrayOop head = oopFactory::new_objectArray(trace_size, CHECK); objArrayHandle new_head(THREAD, head); - typeArrayOop methods = oopFactory::new_metaDataArray(trace_chunk_size, CHECK); + typeArrayOop methods = oopFactory::new_shortArray(trace_chunk_size, CHECK); typeArrayHandle new_methods(THREAD, methods); - typeArrayOop bcis = oopFactory::new_shortArray(trace_chunk_size, CHECK); + typeArrayOop bcis = oopFactory::new_intArray(trace_chunk_size, CHECK); typeArrayHandle new_bcis(THREAD, bcis); objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK); @@ -1376,7 +1269,7 @@ _head = new_head(); _methods = new_methods(); - _bcis = new_bcis(); + _bcis = new_bcis(); _mirrors = new_mirrors(); _index = 0; } @@ -1390,7 +1283,6 @@ // shorts. The later line number lookup would just smear the -1 // to a 0 even if it could be recorded. if (bci == SynchronizationEntryBCI) bci = 0; - assert(bci == (jushort)bci, "doesn't fit"); if (_index >= trace_chunk_size) { methodHandle mhandle(THREAD, method); @@ -1398,26 +1290,148 @@ method = mhandle(); } - _methods->metadata_at_put(_index, method); - _bcis->ushort_at_put(_index, bci); - // we need to save the mirrors in the backtrace to keep the methods from - // being unloaded if their class loader is unloaded while we still have - // this stack trace. + _methods->short_at_put(_index, method->method_idnum()); + _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version())); + + // We need to save the mirrors in the backtrace to keep the class + // from being unloaded while we still have this stack trace. + assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror"); _mirrors->obj_at_put(_index, method->method_holder()->java_mirror()); _index++; } - Method* current_method() { - assert(_index >= 0 && _index < trace_chunk_size, "out of range"); - return ((Method*)_methods->metadata_at(_index)); +}; + +// Print stack trace element to resource allocated buffer +char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror, + int method_id, int version, int bci) { + + // Get strings and string lengths + InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); + const char* klass_name = holder->external_name(); + int buf_len = (int)strlen(klass_name); + + // pushing to the stack trace added one. + Method* method = holder->method_with_idnum(method_id); + char* method_name = method->name()->as_C_string(); + buf_len += (int)strlen(method_name); + + char* source_file_name = NULL; + if (version_matches(method, version)) { + Symbol* source = holder->source_file_name(); + if (source != NULL) { + source_file_name = source->as_C_string(); + buf_len += (int)strlen(source_file_name); + } + } + + // Allocate temporary buffer with extra space for formatting and line number + char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); + + // Print stack trace line in buffer + sprintf(buf, "\tat %s.%s", klass_name, method_name); + + if (!version_matches(method, version)) { + strcat(buf, "(Redefined)"); + } else { + int line_number = get_line_number(method, bci); + if (line_number == -2) { + strcat(buf, "(Native Method)"); + } else { + if (source_file_name != NULL && (line_number != -1)) { + // Sourcename and linenumber + sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number); + } else if (source_file_name != NULL) { + // Just sourcename + sprintf(buf + (int)strlen(buf), "(%s)", source_file_name); + } else { + // Neither sourcename nor linenumber + sprintf(buf + (int)strlen(buf), "(Unknown Source)"); + } + nmethod* nm = method->code(); + if (WizardMode && nm != NULL) { + sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); + } + } } - jushort current_bci() { - assert(_index >= 0 && _index < trace_chunk_size, "out of range"); - return _bcis->ushort_at(_index); + return buf; +} + +void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror, + int method_id, int version, int bci) { + ResourceMark rm; + char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci); + st->print_cr("%s", buf); +} + +void java_lang_Throwable::print_stack_element(outputStream *st, methodHandle method, int bci) { + Handle mirror = method->method_holder()->java_mirror(); + int method_id = method->method_idnum(); + int version = method->constants()->version(); + print_stack_element(st, mirror, method_id, version, bci); +} + +const char* java_lang_Throwable::no_stack_trace_message() { + return "\t<>"; +} + + +// Currently used only for exceptions occurring during startup +void java_lang_Throwable::print_stack_trace(oop throwable, outputStream* st) { + Thread *THREAD = Thread::current(); + Handle h_throwable(THREAD, throwable); + while (h_throwable.not_null()) { + objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable()))); + if (result.is_null()) { + st->print_cr(no_stack_trace_message()); + return; + } + + while (result.not_null()) { + + // Get method id, bci, version and mirror from chunk + typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result)); + typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result)); + objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result)); + + int length = methods()->length(); + for (int index = 0; index < length; index++) { + Handle mirror(THREAD, mirrors->obj_at(index)); + // NULL mirror means end of stack trace + if (mirror.is_null()) goto handle_cause; + int method = methods->short_at(index); + int version = version_at(bcis->int_at(index)); + int bci = bci_at(bcis->int_at(index)); + print_stack_element(st, mirror, method, version, bci); + } + result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset))); + } + handle_cause: + { + EXCEPTION_MARK; + JavaValue cause(T_OBJECT); + JavaCalls::call_virtual(&cause, + h_throwable, + KlassHandle(THREAD, h_throwable->klass()), + vmSymbols::getCause_name(), + vmSymbols::void_throwable_signature(), + THREAD); + // Ignore any exceptions. we are in the middle of exception handling. Same as classic VM. + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + h_throwable = Handle(); + } else { + h_throwable = Handle(THREAD, (oop) cause.get_jobject()); + if (h_throwable.not_null()) { + st->print("Caused by: "); + print(h_throwable, st); + st->cr(); + } + } + } } -}; - +} void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle method, TRAPS) { if (!StackTraceInThrowable) return; @@ -1578,21 +1592,8 @@ // No-op if stack trace is disabled if (!StackTraceInThrowable) return; - - objArrayOop h_oop = oopFactory::new_objectArray(trace_size, CHECK); - objArrayHandle backtrace (THREAD, h_oop); - typeArrayOop m_oop = oopFactory::new_metaDataArray(trace_chunk_size, CHECK); - typeArrayHandle methods (THREAD, m_oop); - typeArrayOop b = oopFactory::new_shortArray(trace_chunk_size, CHECK); - typeArrayHandle bcis(THREAD, b); - objArrayOop mirror_oop = oopFactory::new_objectArray(trace_chunk_size, CHECK); - objArrayHandle mirrors (THREAD, mirror_oop); - - // backtrace has space for one chunk (next is NULL) - backtrace->obj_at_put(trace_methods_offset, methods()); - backtrace->obj_at_put(trace_bcis_offset, bcis()); - backtrace->obj_at_put(trace_mirrors_offset, mirrors()); - set_backtrace(throwable(), backtrace()); + BacktraceBuilder bt(CHECK); // creates a backtrace + set_backtrace(throwable(), bt.backtrace()); } @@ -1604,48 +1605,26 @@ assert(throwable->is_a(SystemDictionary::Throwable_klass()), "sanity check"); - objArrayOop backtrace = (objArrayOop)java_lang_Throwable::backtrace(throwable()); - assert(backtrace != NULL, "backtrace not preallocated"); - - oop m = backtrace->obj_at(trace_methods_offset); - typeArrayOop methods = typeArrayOop(m); - assert(methods != NULL && methods->length() > 0, "method array not preallocated"); - - oop b = backtrace->obj_at(trace_bcis_offset); - typeArrayOop bcis = typeArrayOop(b); - assert(bcis != NULL, "bci array not preallocated"); - - oop mr = backtrace->obj_at(trace_mirrors_offset); - objArrayOop mirrors = objArrayOop(mr); - assert(mirrors != NULL, "bci array not preallocated"); - - assert(methods->length() == bcis->length() && - methods->length() == mirrors->length(), - "method and bci arrays should match"); - - JavaThread* thread = JavaThread::current(); - ResourceMark rm(thread); - vframeStream st(thread); + JavaThread* THREAD = JavaThread::current(); + + objArrayHandle backtrace (THREAD, (objArrayOop)java_lang_Throwable::backtrace(throwable())); + assert(backtrace.not_null(), "backtrace should have been preallocated"); + + ResourceMark rm(THREAD); + vframeStream st(THREAD); + + BacktraceBuilder bt(backtrace); // Unlike fill_in_stack_trace we do not skip fillInStackTrace or throwable init // methods as preallocated errors aren't created by "java" code. // fill in as much stack trace as possible + typeArrayOop methods = BacktraceBuilder::get_methods(backtrace); int max_chunks = MIN2(methods->length(), (int)MaxJavaStackTraceDepth); int chunk_count = 0; for (;!st.at_end(); st.next()) { - // Add entry and smear the -1 bci to 0 since the array only holds - // unsigned shorts. The later line number lookup would just smear - // the -1 to a 0 even if it could be recorded. - int bci = st.bci(); - if (bci == SynchronizationEntryBCI) bci = 0; - assert(bci == (jushort)bci, "doesn't fit"); - bcis->ushort_at_put(chunk_count, bci); - methods->metadata_at_put(chunk_count, st.method()); - mirrors->obj_at_put(chunk_count, - st.method()->method_holder()->java_mirror()); - + bt.push(st.method(), st.bci(), CHECK); chunk_count++; // Bail-out for deep stacks @@ -1659,7 +1638,6 @@ java_lang_Throwable::set_stacktrace(throwable(), java_lang_Throwable::unassigned_stacktrace()); assert(java_lang_Throwable::unassigned_stacktrace() != NULL, "not initialized"); } - } @@ -1678,12 +1656,12 @@ chunk = next; } assert(chunk != NULL && chunk->obj_at(trace_next_offset) == NULL, "sanity check"); - // Count element in remaining partial chunk - typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset)); - typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset)); - assert(methods != NULL && bcis != NULL, "sanity check"); - for (int i = 0; i < methods->length(); i++) { - if (methods->metadata_at(i) == NULL) break; + // Count element in remaining partial chunk. NULL value for mirror + // marks the end of the stack trace elements that are saved. + objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); + assert(mirrors != NULL, "sanity check"); + for (int i = 0; i < mirrors->length(); i++) { + if (mirrors->obj_at(i) == NULL) break; depth++; } } @@ -1709,25 +1687,28 @@ if (chunk == NULL) { THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); } - // Get method,bci from chunk - typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset)); - typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset)); - assert(methods != NULL && bcis != NULL, "sanity check"); - methodHandle method(THREAD, ((Method*)methods->metadata_at(chunk_index))); - int bci = bcis->ushort_at(chunk_index); + // Get method id, bci, version and mirror from chunk + typeArrayOop methods = BacktraceBuilder::get_methods(chunk); + typeArrayOop bcis = BacktraceBuilder::get_bcis(chunk); + objArrayOop mirrors = BacktraceBuilder::get_mirrors(chunk); + + assert(methods != NULL && bcis != NULL && mirrors != NULL, "sanity check"); + + int method = methods->short_at(chunk_index); + int version = version_at(bcis->int_at(chunk_index)); + int bci = bci_at(bcis->int_at(chunk_index)); + Handle mirror(THREAD, mirrors->obj_at(chunk_index)); + // Chunk can be partial full - if (method.is_null()) { + if (mirror.is_null()) { THROW_(vmSymbols::java_lang_IndexOutOfBoundsException(), NULL); } - oop element = java_lang_StackTraceElement::create(method, bci, CHECK_0); + oop element = java_lang_StackTraceElement::create(mirror, method, version, bci, CHECK_0); return element; } -oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { - // SystemDictionary::stackTraceElement_klass() will be null for pre-1.4 JDKs - assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4"); - +oop java_lang_StackTraceElement::create(Handle mirror, int method_id, int version, int bci, TRAPS) { // Allocate java.lang.StackTraceElement instance Klass* k = SystemDictionary::StackTraceElement_klass(); assert(k != NULL, "must be loaded in 1.4+"); @@ -1739,37 +1720,39 @@ Handle element = ik->allocate_instance_handle(CHECK_0); // Fill in class name ResourceMark rm(THREAD); - const char* str = method->method_holder()->external_name(); + InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror())); + const char* str = holder->external_name(); oop classname = StringTable::intern((char*) str, CHECK_0); java_lang_StackTraceElement::set_declaringClass(element(), classname); + // Fill in method name + Method* method = holder->method_with_idnum(method_id); oop methodname = StringTable::intern(method->name(), CHECK_0); java_lang_StackTraceElement::set_methodName(element(), methodname); - // Fill in source file name - Symbol* source = method->method_holder()->source_file_name(); - if (ShowHiddenFrames && source == NULL) - source = vmSymbols::unknown_class_name(); - oop filename = StringTable::intern(source, CHECK_0); - java_lang_StackTraceElement::set_fileName(element(), filename); - // File in source line number - int line_number; - if (method->is_native()) { - // Negative value different from -1 below, enabling Java code in - // class java.lang.StackTraceElement to distinguish "native" from - // "no LineNumberTable". - line_number = -2; + + if (!version_matches(method, version)) { + // The method was redefined, accurate line number information isn't available + java_lang_StackTraceElement::set_fileName(element(), NULL); + java_lang_StackTraceElement::set_lineNumber(element(), -1); } else { - // Returns -1 if no LineNumberTable, and otherwise actual line number - line_number = method->line_number_from_bci(bci); - if (line_number == -1 && ShowHiddenFrames) { - line_number = bci + 1000000; - } + // Fill in source file name and line number. + Symbol* source = holder->source_file_name(); + if (ShowHiddenFrames && source == NULL) + source = vmSymbols::unknown_class_name(); + oop filename = StringTable::intern(source, CHECK_0); + java_lang_StackTraceElement::set_fileName(element(), filename); + + int line_number = get_line_number(method, bci); + java_lang_StackTraceElement::set_lineNumber(element(), line_number); } - java_lang_StackTraceElement::set_lineNumber(element(), line_number); - return element(); } +oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) { + Handle mirror (THREAD, method->method_holder()->java_mirror()); + int method_id = method->method_idnum(); + return create(mirror, method_id, method->constants()->version(), bci, THREAD); +} void java_lang_reflect_AccessibleObject::compute_offsets() { Klass* k = SystemDictionary::reflect_AccessibleObject_klass(); diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/classfile/javaClasses.hpp --- a/src/share/vm/classfile/javaClasses.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/classfile/javaClasses.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -463,8 +463,7 @@ static int static_unassigned_stacktrace_offset; // Printing - static char* print_stack_element_to_buffer(Method* method, int bci); - static void print_to_stream(Handle stream, const char* str); + static char* print_stack_element_to_buffer(Handle mirror, int method, int version, int bci); // StackTrace (programmatic access, new since 1.4) static void clear_stacktrace(oop throwable); // No stack trace available @@ -484,12 +483,9 @@ static oop message(oop throwable); static oop message(Handle throwable); static void set_message(oop throwable, oop value); - // Print stack trace stored in exception by call-back to Java - // Note: this is no longer used in Merlin, but we still suppport - // it for compatibility. - static void print_stack_trace(oop throwable, oop print_stream); - static void print_stack_element(Handle stream, Method* method, int bci); - static void print_stack_element(outputStream *st, Method* method, int bci); + static void print_stack_element(outputStream *st, Handle mirror, int method, + int version, int bci); + static void print_stack_element(outputStream *st, methodHandle method, int bci); static void print_stack_usage(Handle stream); // Allocate space for backtrace (created but stack trace not filled in) @@ -1257,7 +1253,8 @@ static void set_lineNumber(oop element, int value); // Create an instance of StackTraceElement - static oop create(methodHandle m, int bci, TRAPS); + static oop create(Handle mirror, int method, int version, int bci, TRAPS); + static oop create(methodHandle method, int bci, TRAPS); // Debugging friend class JavaClasses; diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/classfile/vmSymbols.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -735,6 +735,11 @@ do_intrinsic(_checkIndex, java_nio_Buffer, checkIndex_name, int_int_signature, F_R) \ do_name( checkIndex_name, "checkIndex") \ \ + do_class(sun_nio_cs_iso8859_1_Encoder, "sun/nio/cs/ISO_8859_1$Encoder") \ + do_intrinsic(_encodeISOArray, sun_nio_cs_iso8859_1_Encoder, encodeISOArray_name, encodeISOArray_signature, F_S) \ + do_name( encodeISOArray_name, "encodeISOArray") \ + do_signature(encodeISOArray_signature, "([CI[BII)I") \ + \ /* java/lang/ref/Reference */ \ do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \ \ diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/compiler/oopMap.cpp --- a/src/share/vm/compiler/oopMap.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/compiler/oopMap.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -542,17 +542,17 @@ st->print("Oop"); break; case OopMapValue::value_value: - st->print("Value" ); + st->print("Value"); break; case OopMapValue::narrowoop_value: - tty->print("NarrowOop" ); + st->print("NarrowOop"); break; case OopMapValue::callee_saved_value: - st->print("Callers_" ); + st->print("Callers_"); optional->print_on(st); break; case OopMapValue::derived_oop_value: - st->print("Derived_oop_" ); + st->print("Derived_oop_"); optional->print_on(st); break; default: diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -555,7 +555,7 @@ reportIndexedFreeListStatistics(); size_t total_size = totalSizeInIndexedFreeLists() + _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock())); - gclog_or_tty->print(" free=%ld frag=%1.4f\n", total_size, flsFrag()); + gclog_or_tty->print(" free=" SIZE_FORMAT " frag=%1.4f\n", total_size, flsFrag()); } } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -3338,7 +3338,7 @@ if (Verbose && PrintGC) { size_t new_mem_size = _virtual_space.committed_size(); size_t old_mem_size = new_mem_size - bytes; - gclog_or_tty->print_cr("Expanding %s from %ldK by %ldK to %ldK", + gclog_or_tty->print_cr("Expanding %s from " SIZE_FORMAT "K by " SIZE_FORMAT "K to " SIZE_FORMAT "K", name(), old_mem_size/K, bytes/K, new_mem_size/K); } } @@ -9203,7 +9203,7 @@ if (Verbose && PrintGCDetails) { size_t new_mem_size = _virtual_space.committed_size(); size_t old_mem_size = new_mem_size + bytes; - gclog_or_tty->print_cr("Shrinking %s from %ldK by %ldK to %ldK", + gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K by " SIZE_FORMAT "K to " SIZE_FORMAT "K", name(), old_mem_size/K, bytes/K, new_mem_size/K); } } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -529,7 +529,7 @@ if (PrintTenuringDistribution) { gclog_or_tty->cr(); - gclog_or_tty->print_cr("Desired survivor size %ld bytes, new threshold %u (max %u)", + gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold %u (max %u)", size_policy->calculated_survivor_size_in_bytes(), _tenuring_threshold, MaxTenuringThreshold); } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/gc_implementation/shared/ageTable.cpp --- a/src/share/vm/gc_implementation/shared/ageTable.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/gc_implementation/shared/ageTable.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,7 +96,7 @@ if (PrintTenuringDistribution) { gclog_or_tty->cr(); - gclog_or_tty->print_cr("Desired survivor size %ld bytes, new threshold %u (max %u)", + gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold %u (max %u)", desired_survivor_size*oopSize, result, MaxTenuringThreshold); } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/memory/universe.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -228,7 +228,7 @@ if (size < alignment || size % alignment != 0) { ResourceMark rm; stringStream st; - st.print("Size of %s (%ld bytes) must be aligned to %ld bytes", name, size, alignment); + st.print("Size of %s (" UINTX_FORMAT " bytes) must be aligned to " UINTX_FORMAT " bytes", name, size, alignment); char* error = st.as_string(); vm_exit_during_initialization(error); } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/oops/constantPool.cpp --- a/src/share/vm/oops/constantPool.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/oops/constantPool.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,7 @@ set_pool_holder(NULL); set_flags(0); // only set to non-zero if constant pool is merged by RedefineClasses - set_orig_length(0); + set_version(0); set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock")); // all fields are initialized; needed for GC set_on_stack(false); diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/oops/constantPool.hpp --- a/src/share/vm/oops/constantPool.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/oops/constantPool.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,8 +103,8 @@ union { // set for CDS to restore resolved references int _resolved_reference_length; - // only set to non-zero if constant pool is merged by RedefineClasses - int _orig_length; + // keeps version number for redefined classes (used in backtrace) + int _version; } _saved; Monitor* _lock; @@ -784,8 +784,11 @@ static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS); static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS); int find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS); - int orig_length() const { return _saved._orig_length; } - void set_orig_length(int orig_length) { _saved._orig_length = orig_length; } + int version() const { return _saved._version; } + void set_version(int version) { _saved._version = version; } + void increment_and_save_version(int version) { + _saved._version = version >= 0 ? (version + 1) : version; // keep overflow + } void set_resolved_reference_length(int length) { _saved._resolved_reference_length = length; } int resolved_reference_length() const { return _saved._resolved_reference_length; } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/c2_globals.hpp --- a/src/share/vm/opto/c2_globals.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/c2_globals.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -516,6 +516,9 @@ develop(bool, SpecialArraysEquals, true, \ "special version of Arrays.equals(char[],char[])") \ \ + product(bool, SpecialEncodeISOArray, true, \ + "special version of ISO_8859_1$Encoder.encodeISOArray") \ + \ develop(bool, BailoutToInterpreterForThrows, false, \ "Compiled methods which throws/catches exceptions will be " \ "deopt and intp.") \ diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/callnode.cpp --- a/src/share/vm/opto/callnode.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/callnode.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -165,13 +165,13 @@ #ifndef PRODUCT -void ReturnNode::dump_req() const { +void ReturnNode::dump_req(outputStream *st) const { // Dump the required inputs, enclosed in '(' and ')' uint i; // Exit value of loop - for( i=0; iprint("returns"); - if( in(i) ) tty->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); - else tty->print("_ "); + for (i = 0; i < req(); i++) { // For all required inputs + if (i == TypeFunc::Parms) st->print("returns"); + if (in(i)) st->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); + else st->print("_ "); } } #endif @@ -208,13 +208,13 @@ } #ifndef PRODUCT -void RethrowNode::dump_req() const { +void RethrowNode::dump_req(outputStream *st) const { // Dump the required inputs, enclosed in '(' and ')' uint i; // Exit value of loop - for( i=0; iprint("exception"); - if( in(i) ) tty->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); - else tty->print("_ "); + for (i = 0; i < req(); i++) { // For all required inputs + if (i == TypeFunc::Parms) st->print("exception"); + if (in(i)) st->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); + else st->print("_ "); } } #endif @@ -330,7 +330,8 @@ st->print(" %s%d]=#ScObj" INT32_FORMAT, msg, i, sco_n); return; } - if( OptoReg::is_valid(regalloc->get_reg_first(n))) { // Check for undefined + if (regalloc->node_regs_max_index() > 0 && + OptoReg::is_valid(regalloc->get_reg_first(n))) { // Check for undefined char buf[50]; regalloc->dump_register(n,buf); st->print(" %s%d]=%s",msg,i,buf); @@ -381,7 +382,7 @@ //------------------------------format----------------------------------------- void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) const { st->print(" #"); - if( _method ) { + if (_method) { _method->print_short_name(st); st->print(" @ bci:%d ",_bci); } else { @@ -393,21 +394,22 @@ MachSafePointNode *mcall = n->as_MachSafePoint(); uint i; // Print locals - for( i = 0; i < (uint)loc_size(); i++ ) - format_helper( regalloc, st, mcall->local(this, i), "L[", i, &scobjs ); + for (i = 0; i < (uint)loc_size(); i++) + format_helper(regalloc, st, mcall->local(this, i), "L[", i, &scobjs); // Print stack for (i = 0; i < (uint)stk_size(); i++) { if ((uint)(_stkoff + i) >= mcall->len()) st->print(" oob "); else - format_helper( regalloc, st, mcall->stack(this, i), "STK[", i, &scobjs ); + format_helper(regalloc, st, mcall->stack(this, i), "STK[", i, &scobjs); } for (i = 0; (int)i < nof_monitors(); i++) { Node *box = mcall->monitor_box(this, i); Node *obj = mcall->monitor_obj(this, i); - if ( OptoReg::is_valid(regalloc->get_reg_first(box)) ) { + if (regalloc->node_regs_max_index() > 0 && + OptoReg::is_valid(regalloc->get_reg_first(box))) { box = BoxLockNode::box_node(box); - format_helper( regalloc, st, box, "MON-BOX[", i, &scobjs ); + format_helper(regalloc, st, box, "MON-BOX[", i, &scobjs); } else { OptoReg::Name box_reg = BoxLockNode::reg(box); st->print(" MON-BOX%d=%s+%d", @@ -420,7 +422,7 @@ if (BoxLockNode::box_node(box)->is_eliminated()) obj_msg = "MON-OBJ(LOCK ELIMINATED)["; } - format_helper( regalloc, st, obj, obj_msg, i, &scobjs ); + format_helper(regalloc, st, obj, obj_msg, i, &scobjs); } for (i = 0; i < (uint)scobjs.length(); i++) { @@ -463,9 +465,9 @@ st->print(" ["); cifield = iklass->nonstatic_field_at(0); cifield->print_name_on(st); - format_helper( regalloc, st, fld_node, ":", 0, &scobjs ); + format_helper(regalloc, st, fld_node, ":", 0, &scobjs); } else { - format_helper( regalloc, st, fld_node, "[", 0, &scobjs ); + format_helper(regalloc, st, fld_node, "[", 0, &scobjs); } for (uint j = 1; j < nf; j++) { fld_node = mcall->in(first_ind+j); @@ -473,9 +475,9 @@ st->print(", ["); cifield = iklass->nonstatic_field_at(j); cifield->print_name_on(st); - format_helper( regalloc, st, fld_node, ":", j, &scobjs ); + format_helper(regalloc, st, fld_node, ":", j, &scobjs); } else { - format_helper( regalloc, st, fld_node, ", [", j, &scobjs ); + format_helper(regalloc, st, fld_node, ", [", j, &scobjs); } } } @@ -483,7 +485,7 @@ } } st->print_cr(""); - if (caller() != NULL) caller()->format(regalloc, n, st); + if (caller() != NULL) caller()->format(regalloc, n, st); } @@ -586,15 +588,15 @@ uint CallNode::cmp( const Node &n ) const { return _tf == ((CallNode&)n)._tf && _jvms == ((CallNode&)n)._jvms; } #ifndef PRODUCT -void CallNode::dump_req() const { +void CallNode::dump_req(outputStream *st) const { // Dump the required inputs, enclosed in '(' and ')' uint i; // Exit value of loop - for( i=0; iprint("("); - if( in(i) ) tty->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); - else tty->print("_ "); + for (i = 0; i < req(); i++) { // For all required inputs + if (i == TypeFunc::Parms) st->print("("); + if (in(i)) st->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); + else st->print("_ "); } - tty->print(")"); + st->print(")"); } void CallNode::dump_spec(outputStream *st) const { diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/callnode.hpp --- a/src/share/vm/opto/callnode.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/callnode.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -126,7 +126,7 @@ virtual uint ideal_reg() const { return NotAMachineReg; } virtual uint match_edge(uint idx) const; #ifndef PRODUCT - virtual void dump_req() const; + virtual void dump_req(outputStream *st = tty) const; #endif }; @@ -147,7 +147,7 @@ virtual uint match_edge(uint idx) const; virtual uint ideal_reg() const { return NotAMachineReg; } #ifndef PRODUCT - virtual void dump_req() const; + virtual void dump_req(outputStream *st = tty) const; #endif }; @@ -579,7 +579,7 @@ virtual uint match_edge(uint idx) const; #ifndef PRODUCT - virtual void dump_req() const; + virtual void dump_req(outputStream *st = tty) const; virtual void dump_spec(outputStream *st) const; #endif }; diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/classes.hpp --- a/src/share/vm/opto/classes.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/classes.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -127,6 +127,7 @@ macro(DivMod) macro(DivModI) macro(DivModL) +macro(EncodeISOArray) macro(EncodeP) macro(EncodePKlass) macro(ExpD) diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/escape.cpp --- a/src/share/vm/opto/escape.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/escape.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -523,7 +523,8 @@ case Op_AryEq: case Op_StrComp: case Op_StrEquals: - case Op_StrIndexOf: { + case Op_StrIndexOf: + case Op_EncodeISOArray: { add_local_var(n, PointsToNode::ArgEscape); delayed_worklist->push(n); // Process it later. break; @@ -701,7 +702,8 @@ case Op_AryEq: case Op_StrComp: case Op_StrEquals: - case Op_StrIndexOf: { + case Op_StrIndexOf: + case Op_EncodeISOArray: { // char[] arrays passed to string intrinsic do not escape but // they are not scalar replaceable. Adjust escape state for them. // Start from in(2) edge since in(1) is memory edge. @@ -2581,15 +2583,22 @@ } // Otherwise skip it (the call updated 'result' value). } else if (result->Opcode() == Op_SCMemProj) { - assert(result->in(0)->is_LoadStore(), "sanity"); - const Type *at = igvn->type(result->in(0)->in(MemNode::Address)); + Node* mem = result->in(0); + Node* adr = NULL; + if (mem->is_LoadStore()) { + adr = mem->in(MemNode::Address); + } else { + assert(mem->Opcode() == Op_EncodeISOArray, "sanity"); + adr = mem->in(3); // Memory edge corresponds to destination array + } + const Type *at = igvn->type(adr); if (at != Type::TOP) { assert (at->isa_ptr() != NULL, "pointer type required."); int idx = C->get_alias_index(at->is_ptr()); assert(idx != alias_idx, "Object is not scalar replaceable if a LoadStore node access its field"); break; } - result = result->in(0)->in(MemNode::Memory); + result = mem->in(MemNode::Memory); } } if (result->is_Phi()) { @@ -2927,6 +2936,11 @@ if (m->is_MergeMem()) { assert(_mergemem_worklist.contains(m->as_MergeMem()), "EA: missing MergeMem node in the worklist"); } + } else if (use->Opcode() == Op_EncodeISOArray) { + if (use->in(MemNode::Memory) == n || use->in(3) == n) { + // EncodeISOArray overwrites destination array + memnode_worklist.append_if_missing(use); + } } else { uint op = use->Opcode(); if (!(op == Op_CmpP || op == Op_Conv2B || @@ -2962,6 +2976,16 @@ n = n->as_MemBar()->proj_out(TypeFunc::Memory); if (n == NULL) continue; + } else if (n->Opcode() == Op_EncodeISOArray) { + // get the memory projection + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + Node *use = n->fast_out(i); + if (use->Opcode() == Op_SCMemProj) { + n = use; + break; + } + } + assert(n->Opcode() == Op_SCMemProj, "memory projection required"); } else { assert(n->is_Mem(), "memory node required."); Node *addr = n->in(MemNode::Address); @@ -2999,7 +3023,7 @@ Node *use = n->fast_out(i); if (use->is_Phi() || use->is_ClearArray()) { memnode_worklist.append_if_missing(use); - } else if(use->is_Mem() && use->in(MemNode::Memory) == n) { + } else if (use->is_Mem() && use->in(MemNode::Memory) == n) { if (use->Opcode() == Op_StoreCM) // Ignore cardmark stores continue; memnode_worklist.append_if_missing(use); @@ -3010,6 +3034,11 @@ assert(use->in(MemNode::Memory) != n, "EA: missing memory path"); } else if (use->is_MergeMem()) { assert(_mergemem_worklist.contains(use->as_MergeMem()), "EA: missing MergeMem node in the worklist"); + } else if (use->Opcode() == Op_EncodeISOArray) { + if (use->in(MemNode::Memory) == n || use->in(3) == n) { + // EncodeISOArray overwrites destination array + memnode_worklist.append_if_missing(use); + } } else { uint op = use->Opcode(); if (!(op == Op_StoreCM || diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/idealGraphPrinter.cpp --- a/src/share/vm/opto/idealGraphPrinter.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/idealGraphPrinter.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -547,7 +547,7 @@ // max. 2 chars allowed if (value >= -9 && value <= 99) { - sprintf(buffer, INT64_FORMAT, value); + sprintf(buffer, JLONG_FORMAT, value); print_prop(short_name, buffer); } else { print_prop(short_name, "L"); diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/lcm.cpp --- a/src/share/vm/opto/lcm.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/lcm.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -175,6 +175,7 @@ case Op_StrEquals: case Op_StrIndexOf: case Op_AryEq: + case Op_EncodeISOArray: // Not a legit memory op for implicit null check regardless of // embedded loads continue; diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/library_call.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -290,6 +290,7 @@ bool inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id); Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting); Node* get_key_start_from_aescrypt_object(Node* aescrypt_object); + bool inline_encodeISOArray(); }; @@ -381,6 +382,10 @@ // These also use the arraycopy intrinsic mechanism: if (!InlineArrayCopy) return NULL; break; + case vmIntrinsics::_encodeISOArray: + if (!SpecialEncodeISOArray) return NULL; + if (!Matcher::match_rule_supported(Op_EncodeISOArray)) return NULL; + break; case vmIntrinsics::_checkIndex: // We do not intrinsify this. The optimizer does fine with it. return NULL; @@ -799,6 +804,9 @@ case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: return inline_cipherBlockChaining_AESCrypt(intrinsic_id()); + case vmIntrinsics::_encodeISOArray: + return inline_encodeISOArray(); + default: // If you get here, it may be that someone has added a new intrinsic // to the list in vmSymbols.hpp without implementing it here. @@ -5368,6 +5376,47 @@ src_start, dest_start, copy_length XTOP); } +//-------------inline_encodeISOArray----------------------------------- +// encode char[] to byte[] in ISO_8859_1 +bool LibraryCallKit::inline_encodeISOArray() { + assert(callee()->signature()->size() == 5, "encodeISOArray has 5 parameters"); + // no receiver since it is static method + Node *src = argument(0); + Node *src_offset = argument(1); + Node *dst = argument(2); + Node *dst_offset = argument(3); + Node *length = argument(4); + + const Type* src_type = src->Value(&_gvn); + const Type* dst_type = dst->Value(&_gvn); + const TypeAryPtr* top_src = src_type->isa_aryptr(); + const TypeAryPtr* top_dest = dst_type->isa_aryptr(); + if (top_src == NULL || top_src->klass() == NULL || + top_dest == NULL || top_dest->klass() == NULL) { + // failed array check + return false; + } + + // Figure out the size and type of the elements we will be copying. + BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + if (src_elem != T_CHAR || dst_elem != T_BYTE) { + return false; + } + Node* src_start = array_element_address(src, src_offset, src_elem); + Node* dst_start = array_element_address(dst, dst_offset, dst_elem); + // 'src_start' points to src array + scaled offset + // 'dst_start' points to dst array + scaled offset + + const TypeAryPtr* mtype = TypeAryPtr::BYTES; + Node* enc = new (C) EncodeISOArrayNode(control(), memory(mtype), src_start, dst_start, length); + enc = _gvn.transform(enc); + Node* res_mem = _gvn.transform(new (C) SCMemProjNode(enc)); + set_memory(res_mem, mtype); + set_result(enc); + return true; +} + //----------------------------inline_reference_get---------------------------- // public T java.lang.ref.Reference.get(); bool LibraryCallKit::inline_reference_get() { diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/loopTransform.cpp --- a/src/share/vm/opto/loopTransform.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/loopTransform.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -613,6 +613,7 @@ case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: + case Op_EncodeISOArray: case Op_AryEq: { return false; } @@ -717,6 +718,7 @@ case Op_StrComp: case Op_StrEquals: case Op_StrIndexOf: + case Op_EncodeISOArray: case Op_AryEq: { // Do not unroll a loop with String intrinsics code. // String intrinsics are large and have loops. diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/machnode.cpp --- a/src/share/vm/opto/machnode.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/machnode.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -506,7 +506,7 @@ #ifndef PRODUCT void MachNullCheckNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { int reg = ra_->get_reg_first(in(1)->in(_vidx)); - tty->print("%s %s", Name(), Matcher::regName[reg]); + st->print("%s %s", Name(), Matcher::regName[reg]); } #endif diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/macro.cpp --- a/src/share/vm/opto/macro.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/macro.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -361,14 +361,21 @@ } // Otherwise skip it (the call updated 'mem' value). } else if (mem->Opcode() == Op_SCMemProj) { - assert(mem->in(0)->is_LoadStore(), "sanity"); - const TypePtr* atype = mem->in(0)->in(MemNode::Address)->bottom_type()->is_ptr(); + mem = mem->in(0); + Node* adr = NULL; + if (mem->is_LoadStore()) { + adr = mem->in(MemNode::Address); + } else { + assert(mem->Opcode() == Op_EncodeISOArray, "sanity"); + adr = mem->in(3); // Destination array + } + const TypePtr* atype = adr->bottom_type()->is_ptr(); int adr_idx = Compile::current()->get_alias_index(atype); if (adr_idx == alias_idx) { assert(false, "Object is not scalar replaceable if a LoadStore node access its field"); return NULL; } - mem = mem->in(0)->in(MemNode::Memory); + mem = mem->in(MemNode::Memory); } else { return mem; } @@ -445,7 +452,7 @@ } values.at_put(j, val); } else if (val->Opcode() == Op_SCMemProj) { - assert(val->in(0)->is_LoadStore(), "sanity"); + assert(val->in(0)->is_LoadStore() || val->in(0)->Opcode() == Op_EncodeISOArray, "sanity"); assert(false, "Object is not scalar replaceable if a LoadStore node access its field"); return NULL; } else { diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/matcher.cpp --- a/src/share/vm/opto/matcher.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/matcher.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -919,6 +919,7 @@ case Op_AryEq: case Op_MemBarVolatile: case Op_MemBarCPUOrder: // %%% these ideals should have narrower adr_type? + case Op_EncodeISOArray: nidx = Compile::AliasIdxTop; nat = NULL; break; @@ -1982,6 +1983,7 @@ case Op_StrEquals: case Op_StrIndexOf: case Op_AryEq: + case Op_EncodeISOArray: set_shared(n); // Force result into register (it will be anyways) break; case Op_ConP: { // Convert pointers above the centerline to NUL @@ -2183,6 +2185,13 @@ n->del_req(4); break; } + case Op_EncodeISOArray: { + // Restructure into a binary tree for Matching. + Node* pair = new (C) BinaryNode(n->in(3), n->in(4)); + n->set_req(3, pair); + n->del_req(4); + break; + } default: break; } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/memnode.cpp --- a/src/share/vm/opto/memnode.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/memnode.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -2797,6 +2797,26 @@ } //============================================================================= +//------------------------------match_edge------------------------------------- +// Do not match memory edge +uint EncodeISOArrayNode::match_edge(uint idx) const { + return idx == 2 || idx == 3; // EncodeISOArray src (Binary dst len) +} + +//------------------------------Ideal------------------------------------------ +// Return a node which is more "ideal" than the current node. Strip out +// control copies +Node *EncodeISOArrayNode::Ideal(PhaseGVN *phase, bool can_reshape) { + return remove_dead_region(phase, can_reshape) ? this : NULL; +} + +//------------------------------Value------------------------------------------ +const Type *EncodeISOArrayNode::Value(PhaseTransform *phase) const { + if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP; + return bottom_type(); +} + +//============================================================================= MemBarNode::MemBarNode(Compile* C, int alias_idx, Node* precedent) : MultiNode(TypeFunc::Parms + (precedent == NULL? 0: 1)), _adr_type(C->get_adr_type(alias_idx)) diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/memnode.hpp --- a/src/share/vm/opto/memnode.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/memnode.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -888,6 +888,22 @@ virtual const Type* bottom_type() const { return TypeInt::BOOL; } }; + +//------------------------------EncodeISOArray-------------------------------- +// encode char[] to byte[] in ISO_8859_1 +class EncodeISOArrayNode: public Node { +public: + EncodeISOArrayNode(Node *control, Node* arymem, Node* s1, Node* s2, Node* c): Node(control, arymem, s1, s2, c) {}; + virtual int Opcode() const; + virtual bool depends_only_on_test() const { return false; } + virtual const Type* bottom_type() const { return TypeInt::INT; } + virtual const TypePtr* adr_type() const { return TypePtr::BOTTOM; } + virtual uint match_edge(uint idx) const; + virtual uint ideal_reg() const { return Op_RegI; } + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual const Type *Value(PhaseTransform *phase) const; +}; + //------------------------------MemBar----------------------------------------- // There are different flavors of Memory Barriers to match the Java Memory // Model. Monitor-enter and volatile-load act as Aquires: no following ref diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/node.cpp --- a/src/share/vm/opto/node.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/node.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1476,35 +1476,35 @@ } #ifdef ASSERT -static void dump_orig(Node* orig) { +static void dump_orig(Node* orig, outputStream *st) { Compile* C = Compile::current(); - if (NotANode(orig)) orig = NULL; - if (orig != NULL && !C->node_arena()->contains(orig)) orig = NULL; - if (orig == NULL) return; - tty->print(" !orig="); + if (NotANode(orig)) orig = NULL; + if (orig != NULL && !C->node_arena()->contains(orig)) orig = NULL; + if (orig == NULL) return; + st->print(" !orig="); Node* fast = orig->debug_orig(); // tortoise & hare algorithm to detect loops - if (NotANode(fast)) fast = NULL; + if (NotANode(fast)) fast = NULL; while (orig != NULL) { bool discon = is_disconnected(orig); // if discon, print [123] else 123 - if (discon) tty->print("["); + if (discon) st->print("["); if (!Compile::current()->node_arena()->contains(orig)) - tty->print("o"); - tty->print("%d", orig->_idx); - if (discon) tty->print("]"); + st->print("o"); + st->print("%d", orig->_idx); + if (discon) st->print("]"); orig = orig->debug_orig(); - if (NotANode(orig)) orig = NULL; - if (orig != NULL && !C->node_arena()->contains(orig)) orig = NULL; - if (orig != NULL) tty->print(","); + if (NotANode(orig)) orig = NULL; + if (orig != NULL && !C->node_arena()->contains(orig)) orig = NULL; + if (orig != NULL) st->print(","); if (fast != NULL) { // Step fast twice for each single step of orig: fast = fast->debug_orig(); - if (NotANode(fast)) fast = NULL; + if (NotANode(fast)) fast = NULL; if (fast != NULL && fast != orig) { fast = fast->debug_orig(); - if (NotANode(fast)) fast = NULL; + if (NotANode(fast)) fast = NULL; } if (fast == orig) { - tty->print("..."); + st->print("..."); break; } } @@ -1531,35 +1531,34 @@ //------------------------------dump------------------------------------------ // Dump a Node -void Node::dump() const { +void Node::dump(const char* suffix, outputStream *st) const { Compile* C = Compile::current(); bool is_new = C->node_arena()->contains(this); _in_dump_cnt++; - tty->print("%c%d\t%s\t=== ", - is_new ? ' ' : 'o', _idx, Name()); + st->print("%c%d\t%s\t=== ", is_new ? ' ' : 'o', _idx, Name()); // Dump the required and precedence inputs - dump_req(); - dump_prec(); + dump_req(st); + dump_prec(st); // Dump the outputs - dump_out(); + dump_out(st); if (is_disconnected(this)) { #ifdef ASSERT - tty->print(" [%d]",debug_idx()); - dump_orig(debug_orig()); + st->print(" [%d]",debug_idx()); + dump_orig(debug_orig(), st); #endif - tty->cr(); + st->cr(); _in_dump_cnt--; return; // don't process dead nodes } // Dump node-specific info - dump_spec(tty); + dump_spec(st); #ifdef ASSERT // Dump the non-reset _debug_idx - if( Verbose && WizardMode ) { - tty->print(" [%d]",debug_idx()); + if (Verbose && WizardMode) { + st->print(" [%d]",debug_idx()); } #endif @@ -1569,88 +1568,88 @@ const TypeInstPtr *toop = t->isa_instptr(); const TypeKlassPtr *tkls = t->isa_klassptr(); ciKlass* klass = toop ? toop->klass() : (tkls ? tkls->klass() : NULL ); - if( klass && klass->is_loaded() && klass->is_interface() ) { - tty->print(" Interface:"); - } else if( toop ) { - tty->print(" Oop:"); - } else if( tkls ) { - tty->print(" Klass:"); + if (klass && klass->is_loaded() && klass->is_interface()) { + st->print(" Interface:"); + } else if (toop) { + st->print(" Oop:"); + } else if (tkls) { + st->print(" Klass:"); } - t->dump(); - } else if( t == Type::MEMORY ) { - tty->print(" Memory:"); - MemNode::dump_adr_type(this, adr_type(), tty); - } else if( Verbose || WizardMode ) { - tty->print(" Type:"); - if( t ) { - t->dump(); + t->dump_on(st); + } else if (t == Type::MEMORY) { + st->print(" Memory:"); + MemNode::dump_adr_type(this, adr_type(), st); + } else if (Verbose || WizardMode) { + st->print(" Type:"); + if (t) { + t->dump_on(st); } else { - tty->print("no type"); + st->print("no type"); } } else if (t->isa_vect() && this->is_MachSpillCopy()) { // Dump MachSpillcopy vector type. - t->dump(); + t->dump_on(st); } if (is_new) { - debug_only(dump_orig(debug_orig())); + debug_only(dump_orig(debug_orig(), st)); Node_Notes* nn = C->node_notes_at(_idx); if (nn != NULL && !nn->is_clear()) { if (nn->jvms() != NULL) { - tty->print(" !jvms:"); - nn->jvms()->dump_spec(tty); + st->print(" !jvms:"); + nn->jvms()->dump_spec(st); } } } - tty->cr(); + if (suffix) st->print(suffix); _in_dump_cnt--; } //------------------------------dump_req-------------------------------------- -void Node::dump_req() const { +void Node::dump_req(outputStream *st) const { // Dump the required input edges for (uint i = 0; i < req(); i++) { // For all required inputs Node* d = in(i); if (d == NULL) { - tty->print("_ "); + st->print("_ "); } else if (NotANode(d)) { - tty->print("NotANode "); // uninitialized, sentinel, garbage, etc. + st->print("NotANode "); // uninitialized, sentinel, garbage, etc. } else { - tty->print("%c%d ", Compile::current()->node_arena()->contains(d) ? ' ' : 'o', d->_idx); + st->print("%c%d ", Compile::current()->node_arena()->contains(d) ? ' ' : 'o', d->_idx); } } } //------------------------------dump_prec------------------------------------- -void Node::dump_prec() const { +void Node::dump_prec(outputStream *st) const { // Dump the precedence edges int any_prec = 0; for (uint i = req(); i < len(); i++) { // For all precedence inputs Node* p = in(i); if (p != NULL) { - if( !any_prec++ ) tty->print(" |"); - if (NotANode(p)) { tty->print("NotANode "); continue; } - tty->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); + if (!any_prec++) st->print(" |"); + if (NotANode(p)) { st->print("NotANode "); continue; } + st->print("%c%d ", Compile::current()->node_arena()->contains(in(i)) ? ' ' : 'o', in(i)->_idx); } } } //------------------------------dump_out-------------------------------------- -void Node::dump_out() const { +void Node::dump_out(outputStream *st) const { // Delimit the output edges - tty->print(" [["); + st->print(" [["); // Dump the output edges for (uint i = 0; i < _outcnt; i++) { // For all outputs Node* u = _out[i]; if (u == NULL) { - tty->print("_ "); + st->print("_ "); } else if (NotANode(u)) { - tty->print("NotANode "); + st->print("NotANode "); } else { - tty->print("%c%d ", Compile::current()->node_arena()->contains(u) ? ' ' : 'o', u->_idx); + st->print("%c%d ", Compile::current()->node_arena()->contains(u) ? ' ' : 'o', u->_idx); } } - tty->print("]] "); + st->print("]] "); } //------------------------------dump_nodes------------------------------------- diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/node.hpp --- a/src/share/vm/opto/node.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/node.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -994,12 +994,13 @@ #ifndef PRODUCT Node* find(int idx) const; // Search the graph for the given idx. Node* find_ctrl(int idx) const; // Search control ancestors for the given idx. - void dump() const; // Print this node, + void dump() const { dump("\n"); } // Print this node. + void dump(const char* suffix, outputStream *st = tty) const;// Print this node. void dump(int depth) const; // Print this node, recursively to depth d void dump_ctrl(int depth) const; // Print control nodes, to depth d - virtual void dump_req() const; // Print required-edge info - virtual void dump_prec() const; // Print precedence-edge info - virtual void dump_out() const; // Print the output edge info + virtual void dump_req(outputStream *st = tty) const; // Print required-edge info + virtual void dump_prec(outputStream *st = tty) const; // Print precedence-edge info + virtual void dump_out(outputStream *st = tty) const; // Print the output edge info virtual void dump_spec(outputStream *st) const {}; // Print per-node info void verify_edges(Unique_Node_List &visited); // Verify bi-directional edges void verify() const; // Check Def-Use info for my subgraph diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/optoreg.hpp --- a/src/share/vm/opto/optoreg.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/optoreg.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -77,7 +77,7 @@ // (We would like to have an operator+ for RegName, but it is not // a class, so this would be illegal in C++.) - static void dump( int ); + static void dump(int, outputStream *st = tty); // Get the stack slot number of an OptoReg::Name static unsigned int reg2stack( OptoReg::Name r) { diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/regalloc.cpp --- a/src/share/vm/opto/regalloc.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/regalloc.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -40,6 +40,7 @@ Phase(Register_Allocation), _cfg(cfg), _matcher(matcher), _node_oops(Thread::current()->resource_area()), _node_regs(0), + _node_regs_max_index(0), _framesize(0xdeadbeef) { int i; diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/regmask.cpp --- a/src/share/vm/opto/regmask.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/regmask.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -108,13 +108,13 @@ //------------------------------dump------------------------------------------- #ifndef PRODUCT -void OptoReg::dump( int r ) { - switch( r ) { - case Special: tty->print("r---"); break; - case Bad: tty->print("rBAD"); break; +void OptoReg::dump(int r, outputStream *st) { + switch (r) { + case Special: st->print("r---"); break; + case Bad: st->print("rBAD"); break; default: - if( r < _last_Mach_Reg ) tty->print(Matcher::regName[r]); - else tty->print("rS%d",r); + if (r < _last_Mach_Reg) st->print(Matcher::regName[r]); + else st->print("rS%d",r); break; } } @@ -404,53 +404,53 @@ #ifndef PRODUCT //------------------------------print------------------------------------------ -void RegMask::dump( ) const { - tty->print("["); +void RegMask::dump(outputStream *st) const { + st->print("["); RegMask rm = *this; // Structure copy into local temp OptoReg::Name start = rm.find_first_elem(); // Get a register - if( OptoReg::is_valid(start) ) { // Check for empty mask + if (OptoReg::is_valid(start)) { // Check for empty mask rm.Remove(start); // Yank from mask - OptoReg::dump(start); // Print register + OptoReg::dump(start, st); // Print register OptoReg::Name last = start; // Now I have printed an initial register. // Print adjacent registers as "rX-rZ" instead of "rX,rY,rZ". // Begin looping over the remaining registers. - while( 1 ) { // + while (1) { // OptoReg::Name reg = rm.find_first_elem(); // Get a register - if( !OptoReg::is_valid(reg) ) + if (!OptoReg::is_valid(reg)) break; // Empty mask, end loop rm.Remove(reg); // Yank from mask - if( last+1 == reg ) { // See if they are adjacent + if (last+1 == reg) { // See if they are adjacent // Adjacent registers just collect into long runs, no printing. last = reg; } else { // Ending some kind of run - if( start == last ) { // 1-register run; no special printing - } else if( start+1 == last ) { - tty->print(","); // 2-register run; print as "rX,rY" - OptoReg::dump(last); + if (start == last) { // 1-register run; no special printing + } else if (start+1 == last) { + st->print(","); // 2-register run; print as "rX,rY" + OptoReg::dump(last, st); } else { // Multi-register run; print as "rX-rZ" - tty->print("-"); - OptoReg::dump(last); + st->print("-"); + OptoReg::dump(last, st); } - tty->print(","); // Seperate start of new run + st->print(","); // Seperate start of new run start = last = reg; // Start a new register run - OptoReg::dump(start); // Print register + OptoReg::dump(start, st); // Print register } // End of if ending a register run or not } // End of while regmask not empty - if( start == last ) { // 1-register run; no special printing - } else if( start+1 == last ) { - tty->print(","); // 2-register run; print as "rX,rY" - OptoReg::dump(last); + if (start == last) { // 1-register run; no special printing + } else if (start+1 == last) { + st->print(","); // 2-register run; print as "rX,rY" + OptoReg::dump(last, st); } else { // Multi-register run; print as "rX-rZ" - tty->print("-"); - OptoReg::dump(last); + st->print("-"); + OptoReg::dump(last, st); } - if( rm.is_AllStack() ) tty->print("..."); + if (rm.is_AllStack()) st->print("..."); } - tty->print("]"); + st->print("]"); } #endif diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/regmask.hpp --- a/src/share/vm/opto/regmask.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/regmask.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -310,7 +310,7 @@ #ifndef PRODUCT void print() const { dump(); } - void dump() const; // Print a mask + void dump(outputStream *st = tty) const; // Print a mask #endif static const RegMask Empty; // Common empty mask diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/opto/type.cpp --- a/src/share/vm/opto/type.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/opto/type.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1542,10 +1542,10 @@ static const char* longnamenear(jlong x, const char* xname, char* buf, jlong n) { if (n > x) { if (n >= x + 10000) return NULL; - sprintf(buf, "%s+" INT64_FORMAT, xname, n - x); + sprintf(buf, "%s+" JLONG_FORMAT, xname, n - x); } else if (n < x) { if (n <= x - 10000) return NULL; - sprintf(buf, "%s-" INT64_FORMAT, xname, x - n); + sprintf(buf, "%s-" JLONG_FORMAT, xname, x - n); } else { return xname; } @@ -1557,11 +1557,11 @@ if (n == min_jlong) return "min"; else if (n < min_jlong + 10000) - sprintf(buf, "min+" INT64_FORMAT, n - min_jlong); + sprintf(buf, "min+" JLONG_FORMAT, n - min_jlong); else if (n == max_jlong) return "max"; else if (n > max_jlong - 10000) - sprintf(buf, "max-" INT64_FORMAT, max_jlong - n); + sprintf(buf, "max-" JLONG_FORMAT, max_jlong - n); else if ((str = longnamenear(max_juint, "maxuint", buf, n)) != NULL) return str; else if ((str = longnamenear(max_jint, "maxint", buf, n)) != NULL) @@ -1569,7 +1569,7 @@ else if ((str = longnamenear(min_jint, "minint", buf, n)) != NULL) return str; else - sprintf(buf, INT64_FORMAT, n); + sprintf(buf, JLONG_FORMAT, n); return buf; } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/prims/jvm.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -484,15 +484,6 @@ JVM_END -JVM_ENTRY(void, JVM_PrintStackTrace(JNIEnv *env, jobject receiver, jobject printable)) - JVMWrapper("JVM_PrintStackTrace"); - // Note: This is no longer used in Merlin, but we still support it for compatibility. - oop exception = JNIHandles::resolve_non_null(receiver); - oop stream = JNIHandles::resolve_non_null(printable); - java_lang_Throwable::print_stack_trace(exception, stream); -JVM_END - - JVM_ENTRY(jint, JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable)) JVMWrapper("JVM_GetStackTraceDepth"); oop exception = JNIHandles::resolve(throwable); diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/prims/jvm.h --- a/src/share/vm/prims/jvm.h Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/prims/jvm.h Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -212,9 +212,6 @@ JNIEXPORT void JNICALL JVM_FillInStackTrace(JNIEnv *env, jobject throwable); -JNIEXPORT void JNICALL -JVM_PrintStackTrace(JNIEnv *env, jobject throwable, jobject printable); - JNIEXPORT jint JNICALL JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable); diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1334,20 +1334,8 @@ return JVMTI_ERROR_INTERNAL; } - int orig_length = old_cp->orig_length(); - if (orig_length == 0) { - // This old_cp is an actual original constant pool. We save - // the original length in the merged constant pool so that - // merge_constant_pools() can be more efficient. If a constant - // pool has a non-zero orig_length() value, then that constant - // pool was created by a merge operation in RedefineClasses. - merge_cp->set_orig_length(old_cp->length()); - } else { - // This old_cp is a merged constant pool from a previous - // RedefineClasses() calls so just copy the orig_length() - // value. - merge_cp->set_orig_length(old_cp->orig_length()); - } + // Update the version number of the constant pool + merge_cp->increment_and_save_version(old_cp->version()); ResourceMark rm(THREAD); _index_map_count = 0; @@ -2417,18 +2405,19 @@ int scratch_cp_length, TRAPS) { assert(scratch_cp->length() >= scratch_cp_length, "sanity check"); - // scratch_cp is a merged constant pool and has enough space for a - // worst case merge situation. We want to associate the minimum - // sized constant pool with the klass to save space. - constantPoolHandle smaller_cp(THREAD, - ConstantPool::allocate(loader_data, scratch_cp_length, - THREAD)); - // preserve orig_length() value in the smaller copy - int orig_length = scratch_cp->orig_length(); - assert(orig_length != 0, "sanity check"); - smaller_cp->set_orig_length(orig_length); - scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD); - scratch_cp = smaller_cp; + // scratch_cp is a merged constant pool and has enough space for a + // worst case merge situation. We want to associate the minimum + // sized constant pool with the klass to save space. + constantPoolHandle smaller_cp(THREAD, + ConstantPool::allocate(loader_data, scratch_cp_length, THREAD)); + + // preserve version() value in the smaller copy + int version = scratch_cp->version(); + assert(version != 0, "sanity check"); + smaller_cp->set_version(version); + + scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD); + scratch_cp = smaller_cp; // attach new constant pool to klass scratch_cp->set_pool_holder(scratch_class()); diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/runtime/aprofiler.cpp --- a/src/share/vm/runtime/aprofiler.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/runtime/aprofiler.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -129,7 +129,7 @@ assert(!is_active(), "AllocationProfiler cannot be active while printing profile"); tty->cr(); - tty->print_cr("Allocation profile (sizes in bytes, cutoff = %ld bytes):", cutoff * BytesPerWord); + tty->print_cr("Allocation profile (sizes in bytes, cutoff = " SIZE_FORMAT " bytes):", cutoff * BytesPerWord); tty->cr(); // Print regular instance klasses and basic type array klasses diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/runtime/arguments.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -532,7 +532,7 @@ // Parses a memory size specification string. static bool atomull(const char *s, julong* result) { julong n = 0; - int args_read = sscanf(s, os::julong_format_specifier(), &n); + int args_read = sscanf(s, JULONG_FORMAT, &n); if (args_read != 1) { return false; } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/runtime/objectMonitor.cpp --- a/src/share/vm/runtime/objectMonitor.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/runtime/objectMonitor.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -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 @@ -653,8 +653,7 @@ assert (_succ != Self, "invariant") ; if (_Responsible == Self) { _Responsible = NULL ; - // Dekker pivot-point. - // Consider OrderAccess::storeload() here + OrderAccess::fence(); // Dekker pivot-point // We may leave threads on cxq|EntryList without a designated // "Responsible" thread. This is benign. When this thread subsequently @@ -674,10 +673,6 @@ // // The MEMBAR, above, prevents the LD of cxq|EntryList in the subsequent // exit operation from floating above the ST Responsible=null. - // - // In *practice* however, EnterI() is always followed by some atomic - // operation such as the decrement of _count in ::enter(). Those atomics - // obviate the need for the explicit MEMBAR, above. } // We've acquired ownership with CAS(). diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/runtime/objectMonitor.inline.hpp --- a/src/share/vm/runtime/objectMonitor.inline.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/runtime/objectMonitor.inline.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, 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 @@ -101,10 +101,12 @@ return _count; } +// Do NOT set _count = 0. There is a race such that _count could +// be set while inflating prior to setting _owner +// Just use Atomic::inc/dec and assert 0 when monitor put on free list inline void ObjectMonitor::set_owner(void* owner) { _owner = owner; _recursions = 0; - _count = 0; } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/runtime/os.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -641,10 +641,6 @@ static struct hostent* get_host_by_name(char* name); - // Printing 64 bit integers - static const char* jlong_format_specifier(); - static const char* julong_format_specifier(); - // Support for signals (see JVM_RaiseSignal, JVM_RegisterSignal) static void signal_init(); static void signal_init_pd(); diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/runtime/perfData.cpp --- a/src/share/vm/runtime/perfData.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/runtime/perfData.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -192,7 +192,7 @@ } int PerfLong::format(char* buffer, int length) { - return jio_snprintf(buffer, length,"%lld", *(jlong*)_valuep); + return jio_snprintf(buffer, length, JLONG_FORMAT, *(jlong*)_valuep); } PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u, diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/runtime/synchronizer.cpp --- a/src/share/vm/runtime/synchronizer.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/runtime/synchronizer.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -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 @@ -333,7 +333,9 @@ void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) { TEVENT (jni_exit) ; if (UseBiasedLocking) { - BiasedLocking::revoke_and_rebias(obj, false, THREAD); + Handle h_obj(THREAD, obj); + BiasedLocking::revoke_and_rebias(h_obj, false, THREAD); + obj = h_obj(); } assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/runtime/virtualspace.cpp --- a/src/share/vm/runtime/virtualspace.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/runtime/virtualspace.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -868,8 +868,8 @@ tty->print ("Virtual space:"); if (special()) tty->print(" (pinned in memory)"); tty->cr(); - tty->print_cr(" - committed: %ld", committed_size()); - tty->print_cr(" - reserved: %ld", reserved_size()); + tty->print_cr(" - committed: " SIZE_FORMAT, committed_size()); + tty->print_cr(" - reserved: " SIZE_FORMAT, reserved_size()); tty->print_cr(" - [low, high]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low(), high()); tty->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low_boundary(), high_boundary()); } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/runtime/vmStructs.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -2291,6 +2291,7 @@ /*************************************/ \ \ declare_preprocessor_constant("FIELDINFO_TAG_SIZE", FIELDINFO_TAG_SIZE) \ + declare_preprocessor_constant("FIELDINFO_TAG_MASK", FIELDINFO_TAG_MASK) \ declare_preprocessor_constant("FIELDINFO_TAG_OFFSET", FIELDINFO_TAG_OFFSET) \ \ /************************************************/ \ diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/runtime/vmThread.cpp --- a/src/share/vm/runtime/vmThread.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/runtime/vmThread.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -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 @@ -570,7 +570,11 @@ if (!t->is_VM_thread()) { SkipGCALot sgcalot(t); // avoid re-entrant attempts to gc-a-lot // JavaThread or WatcherThread - t->check_for_valid_safepoint_state(true); + bool concurrent = op->evaluate_concurrently(); + // only blocking VM operations need to verify the caller's safepoint state: + if (!concurrent) { + t->check_for_valid_safepoint_state(true); + } // New request from Java thread, evaluate prologue if (!op->doit_prologue()) { @@ -582,7 +586,6 @@ // It does not make sense to execute the epilogue, if the VM operation object is getting // deallocated by the VM thread. - bool concurrent = op->evaluate_concurrently(); bool execute_epilog = !op->is_cheap_allocated(); assert(!concurrent || op->is_cheap_allocated(), "concurrent => cheap_allocated"); diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/services/diagnosticArgument.cpp --- a/src/share/vm/services/diagnosticArgument.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/services/diagnosticArgument.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,7 +86,7 @@ template <> void DCmdArgument::parse_value(const char* str, size_t len, TRAPS) { - if (str == NULL || sscanf(str, INT64_FORMAT, &_value) != 1) { + if (str == NULL || sscanf(str, JLONG_FORMAT, &_value) != 1) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Integer parsing error in diagnostic command arguments\n"); } @@ -171,7 +171,7 @@ "Integer parsing error nanotime value: syntax error"); } - int argc = sscanf(str, INT64_FORMAT , &_value._time); + int argc = sscanf(str, JLONG_FORMAT, &_value._time); if (argc != 1) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Integer parsing error nanotime value: syntax error"); diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/services/heapDumper.cpp --- a/src/share/vm/services/heapDumper.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/services/heapDumper.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1866,7 +1866,7 @@ if (error() == NULL) { char msg[256]; sprintf(msg, "Heap dump file created [%s bytes in %3.3f secs]", - os::jlong_format_specifier(), timer()->seconds()); + JLONG_FORMAT, timer()->seconds()); tty->print_cr(msg, writer.bytes_written()); } else { tty->print_cr("Dump file is incomplete: %s", writer.error()); diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/services/lowMemoryDetector.cpp --- a/src/share/vm/services/lowMemoryDetector.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/services/lowMemoryDetector.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -353,7 +353,7 @@ #ifndef PRODUCT void SensorInfo::print() { - tty->print_cr("%s count = %ld pending_triggers = %ld pending_clears = %ld", + tty->print_cr("%s count = " SIZE_FORMAT " pending_triggers = %ld pending_clears = %ld", (_sensor_on ? "on" : "off"), _sensor_count, _pending_trigger_count, _pending_clear_count); } diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/utilities/globalDefinitions.hpp --- a/src/share/vm/utilities/globalDefinitions.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/utilities/globalDefinitions.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1250,6 +1250,14 @@ #define PTR64_FORMAT "0x%016" PRIx64 +// Format jlong, if necessary +#ifndef JLONG_FORMAT +#define JLONG_FORMAT INT64_FORMAT +#endif +#ifndef JULONG_FORMAT +#define JULONG_FORMAT UINT64_FORMAT +#endif + // Format pointers which change size between 32- and 64-bit. #ifdef _LP64 #define INTPTR_FORMAT "0x%016" PRIxPTR diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/utilities/globalDefinitions_gcc.hpp --- a/src/share/vm/utilities/globalDefinitions_gcc.hpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/utilities/globalDefinitions_gcc.hpp Mon Feb 04 13:26:04 2013 -0800 @@ -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 @@ -306,4 +306,8 @@ #endif #define offsetof(klass,field) offset_of(klass,field) +#if defined(_LP64) && defined(__APPLE__) +#define JLONG_FORMAT "%ld" +#endif // _LP64 && __APPLE__ + #endif // SHARE_VM_UTILITIES_GLOBALDEFINITIONS_GCC_HPP diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/utilities/ostream.cpp --- a/src/share/vm/utilities/ostream.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/utilities/ostream.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,13 +243,11 @@ } void outputStream::print_jlong(jlong value) { - // N.B. Same as INT64_FORMAT - print(os::jlong_format_specifier(), value); + print(JLONG_FORMAT, value); } void outputStream::print_julong(julong value) { - // N.B. Same as UINT64_FORMAT - print(os::julong_format_specifier(), value); + print(JULONG_FORMAT, value); } /** diff -r 256d3f43c177 -r f2f0cf0f5444 src/share/vm/utilities/taskqueue.cpp --- a/src/share/vm/utilities/taskqueue.cpp Thu Jan 31 10:45:09 2013 -0800 +++ b/src/share/vm/utilities/taskqueue.cpp Mon Feb 04 13:26:04 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -239,8 +239,8 @@ #ifdef TRACESPINNING void ParallelTaskTerminator::print_termination_counts() { - gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: %lld " - "Total spins: %lld Total peeks: %lld", + gclog_or_tty->print_cr("ParallelTaskTerminator Total yields: " UINT32_FORMAT + " Total spins: " UINT32_FORMAT " Total peeks: " UINT32_FORMAT, total_yields(), total_spins(), total_peeks()); diff -r 256d3f43c177 -r f2f0cf0f5444 test/compiler/6896617/Test6896617.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6896617/Test6896617.java Mon Feb 04 13:26:04 2013 -0800 @@ -0,0 +1,331 @@ +/* + * 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 6896617 + * @summary Optimize sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() with SSE instructions on x86 + * @run main/othervm/timeout=1200 -Xbatch -Xmx256m Test6896617 + * + */ + +import java.util.*; +import java.nio.*; +import java.nio.charset.*; + +public class Test6896617 { + final static int SIZE = 256; + + public static void main(String[] args) { + String csn = "ISO-8859-1"; + Charset cs = Charset.forName(csn); + CharsetEncoder enc = cs.newEncoder(); + enc.onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + CharsetDecoder dec = cs.newDecoder(); + dec.onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + + byte repl = (byte)'?'; + enc.replaceWith(new byte[] { repl }); + + // Use internal API for tests. + sun.nio.cs.ArrayEncoder arrenc = (sun.nio.cs.ArrayEncoder)enc; + sun.nio.cs.ArrayDecoder arrdec = (sun.nio.cs.ArrayDecoder)dec; + + // Populate char[] with chars which can be encoded by ISO_8859_1 (<= 0xFF) + Random rnd = new Random(0); + int maxchar = 0xFF; + char[] a = new char[SIZE]; + byte[] b = new byte[SIZE]; + char[] at = new char[SIZE]; + byte[] bt = new byte[SIZE]; + for (int i = 0; i < SIZE; i++) { + char c = (char) rnd.nextInt(maxchar); + if (!enc.canEncode(c)) { + System.out.printf("Something wrong: can't encode c=%03x\n", (int)c); + System.exit(97); + } + a[i] = c; + b[i] = (byte)c; + at[i] = (char)-1; + bt[i] = (byte)-1; + } + if (arrenc.encode(a, 0, SIZE, bt) != SIZE || !Arrays.equals(b, bt)) { + System.out.println("Something wrong: ArrayEncoder.encode failed"); + System.exit(97); + } + if (arrdec.decode(b, 0, SIZE, at) != SIZE || !Arrays.equals(a, at)) { + System.out.println("Something wrong: ArrayDecoder.decode failed"); + System.exit(97); + } + for (int i = 0; i < SIZE; i++) { + at[i] = (char)-1; + bt[i] = (byte)-1; + } + + ByteBuffer bb = ByteBuffer.wrap(b); + CharBuffer ba = CharBuffer.wrap(a); + ByteBuffer bbt = ByteBuffer.wrap(bt); + CharBuffer bat = CharBuffer.wrap(at); + if (!enc.encode(ba, bbt, true).isUnderflow() || !Arrays.equals(b, bt)) { + System.out.println("Something wrong: Encoder.encode failed"); + System.exit(97); + } + if (!dec.decode(bb, bat, true).isUnderflow() || !Arrays.equals(a, at)) { + System.out.println("Something wrong: Decoder.decode failed"); + System.exit(97); + } + for (int i = 0; i < SIZE; i++) { + at[i] = (char)-1; + bt[i] = (byte)-1; + } + + // Warm up + boolean failed = false; + int result = 0; + for (int i = 0; i < 10000; i++) { + result += arrenc.encode(a, 0, SIZE, bt); + result -= arrdec.decode(b, 0, SIZE, at); + } + for (int i = 0; i < 10000; i++) { + result += arrenc.encode(a, 0, SIZE, bt); + result -= arrdec.decode(b, 0, SIZE, at); + } + for (int i = 0; i < 10000; i++) { + result += arrenc.encode(a, 0, SIZE, bt); + result -= arrdec.decode(b, 0, SIZE, at); + } + if (result != 0 || !Arrays.equals(b, bt) || !Arrays.equals(a, at)) { + failed = true; + System.out.println("Failed: ArrayEncoder.encode char[" + SIZE + "] and ArrayDecoder.decode byte[" + SIZE + "]"); + } + for (int i = 0; i < SIZE; i++) { + at[i] = (char)-1; + bt[i] = (byte)-1; + } + + boolean is_underflow = true; + for (int i = 0; i < 10000; i++) { + ba.clear(); bb.clear(); bat.clear(); bbt.clear(); + boolean enc_res = enc.encode(ba, bbt, true).isUnderflow(); + boolean dec_res = dec.decode(bb, bat, true).isUnderflow(); + is_underflow = is_underflow && enc_res && dec_res; + } + for (int i = 0; i < SIZE; i++) { + at[i] = (char)-1; + bt[i] = (byte)-1; + } + for (int i = 0; i < 10000; i++) { + ba.clear(); bb.clear(); bat.clear(); bbt.clear(); + boolean enc_res = enc.encode(ba, bbt, true).isUnderflow(); + boolean dec_res = dec.decode(bb, bat, true).isUnderflow(); + is_underflow = is_underflow && enc_res && dec_res; + } + for (int i = 0; i < SIZE; i++) { + at[i] = (char)-1; + bt[i] = (byte)-1; + } + for (int i = 0; i < 10000; i++) { + ba.clear(); bb.clear(); bat.clear(); bbt.clear(); + boolean enc_res = enc.encode(ba, bbt, true).isUnderflow(); + boolean dec_res = dec.decode(bb, bat, true).isUnderflow(); + is_underflow = is_underflow && enc_res && dec_res; + } + if (!is_underflow || !Arrays.equals(b, bt) || !Arrays.equals(a, at)) { + failed = true; + System.out.println("Failed: Encoder.encode char[" + SIZE + "] and Decoder.decode byte[" + SIZE + "]"); + } + + // Test encoder with different source and destination sizes + System.out.println("Testing different source and destination sizes"); + for (int i = 1; i <= SIZE; i++) { + for (int j = 1; j <= SIZE; j++) { + bt = new byte[j]; + // very source's SIZE + result = arrenc.encode(a, 0, i, bt); + int l = Math.min(i, j); + if (result != l) { + failed = true; + System.out.println("Failed: encode char[" + i + "] to byte[" + j + "]: result = " + result + ", expected " + l); + } + for (int k = 0; k < l; k++) { + if (bt[k] != b[k]) { + failed = true; + System.out.println("Failed: encoded byte[" + k + "] (" + bt[k] + ") != " + b[k]); + } + } + // very source's offset + int sz = SIZE - i + 1; + result = arrenc.encode(a, i-1, sz, bt); + l = Math.min(sz, j); + if (result != l) { + failed = true; + System.out.println("Failed: encode char[" + sz + "] to byte[" + j + "]: result = " + result + ", expected " + l); + } + for (int k = 0; k < l; k++) { + if (bt[k] != b[i+k-1]) { + failed = true; + System.out.println("Failed: encoded byte[" + k + "] (" + bt[k] + ") != " + b[i+k-1]); + } + } + } + } + + // Test encoder with char > 0xFF + System.out.println("Testing big char"); + + byte orig = (byte)'A'; + bt = new byte[SIZE]; + for (int i = 1; i <= SIZE; i++) { + for (int j = 0; j < i; j++) { + a[j] += 0x100; + // make sure to replace a different byte + bt[j] = orig; + result = arrenc.encode(a, 0, i, bt); + if (result != i) { + failed = true; + System.out.println("Failed: encode char[" + i + "] to byte[" + i + "]: result = " + result + ", expected " + i); + } + if (bt[j] != repl) { + failed = true; + System.out.println("Failed: encoded replace byte[" + j + "] (" + bt[j] + ") != " + repl); + } + bt[j] = b[j]; // Restore to compare whole array + for (int k = 0; k < i; k++) { + if (bt[k] != b[k]) { + failed = true; + System.out.println("Failed: encoded byte[" + k + "] (" + bt[k] + ") != " + b[k]); + } + } + a[j] -= 0x100; // Restore + } + } + + // Test sun.nio.cs.ISO_8859_1$Encode.encodeArrayLoop() performance. + + int itrs = Integer.getInteger("iterations", 1000000); + int size = Integer.getInteger("size", 256); + a = new char[size]; + b = new byte[size]; + bt = new byte[size]; + for (int i = 0; i < size; i++) { + char c = (char) rnd.nextInt(maxchar); + if (!enc.canEncode(c)) { + System.out.printf("Something wrong: can't encode c=%03x\n", (int)c); + System.exit(97); + } + a[i] = c; + b[i] = (byte)-1; + bt[i] = (byte)c; + } + ba = CharBuffer.wrap(a); + bb = ByteBuffer.wrap(b); + boolean enc_res = enc.encode(ba, bb, true).isUnderflow(); + if (!enc_res || !Arrays.equals(b, bt)) { + failed = true; + System.out.println("Failed 1: Encoder.encode char[" + size + "]"); + } + for (int i = 0; i < size; i++) { + b[i] = (byte)-1; + } + + // Make sure to recompile method if needed before performance run. + for (int i = 0; i < 10000; i++) { + ba.clear(); bb.clear(); + enc_res = enc_res && enc.encode(ba, bb, true).isUnderflow(); + } + for (int i = 0; i < size; i++) { + b[i] = (byte)-1; + } + for (int i = 0; i < 10000; i++) { + ba.clear(); bb.clear(); + enc_res = enc_res && enc.encode(ba, bb, true).isUnderflow(); + } + if (!enc_res || !Arrays.equals(b, bt)) { + failed = true; + System.out.println("Failed 2: Encoder.encode char[" + size + "]"); + } + for (int i = 0; i < size; i++) { + b[i] = (byte)-1; + } + + System.out.println("Testing ISO_8859_1$Encode.encodeArrayLoop() performance"); + long start = System.currentTimeMillis(); + for (int i = 0; i < itrs; i++) { + ba.clear(); bb.clear(); + enc_res = enc_res && enc.encode(ba, bb, true).isUnderflow(); + } + long end = System.currentTimeMillis(); + if (!enc_res || !Arrays.equals(b, bt)) { + failed = true; + System.out.println("Failed 3: Encoder.encode char[" + size + "]"); + } else { + System.out.println("size: " + size + " time: " + (end - start)); + } + + // Test sun.nio.cs.ISO_8859_1$Encode.encode() performance. + + // Make sure to recompile method if needed before performance run. + result = 0; + for (int i = 0; i < size; i++) { + b[i] = (byte)-1; + } + for (int i = 0; i < 10000; i++) { + result += arrenc.encode(a, 0, size, b); + } + for (int i = 0; i < size; i++) { + b[i] = (byte)-1; + } + for (int i = 0; i < 10000; i++) { + result += arrenc.encode(a, 0, size, b); + } + if (result != size*20000 || !Arrays.equals(b, bt)) { + failed = true; + System.out.println("Failed 1: ArrayEncoder.encode char[" + SIZE + "]"); + } + for (int i = 0; i < size; i++) { + b[i] = (byte)-1; + } + + System.out.println("Testing ISO_8859_1$Encode.encode() performance"); + result = 0; + start = System.currentTimeMillis(); + for (int i = 0; i < itrs; i++) { + result += arrenc.encode(a, 0, size, b); + } + end = System.currentTimeMillis(); + if (!Arrays.equals(b, bt)) { + failed = true; + System.out.println("Failed 2: ArrayEncoder.encode char[" + size + "]"); + } else { + System.out.println("size: " + size + " time: " + (end - start)); + } + + if (failed) { + System.out.println("FAILED"); + System.exit(97); + } + System.out.println("PASSED"); + } +}