diff --git a/src/hotspot/cpu/arm/frame_arm.cpp b/src/hotspot/cpu/arm/frame_arm.cpp index 1ee8df049fccb..d923e1f43ad43 100644 --- a/src/hotspot/cpu/arm/frame_arm.cpp +++ b/src/hotspot/cpu/arm/frame_arm.cpp @@ -279,7 +279,6 @@ BasicObjectLock* frame::interpreter_frame_monitor_begin() const { return (BasicObjectLock*) addr_at(interpreter_frame_monitor_block_bottom_offset); } -// Pointer beyond the "oldest/deepest" BasicObjectLock on stack. BasicObjectLock* frame::interpreter_frame_monitor_end() const { BasicObjectLock* result = (BasicObjectLock*) *addr_at(interpreter_frame_monitor_block_top_offset); // make sure the pointer points inside the frame diff --git a/src/hotspot/cpu/ppc/frame_ppc.cpp b/src/hotspot/cpu/ppc/frame_ppc.cpp index 96a87ea9d1179..637883986195b 100644 --- a/src/hotspot/cpu/ppc/frame_ppc.cpp +++ b/src/hotspot/cpu/ppc/frame_ppc.cpp @@ -454,7 +454,6 @@ intptr_t *frame::initial_deoptimization_info() { frame::frame(void* sp, void* fp, void* pc) : frame((intptr_t*)sp, (address)pc) {} #endif -// Pointer beyond the "oldest/deepest" BasicObjectLock on stack. BasicObjectLock* frame::interpreter_frame_monitor_end() const { BasicObjectLock* result = (BasicObjectLock*) at_relative(ijava_idx(monitors)); // make sure the pointer points inside the frame diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp index 97dc537de6a67..7473775c50d6f 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp @@ -1978,7 +1978,7 @@ void InterpreterMacroAssembler::profile_parameters_type(Register tmp1, Register } } -// Add a InterpMonitorElem to stack (see frame_sparc.hpp). +// Add a monitor (see frame_ppc.hpp). void InterpreterMacroAssembler::add_monitor_to_stack(bool stack_is_empty, Register Rtemp1, Register Rtemp2) { // Very-local scratch registers. diff --git a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp index ef2d642ede07e..9ffb75483b8a6 100644 --- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp @@ -4159,79 +4159,67 @@ void TemplateTable::athrow() { // at next monitor exit. void TemplateTable::monitorenter() { transition(atos, vtos); - __ verify_oop(R17_tos); - Register Rcurrent_monitor = R11_scratch1, - Rcurrent_obj = R12_scratch2, + Register Rcurrent_monitor = R3_ARG1, + Rcurrent_obj = R4_ARG2, Robj_to_lock = R17_tos, - Rscratch1 = R3_ARG1, - Rscratch2 = R4_ARG2, - Rscratch3 = R5_ARG3, - Rcurrent_obj_addr = R6_ARG4; + Rscratch1 = R11_scratch1, + Rscratch2 = R12_scratch2, + Rbot = R5_ARG3, + Rfree_slot = R6_ARG4; + + Label Lfound, Lallocate_new; + + __ ld(Rscratch1, _abi0(callers_sp), R1_SP); // load FP + __ li(Rfree_slot, 0); // Points to free slot or null. + + // Set up search loop - start with topmost monitor. + __ mr(Rcurrent_monitor, R26_monitor); + __ addi(Rbot, Rscratch1, -frame::ijava_state_size); // ------------------------------------------------------------------------------ // Null pointer exception. - __ null_check_throw(Robj_to_lock, -1, R11_scratch1); + __ null_check_throw(Robj_to_lock, -1, Rscratch1); - // Try to acquire a lock on the object. - // Repeat until succeeded (i.e., until monitorenter returns true). + // Check if any slot is present => short cut to allocation if not. + __ cmpld(CCR0, Rcurrent_monitor, Rbot); + __ beq(CCR0, Lallocate_new); // ------------------------------------------------------------------------------ // Find a free slot in the monitor block. - Label Lfound, Lexit, Lallocate_new; - ConditionRegister found_free_slot = CCR0, - found_same_obj = CCR1, - reached_limit = CCR6; + // Note: The order of the monitors is important for C2 OSR which derives the + // unlock order from it (see comments for interpreter_frame_monitor_*). { - Label Lloop; - Register Rlimit = Rcurrent_monitor; - - // Set up search loop - start with topmost monitor. - __ addi(Rcurrent_obj_addr, R26_monitor, in_bytes(BasicObjectLock::obj_offset())); + Label Lloop, LnotFree, Lexit; - __ ld(Rlimit, 0, R1_SP); - __ addi(Rlimit, Rlimit, - (frame::ijava_state_size + frame::interpreter_frame_monitor_size_in_bytes() - in_bytes(BasicObjectLock::obj_offset()))); // Monitor base + __ bind(Lloop); + __ ld(Rcurrent_obj, in_bytes(BasicObjectLock::obj_offset()), Rcurrent_monitor); + // Exit if current entry is for same object; this guarantees, that new monitor + // used for recursive lock is above the older one. + __ cmpd(CCR0, Rcurrent_obj, Robj_to_lock); + __ beq(CCR0, Lexit); // recursive locking - // Check if any slot is present => short cut to allocation if not. - __ cmpld(reached_limit, Rcurrent_obj_addr, Rlimit); - __ bgt(reached_limit, Lallocate_new); + __ cmpdi(CCR0, Rcurrent_obj, 0); + __ bne(CCR0, LnotFree); + __ mr(Rfree_slot, Rcurrent_monitor); // remember free slot closest to the bottom + __ bind(LnotFree); - // Pre-load topmost slot. - __ ld(Rcurrent_obj, 0, Rcurrent_obj_addr); - __ addi(Rcurrent_obj_addr, Rcurrent_obj_addr, frame::interpreter_frame_monitor_size_in_bytes()); - // The search loop. - __ bind(Lloop); - // Found free slot? - __ cmpdi(found_free_slot, Rcurrent_obj, 0); - // Is this entry for same obj? If so, stop the search and take the found - // free slot or allocate a new one to enable recursive locking. - __ cmpd(found_same_obj, Rcurrent_obj, Robj_to_lock); - __ cmpld(reached_limit, Rcurrent_obj_addr, Rlimit); - __ beq(found_free_slot, Lexit); - __ beq(found_same_obj, Lallocate_new); - __ bgt(reached_limit, Lallocate_new); - // Check if last allocated BasicLockObj reached. - __ ld(Rcurrent_obj, 0, Rcurrent_obj_addr); - __ addi(Rcurrent_obj_addr, Rcurrent_obj_addr, frame::interpreter_frame_monitor_size_in_bytes()); - // Next iteration if unchecked BasicObjectLocks exist on the stack. - __ b(Lloop); + __ addi(Rcurrent_monitor, Rcurrent_monitor, frame::interpreter_frame_monitor_size_in_bytes()); + __ cmpld(CCR0, Rcurrent_monitor, Rbot); + __ bne(CCR0, Lloop); + __ bind(Lexit); } // ------------------------------------------------------------------------------ // Check if we found a free slot. - __ bind(Lexit); - - __ addi(Rcurrent_monitor, Rcurrent_obj_addr, -(frame::interpreter_frame_monitor_size_in_bytes()) - in_bytes(BasicObjectLock::obj_offset())); - __ addi(Rcurrent_obj_addr, Rcurrent_obj_addr, - frame::interpreter_frame_monitor_size_in_bytes()); - __ b(Lfound); + __ cmpdi(CCR0, Rfree_slot, 0); + __ bne(CCR0, Lfound); // We didn't find a free BasicObjLock => allocate one. - __ align(32, 12); __ bind(Lallocate_new); __ add_monitor_to_stack(false, Rscratch1, Rscratch2); - __ mr(Rcurrent_monitor, R26_monitor); - __ addi(Rcurrent_obj_addr, R26_monitor, in_bytes(BasicObjectLock::obj_offset())); + __ mr(Rfree_slot, R26_monitor); // ------------------------------------------------------------------------------ // We now have a slot to lock. @@ -4241,8 +4229,8 @@ void TemplateTable::monitorenter() { // The object has already been popped from the stack, so the expression stack looks correct. __ addi(R14_bcp, R14_bcp, 1); - __ std(Robj_to_lock, 0, Rcurrent_obj_addr); - __ lock_object(Rcurrent_monitor, Robj_to_lock); + __ std(Robj_to_lock, in_bytes(BasicObjectLock::obj_offset()), Rfree_slot); + __ lock_object(Rfree_slot, Robj_to_lock); // Check if there's enough space on the stack for the monitors after locking. // This emits a single store. @@ -4256,46 +4244,40 @@ void TemplateTable::monitorexit() { transition(atos, vtos); __ verify_oop(R17_tos); - Register Rcurrent_monitor = R11_scratch1, - Rcurrent_obj = R12_scratch2, + Register Rcurrent_monitor = R3_ARG1, + Rcurrent_obj = R4_ARG2, Robj_to_lock = R17_tos, - Rcurrent_obj_addr = R3_ARG1, - Rlimit = R4_ARG2; + Rscratch = R11_scratch1, + Rbot = R12_scratch2; + Label Lfound, Lillegal_monitor_state; - // Check corner case: unbalanced monitorEnter / Exit. - __ ld(Rlimit, 0, R1_SP); - __ addi(Rlimit, Rlimit, - (frame::ijava_state_size + frame::interpreter_frame_monitor_size_in_bytes())); // Monitor base + __ ld(Rscratch, _abi0(callers_sp), R1_SP); // load FP + + // Set up search loop - start with topmost monitor. + __ mr(Rcurrent_monitor, R26_monitor); + __ addi(Rbot, Rscratch, -frame::ijava_state_size); // Null pointer check. - __ null_check_throw(Robj_to_lock, -1, R11_scratch1); + __ null_check_throw(Robj_to_lock, -1, Rscratch); - __ cmpld(CCR0, R26_monitor, Rlimit); - __ bgt(CCR0, Lillegal_monitor_state); + // Check corner case: unbalanced monitorEnter / Exit. + __ cmpld(CCR0, Rcurrent_monitor, Rbot); + __ beq(CCR0, Lillegal_monitor_state); // Find the corresponding slot in the monitors stack section. { Label Lloop; - // Start with topmost monitor. - __ addi(Rcurrent_obj_addr, R26_monitor, in_bytes(BasicObjectLock::obj_offset())); - __ addi(Rlimit, Rlimit, in_bytes(BasicObjectLock::obj_offset())); - __ ld(Rcurrent_obj, 0, Rcurrent_obj_addr); - __ addi(Rcurrent_obj_addr, Rcurrent_obj_addr, frame::interpreter_frame_monitor_size_in_bytes()); - __ bind(Lloop); + __ ld(Rcurrent_obj, in_bytes(BasicObjectLock::obj_offset()), Rcurrent_monitor); // Is this entry for same obj? __ cmpd(CCR0, Rcurrent_obj, Robj_to_lock); __ beq(CCR0, Lfound); - // Check if last allocated BasicLockObj reached. - - __ ld(Rcurrent_obj, 0, Rcurrent_obj_addr); - __ cmpld(CCR0, Rcurrent_obj_addr, Rlimit); - __ addi(Rcurrent_obj_addr, Rcurrent_obj_addr, frame::interpreter_frame_monitor_size_in_bytes()); - - // Next iteration if unchecked BasicObjectLocks exist on the stack. - __ ble(CCR0, Lloop); + __ addi(Rcurrent_monitor, Rcurrent_monitor, frame::interpreter_frame_monitor_size_in_bytes()); + __ cmpld(CCR0, Rcurrent_monitor, Rbot); + __ bne(CCR0, Lloop); } // Fell through without finding the basic obj lock => throw up! @@ -4305,8 +4287,6 @@ void TemplateTable::monitorexit() { __ align(32, 12); __ bind(Lfound); - __ addi(Rcurrent_monitor, Rcurrent_obj_addr, - -(frame::interpreter_frame_monitor_size_in_bytes()) - in_bytes(BasicObjectLock::obj_offset())); __ unlock_object(Rcurrent_monitor); } diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index 2431df1178dfa..a2815db2b4e5a 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -3932,43 +3932,46 @@ class StubGenerator: public StubCodeGenerator { } } - void gen_loads(Register base) { - for (uint i = 0; i < L; i += 1) { - __ ld(_regs[i], Address(base, 8 * i)); - } + // generate load for the i'th register + void gen_load(uint i, Register base) { + assert(i < L, "invalid i: %u", i); + __ ld(_regs[i], Address(base, 8 * i)); } - // Generate code extracting i-th unsigned word (4 bytes). - void get_u32(Register dest, uint i, Register rmask32) { + // add i'th 32-bit integer to dest + void add_u32(const Register dest, uint i, const Register rtmp = t0) { assert(i < 2 * L, "invalid i: %u", i); - if (i % 2 == 0) { - __ andr(dest, _regs[i / 2], rmask32); + if (is_even(i)) { + // Use the bottom 32 bits. No need to mask off the top 32 bits + // as addw will do the right thing. + __ addw(dest, dest, _regs[i / 2]); } else { - __ srli(dest, _regs[i / 2], 32); + // Use the top 32 bits by right-shifting them. + __ srli(rtmp, _regs[i / 2], 32); + __ addw(dest, dest, rtmp); } } }; typedef RegCache<8> BufRegCache; - // a += rtmp1 + x + ac; + // a += value + x + ac; // a = Integer.rotateLeft(a, s) + b; void m5_FF_GG_HH_II_epilogue(BufRegCache& reg_cache, Register a, Register b, Register c, Register d, int k, int s, int t, - Register rtmp1, Register rtmp2, Register rmask32) { - // rtmp1 = rtmp1 + x + ac - reg_cache.get_u32(rtmp2, k, rmask32); - __ addw(rtmp1, rtmp1, rtmp2); - __ mv(rtmp2, t); - __ addw(rtmp1, rtmp1, rtmp2); + Register value) { + // a += ac + __ addw(a, a, t, t1); - // a += rtmp1 + x + ac - __ addw(a, a, rtmp1); + // a += x; + reg_cache.add_u32(a, k); + // a += value; + __ addw(a, a, value); // a = Integer.rotateLeft(a, s) + b; - __ rolw_imm(a, a, s, rtmp1); + __ rolw_imm(a, a, s); __ addw(a, a, b); } @@ -3977,7 +3980,7 @@ class StubGenerator: public StubCodeGenerator { void md5_FF(BufRegCache& reg_cache, Register a, Register b, Register c, Register d, int k, int s, int t, - Register rtmp1, Register rtmp2, Register rmask32) { + Register rtmp1, Register rtmp2) { // rtmp1 = b & c __ andr(rtmp1, b, c); @@ -3987,8 +3990,7 @@ class StubGenerator: public StubCodeGenerator { // rtmp1 = (b & c) | ((~b) & d) __ orr(rtmp1, rtmp1, rtmp2); - m5_FF_GG_HH_II_epilogue(reg_cache, a, b, c, d, k, s, t, - rtmp1, rtmp2, rmask32); + m5_FF_GG_HH_II_epilogue(reg_cache, a, b, c, d, k, s, t, rtmp1); } // a += ((b & d) | (c & (~d))) + x + ac; @@ -3996,7 +3998,7 @@ class StubGenerator: public StubCodeGenerator { void md5_GG(BufRegCache& reg_cache, Register a, Register b, Register c, Register d, int k, int s, int t, - Register rtmp1, Register rtmp2, Register rmask32) { + Register rtmp1, Register rtmp2) { // rtmp1 = b & d __ andr(rtmp1, b, d); @@ -4006,8 +4008,7 @@ class StubGenerator: public StubCodeGenerator { // rtmp1 = (b & d) | (c & (~d)) __ orr(rtmp1, rtmp1, rtmp2); - m5_FF_GG_HH_II_epilogue(reg_cache, a, b, c, d, k, s, t, - rtmp1, rtmp2, rmask32); + m5_FF_GG_HH_II_epilogue(reg_cache, a, b, c, d, k, s, t, rtmp1); } // a += ((b ^ c) ^ d) + x + ac; @@ -4015,13 +4016,12 @@ class StubGenerator: public StubCodeGenerator { void md5_HH(BufRegCache& reg_cache, Register a, Register b, Register c, Register d, int k, int s, int t, - Register rtmp1, Register rtmp2, Register rmask32) { + Register rtmp1, Register rtmp2) { // rtmp1 = (b ^ c) ^ d - __ xorr(rtmp1, b, c); - __ xorr(rtmp1, rtmp1, d); + __ xorr(rtmp2, b, c); + __ xorr(rtmp1, rtmp2, d); - m5_FF_GG_HH_II_epilogue(reg_cache, a, b, c, d, k, s, t, - rtmp1, rtmp2, rmask32); + m5_FF_GG_HH_II_epilogue(reg_cache, a, b, c, d, k, s, t, rtmp1); } // a += (c ^ (b | (~d))) + x + ac; @@ -4029,13 +4029,12 @@ class StubGenerator: public StubCodeGenerator { void md5_II(BufRegCache& reg_cache, Register a, Register b, Register c, Register d, int k, int s, int t, - Register rtmp1, Register rtmp2, Register rmask32) { + Register rtmp1, Register rtmp2) { // rtmp1 = c ^ (b | (~d)) - __ orn(rtmp1, b, d); - __ xorr(rtmp1, c, rtmp1); + __ orn(rtmp2, b, d); + __ xorr(rtmp1, c, rtmp2); - m5_FF_GG_HH_II_epilogue(reg_cache, a, b, c, d, k, s, t, - rtmp1, rtmp2, rmask32); + m5_FF_GG_HH_II_epilogue(reg_cache, a, b, c, d, k, s, t, rtmp1); } // Arguments: @@ -4052,11 +4051,11 @@ class StubGenerator: public StubCodeGenerator { // x2 sp (stack pointer) // x3 gp (global pointer) // x4 tp (thread pointer) - // x5 t0 state0 - // x6 t1 state1 - // x7 t2 state2 + // x5 t0 (tmp register) + // x6 t1 (tmp register) + // x7 t2 state0 // x8 f0/s0 (frame pointer) - // x9 s1 state3 [saved-reg] + // x9 s1 // x10 a0 rtmp1 / c_rarg0 // x11 a1 rtmp2 / c_rarg1 // x12 a2 a / c_rarg2 @@ -4067,9 +4066,9 @@ class StubGenerator: public StubCodeGenerator { // x17 a7 state // x18 s2 ofs [saved-reg] (multi_block == True) // x19 s3 limit [saved-reg] (multi_block == True) - // x20 s4 - // x21 s5 - // x22 s6 mask32 [saved-reg] + // x20 s4 state1 [saved-reg] + // x21 s5 state2 [saved-reg] + // x22 s6 state3 [saved-reg] // x23 s7 // x24 s8 buf0 [saved-reg] // x25 s9 buf1 [saved-reg] @@ -4102,6 +4101,8 @@ class StubGenerator: public StubCodeGenerator { const int S43 = 15; const int S44 = 21; + const int64_t mask32 = 0xffffffff; + Register buf_arg = c_rarg0; // a0 Register state_arg = c_rarg1; // a1 Register ofs_arg = c_rarg2; // a2 @@ -4121,18 +4122,15 @@ class StubGenerator: public StubCodeGenerator { Register c = x14; // a4 Register d = x15; // a5 - Register state0 = x5; // t0 - Register state1 = x6; // t1 - Register state2 = x7; // t2 - Register state3 = x9; // s1 + Register state0 = x7; // t2 + Register state1 = x20; // s4 + Register state2 = x21; // s5 + Register state3 = x22; // s6 - // using x9->x11 to allow compressed instructions + // using x10->x11 to allow compressed instructions Register rtmp1 = x10; // a0 Register rtmp2 = x11; // a1 - const int64_t MASK_32 = 0xffffffff; - Register rmask32 = x22; // s6 - RegSet reg_cache_saved_regs = RegSet::of(x24, x25, x26, x27); // s8, s9, s10, s11 RegSet reg_cache_regs; reg_cache_regs += reg_cache_saved_regs; @@ -4143,7 +4141,7 @@ class StubGenerator: public StubCodeGenerator { if (multi_block) { saved_regs += RegSet::of(ofs, limit); } - saved_regs += RegSet::of(state3, rmask32); + saved_regs += RegSet::of(state1, state2, state3); saved_regs += reg_cache_saved_regs; __ push_reg(saved_regs, sp); @@ -4154,99 +4152,105 @@ class StubGenerator: public StubCodeGenerator { __ mv(ofs, ofs_arg); __ mv(limit, limit_arg); } - __ mv(rmask32, MASK_32); // to minimize the number of memory operations: // read the 4 state 4-byte values in pairs, with a single ld, // and split them into 2 registers + __ mv(t0, mask32); __ ld(state0, Address(state)); __ srli(state1, state0, 32); - __ andr(state0, state0, rmask32); + __ andr(state0, state0, t0); __ ld(state2, Address(state, 8)); __ srli(state3, state2, 32); - __ andr(state2, state2, rmask32); + __ andr(state2, state2, t0); Label md5_loop; __ BIND(md5_loop); - reg_cache.gen_loads(buf); - __ mv(a, state0); __ mv(b, state1); __ mv(c, state2); __ mv(d, state3); // Round 1 - md5_FF(reg_cache, a, b, c, d, 0, S11, 0xd76aa478, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, d, a, b, c, 1, S12, 0xe8c7b756, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, c, d, a, b, 2, S13, 0x242070db, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, b, c, d, a, 3, S14, 0xc1bdceee, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, a, b, c, d, 4, S11, 0xf57c0faf, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, d, a, b, c, 5, S12, 0x4787c62a, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, c, d, a, b, 6, S13, 0xa8304613, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, b, c, d, a, 7, S14, 0xfd469501, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, a, b, c, d, 8, S11, 0x698098d8, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, d, a, b, c, 9, S12, 0x8b44f7af, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, c, d, a, b, 10, S13, 0xffff5bb1, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, b, c, d, a, 11, S14, 0x895cd7be, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, a, b, c, d, 12, S11, 0x6b901122, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, d, a, b, c, 13, S12, 0xfd987193, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, c, d, a, b, 14, S13, 0xa679438e, rtmp1, rtmp2, rmask32); - md5_FF(reg_cache, b, c, d, a, 15, S14, 0x49b40821, rtmp1, rtmp2, rmask32); + reg_cache.gen_load(0, buf); + md5_FF(reg_cache, a, b, c, d, 0, S11, 0xd76aa478, rtmp1, rtmp2); + md5_FF(reg_cache, d, a, b, c, 1, S12, 0xe8c7b756, rtmp1, rtmp2); + reg_cache.gen_load(1, buf); + md5_FF(reg_cache, c, d, a, b, 2, S13, 0x242070db, rtmp1, rtmp2); + md5_FF(reg_cache, b, c, d, a, 3, S14, 0xc1bdceee, rtmp1, rtmp2); + reg_cache.gen_load(2, buf); + md5_FF(reg_cache, a, b, c, d, 4, S11, 0xf57c0faf, rtmp1, rtmp2); + md5_FF(reg_cache, d, a, b, c, 5, S12, 0x4787c62a, rtmp1, rtmp2); + reg_cache.gen_load(3, buf); + md5_FF(reg_cache, c, d, a, b, 6, S13, 0xa8304613, rtmp1, rtmp2); + md5_FF(reg_cache, b, c, d, a, 7, S14, 0xfd469501, rtmp1, rtmp2); + reg_cache.gen_load(4, buf); + md5_FF(reg_cache, a, b, c, d, 8, S11, 0x698098d8, rtmp1, rtmp2); + md5_FF(reg_cache, d, a, b, c, 9, S12, 0x8b44f7af, rtmp1, rtmp2); + reg_cache.gen_load(5, buf); + md5_FF(reg_cache, c, d, a, b, 10, S13, 0xffff5bb1, rtmp1, rtmp2); + md5_FF(reg_cache, b, c, d, a, 11, S14, 0x895cd7be, rtmp1, rtmp2); + reg_cache.gen_load(6, buf); + md5_FF(reg_cache, a, b, c, d, 12, S11, 0x6b901122, rtmp1, rtmp2); + md5_FF(reg_cache, d, a, b, c, 13, S12, 0xfd987193, rtmp1, rtmp2); + reg_cache.gen_load(7, buf); + md5_FF(reg_cache, c, d, a, b, 14, S13, 0xa679438e, rtmp1, rtmp2); + md5_FF(reg_cache, b, c, d, a, 15, S14, 0x49b40821, rtmp1, rtmp2); // Round 2 - md5_GG(reg_cache, a, b, c, d, 1, S21, 0xf61e2562, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, d, a, b, c, 6, S22, 0xc040b340, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, c, d, a, b, 11, S23, 0x265e5a51, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, b, c, d, a, 0, S24, 0xe9b6c7aa, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, a, b, c, d, 5, S21, 0xd62f105d, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, d, a, b, c, 10, S22, 0x02441453, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, c, d, a, b, 15, S23, 0xd8a1e681, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, b, c, d, a, 4, S24, 0xe7d3fbc8, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, a, b, c, d, 9, S21, 0x21e1cde6, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, d, a, b, c, 14, S22, 0xc33707d6, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, c, d, a, b, 3, S23, 0xf4d50d87, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, b, c, d, a, 8, S24, 0x455a14ed, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, a, b, c, d, 13, S21, 0xa9e3e905, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, d, a, b, c, 2, S22, 0xfcefa3f8, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, c, d, a, b, 7, S23, 0x676f02d9, rtmp1, rtmp2, rmask32); - md5_GG(reg_cache, b, c, d, a, 12, S24, 0x8d2a4c8a, rtmp1, rtmp2, rmask32); + md5_GG(reg_cache, a, b, c, d, 1, S21, 0xf61e2562, rtmp1, rtmp2); + md5_GG(reg_cache, d, a, b, c, 6, S22, 0xc040b340, rtmp1, rtmp2); + md5_GG(reg_cache, c, d, a, b, 11, S23, 0x265e5a51, rtmp1, rtmp2); + md5_GG(reg_cache, b, c, d, a, 0, S24, 0xe9b6c7aa, rtmp1, rtmp2); + md5_GG(reg_cache, a, b, c, d, 5, S21, 0xd62f105d, rtmp1, rtmp2); + md5_GG(reg_cache, d, a, b, c, 10, S22, 0x02441453, rtmp1, rtmp2); + md5_GG(reg_cache, c, d, a, b, 15, S23, 0xd8a1e681, rtmp1, rtmp2); + md5_GG(reg_cache, b, c, d, a, 4, S24, 0xe7d3fbc8, rtmp1, rtmp2); + md5_GG(reg_cache, a, b, c, d, 9, S21, 0x21e1cde6, rtmp1, rtmp2); + md5_GG(reg_cache, d, a, b, c, 14, S22, 0xc33707d6, rtmp1, rtmp2); + md5_GG(reg_cache, c, d, a, b, 3, S23, 0xf4d50d87, rtmp1, rtmp2); + md5_GG(reg_cache, b, c, d, a, 8, S24, 0x455a14ed, rtmp1, rtmp2); + md5_GG(reg_cache, a, b, c, d, 13, S21, 0xa9e3e905, rtmp1, rtmp2); + md5_GG(reg_cache, d, a, b, c, 2, S22, 0xfcefa3f8, rtmp1, rtmp2); + md5_GG(reg_cache, c, d, a, b, 7, S23, 0x676f02d9, rtmp1, rtmp2); + md5_GG(reg_cache, b, c, d, a, 12, S24, 0x8d2a4c8a, rtmp1, rtmp2); // Round 3 - md5_HH(reg_cache, a, b, c, d, 5, S31, 0xfffa3942, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, d, a, b, c, 8, S32, 0x8771f681, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, c, d, a, b, 11, S33, 0x6d9d6122, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, b, c, d, a, 14, S34, 0xfde5380c, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, a, b, c, d, 1, S31, 0xa4beea44, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, d, a, b, c, 4, S32, 0x4bdecfa9, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, c, d, a, b, 7, S33, 0xf6bb4b60, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, b, c, d, a, 10, S34, 0xbebfbc70, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, a, b, c, d, 13, S31, 0x289b7ec6, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, d, a, b, c, 0, S32, 0xeaa127fa, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, c, d, a, b, 3, S33, 0xd4ef3085, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, b, c, d, a, 6, S34, 0x04881d05, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, a, b, c, d, 9, S31, 0xd9d4d039, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, d, a, b, c, 12, S32, 0xe6db99e5, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, c, d, a, b, 15, S33, 0x1fa27cf8, rtmp1, rtmp2, rmask32); - md5_HH(reg_cache, b, c, d, a, 2, S34, 0xc4ac5665, rtmp1, rtmp2, rmask32); + md5_HH(reg_cache, a, b, c, d, 5, S31, 0xfffa3942, rtmp1, rtmp2); + md5_HH(reg_cache, d, a, b, c, 8, S32, 0x8771f681, rtmp1, rtmp2); + md5_HH(reg_cache, c, d, a, b, 11, S33, 0x6d9d6122, rtmp1, rtmp2); + md5_HH(reg_cache, b, c, d, a, 14, S34, 0xfde5380c, rtmp1, rtmp2); + md5_HH(reg_cache, a, b, c, d, 1, S31, 0xa4beea44, rtmp1, rtmp2); + md5_HH(reg_cache, d, a, b, c, 4, S32, 0x4bdecfa9, rtmp1, rtmp2); + md5_HH(reg_cache, c, d, a, b, 7, S33, 0xf6bb4b60, rtmp1, rtmp2); + md5_HH(reg_cache, b, c, d, a, 10, S34, 0xbebfbc70, rtmp1, rtmp2); + md5_HH(reg_cache, a, b, c, d, 13, S31, 0x289b7ec6, rtmp1, rtmp2); + md5_HH(reg_cache, d, a, b, c, 0, S32, 0xeaa127fa, rtmp1, rtmp2); + md5_HH(reg_cache, c, d, a, b, 3, S33, 0xd4ef3085, rtmp1, rtmp2); + md5_HH(reg_cache, b, c, d, a, 6, S34, 0x04881d05, rtmp1, rtmp2); + md5_HH(reg_cache, a, b, c, d, 9, S31, 0xd9d4d039, rtmp1, rtmp2); + md5_HH(reg_cache, d, a, b, c, 12, S32, 0xe6db99e5, rtmp1, rtmp2); + md5_HH(reg_cache, c, d, a, b, 15, S33, 0x1fa27cf8, rtmp1, rtmp2); + md5_HH(reg_cache, b, c, d, a, 2, S34, 0xc4ac5665, rtmp1, rtmp2); // Round 4 - md5_II(reg_cache, a, b, c, d, 0, S41, 0xf4292244, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, d, a, b, c, 7, S42, 0x432aff97, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, c, d, a, b, 14, S43, 0xab9423a7, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, b, c, d, a, 5, S44, 0xfc93a039, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, a, b, c, d, 12, S41, 0x655b59c3, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, d, a, b, c, 3, S42, 0x8f0ccc92, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, c, d, a, b, 10, S43, 0xffeff47d, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, b, c, d, a, 1, S44, 0x85845dd1, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, a, b, c, d, 8, S41, 0x6fa87e4f, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, d, a, b, c, 15, S42, 0xfe2ce6e0, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, c, d, a, b, 6, S43, 0xa3014314, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, b, c, d, a, 13, S44, 0x4e0811a1, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, a, b, c, d, 4, S41, 0xf7537e82, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, d, a, b, c, 11, S42, 0xbd3af235, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, c, d, a, b, 2, S43, 0x2ad7d2bb, rtmp1, rtmp2, rmask32); - md5_II(reg_cache, b, c, d, a, 9, S44, 0xeb86d391, rtmp1, rtmp2, rmask32); + md5_II(reg_cache, a, b, c, d, 0, S41, 0xf4292244, rtmp1, rtmp2); + md5_II(reg_cache, d, a, b, c, 7, S42, 0x432aff97, rtmp1, rtmp2); + md5_II(reg_cache, c, d, a, b, 14, S43, 0xab9423a7, rtmp1, rtmp2); + md5_II(reg_cache, b, c, d, a, 5, S44, 0xfc93a039, rtmp1, rtmp2); + md5_II(reg_cache, a, b, c, d, 12, S41, 0x655b59c3, rtmp1, rtmp2); + md5_II(reg_cache, d, a, b, c, 3, S42, 0x8f0ccc92, rtmp1, rtmp2); + md5_II(reg_cache, c, d, a, b, 10, S43, 0xffeff47d, rtmp1, rtmp2); + md5_II(reg_cache, b, c, d, a, 1, S44, 0x85845dd1, rtmp1, rtmp2); + md5_II(reg_cache, a, b, c, d, 8, S41, 0x6fa87e4f, rtmp1, rtmp2); + md5_II(reg_cache, d, a, b, c, 15, S42, 0xfe2ce6e0, rtmp1, rtmp2); + md5_II(reg_cache, c, d, a, b, 6, S43, 0xa3014314, rtmp1, rtmp2); + md5_II(reg_cache, b, c, d, a, 13, S44, 0x4e0811a1, rtmp1, rtmp2); + md5_II(reg_cache, a, b, c, d, 4, S41, 0xf7537e82, rtmp1, rtmp2); + md5_II(reg_cache, d, a, b, c, 11, S42, 0xbd3af235, rtmp1, rtmp2); + md5_II(reg_cache, c, d, a, b, 2, S43, 0x2ad7d2bb, rtmp1, rtmp2); + md5_II(reg_cache, b, c, d, a, 9, S44, 0xeb86d391, rtmp1, rtmp2); __ addw(state0, state0, a); __ addw(state1, state1, b); @@ -4263,11 +4267,12 @@ class StubGenerator: public StubCodeGenerator { // to minimize the number of memory operations: // write back the 4 state 4-byte values in pairs, with a single sd - __ andr(state0, state0, rmask32); + __ mv(t0, mask32); + __ andr(state0, state0, t0); __ slli(state1, state1, 32); __ orr(state0, state0, state1); __ sd(state0, Address(state)); - __ andr(state2, state2, rmask32); + __ andr(state2, state2, t0); __ slli(state3, state3, 32); __ orr(state2, state2, state3); __ sd(state2, Address(state, 8)); diff --git a/src/hotspot/cpu/s390/frame_s390.cpp b/src/hotspot/cpu/s390/frame_s390.cpp index ac24e43f00ce4..dbaa243eb1cac 100644 --- a/src/hotspot/cpu/s390/frame_s390.cpp +++ b/src/hotspot/cpu/s390/frame_s390.cpp @@ -672,7 +672,6 @@ intptr_t *frame::initial_deoptimization_info() { return fp(); } -// Pointer beyond the "oldest/deepest" BasicObjectLock on stack. BasicObjectLock* frame::interpreter_frame_monitor_end() const { return interpreter_frame_monitors(); } diff --git a/src/hotspot/cpu/zero/frame_zero.cpp b/src/hotspot/cpu/zero/frame_zero.cpp index 923d3082b25e7..5ddd23a9d59ef 100644 --- a/src/hotspot/cpu/zero/frame_zero.cpp +++ b/src/hotspot/cpu/zero/frame_zero.cpp @@ -82,7 +82,6 @@ BasicObjectLock* frame::interpreter_frame_monitor_begin() const { return get_interpreterState()->monitor_base(); } -// Pointer beyond the "oldest/deepest" BasicObjectLock on stack. BasicObjectLock* frame::interpreter_frame_monitor_end() const { return (BasicObjectLock*) get_interpreterState()->stack_base(); } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 0469af4b25040..d41fd381e2365 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -2760,7 +2760,7 @@ void G1CMTask::do_marking_step(double time_target_ms, // Separated the asserts so that we know which one fires. assert(_cm->out_of_regions(), "only way to reach here"); assert(_task_queue->size() == 0, "only way to reach here"); - double termination_start_time_ms = os::elapsedVTime() * 1000.0; + double termination_start_time_ms = os::elapsedTime() * 1000.0; // The G1CMTask class also extends the TerminatorTerminator class, // hence its should_exit_termination() method will also decide diff --git a/src/hotspot/share/gc/parallel/mutableSpace.cpp b/src/hotspot/share/gc/parallel/mutableSpace.cpp index c6462f8c9d718..73329aa6d33cb 100644 --- a/src/hotspot/share/gc/parallel/mutableSpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableSpace.cpp @@ -235,8 +235,19 @@ void MutableSpace::oop_iterate(OopIterateClosure* cl) { void MutableSpace::object_iterate(ObjectClosure* cl) { HeapWord* p = bottom(); while (p < top()) { - cl->do_object(cast_to_oop(p)); - p += cast_to_oop(p)->size(); + oop obj = cast_to_oop(p); + // When promotion-failure occurs during Young GC, eden/from space is not cleared, + // so we can encounter objects with "forwarded" markword. + // They are essentially dead, so skipping them + if (!obj->is_forwarded()) { + cl->do_object(obj); + } +#ifdef ASSERT + else { + assert(obj->forwardee() != obj, "must not be self-forwarded"); + } +#endif + p += obj->size(); } } diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index f5a3e5b4d4d14..47db09d6922c7 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -589,7 +589,9 @@ jboolean JVMCIEnv::transfer_pending_exception(JavaThread* THREAD, JVMCIEnv* peer JVMCIEnv::~JVMCIEnv() { if (_init_error_msg != nullptr) { - os::free((void*) _init_error_msg); + // The memory allocated in libjvmci was not allocated with os::malloc + // so must not be freed with os::free. + ALLOW_C_FUNCTION(::free((void*) _init_error_msg)); } if (_init_error != JNI_OK) { return; diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 00803a84af545..4df0fdee17aef 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -1261,50 +1261,24 @@ bool SuperWord::are_adjacent_refs(Node* s1, Node* s2) { //------------------------------isomorphic--------------------------- // Are s1 and s2 similar? bool SuperWord::isomorphic(Node* s1, Node* s2) { - if (s1->Opcode() != s2->Opcode()) return false; - if (s1->req() != s2->req()) return false; - if (!same_velt_type(s1, s2)) return false; - if (s1->is_Bool() && s1->as_Bool()->_test._test != s2->as_Bool()->_test._test) return false; + if (s1->Opcode() != s2->Opcode() || + s1->req() != s2->req() || + !same_velt_type(s1, s2) || + (s1->is_Bool() && s1->as_Bool()->_test._test != s2->as_Bool()->_test._test)) { + return false; + } + Node* s1_ctrl = s1->in(0); Node* s2_ctrl = s2->in(0); // If the control nodes are equivalent, no further checks are required to test for isomorphism. if (s1_ctrl == s2_ctrl) { return true; } else { - bool s1_ctrl_inv = ((s1_ctrl == nullptr) ? true : lpt()->is_invariant(s1_ctrl)); - bool s2_ctrl_inv = ((s2_ctrl == nullptr) ? true : lpt()->is_invariant(s2_ctrl)); // If the control nodes are not invariant for the loop, fail isomorphism test. - if (!s1_ctrl_inv || !s2_ctrl_inv) { - return false; - } - if(s1_ctrl != nullptr && s2_ctrl != nullptr) { - if (s1_ctrl->is_Proj()) { - s1_ctrl = s1_ctrl->in(0); - assert(lpt()->is_invariant(s1_ctrl), "must be invariant"); - } - if (s2_ctrl->is_Proj()) { - s2_ctrl = s2_ctrl->in(0); - assert(lpt()->is_invariant(s2_ctrl), "must be invariant"); - } - if (!s1_ctrl->is_RangeCheck() || !s2_ctrl->is_RangeCheck()) { - return false; - } - } - // Control nodes are invariant. However, we have no way of checking whether they resolve - // in an equivalent manner. But, we know that invariant range checks are guaranteed to - // throw before the loop (if they would have thrown). Thus, the loop would not have been reached. - // Therefore, if the control nodes for both are range checks, we accept them to be isomorphic. - for (DUIterator_Fast imax, i = s1->fast_outs(imax); i < imax; i++) { - Node* t1 = s1->fast_out(i); - for (DUIterator_Fast jmax, j = s2->fast_outs(jmax); j < jmax; j++) { - Node* t2 = s2->fast_out(j); - if (VectorNode::is_muladds2i(t1) && VectorNode::is_muladds2i(t2)) { - return true; - } - } - } + const bool s1_ctrl_inv = (s1_ctrl == nullptr) || lpt()->is_invariant(s1_ctrl); + const bool s2_ctrl_inv = (s2_ctrl == nullptr) || lpt()->is_invariant(s2_ctrl); + return s1_ctrl_inv && s2_ctrl_inv; } - return false; } //------------------------------independent--------------------------- diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 4ae156a773ea3..17dfaee8a7629 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1978,11 +1978,11 @@ const int ObjectAlignmentInBytes = 8; "Mark all threads after a safepoint, and clear on a modify " \ "fence. Add cleanliness checks.") \ \ - product(int, LockingMode, LM_LIGHTWEIGHT, \ + product(int, LockingMode, LM_LEGACY, \ "Select locking mode: " \ "0: monitors only (LM_MONITOR), " \ - "1: monitors & legacy stack-locking (LM_LEGACY), " \ - "2: monitors & new lightweight locking (LM_LIGHTWEIGHT, default)") \ + "1: monitors & legacy stack-locking (LM_LEGACY, default), " \ + "2: monitors & new lightweight locking (LM_LIGHTWEIGHT)") \ range(0, 2) \ \ product(uint, TrimNativeHeapInterval, 0, EXPERIMENTAL, \ diff --git a/src/java.base/share/classes/java/math/BigDecimal.java b/src/java.base/share/classes/java/math/BigDecimal.java index dd34ad245716e..207ff9bdf544f 100644 --- a/src/java.base/share/classes/java/math/BigDecimal.java +++ b/src/java.base/share/classes/java/math/BigDecimal.java @@ -3503,21 +3503,19 @@ public String toPlainString() { return "0"; } int trailingZeros = checkScaleNonZero((-(long)scale)); - StringBuilder buf; - if(intCompact!=INFLATED) { - buf = new StringBuilder(20+trailingZeros); - buf.append(intCompact); - } else { - String str = intVal.toString(); - buf = new StringBuilder(str.length()+trailingZeros); - buf.append(str); - } - for (int i = 0; i < trailingZeros; i++) { - buf.append('0'); + String str = intCompact != INFLATED + ? Long.toString(intCompact) + : intVal.toString(); + int len = str.length() + trailingZeros; + if (len < 0) { + throw new OutOfMemoryError("too large to fit in a String"); } + StringBuilder buf = new StringBuilder(len); + buf.append(str); + buf.repeat('0', trailingZeros); return buf.toString(); } - String str ; + String str; if(intCompact!=INFLATED) { str = Long.toString(Math.abs(intCompact)); } else { @@ -3527,11 +3525,11 @@ public String toPlainString() { } /* Returns a digit.digit string */ - private String getValueString(int signum, String intString, int scale) { + private static String getValueString(int signum, String intString, int scale) { /* Insert decimal point */ StringBuilder buf; int insertionPoint = intString.length() - scale; - if (insertionPoint == 0) { /* Point goes right before intVal */ + if (insertionPoint == 0) { /* Point goes just before intVal */ return (signum<0 ? "-0." : "0.") + intString; } else if (insertionPoint > 0) { /* Point goes inside intVal */ buf = new StringBuilder(intString); @@ -3539,11 +3537,13 @@ private String getValueString(int signum, String intString, int scale) { if (signum < 0) buf.insert(0, '-'); } else { /* We must insert zeros between point and intVal */ - buf = new StringBuilder(3-insertionPoint + intString.length()); - buf.append(signum<0 ? "-0." : "0."); - for (int i=0; i<-insertionPoint; i++) { - buf.append('0'); + int len = (signum < 0 ? 3 : 2) + scale; + if (len < 0) { + throw new OutOfMemoryError("too large to fit in a String"); } + buf = new StringBuilder(len); + buf.append(signum<0 ? "-0." : "0."); + buf.repeat('0', -insertionPoint); // insertionPoint != MIN_VALUE buf.append(intString); } return buf.toString(); diff --git a/src/java.base/share/classes/java/time/Year.java b/src/java.base/share/classes/java/time/Year.java index df4707e8b32ff..cdcaa390320e3 100644 --- a/src/java.base/share/classes/java/time/Year.java +++ b/src/java.base/share/classes/java/time/Year.java @@ -315,7 +315,10 @@ public static Year parse(CharSequence text, DateTimeFormatter formatter) { * @return true if the year is leap, false otherwise */ public static boolean isLeap(long year) { - return ((year & 3) == 0) && ((year % 100) != 0 || (year % 400) == 0); + // A year that is a multiple of 100, 200 and 300 is not divisible by 16, but 400 is. + // So for a year that's divisible by 4, checking that it's also divisible by 16 + // is sufficient to determine it must be a leap year. + return (year & 15) == 0 ? (year & 3) == 0 : (year & 3) == 0 && year % 100 != 0; } //----------------------------------------------------------------------- diff --git a/src/java.base/share/classes/java/time/chrono/IsoChronology.java b/src/java.base/share/classes/java/time/chrono/IsoChronology.java index caeb980056b30..d2590ad315850 100644 --- a/src/java.base/share/classes/java/time/chrono/IsoChronology.java +++ b/src/java.base/share/classes/java/time/chrono/IsoChronology.java @@ -475,7 +475,7 @@ public LocalDate dateNow(Clock clock) { */ @Override public boolean isLeapYear(long prolepticYear) { - return ((prolepticYear & 3) == 0) && ((prolepticYear % 100) != 0 || (prolepticYear % 400) == 0); + return Year.isLeap(prolepticYear); } @Override diff --git a/src/java.base/share/classes/java/util/GregorianCalendar.java b/src/java.base/share/classes/java/util/GregorianCalendar.java index d6e559fabfc04..c9f25edbab778 100644 --- a/src/java.base/share/classes/java/util/GregorianCalendar.java +++ b/src/java.base/share/classes/java/util/GregorianCalendar.java @@ -826,7 +826,10 @@ public boolean isLeapYear(int year) { } if (year > gregorianCutoverYear) { - return (year%100 != 0) || (year%400 == 0); // Gregorian + // A multiple of 100, 200 and 300 is not divisible by 16, but 400 is. + // So for a year that's divisible by 4, checking that it's also divisible by 16 + // is sufficient to determine it must be a leap year. + return (year & 15) == 0 || (year % 100 != 0); // Gregorian } if (year < gregorianCutoverYearJulian) { return true; // Julian @@ -840,7 +843,7 @@ public boolean isLeapYear(int year) { } else { gregorian = year == gregorianCutoverYear; } - return gregorian ? (year%100 != 0) || (year%400 == 0) : true; + return !gregorian || (year & 15) == 0 || (year % 100 != 0); } /** diff --git a/src/java.base/share/classes/sun/util/calendar/CalendarUtils.java b/src/java.base/share/classes/sun/util/calendar/CalendarUtils.java index 60c2decc48b47..4cbb76455a9cc 100644 --- a/src/java.base/share/classes/sun/util/calendar/CalendarUtils.java +++ b/src/java.base/share/classes/sun/util/calendar/CalendarUtils.java @@ -40,8 +40,12 @@ private CalendarUtils() {} * @see CalendarDate#isLeapYear */ public static boolean isGregorianLeapYear(int gregorianYear) { - return (((gregorianYear % 4) == 0) && (((gregorianYear % 100) != 0) - || ((gregorianYear % 400) == 0))); + // A year that is a multiple of 100, 200 and 300 is not divisible by 16, but 400 is. + // So for a year that's divisible by 4, checking that it's also divisible by 16 + // is sufficient to determine it must be a leap year. + return (gregorianYear & 15) == 0 + ? (gregorianYear & 3) == 0 + : (gregorianYear & 3) == 0 && gregorianYear % 100 != 0; } /** diff --git a/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java b/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java index 17c0270633687..6abc5b6eec59c 100644 --- a/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java +++ b/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java @@ -929,7 +929,7 @@ long getTransitionEpochSecond(int year) { } static final boolean isLeapYear(int year) { - return ((year & 3) == 0) && ((year % 100) != 0 || (year % 400) == 0); + return CalendarUtils.isGregorianLeapYear(year); } static final int lengthOfMonth(int year, int month) { diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m index b314200e029ac..3daa90d7934a2 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m @@ -23,7 +23,6 @@ * questions. */ -#include #import "CMenuItem.h" #import "CMenu.h" #import "AWTEvent.h" diff --git a/src/java.desktop/macosx/native/libosxui/ScreenMenu.h b/src/java.desktop/macosx/native/libosxui/ScreenMenu.h index 21402d68315e7..97d6d5e6d7f03 100644 --- a/src/java.desktop/macosx/native/libosxui/ScreenMenu.h +++ b/src/java.desktop/macosx/native/libosxui/ScreenMenu.h @@ -24,4 +24,3 @@ */ #import -#import diff --git a/src/java.desktop/share/classes/javax/swing/text/rtf/RTFParser.java b/src/java.desktop/share/classes/javax/swing/text/rtf/RTFParser.java index 259b63ed8eebc..05f45cc6bb0dc 100644 --- a/src/java.desktop/share/classes/javax/swing/text/rtf/RTFParser.java +++ b/src/java.desktop/share/classes/javax/swing/text/rtf/RTFParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,10 @@ import java.io.*; import java.lang.*; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CoderResult; /** * RTFParser is a subclass of AbstractFilter which understands basic RTF syntax @@ -69,6 +73,11 @@ abstract class RTFParser extends AbstractFilter private final int S_inblob = 6; // in a \bin blob + // For fcharset control word + protected CharsetDecoder decoder = null; + private byte[] ba = new byte[2]; + protected ByteBuffer decoderBB = ByteBuffer.wrap(ba); + /** Implemented by subclasses to interpret a parameter-less RTF keyword. * The keyword is passed without the leading '/' or any delimiting * whitespace. */ @@ -100,6 +109,9 @@ public void handleText(char ch) rtfSpecialsTable['\\'] = true; } + // Defined for replacement character + static final char REPLACEMENT_CHAR = '\uFFFD'; + public RTFParser() { currentCharacters = new StringBuffer(); @@ -109,6 +121,9 @@ public RTFParser() //warnings = System.out; specialsTable = rtfSpecialsTable; + // Initialize byte buffer for CharsetDecoder + decoderBB.clear(); + decoderBB.limit(1); } // TODO: Handle wrapup at end of file correctly. @@ -182,6 +197,9 @@ public void write(char ch) } state = S_backslashed; } else { + // SBCS: ASCII character + // DBCS: Non lead byte + ch = decode(ch); currentCharacters.append(ch); } break; @@ -301,7 +319,9 @@ public void write(char ch) if (Character.digit(ch, 16) != -1) { pendingCharacter = pendingCharacter * 16 + Character.digit(ch, 16); - ch = translationTable[pendingCharacter]; + // Use translationTable if decoder is not defined + ch = decoder == null ? translationTable[pendingCharacter] + : decode((char)pendingCharacter); if (ch != 0) handleText(ch); } @@ -360,4 +380,37 @@ public void close() super.close(); } + // For fcharset control word + private char[] ca = new char[1]; + private CharBuffer decoderCB = CharBuffer.wrap(ca); + + private char decode(char ch) { + if (decoder == null) return ch; + decoderBB.put((byte) ch); + decoderBB.rewind(); + decoderCB.clear(); + CoderResult cr = decoder.decode(decoderBB, decoderCB, false); + if (cr.isUnderflow()) { + if (decoderCB.position() == 1) { + // Converted to Unicode (including replacement character) + decoder.reset(); + decoderBB.clear(); + decoderBB.limit(1); + return ca[0]; + } else { + // Detected lead byte + decoder.reset(); + decoderBB.limit(2); + decoderBB.position(1); + return 0; // Skip write operation if return value is 0 + } + } else { + // Fallback, should not be called + decoder.reset(); + decoderBB.clear(); + decoderBB.limit(1); + return REPLACEMENT_CHAR; + } + } + } diff --git a/src/java.desktop/share/classes/javax/swing/text/rtf/RTFReader.java b/src/java.desktop/share/classes/javax/swing/text/rtf/RTFReader.java index 9128a71ed01e9..60cfd585c732e 100644 --- a/src/java.desktop/share/classes/javax/swing/text/rtf/RTFReader.java +++ b/src/java.desktop/share/classes/javax/swing/text/rtf/RTFReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,11 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.StreamTokenizer; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CodingErrorAction; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Dictionary; @@ -87,6 +92,10 @@ class RTFReader extends RTFParser /** This Dictionary maps Integer font numbers to String font names. */ Dictionary fontTable; + /** This Dictionary maps Integer font numbers to Charset font charset. */ + Dictionary fcharsetTable; + /** This Dictionary maps String font charset to String code page. */ + static Dictionary fcharsetToCP = null; /** This array maps color indices to Color objects. */ Color[] colorTable; /** This Map maps character style numbers to Style objects. */ @@ -133,6 +142,7 @@ class RTFReader extends RTFParser textKeywords.put("emspace", "\u2003"); textKeywords.put("endash", "\u2013"); textKeywords.put("enspace", "\u2002"); + textKeywords.put("line", "\n"); textKeywords.put("ldblquote", "\u201C"); textKeywords.put("lquote", "\u2018"); textKeywords.put("ltrmark", "\u200E"); @@ -159,7 +169,50 @@ class RTFReader extends RTFParser defineCharacterSet("ansicpg", latin1TranslationTable); } -/* TODO: per-font font encodings ( \fcharset control word ) ? */ + /** + * Windows font charset + */ + private static final int ANSI_CHARSET = 0; + private static final int DEFAULT_CHARSET = 1; + private static final int SYMBOL_CHARSET = 2; + private static final int MAC_CHARSET = 77; + private static final int SHIFTJIS_CHARSET = 128; + private static final int HANGUL_CHARSET = 129; + private static final int JOHAB_CHARSET = 130; + private static final int GB2312_CHARSET = 134; + private static final int CHINESEBIG5_CHARSET = 136; + private static final int GREEK_CHARSET = 161; + private static final int TURKISH_CHARSET = 162; + private static final int VIETNAMESE_CHARSET = 163; + private static final int HEBREW_CHARSET = 177; + private static final int ARABIC_CHARSET = 178; + private static final int BALTIC_CHARSET = 186; + private static final int RUSSIAN_CHARSET = 204; + private static final int THAI_CHARSET = 222; + private static final int EASTEUROPE_CHARSET = 238; + private static final int OEM_CHARSET = 255; + + static { + fcharsetToCP = new Hashtable(); + fcharsetToCP.put("fcharset" + ANSI_CHARSET, "windows-1252"); + fcharsetToCP.put("fcharset" + SHIFTJIS_CHARSET, "ms932"); + fcharsetToCP.put("fcharset" + HANGUL_CHARSET, "ms949"); + fcharsetToCP.put("fcharset" + JOHAB_CHARSET, "ms1361"); + fcharsetToCP.put("fcharset" + GB2312_CHARSET, "ms936"); + fcharsetToCP.put("fcharset" + CHINESEBIG5_CHARSET, "ms950"); + fcharsetToCP.put("fcharset" + GREEK_CHARSET, "windows-1253"); + fcharsetToCP.put("fcharset" + TURKISH_CHARSET, "windows-1254"); + fcharsetToCP.put("fcharset" + VIETNAMESE_CHARSET, "windows-1258"); + fcharsetToCP.put("fcharset" + HEBREW_CHARSET, "windows-1255"); + fcharsetToCP.put("fcharset" + ARABIC_CHARSET, "windows-1256"); + fcharsetToCP.put("fcharset" + BALTIC_CHARSET, "windows-1257"); + fcharsetToCP.put("fcharset" + RUSSIAN_CHARSET, "windows-1251"); + fcharsetToCP.put("fcharset" + THAI_CHARSET, "ms874"); + fcharsetToCP.put("fcharset" + EASTEUROPE_CHARSET, "windows-1250"); + } + + // Defined for replacement character + private static final String REPLACEMENT_CHAR = "\uFFFD"; /** * Creates a new RTFReader instance. Text will be sent to @@ -174,6 +227,7 @@ public RTFReader(StyledDocument destination) target = destination; parserState = new Hashtable(); fontTable = new Hashtable(); + fcharsetTable = new Hashtable(); rtfversion = -1; @@ -762,6 +816,25 @@ public boolean handleKeyword(String keyword, int parameter) nextFontNumber = parameter; return true; } + // For fcharset control word + if (keyword.equals("fcharset")) { + String fcharset = keyword+parameter; + String csName = fcharsetToCP.get(fcharset); + Charset cs; + if (csName != null) { + try { + cs = Charset.forName(csName); + } catch (IllegalArgumentException iae) { + // Fallback, should not be called + cs = ISO_8859_1; + } + } else { + // Fallback, fcharset control word number is not defined + cs = ISO_8859_1; + } + fcharsetTable.put(nextFontNumber, cs); + return true; + } return false; } @@ -1216,6 +1289,25 @@ public boolean handleKeyword(String keyword, int parameter) if (keyword.equals("f")) { parserState.put(keyword, Integer.valueOf(parameter)); + + // Check lead byte is stored or not + if (decoderBB.position() == 1) { + handleText(REPLACEMENT_CHAR); + } + // Reset decoder byte buffer + decoderBB.clear(); + decoderBB.limit(1); + // Check fcharset is used or not + Charset cs = fcharsetTable.get(parameter); + if (cs != null) { + decoder = cs.newDecoder(); + decoder.onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + } else { + // fcharset is not used, use translationTable + decoder = null; + } + return true; } if (keyword.equals("cf")) { @@ -1610,6 +1702,12 @@ public boolean handleKeyword(String keyword) if (keyword.equals("par")) { // warnings.println("Ending paragraph."); + // Check lead byte is stored or not + if (decoderBB.position() == 1) { + handleText(REPLACEMENT_CHAR); + decoderBB.clear(); + decoderBB.limit(1); + } endParagraph(); return true; } diff --git a/test/hotspot/gtest/logging/test_logTagSet.cpp b/test/hotspot/gtest/logging/test_logTagSet.cpp index b6133673c4533..2243762365b55 100644 --- a/test/hotspot/gtest/logging/test_logTagSet.cpp +++ b/test/hotspot/gtest/logging/test_logTagSet.cpp @@ -32,7 +32,7 @@ #include "unittest.hpp" // Test the default level for each tagset -TEST(LogTagSet, defaults) { +TEST_VM(LogTagSet, defaults) { for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) { char buf[256]; ts->label(buf, sizeof(buf)); @@ -45,7 +45,7 @@ TEST(LogTagSet, defaults) { } } -TEST(LogTagSet, has_output) { +TEST_VM(LogTagSet, has_output) { LogTagSet& ts = LogTagSetMapping::tagset(); ts.set_output_level(LogConfiguration::StderrLog, LogLevel::Trace); EXPECT_TRUE(ts.has_output(LogConfiguration::StderrLog)); @@ -54,14 +54,14 @@ TEST(LogTagSet, has_output) { EXPECT_FALSE(ts.has_output(LogConfiguration::StderrLog)); } -TEST(LogTagSet, ntags) { +TEST_VM(LogTagSet, ntags) { const LogTagSet& ts = LogTagSetMapping::tagset(); EXPECT_EQ(1u, ts.ntags()); const LogTagSet& ts2 = LogTagSetMapping::tagset(); EXPECT_EQ(5u, ts2.ntags()); } -TEST(LogTagSet, is_level) { +TEST_VM(LogTagSet, is_level) { LogTagSet& ts = LogTagSetMapping::tagset(); // Set info level on stdout and verify that is_level() reports correctly ts.set_output_level(LogConfiguration::StdoutLog, LogLevel::Info); @@ -72,9 +72,10 @@ TEST(LogTagSet, is_level) { EXPECT_FALSE(ts.is_level(LogLevel::Trace)); ts.set_output_level(LogConfiguration::StdoutLog, LogLevel::Default); EXPECT_TRUE(ts.is_level(LogLevel::Default)); + ts.set_output_level(LogConfiguration::StdoutLog, LogLevel::Off); } -TEST(LogTagSet, level_for) { +TEST_VM(LogTagSet, level_for) { LogOutput* output = LogConfiguration::StdoutLog; LogTagSet& ts = LogTagSetMapping::tagset(); for (uint i = 0; i < LogLevel::Count; i++) { @@ -83,10 +84,10 @@ TEST(LogTagSet, level_for) { ts.set_output_level(output, level); EXPECT_EQ(level, ts.level_for(output)); } - ts.set_output_level(output, LogLevel::Default); + ts.set_output_level(output, LogLevel::Off); } -TEST(LogTagSet, contains) { +TEST_VM(LogTagSet, contains) { // Verify that contains works as intended for a few predetermined tagsets const LogTagSet& ts = LogTagSetMapping::tagset(); EXPECT_TRUE(ts.contains(PREFIX_LOG_TAG(logging))); @@ -112,7 +113,7 @@ TEST(LogTagSet, contains) { EXPECT_TRUE(ts4.contains(PREFIX_LOG_TAG(heap))); } -TEST(LogTagSet, label) { +TEST_VM(LogTagSet, label) { char buf[256]; const LogTagSet& ts = LogTagSetMapping::tagset(); ASSERT_NE(-1, ts.label(buf, sizeof(buf))); @@ -138,7 +139,7 @@ TEST(LogTagSet, label) { } -TEST(LogTagSet, duplicates) { +TEST_VM(LogTagSet, duplicates) { for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) { char ts_name[512]; ts->label(ts_name, sizeof(ts_name), ","); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 1778c2292df4e..58d17f3a0d41e 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -927,6 +927,22 @@ public class IRNode { beforeMatchingNameRegex(MUL, "Mul(I|L|F|D)"); } + public static final String MUL_ADD_S2I = PREFIX + "MUL_ADD_S2I" + POSTFIX; + static { + beforeMatchingNameRegex(MUL_ADD_S2I, "MulAddS2I"); + } + + public static final String MUL_ADD_VS2VI = VECTOR_PREFIX + "MUL_ADD_VS2VI" + POSTFIX; + static { + vectorNode(MUL_ADD_VS2VI, "MulAddVS2VI", TYPE_INT); + } + + // Can only be used if avx512_vnni is available. + public static final String MUL_ADD_VS2VI_VNNI = PREFIX + "MUL_ADD_VS2VI_VNNI" + POSTFIX; + static { + machOnly(MUL_ADD_VS2VI_VNNI, "vmuladdaddS2I_reg"); + } + public static final String MUL_D = PREFIX + "MUL_D" + POSTFIX; static { beforeMatchingNameRegex(MUL_D, "MulD"); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java index 0069890348238..939267234bd09 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java @@ -98,6 +98,7 @@ public class IREncodingPrinter { "avx512dq", "avx512vl", "avx512f", + "avx512_vnni", // AArch64 "sha3", "asimd", diff --git a/test/hotspot/jtreg/compiler/locks/TestUnlockOSR.java b/test/hotspot/jtreg/compiler/locks/TestUnlockOSR.java new file mode 100644 index 0000000000000..f2133b49658c6 --- /dev/null +++ b/test/hotspot/jtreg/compiler/locks/TestUnlockOSR.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8316746 + * @summary During OSR, locks get transferred from interpreter frame. + * Check that unlocking 2 such locks works in the OSR compiled nmethod. + * Some platforms verify that the unlocking happens in the corrent order. + * + * @run main/othervm -Xbatch TestUnlockOSR + */ + +public class TestUnlockOSR { + static void test_method(Object a, Object b, int limit) { + synchronized(a) { // allocate space for monitors + synchronized(b) { + } + } // free space to test allocation in reused space + synchronized(a) { // reuse the space + synchronized(b) { + for (int i = 0; i < limit; i++) {} + } + } + } + + public static void main(String[] args) { + Object a = new TestUnlockOSR(), + b = new TestUnlockOSR(); + // avoid uncommon trap before last unlocks + for (int i = 0; i < 100; i++) { test_method(a, b, 0); } + // trigger OSR + test_method(a, b, 100000); + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java new file mode 100644 index 0000000000000..78e97f26817f8 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8310886 + * @requires os.arch == "x86_64" | os.arch == "aarch64" + * @summary Test MulAddS2I vectorization. + * @library /test/lib / + * @run driver compiler.loopopts.superword.TestMulAddS2I + */ + +package compiler.loopopts.superword; + +import compiler.lib.ir_framework.*; +import jdk.test.lib.Asserts; +import jdk.test.lib.Platform; + +public class TestMulAddS2I { + static final int RANGE = 1024; + static final int ITER = RANGE/2 - 1; + + static short[] sArr1 = new short[RANGE]; + static short[] sArr2 = new short[RANGE]; + static final int[] GOLDEN; + + static { + for (int i = 0; i < RANGE; i++) { + sArr1[i] = (short)(AbstractInfo.getRandom().nextInt()); + sArr2[i] = (short)(AbstractInfo.getRandom().nextInt()); + } + GOLDEN = test(); + } + + + public static void main(String[] args) { + if (Platform.isX64() || Platform.isX86()) { + TestFramework.runWithFlags("-XX:+UseUnalignedLoadStores"); + TestFramework.runWithFlags("-XX:-UseUnalignedLoadStores"); + } else { + TestFramework.run(); + } + } + + @Run(test = "test") + @Warmup(0) + public static void run() { + compare(test()); + } + + public static void compare(int[] out) { + for (int i = 0; i < ITER; i++) { + Asserts.assertEQ(out[i], GOLDEN[i], "wrong result for out[" + i + "]"); + } + } + + @Test + @IR(applyIfCPUFeature = {"sse2", "true"}, applyIf = {"UseUnalignedLoadStores", "true"}, + counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) + @IR(applyIfCPUFeature = {"sse2", "true"}, applyIf = {"UseUnalignedLoadStores", "false"}, + failOn = {IRNode.MUL_ADD_VS2VI}, // Can only pack LoadS if UseUnalignedLoadStores is true (default if sse4.2) + counts = {IRNode.MUL_ADD_S2I, "> 0"}) + @IR(applyIfCPUFeature = {"asimd", "true"}, applyIf = {"MaxVectorSize", "16"}, // AD file requires vector_length = 16 + counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) + @IR(applyIfCPUFeature = {"avx512_vnni", "true"}, applyIf = {"UseUnalignedLoadStores", "true"}, + counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI_VNNI, "> 0"}) + public static int[] test() { + int[] out = new int[ITER]; + int[] out2 = new int[ITER]; + for (int i = 0; i < ITER; i++) { + out[i] += ((sArr1[2*i] * sArr1[2*i]) + (sArr1[2*i+1] * sArr1[2*i+1])); + out2[i] += out[i]; + } + return out; + } +} diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups index 660c7e2cdca6a..a39dfe8b09d16 100644 --- a/test/jdk/TEST.groups +++ b/test/jdk/TEST.groups @@ -596,7 +596,8 @@ jdk_core_manual_no_input = \ java/util/ArrayList/Bug8146568.java \ java/util/Vector/Bug8148174.java \ com/sun/net/httpserver/simpleserver/CommandLinePortNotSpecifiedTest.java \ - com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePortNotSpecifiedTest.java + com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePortNotSpecifiedTest.java \ + javax/xml/jaxp/datatype/8033980/GregorianCalAndDurSerDataUtil.java jdk_core_manual_no_input_security = \ com/sun/crypto/provider/Cipher/DES/PerformanceTest.java \ @@ -619,7 +620,8 @@ jdk_core_manual_no_input_security = \ sun/security/smartcardio/TestMultiplePresent.java \ sun/security/smartcardio/TestPresent.java \ sun/security/smartcardio/TestTransmit.java \ - sun/security/tools/jarsigner/compatibility/Compatibility.java + sun/security/tools/jarsigner/compatibility/Compatibility.java \ + sun/security/tools/keytool/ListKeyChainStore.java jdk_core_manual_interactive = \ com/sun/jndi/dns/Test6991580.java \ diff --git a/test/jdk/java/math/BigDecimal/ToPlainStringTests.java b/test/jdk/java/math/BigDecimal/ToPlainStringTests.java index 7c7928ca85caa..0a1f617c0e578 100644 --- a/test/jdk/java/math/BigDecimal/ToPlainStringTests.java +++ b/test/jdk/java/math/BigDecimal/ToPlainStringTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4984872 + * @bug 4984872 8318915 * @summary Basic tests of toPlainString method * @run main ToPlainStringTests * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 ToPlainStringTests @@ -67,6 +67,11 @@ public static void main(String argv[]) { {"12345678901234567890", "12345678901234567890"}, {"12345678901234567890e22", "123456789012345678900000000000000000000000"}, {"12345678901234567890e-22", "0.0012345678901234567890"}, + + {"12345e-1", "1234.5"}, + {"12345e-2", "123.45"}, + {"12345e-3", "12.345"}, + {"12345e-4", "1.2345"}, }; int errors = 0; @@ -89,6 +94,38 @@ public static void main(String argv[]) { } } + String[] failingCases = { + "1E-" + (Integer.MAX_VALUE - 0), // MAX_VALUE + 2 chars + "1E-" + (Integer.MAX_VALUE - 1), // MAX_VALUE + 1 chars + + "-1E-" + (Integer.MAX_VALUE - 0), // MAX_VALUE + 3 chars + "-1E-" + (Integer.MAX_VALUE - 1), // MAX_VALUE + 2 chars + "-1E-" + (Integer.MAX_VALUE - 2), // MAX_VALUE + 1 chars + + "123456789E-" + (Integer.MAX_VALUE - 0), // MAX_VALUE + 2 chars + "123456789E-" + (Integer.MAX_VALUE - 1), // MAX_VALUE + 1 chars + + "-123456789E-" + (Integer.MAX_VALUE - 0), // MAX_VALUE + 3 chars + "-123456789E-" + (Integer.MAX_VALUE - 1), // MAX_VALUE + 2 chars + "-123456789E-" + (Integer.MAX_VALUE - 2), // MAX_VALUE + 1 chars + + "1E" + Integer.MAX_VALUE, // MAX_VALUE + 1 chars + "123456789E" + Integer.MAX_VALUE, // MAX_VALUE + 9 chars + + "-1E" + Integer.MAX_VALUE, // MAX_VALUE + 2 chars + "-123456789E" + Integer.MAX_VALUE, // MAX_VALUE + 10 chars + }; + /* We expect pre-emptive OutOfMemoryErrors, nothing else */ + for (String failingCase : failingCases) { + try { + new BigDecimal(failingCase).toPlainString(); + } catch (OutOfMemoryError expected) { + continue; + } catch (Throwable ignored) { + } + ++errors; + } + if(errors > 0) throw new RuntimeException(errors + " errors during run."); } diff --git a/test/jdk/javax/swing/text/rtf/RTFReadFontCharsetTest.java b/test/jdk/javax/swing/text/rtf/RTFReadFontCharsetTest.java new file mode 100644 index 0000000000000..629b37285a3c9 --- /dev/null +++ b/test/jdk/javax/swing/text/rtf/RTFReadFontCharsetTest.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6928542 + * @summary Verify RTFEditorKit.read() with fcharset + */ + +import java.io.ByteArrayInputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.rtf.RTFEditorKit; + +import static java.nio.charset.StandardCharsets.ISO_8859_1; + +public class RTFReadFontCharsetTest { + public static void main(String[] args) throws Exception { + String s = + "{\\rtf1\\fbidis\\ansi\\ansicpg932\\deff0\\nouicomp" + + "at\\deflang1033\\deflangfe1041{\\fonttbl{\\f0\\fni" + + "l\\fcharset0 Segoe UI;}{\\f1\\fnil\\fcharset128 Yu" + + " Gothic UI;}{\\f2\\fswiss\\fprq2\\fcharset129 Malg" + + "un Gothic;}{\\f3\\fnil\\fcharset134 Microsoft YaHe" + + "i;}{\\f4\\fnil\\fcharset136 Microsoft JhengHei;}{\\" + + "f5\\fnil\\fcharset161 Segoe UI;}{\\f6\\fnil\\fcha" + + "rset162 Segoe UI;}{\\f7\\fnil\\fcharset163 Segoe U" + + "I;}{\\f8\\fnil\\fcharset177 Segoe UI;}{\\f9\\fnil\\" + + "fcharset178 Segoe UI;}{\\f10\\fnil\\fcharset186 S" + + "egoe UI;}{\\f11\\fnil\\fcharset204 Segoe UI;}{\\f1" + + "2\\fnil\\fcharset222 Leelawadee UI;}{\\f13\\fnil\\" + + "fcharset0 Leelawadee UI;}{\\f14\\fnil\\fcharset238" + + " Segoe UI;}}\r\n{\\*\\generator Riched20 10.0.1904" + + "1}\\viewkind4\\uc1 \r\n\\pard\\ltrpar\\nowidctlpar" + + "\\sa200\\sl276\\slmult1\\f0\\fs22\\lang1041 Gr\\'f" + + "cezi - Switzerland 0\\line\\f1\\'82\\'b1\\'82\\'f" + + "1\\'82\\'c9\\'82\\'bf\\'82\\'cd - Japanese 128\\li" + + "ne\\f2\\lang17\\'be\\'c8\\'b3\\'e7\\'c7\\'cf\\'bc\\" + + "'bc\\'bf\\'e4\\lang1041 - Korean 129\\line\\kern" + + "ing2\\f3\\lang1033\\'c4\\'e3\\'ba\\'c3 - China 134" + + "\\line\\f4\\'bb\\'4f\\'c6\\'57 - Traditional Chine" + + "se - Taiwan 136\\line\\kerning0\\f5\\lang17\\'e3\\" + + "'e5\\'e9\\'e1 \\'f3\\'ef\\'f5 - Greek\\f0\\lang104" + + "1 161\\line\\f6\\lang17 A\\'f0a\\'e7 - \\f0 Turki" + + "sh (Tree) 162\\line\\f7\\'fe\\f0\\lang1041 \\lang" + + "1033 - \\lang17 Vietnam currency\\lang1041 163\\l" + + "ine\\f8\\rtlch\\lang17\\'f9\\'c8\\'d1\\'ec\\'e5\\'" + + "c9\\'ed\\f0\\ltrch - Hebrew 177\\line\\f9\\rtlch\\" + + "lang1025\\'e3\\'d1\\'cd\\'c8\\'c7\\f0\\ltrch\\lan" + + "g17 - Arabic 178\\line\\kerning2\\f10\\lang1033 A" + + "\\'e8i\\'fb - Lithuanian (Thank you) 186\\kerning0" + + "\\f0\\lang1041\\line\\kerning2\\f11\\lang1049\\'c7" + + "\\'e4\\'f0\\'e0\\'e2\\'f1\\'f2\\'e2\\'f3\\'e9\\'f2" + + "\\'e5\\f0\\lang1033 - Russian 204\\line\\kerning0" + + "\\f12\\lang1054\\'ca\\'c7\\'d1\\'ca\\'b4\\'d5 \\f1" + + "3\\lang1033 - Thailand 222\\line\\kerning2\\f14 cz" + + "e\\'9c\\'e6 - Polish 238\\par\r\n}\r\n\u0000"; + String expected = + "Gr\u00fcezi - Switzerland 0\n" + + "\u3053\u3093\u306b\u3061\u306f - Japanese 128\n" + + "\uc548\ub155\ud558\uc138\uc694 - Korean 129\n" + + "\u4f60\u597d - China 134\n" + + "\u81fa\u7063 - Traditional Chinese - Taiwan 136\n" + + "\u03b3\u03b5\u03b9\u03b1 \u03c3\u03bf\u03c5 - Greek 161\n" + + "A\u011fa\u00e7 - Turkish (Tree) 162\n" + + "\u20ab - Vietnam currency 163\n" + + "\u05e9\u05b8\u05c1\u05dc\u05d5\u05b9\u05dd - Hebrew 177\n" + + "\u0645\u0631\u062d\u0628\u0627 - Arabic 178\n" + + "A\u010di\u016b - Lithuanian (Thank you) 186\n" + + "\u0417\u0434\u0440\u0430\u0432\u0441\u0442" + + "\u0432\u0443\u0439\u0442\u0435 - Russian 204\n" + + "\u0e2a\u0e27\u0e31\u0e2a\u0e14\u0e35 - Thailand 222\n" + + "cze\u015b\u0107 - Polish 238\n" + + "\n"; + ByteArrayInputStream bais = new ByteArrayInputStream( + s.getBytes(ISO_8859_1)); + InputStreamReader isr = new InputStreamReader(bais, ISO_8859_1); + RTFEditorKit kit = new RTFEditorKit(); + Document doc = kit.createDefaultDocument(); + kit.read(isr, doc, 0); + Element elem = doc.getDefaultRootElement(); + int elemStart = elem.getStartOffset(); + int elemEnd = elem.getEndOffset(); + String text = doc.getText(elemStart, elemEnd - elemStart); + if (!expected.equals(text)) { + System.err.println("Read data"); + System.err.println("========="); + dump(text, System.err); + System.err.println("Expected data"); + System.err.println("============="); + dump(expected, System.err); + throw new RuntimeException("Test failed"); + } + } + + private static void dump(String s, PrintStream ps) { + for(char ch : s.toCharArray()) { + if (ch == '\\') + ps.print("\\\\"); + else if (ch >= 0x20 && ch <= 0x7e) + ps.print(ch); + else if (ch == '\n') + ps.println(); + else + ps.printf("\\u%04x", (int)ch); + } + } + +} diff --git a/test/jdk/jdk/lambda/TEST.properties b/test/jdk/jdk/lambda/TEST.properties index eaae109a7fc06..bd37b556c82e6 100644 --- a/test/jdk/jdk/lambda/TEST.properties +++ b/test/jdk/jdk/lambda/TEST.properties @@ -3,4 +3,7 @@ TestNG.dirs = . maxOutputSize = 250000 -modules = jdk.compiler jdk.zipfs +modules = java.base/jdk.internal.classfile \ + java.base/jdk.internal.classfile.constantpool \ + java.base/jdk.internal.classfile.instruction \ + jdk.compiler jdk.zipfs diff --git a/test/jdk/jdk/lambda/separate/AttributeInjector.java b/test/jdk/jdk/lambda/separate/AttributeInjector.java deleted file mode 100644 index 526895211e7bf..0000000000000 --- a/test/jdk/jdk/lambda/separate/AttributeInjector.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2012, 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. - */ - -package separate; - -import java.io.*; - -public class AttributeInjector implements ClassFilePreprocessor { - - private String attributeName; - private byte[] attributeData; - - public AttributeInjector(String attributeName, byte[] attributeData) { - this.attributeName = attributeName; - this.attributeData = attributeData; - } - - public byte[] preprocess(String name, byte[] cf) { - ClassFile classfile = new ClassFile(cf); - - short cpIndex = (short)classfile.constant_pool.size(); - - ClassFile.CpUtf8 entry = new ClassFile.CpUtf8(); - entry.bytes = new byte[attributeName.length()]; - for (int i = 0; i < attributeName.length(); ++i) { - entry.bytes[i] = (byte)attributeName.charAt(i); - } - - classfile.constant_pool.add(entry); - - ClassFile.Attribute attr = new ClassFile.Attribute(); - attr.attribute_name_index = cpIndex; - attr.info = attributeData; - - classfile.attributes.add(attr); - return classfile.toByteArray(); - } - -/* - public static void main(String argv[]) throws Exception { - File input = new File(argv[0]); - byte[] buffer = new byte[(int)input.length()]; - new FileInputStream(input).read(buffer); - - ClassFilePreprocessor cfp = - new AttributeInjector("RequiresBridges", new byte[0]); - byte[] cf = cfp.preprocess(argv[0], buffer); - new FileOutputStream(argv[0] + ".mod").write(cf); - } -*/ -} diff --git a/test/jdk/jdk/lambda/separate/ClassFile.java b/test/jdk/jdk/lambda/separate/ClassFile.java deleted file mode 100644 index d49e478fa2399..0000000000000 --- a/test/jdk/jdk/lambda/separate/ClassFile.java +++ /dev/null @@ -1,452 +0,0 @@ -/* - * Copyright (c) 2012, 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. - */ - -package separate; - -import java.io.*; -import java.util.*; - -class CfInputStream extends ByteArrayInputStream { - private int ct; - public CfInputStream(byte[] input) { - super(input); - } - - byte u1() { return (byte)read(); } - short u2() { - int b0 = read() << 8; - int b1 = read(); - return (short)(b0 | b1); - } - int u4() { - int b0 = read() << 24; - int b1 = read() << 16; - int b2 = read() << 8; - int b3 = read(); - return b0 | b1 | b2 | b3; - } - byte[] array(int count) { - byte[] ret = new byte[count]; - read(ret, 0, count); - return ret; - } -}; - -class CfOutputStream extends ByteArrayOutputStream { - void u1(byte b) { write((int)b); } - void u2(short s) { - write((s >> 8) & 0xff); - write(s & 0xff); - } - void u4(int i) { - write((i >> 24) & 0xff); - write((i >> 16) & 0xff); - write((i >> 8) & 0xff); - write(i & 0xff); - } - void array(byte[] a) { - write(a, 0, a.length); - } - - public byte[] toByteArray() { return super.toByteArray(); } -}; - -// A quick and dirty class file parser and representation -public class ClassFile { - - int magic; - short minor_version; - short major_version; - ArrayList constant_pool; - short access_flags; - short this_class; - short super_class; - ArrayList interfaces; - ArrayList fields; - ArrayList methods; - ArrayList attributes; - - ClassFile(byte[] cf) { - CfInputStream in = new CfInputStream(cf); - - magic = in.u4(); - minor_version = in.u2(); - major_version = in.u2(); - - short cpCount = in.u2(); - constant_pool = new ArrayList<>(); - constant_pool.add(new CpNull()); - for (int i = 1; i < cpCount; ++i) { - constant_pool.add(CpEntry.newCpEntry(in)); - } - - access_flags = in.u2(); - this_class = in.u2(); - super_class = in.u2(); - - short ifaceCount = in.u2(); - interfaces = new ArrayList<>(); - for (int i = 0; i < ifaceCount; ++i) { - interfaces.add(new Interface(in)); - } - - short fieldCount = in.u2(); - fields = new ArrayList<>(); - for (int i = 0; i < fieldCount; ++i) { - fields.add(new Field(in)); - } - - short methodCount = in.u2(); - methods = new ArrayList<>(); - for (int i = 0; i < methodCount; ++i) { - methods.add(new Method(in)); - } - - short attributeCount = in.u2(); - attributes = new ArrayList<>(); - for (int i = 0; i < attributeCount; ++i) { - attributes.add(new Attribute(in)); - } - } - - byte[] toByteArray() { - CfOutputStream out = new CfOutputStream(); - - out.u4(magic); - out.u2(minor_version); - out.u2(major_version); - - out.u2((short)(constant_pool.size())); - for (CpEntry cp : constant_pool) { - cp.write(out); - } - - out.u2(access_flags); - out.u2(this_class); - out.u2(super_class); - - out.u2((short)interfaces.size()); - for (Interface iface : interfaces) { - iface.write(out); - } - - out.u2((short)fields.size()); - for (Field field : fields) { - field.write(out); - } - - out.u2((short)methods.size()); - for (Method method : methods) { - method.write(out); - } - - out.u2((short)attributes.size()); - for (Attribute attribute : attributes) { - attribute.write(out); - } - - return out.toByteArray(); - } - - static abstract class CpEntry { - byte tag; - - CpEntry(byte t) { tag = t; } - void write(CfOutputStream out) { - out.u1(tag); - } - - static CpEntry newCpEntry(CfInputStream in) { - byte tag = in.u1(); - switch (tag) { - case CpUtf8.TAG: return new CpUtf8(in); - case CpInteger.TAG: return new CpInteger(in); - case CpFloat.TAG: return new CpFloat(in); - case CpLong.TAG: return new CpLong(in); - case CpDouble.TAG: return new CpDouble(in); - case CpClass.TAG: return new CpClass(in); - case CpString.TAG: return new CpString(in); - case CpFieldRef.TAG: return new CpFieldRef(in); - case CpMethodRef.TAG: return new CpMethodRef(in); - case CpInterfaceMethodRef.TAG: - return new CpInterfaceMethodRef(in); - case CpNameAndType.TAG: return new CpNameAndType(in); - case CpMethodHandle.TAG: return new CpMethodHandle(in); - case CpMethodType.TAG: return new CpMethodType(in); - case CpInvokeDynamic.TAG: return new CpInvokeDynamic(in); - default: throw new RuntimeException("Bad cp entry tag: " + tag); - } - } - } - - static class CpNull extends CpEntry { - CpNull() { super((byte)0); } - CpNull(CfInputStream in) { super((byte)0); } - void write(CfOutputStream out) {} - } - - static class CpUtf8 extends CpEntry { - static final byte TAG = 1; - byte[] bytes; - - CpUtf8() { super(TAG); } - CpUtf8(CfInputStream in) { - this(); - short length = in.u2(); - bytes = in.array(length); - } - void write(CfOutputStream out) { - super.write(out); - out.u2((short)bytes.length); - out.array(bytes); - } - } - - static class CpU4Constant extends CpEntry { - byte[] bytes; - - CpU4Constant(byte tag) { super(tag); } - CpU4Constant(byte tag, CfInputStream in) { - this(tag); - bytes = in.array(4); - } - void write(CfOutputStream out) { super.write(out); out.array(bytes); } - } - static class CpInteger extends CpU4Constant { - static final byte TAG = 3; - CpInteger() { super(TAG); } - CpInteger(CfInputStream in) { super(TAG, in); } - } - static class CpFloat extends CpU4Constant { - static final byte TAG = 4; - CpFloat() { super(TAG); } - CpFloat(CfInputStream in) { super(TAG, in); } - } - - static class CpU8Constant extends CpEntry { - byte[] bytes; - - CpU8Constant(byte tag) { super(tag); } - CpU8Constant(byte tag, CfInputStream in) { - this(tag); - bytes = in.array(8); - } - void write(CfOutputStream out) { super.write(out); out.array(bytes); } - } - static class CpLong extends CpU8Constant { - static final byte TAG = 5; - CpLong() { super(TAG); } - CpLong(CfInputStream in) { super(TAG, in); } - } - static class CpDouble extends CpU8Constant { - static final byte TAG = 6; - CpDouble() { super(TAG); } - CpDouble(CfInputStream in) { super(TAG, in); } - } - - static class CpClass extends CpEntry { - static final byte TAG = 7; - short name_index; - - CpClass() { super(TAG); } - CpClass(CfInputStream in) { super(TAG); name_index = in.u2(); } - void write(CfOutputStream out) { - super.write(out); - out.u2(name_index); - } - } - - static class CpString extends CpEntry { - static final byte TAG = 8; - short string_index; - - CpString() { super(TAG); } - CpString(CfInputStream in) { super(TAG); string_index = in.u2(); } - void write(CfOutputStream out) { - super.write(out); - out.u2(string_index); - } - } - - static class CpRef extends CpEntry { - short class_index; - short name_and_type_index; - - CpRef(byte tag) { super(tag); } - CpRef(byte tag, CfInputStream in) { - this(tag); - class_index = in.u2(); - name_and_type_index = in.u2(); - } - void write(CfOutputStream out) { - super.write(out); - out.u2(class_index); - out.u2(name_and_type_index); - } - } - static class CpFieldRef extends CpRef { - static final byte TAG = 9; - CpFieldRef() { super(TAG); } - CpFieldRef(CfInputStream in) { super(TAG, in); } - } - static class CpMethodRef extends CpRef { - static final byte TAG = 10; - CpMethodRef() { super(TAG); } - CpMethodRef(CfInputStream in) { super(TAG, in); } - } - static class CpInterfaceMethodRef extends CpRef { - static final byte TAG = 11; - CpInterfaceMethodRef() { super(TAG); } - CpInterfaceMethodRef(CfInputStream in) { super(TAG, in); } - } - - static class CpNameAndType extends CpEntry { - static final byte TAG = 12; - short name_index; - short descriptor_index; - - CpNameAndType() { super(TAG); } - CpNameAndType(CfInputStream in) { - this(); - name_index = in.u2(); - descriptor_index = in.u2(); - } - void write(CfOutputStream out) { - super.write(out); - out.u2(name_index); - out.u2(descriptor_index); - } - } - - static class CpMethodHandle extends CpEntry { - static final byte TAG = 15; - byte reference_kind; - short reference_index; - - CpMethodHandle() { super(TAG); } - CpMethodHandle(CfInputStream in) { - this(); - reference_kind = in.u1(); - reference_index = in.u2(); - } - void write(CfOutputStream out) { - super.write(out); - out.u1(reference_kind); - out.u2(reference_index); - } - } - - static class CpMethodType extends CpEntry { - static final byte TAG = 16; - short descriptor_index; - - CpMethodType() { super(TAG); } - CpMethodType(CfInputStream in) { - this(); - descriptor_index = in.u2(); - } - void write(CfOutputStream out) { - super.write(out); - out.u2(descriptor_index); - } - } - - static class CpInvokeDynamic extends CpEntry { - static final byte TAG = 18; - short bootstrap_index; - short name_and_type_index; - - CpInvokeDynamic() { super(TAG); } - CpInvokeDynamic(CfInputStream in) { - this(); - bootstrap_index = in.u2(); - name_and_type_index = in.u2(); - } - void write(CfOutputStream out) { - super.write(out); - out.u2(bootstrap_index); - out.u2(name_and_type_index); - } - } - - static class Interface { - short index; - - Interface() {} - Interface(CfInputStream in) { index = in.u2(); } - void write(CfOutputStream out) { out.u2(index); } - } - - static class FieldOrMethod { - short access_flags; - short name_index; - short descriptor_index; - ArrayList attributes; - - FieldOrMethod() { attributes = new ArrayList<>(); } - FieldOrMethod(CfInputStream in) { - access_flags = in.u2(); - name_index = in.u2(); - descriptor_index = in.u2(); - - short attrCount = in.u2(); - attributes = new ArrayList<>(); - for (int i = 0; i < attrCount; ++i) { - attributes.add(new Attribute(in)); - } - } - void write(CfOutputStream out) { - out.u2(access_flags); - out.u2(name_index); - out.u2(descriptor_index); - out.u2((short)attributes.size()); - for (Attribute attribute : attributes) { attribute.write(out); } - } - } - - static class Field extends FieldOrMethod { - Field() {} - Field(CfInputStream in) { super(in); } - } - static class Method extends FieldOrMethod { - Method() {} - Method(CfInputStream in) { super(in); } - } - - static class Attribute { - short attribute_name_index; - byte[] info; - - Attribute() { info = new byte[0]; } - Attribute(CfInputStream in) { - attribute_name_index = in.u2(); - int length = in.u4(); - info = in.array(length); - } - void write(CfOutputStream out) { - out.u2(attribute_name_index); - out.u4(info.length); - out.array(info); - } - } -} diff --git a/test/jdk/jdk/lambda/separate/ClassToInterfaceConverter.java b/test/jdk/jdk/lambda/separate/ClassToInterfaceConverter.java index 61598bd035d8b..6b39981bfbde3 100644 --- a/test/jdk/jdk/lambda/separate/ClassToInterfaceConverter.java +++ b/test/jdk/jdk/lambda/separate/ClassToInterfaceConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,75 +23,44 @@ package separate; -import java.io.*; -import java.util.*; +import jdk.internal.classfile.*; +import jdk.internal.classfile.instruction.InvokeInstruction; +import static java.lang.constant.ConstantDescs.INIT_NAME; +import static jdk.internal.classfile.Classfile.*; public class ClassToInterfaceConverter implements ClassFilePreprocessor { - private String whichClass; + private final String whichClass; public ClassToInterfaceConverter(String className) { this.whichClass = className; } - private boolean utf8Matches(ClassFile.CpEntry entry, String v) { - if (!(entry instanceof ClassFile.CpUtf8)) { - return false; - } - ClassFile.CpUtf8 utf8 = (ClassFile.CpUtf8)entry; - if (v.length() != utf8.bytes.length) { - return false; - } - for (int i = 0; i < v.length(); ++i) { - if (v.charAt(i) != utf8.bytes[i]) { - return false; + private byte[] convertToInterface(ClassModel classModel) { + // Convert method tag. Find Methodref which is only invoked by other methods + // in the interface, convert it to InterfaceMethodref. If opcode is invokevirtual, + // convert it to invokeinterface + CodeTransform ct = (b, e) -> { + if (e instanceof InvokeInstruction i && i.owner() == classModel.thisClass()) { + Opcode opcode = i.opcode() == Opcode.INVOKEVIRTUAL ? Opcode.INVOKEINTERFACE : i.opcode(); + b.invokeInstruction(opcode, i.owner().asSymbol(), + i.name().stringValue(), i.typeSymbol(), true); + } else { + b.with(e); } - } - return true; - } + }; - private void convertToInterface(ClassFile cf) { - cf.access_flags = 0x0601; // ACC_INTERFACE | ACC_ABSTRACT | ACC_PUBLIC - ArrayList new_methods = new ArrayList<>(); - // Find method and delete it - for (int i = 0; i < cf.methods.size(); ++i) { - ClassFile.Method method = cf.methods.get(i); - ClassFile.CpEntry name = cf.constant_pool.get(method.name_index); - if (!utf8Matches(name, "")) { - new_methods.add(method); - } - } - cf.methods = new_methods; - // Convert method tag. Find Methodref, which is not "" and only invoked by other methods - // in the interface, convert it to InterfaceMethodref - ArrayList cpool = new ArrayList<>(); - for (int i = 0; i < cf.constant_pool.size(); i++) { - ClassFile.CpEntry ce = cf.constant_pool.get(i); - if (ce instanceof ClassFile.CpMethodRef) { - ClassFile.CpMethodRef me = (ClassFile.CpMethodRef)ce; - ClassFile.CpNameAndType nameType = (ClassFile.CpNameAndType)cf.constant_pool.get(me.name_and_type_index); - ClassFile.CpEntry name = cf.constant_pool.get(nameType.name_index); - if (!utf8Matches(name, "") && cf.this_class == me.class_index) { - ClassFile.CpInterfaceMethodRef newEntry = new ClassFile.CpInterfaceMethodRef(); - newEntry.class_index = me.class_index; - newEntry.name_and_type_index = me.name_and_type_index; - ce = newEntry; - } - } - cpool.add(ce); - } - cf.constant_pool = cpool; + return Classfile.of().transform(classModel, + ClassTransform.dropping(ce -> ce instanceof MethodModel mm && mm.methodName().equalsString(INIT_NAME)) + .andThen(ClassTransform.transformingMethodBodies(ct)) + .andThen(ClassTransform.endHandler(b -> b.withFlags(ACC_INTERFACE | ACC_ABSTRACT | ACC_PUBLIC))) + ); } public byte[] preprocess(String classname, byte[] bytes) { - ClassFile cf = new ClassFile(bytes); - - ClassFile.CpEntry entry = cf.constant_pool.get(cf.this_class); - ClassFile.CpEntry name = cf.constant_pool.get( - ((ClassFile.CpClass)entry).name_index); - if (utf8Matches(name, whichClass)) { - convertToInterface(cf); - return cf.toByteArray(); + ClassModel classModel = Classfile.of().parse(bytes); + if (classModel.thisClass().asInternalName().equals(whichClass)) { + return convertToInterface(classModel); } else { return bytes; // unmodified } diff --git a/test/jdk/jdk/lambda/vm/InterfaceAccessFlagsTest.java b/test/jdk/jdk/lambda/vm/InterfaceAccessFlagsTest.java index d4cf8e0b1180a..a604993a99641 100644 --- a/test/jdk/jdk/lambda/vm/InterfaceAccessFlagsTest.java +++ b/test/jdk/jdk/lambda/vm/InterfaceAccessFlagsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,10 @@ package vm; -import java.io.*; - import org.testng.annotations.Test; -import separate.*; +import separate.ClassToInterfaceConverter; import separate.Compiler; +import separate.TestHarness; import static org.testng.Assert.*; import static separate.SourceModel.*; @@ -71,8 +70,7 @@ public void testMethodCallWithFlag(AccessFlag ... flags) { } } - /* excluded: 8187655 */ - @Test(enabled=false, groups = "vm_prototype") + @Test(groups = "vm_prototype") public void testPrivateMethodCall() { testMethodCallWithFlag(AccessFlag.PRIVATE); } diff --git a/test/lib/jdk/test/lib/process/ProcessTools.java b/test/lib/jdk/test/lib/process/ProcessTools.java index b4ee084d69f6a..db80a439f2b25 100644 --- a/test/lib/jdk/test/lib/process/ProcessTools.java +++ b/test/lib/jdk/test/lib/process/ProcessTools.java @@ -492,12 +492,21 @@ private static void printStack(Thread t, StackTraceElement[] stack) { } /** - * Create ProcessBuilder using the java launcher from the jdk to be tested. - * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added. - *

- * The command line will be like: - * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds - * Create ProcessBuilder using the java launcher from the jdk to be tested. + * Create ProcessBuilder using the java launcher from the jdk to + * be tested. The default jvm options from jtreg, test.vm.opts and + * test.java.opts, are added. + * + *

Unless the "test.noclasspath" property is "true" the + * classpath property "java.class.path" is appended to the command + * line and the environment of the ProcessBuilder is modified to + * remove "CLASSPATH". If the property "test.thread.factory" is + * provided the command args are updated and appended to invoke + * ProcessTools main() and provide the name of the thread factory. + * + *

The "-Dtest.thread.factory" is appended to the arguments + * with the thread factory value. The remaining command args are + * scanned for unsupported options and are appended to the + * ProcessBuilder. * * @param command Arguments to pass to the java command. * @return The ProcessBuilder instance representing the java command. @@ -507,12 +516,21 @@ public static ProcessBuilder createTestJavaProcessBuilder(List command) } /** - * Create ProcessBuilder using the java launcher from the jdk to be tested. - * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added. - *

- * The command line will be like: - * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds - * Create ProcessBuilder using the java launcher from the jdk to be tested. + * Create ProcessBuilder using the java launcher from the jdk to + * be tested. The default jvm options from jtreg, test.vm.opts and + * test.java.opts, are added. + * + *

Unless the "test.noclasspath" property is "true" the + * classpath property "java.class.path" is appended to the command + * line and the environment of the ProcessBuilder is modified to + * remove "CLASSPATH". If the property "test.thread.factory" is + * provided the command args are updated and appended to invoke + * ProcessTools main() and provide the name of the thread factory. + * + *

The "-Dtest.thread.factory" is appended to the arguments + * with the thread factory value. The remaining command args are + * scanned for unsupported options and are appended to the + * ProcessBuilder. * * @param command Arguments to pass to the java command. * @return The ProcessBuilder instance representing the java command. @@ -536,6 +554,18 @@ public static ProcessBuilder createTestJavaProcessBuilder(String... command) { * it in combination with @requires vm.flagless JTREG * anotation as to not waste energy and test resources. * + *

Unless the "test.noclasspath" property is "true" the + * classpath property "java.class.path" is appended to the command + * line and the environment of the ProcessBuilder is modified to + * remove "CLASSPATH". If the property "test.thread.factory" is + * provided the command args are updated and appended to invoke + * ProcessTools main() and provide the name of the thread factory. + * + *

The "-Dtest.thread.factory" is appended to the arguments + * with the thread factory value. The remaining command args are + * scanned for unsupported options and are appended to the + * ProcessBuilder. + * * @param command Arguments to pass to the java command. * @return The ProcessBuilder instance representing the java command. */ @@ -558,6 +588,18 @@ public static ProcessBuilder createLimitedTestJavaProcessBuilder(List co * it in combination with @requires vm.flagless JTREG * anotation as to not waste energy and test resources. * + *

Unless the "test.noclasspath" property is "true" the + * classpath property "java.class.path" is appended to the command + * line and the environment of the ProcessBuilder is modified to + * remove "CLASSPATH". If the property "test.thread.factory" is + * provided the command args are updated and appended to invoke + * ProcessTools main() and provide the name of the thread factory. + * + *

The "-Dtest.thread.factory" is appended to the arguments + * with the thread factory value. The remaining command args are + * scanned for unsupported options and are appended to the + * ProcessBuilder. + * * @param command Arguments to pass to the java command. * @return The ProcessBuilder instance representing the java command. */ @@ -566,14 +608,12 @@ public static ProcessBuilder createLimitedTestJavaProcessBuilder(String... comma } /** - * Executes a test jvm process, waits for it to finish and returns the process output. - * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added. - * The java from the test.jdk is used to execute the command. - *

- * The command line will be like: - * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds - *

- * The jvm process will have exited before this method returns. + * Executes a test jvm process, waits for it to finish and returns + * the process output. + * + *

The process is created using runtime flags set up by: + * {@link #createTestJavaProcessBuilder(String...)}. The + * jvm process will have exited before this method returns. * * @param cmds User specified arguments. * @return The output from the process. @@ -583,14 +623,12 @@ public static OutputAnalyzer executeTestJvm(List cmds) throws Exception } /** - * Executes a test jvm process, waits for it to finish and returns the process output. - * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added. - * The java from the test.jdk is used to execute the command. - *

- * The command line will be like: - * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds - *

- * The jvm process will have exited before this method returns. + * Executes a test jvm process, waits for it to finish and returns + * the process output. + * + *

The process is created using runtime flags set up by: + * {@link #createTestJavaProcessBuilder(String...)}. The + * jvm process will have exited before this method returns. * * @param cmds User specified arguments. * @return The output from the process. diff --git a/test/micro/org/openjdk/bench/java/time/LeapYearBench.java b/test/micro/org/openjdk/bench/java/time/LeapYearBench.java new file mode 100644 index 0000000000000..d7a00ba3bc228 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/time/LeapYearBench.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.openjdk.bench.java.time; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; + +import java.time.Duration; +import java.time.Instant; +import java.time.Year; +import java.time.ZonedDateTime; +import java.time.chrono.IsoChronology; +import java.time.temporal.ChronoUnit; +import java.util.GregorianCalendar; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; + +/** + * Examine Year.leapYear-related operations + */ +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@Fork(3) +@State(Scope.Thread) +public class LeapYearBench { + + private long[] years; + + private GregorianCalendar calendar; + + @Setup + public void createInstants() { + // Large enough number of years to guarantee that the distribution of + // leap years is reasonably realistic + years = new long[2048]; + final Random random = new Random(0); + for (int i = 0; i < years.length; i++) { + years[i] = random.nextLong(2000) + 2000; + } + calendar = GregorianCalendar.from(ZonedDateTime.now()); + } + + @Benchmark + public void isLeapYear(Blackhole bh) { + for (long year : years) { + bh.consume(Year.isLeap(year)); + } + } + + @Benchmark + public void isLeapYearChrono(Blackhole bh) { + for (long year : years) { + bh.consume(IsoChronology.INSTANCE.isLeapYear(year)); + } + } + + @Benchmark + public void isLeapYearGregorian(Blackhole bh) { + for (long year : years) { + bh.consume(calendar.isLeapYear((int)year)); + } + } + + public static boolean isLeapNeriSchneider(long year) { + int d = year % 100 != 0 ? 4 : 16; + return (year & (d - 1)) == 0; + } + + @Benchmark + public void isLeapYearNS(Blackhole bh) { + for (long year : years) { + bh.consume(isLeapNeriSchneider(year)); + } + } +}