# HG changeset patch # User andrew # Date 1461120206 -3600 # Node ID 3f9a4c47edee7a6d36b4344acee9a5ed3c3de4d0 # Parent 49b8cecd1bbe2c2ba0ad1aec6722078b621866a1# Parent fa8991ccf6e5b74890a0b5672440b3c09d8d8732 Merge jdk8u91-b14 diff -r 49b8cecd1bbe -r 3f9a4c47edee .hgtags --- a/.hgtags Sun Apr 10 01:08:29 2016 +0100 +++ b/.hgtags Wed Apr 20 03:43:26 2016 +0100 @@ -689,6 +689,7 @@ 20bad8c6c7b406c3603b4e22b15cd990840a9d62 jdk8u51-b31 e51afd2a1fc17de59ff3c79003210a40a28ac960 jdk8u51-b32 b2427357cc98aeb2716ee2e89e733794afb4057b jdk8u51-b33 +4b722db6d38583ee3e71c43d9996bf1ebb8a412e jdk8u51-b34 d9349fa8822336e0244da0a8448f3e6b2d62741d jdk8u60-b00 d9349fa8822336e0244da0a8448f3e6b2d62741d hs25.60-b00 ebf89088c08ab0508b9002b48dd3d68a340259af hs25.60-b01 @@ -787,6 +788,11 @@ a6f2a7ba281291f5dab79fa494f7cfaa6232c88b jdk8u66-b17 9ae2a5adabba97d9ebf79e13b325f1ff368ce014 jdk8u66-b18 527f62b70faee4a0c15f365def024b87012e6934 jdk8u66-b31 +d8be40462cfb6de441818aec8c30e03077189010 jdk8u66-b32 +6a0b19c56d797c2975f0cf505190e8f5d69b0b7a jdk8u66-b33 +3d55b1055c782375e39ebbddba2887379bc3531c jdk8u66-b34 +95b0e04287fb443a4eee64504e0f18bc324c7abd jdk8u66-b35 +dce99debdba26def128cd8b2d3eae93d7d789ee2 jdk8u66-b36 9a158a0c243beb610dbaabd63d6218d3ce5825f1 jdk8u71-b00 67df26e363fb7e722032fd286673642fc999957c jdk8u71-b01 1a799d49de23d84f658ade1d3805a1924e7e1e84 jdk8u71-b02 @@ -826,8 +832,24 @@ 451dda77f6c29bd3260e87f847a9eadae122a759 jdk8u74-b00 c1031a924f2c910fad078838b88a2f0146f2de98 jdk8u74-b01 ca9cae9aa9e989bbe6713c91d55c913edeaecce4 jdk8u74-b02 +da43260704c28b9f19cb652090ae65c258220fd6 jdk8u72-b31 +c0242ea4bde19d72be5149feda112a39e8c89b0a jdk8u75-b00 +ca3b8c8e390ab0540b0cc2e5def869b38e460d86 jdk8u75-b01 +9aef5b5e0a68f20059cfa9e2806b4ff0e11a3d31 jdk8u75-b02 +2df9fe896819362b9075a670b78106b249e50d6d jdk8u75-b03 +32b682649973231b54740c09b10889660f6ebde5 jdk8u75-b04 +1f43bd4fab06d2ca5d1964611df14d8506d6b36e jdk8u75-b05 +916712f178c39d0acbc590f38802133fc86a7346 jdk8u75-b06 +8c791dd1c24d85ebd18b03d49185c2a25263c129 jdk8u75-b07 +e4a935cb6f7178912fd653e2a9514eadec7935ab jdk8u75-b08 +e97c45c377eb8d022cfe24b73737fa312107e0a5 jdk8u75-b09 +d44c7e324682a30e064503ef9582d83a41f4173e jdk8u75-b10 +cc78c97abff85062d6844fa253081e26a0a60150 jdk8u75-b12 1b6d4fd2730e58f17820930f797938dc182117c4 jdk8u77-b00 ddd297e340b1170d3cec011ee64e729f8b493c86 jdk8u77-b01 1b4072e4bb3ad54c4e894998486a8b33f0689160 jdk8u77-b02 e9585e814cc954c06e870f3bdf37171029da0d5e icedtea-3.0.0pre10 5e587a29a6aac06d6b5a7ebeea99a291d82520c8 icedtea-3.0.0 +223b64a19e94222dd97b92bb40abcfbc0bf6ef1f jdk8u77-b03 +bbbb05e91c629f8d9eef2ba43933767f68a898b0 jdk8u91-b00 +e36b6ade0499eadfd8673fe62ef0a613af2e6d67 jdk8u91-b13 diff -r 49b8cecd1bbe -r 3f9a4c47edee agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java --- a/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java Sun Apr 10 01:08:29 2016 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/interpreter/Bytecodes.java Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -253,29 +253,30 @@ public static final int _fast_sgetfield = 210; public static final int _fast_aputfield = 211; public static final int _fast_bputfield = 212; - public static final int _fast_cputfield = 213; - public static final int _fast_dputfield = 214; - public static final int _fast_fputfield = 215; - public static final int _fast_iputfield = 216; - public static final int _fast_lputfield = 217; - public static final int _fast_sputfield = 218; - public static final int _fast_aload_0 = 219; - public static final int _fast_iaccess_0 = 220; - public static final int _fast_aaccess_0 = 221; - public static final int _fast_faccess_0 = 222; - public static final int _fast_iload = 223; - public static final int _fast_iload2 = 224; - public static final int _fast_icaload = 225; - public static final int _fast_invokevfinal = 226; - public static final int _fast_linearswitch = 227; - public static final int _fast_binaryswitch = 228; - public static final int _fast_aldc = 229; - public static final int _fast_aldc_w = 230; - public static final int _return_register_finalizer = 231; - public static final int _invokehandle = 232; - public static final int _shouldnotreachhere = 233; // For debugging + public static final int _fast_zputfield = 213; + public static final int _fast_cputfield = 214; + public static final int _fast_dputfield = 215; + public static final int _fast_fputfield = 216; + public static final int _fast_iputfield = 217; + public static final int _fast_lputfield = 218; + public static final int _fast_sputfield = 219; + public static final int _fast_aload_0 = 220; + public static final int _fast_iaccess_0 = 221; + public static final int _fast_aaccess_0 = 222; + public static final int _fast_faccess_0 = 223; + public static final int _fast_iload = 224; + public static final int _fast_iload2 = 225; + public static final int _fast_icaload = 226; + public static final int _fast_invokevfinal = 227; + public static final int _fast_linearswitch = 228; + public static final int _fast_binaryswitch = 229; + public static final int _fast_aldc = 230; + public static final int _fast_aldc_w = 231; + public static final int _return_register_finalizer = 232; + public static final int _invokehandle = 233; + public static final int _shouldnotreachhere = 234; // For debugging - public static final int number_of_codes = 234; + public static final int number_of_codes = 235; // Flag bits derived from format strings, can_trap, can_rewrite, etc.: // semantic flags: @@ -776,6 +777,7 @@ def(_fast_aputfield , "fast_aputfield" , "bJJ" , null , BasicType.getTObject() , 0, true , _putfield ); def(_fast_bputfield , "fast_bputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield ); + def(_fast_zputfield , "fast_zputfield" , "bJJ" , null , BasicType.getTInt() , 0, true , _putfield ); def(_fast_cputfield , "fast_cputfield" , "bJJ" , null , BasicType.getTChar() , 0, true , _putfield ); def(_fast_dputfield , "fast_dputfield" , "bJJ" , null , BasicType.getTDouble() , 0, true , _putfield ); def(_fast_fputfield , "fast_fputfield" , "bJJ" , null , BasicType.getTFloat() , 0, true , _putfield ); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/ppc/vm/interp_masm_ppc_64.cpp --- a/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -174,6 +174,7 @@ case ltos: ld(R17_tos, in_bytes(JvmtiThreadState::earlyret_value_offset()), RjvmtiState); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: lwz(R17_tos, in_bytes(JvmtiThreadState::earlyret_value_offset()), RjvmtiState); @@ -302,6 +303,7 @@ switch (state) { case atos: push_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: push_i(); break; @@ -317,6 +319,7 @@ switch (state) { case atos: pop_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: pop_i(); break; @@ -751,6 +754,43 @@ stdux(Rscratch2, R1_SP, Rscratch1); // atomically set *(SP = top_frame_sp) = **SP } +void InterpreterMacroAssembler::narrow(Register result) { + Register ret_type = R11_scratch1; + ld(R11_scratch1, in_bytes(Method::const_offset()), R19_method); + lbz(ret_type, in_bytes(ConstMethod::result_type_offset()), R11_scratch1); + + Label notBool, notByte, notChar, done; + + // common case first + cmpwi(CCR0, ret_type, T_INT); + beq(CCR0, done); + + cmpwi(CCR0, ret_type, T_BOOLEAN); + bne(CCR0, notBool); + andi(result, result, 0x1); + b(done); + + bind(notBool); + cmpwi(CCR0, ret_type, T_BYTE); + bne(CCR0, notByte); + extsb(result, result); + b(done); + + bind(notByte); + cmpwi(CCR0, ret_type, T_CHAR); + bne(CCR0, notChar); + andi(result, result, 0xffff); + b(done); + + bind(notChar); + // cmpwi(CCR0, ret_type, T_SHORT); // all that's left + // bne(CCR0, done); + extsh(result, result); + + // Nothing to do for T_INT + bind(done); +} + // Remove activation. // // Unlock the receiver if this is a synchronized method. diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/ppc/vm/interp_masm_ppc_64.hpp --- a/src/cpu/ppc/vm/interp_masm_ppc_64.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/ppc/vm/interp_masm_ppc_64.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -149,6 +149,8 @@ void get_cpool_and_tags(Register Rcpool, Register Rtags); void is_a(Label& L); + void narrow(Register result); + // Java Call Helpers void call_from_interpreter(Register Rtarget_method, Register Rret_addr, Register Rscratch1, Register Rscratch2); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/ppc/vm/interpreter_ppc.cpp --- a/src/cpu/ppc/vm/interpreter_ppc.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/ppc/vm/interpreter_ppc.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -632,6 +632,16 @@ __ blr(); } + if (branch_table[ztos] == 0) { // generate only once + __ align(32, 28, 28); // align load + __ fence(); // volatile entry point (one instruction before non-volatile_entry point) + branch_table[ztos] = __ pc(); // non-volatile_entry point + __ lbzx(R3_RET, Rclass_or_obj, Roffset); + __ extsb(R3_RET, R3_RET); + __ beq(CCR6, Lacquire); + __ blr(); + } + if (branch_table[ctos] == 0) { // generate only once __ align(32, 28, 28); // align load __ fence(); // volatile entry point (one instruction before non-volatile_entry point) diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/ppc/vm/templateInterpreter_ppc.cpp --- a/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -154,6 +154,7 @@ switch (state) { case ltos: case btos: + case ztos: case ctos: case stos: case atos: @@ -200,6 +201,7 @@ switch (state) { case ltos: case btos: + case ztos: case ctos: case stos: case atos: @@ -1642,12 +1644,14 @@ // Copied from TemplateTable::_return. // Restoration of lr done by remove_activation. switch (state) { + // Narrow result if state is itos but result type is smaller. + case itos: __ narrow(R17_tos); /* fall through */ case ltos: case btos: + case ztos: case ctos: case stos: - case atos: - case itos: __ mr(R3_RET, R17_tos); break; + case atos: __ mr(R3_RET, R17_tos); break; case ftos: case dtos: __ fmr(F1_RET, F15_ftos); break; case vtos: // This might be a constructor. Final fields (and volatile fields on PPC64) need @@ -1717,6 +1721,10 @@ bname = "trace_code_btos {"; tsize = 2; break; + case ztos: + bname = "trace_code_ztos {"; + tsize = 2; + break; case ctos: bname = "trace_code_ctos {"; tsize = 2; diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/ppc/vm/templateTable_ppc_64.cpp --- a/src/cpu/ppc/vm/templateTable_ppc_64.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/ppc/vm/templateTable_ppc_64.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -173,6 +173,7 @@ switch (new_bc) { case Bytecodes::_fast_aputfield: case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_zputfield: case Bytecodes::_fast_cputfield: case Bytecodes::_fast_dputfield: case Bytecodes::_fast_fputfield: @@ -969,9 +970,21 @@ Rarray = R12_scratch2, Rscratch = R3_ARG1; __ pop_i(Rindex); + __ pop_ptr(Rarray); // tos: val - // Rarray: array ptr (popped by index_check) - __ index_check(Rarray, Rindex, 0, Rscratch, Rarray); + + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(Rscratch, Rarray); + __ lwz(Rscratch, in_bytes(Klass::layout_helper_offset()), Rscratch); + int diffbit = exact_log2(Klass::layout_helper_boolean_diffbit()); + __ testbitdi(CCR0, R0, Rscratch, diffbit); + Label L_skip; + __ bfalse(CCR0, L_skip); + __ andi(R17_tos, R17_tos, 1); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); + + __ index_check_without_pop(Rarray, Rindex, 0, Rscratch, Rarray); __ stb(R17_tos, arrayOopDesc::base_offset_in_bytes(T_BYTE), Rarray); } @@ -2100,12 +2113,16 @@ __ remove_activation(state, /* throw_monitor_exception */ true); // Restoration of lr done by remove_activation. switch (state) { + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + case itos: __ narrow(R17_tos); /* fall through */ case ltos: case btos: + case ztos: case ctos: case stos: - case atos: - case itos: __ mr(R3_RET, R17_tos); break; + case atos: __ mr(R3_RET, R17_tos); break; case ftos: case dtos: __ fmr(F1_RET, F15_ftos); break; case vtos: // This might be a constructor. Final fields (and volatile fields on PPC64) need @@ -2501,6 +2518,21 @@ __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); __ align(32, 28, 28); // Align load. + // __ bind(Lztos); (same code as btos) + __ fence(); // Volatile entry point (one instruction before non-volatile_entry point). + assert(branch_table[ztos] == 0, "can't compute twice"); + branch_table[ztos] = __ pc(); // non-volatile_entry point + __ lbzx(R17_tos, Rclass_or_obj, Roffset); + __ extsb(R17_tos, R17_tos); + __ push(ztos); + if (!is_static) { + // use btos rewriting, no truncating to t/f bit is needed for getfield. + patch_bytecode(Bytecodes::_fast_bgetfield, Rbc, Rscratch); + } + __ beq(CCR6, Lacquire); // Volatile? + __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + + __ align(32, 28, 28); // Align load. // __ bind(Lctos); __ fence(); // Volatile entry point (one instruction before non-volatile_entry point). assert(branch_table[ctos] == 0, "can't compute twice"); @@ -2590,6 +2622,7 @@ case Bytecodes::_fast_aputfield: __ push_ptr(); offs+= Interpreter::stackElementSize; break; case Bytecodes::_fast_iputfield: // Fall through case Bytecodes::_fast_bputfield: // Fall through + case Bytecodes::_fast_zputfield: // Fall through case Bytecodes::_fast_cputfield: // Fall through case Bytecodes::_fast_sputfield: __ push_i(); offs+= Interpreter::stackElementSize; break; case Bytecodes::_fast_lputfield: __ push_l(); offs+=2*Interpreter::stackElementSize; break; @@ -2630,6 +2663,7 @@ case Bytecodes::_fast_aputfield: __ pop_ptr(); break; case Bytecodes::_fast_iputfield: // Fall through case Bytecodes::_fast_bputfield: // Fall through + case Bytecodes::_fast_zputfield: // Fall through case Bytecodes::_fast_cputfield: // Fall through case Bytecodes::_fast_sputfield: __ pop_i(); break; case Bytecodes::_fast_lputfield: __ pop_l(); break; @@ -2781,6 +2815,21 @@ __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); __ align(32, 28, 28); // Align pop. + // __ bind(Lztos); + __ release(); // Volatile entry point (one instruction before non-volatile_entry point). + assert(branch_table[ztos] == 0, "can't compute twice"); + branch_table[ztos] = __ pc(); // non-volatile_entry point + __ pop(ztos); + if (!is_static) { pop_and_check_object(Rclass_or_obj); } // Kills R11_scratch1. + __ andi(R17_tos, R17_tos, 0x1); + __ stbx(R17_tos, Rclass_or_obj, Roffset); + if (!is_static) { patch_bytecode(Bytecodes::_fast_zputfield, Rbc, Rscratch, true, byte_no); } + if (!support_IRIW_for_not_multiple_copy_atomic_cpu) { + __ beq(CR_is_vol, Lvolatile); // Volatile? + } + __ dispatch_epilog(vtos, Bytecodes::length_for(bytecode())); + + __ align(32, 28, 28); // Align pop. // __ bind(Lctos); __ release(); // Volatile entry point (one instruction before non-volatile_entry point). assert(branch_table[ctos] == 0, "can't compute twice"); @@ -2895,6 +2944,9 @@ __ stdx(R17_tos, Rclass_or_obj, Roffset); break; + case Bytecodes::_fast_zputfield: + __ andi(R17_tos, R17_tos, 0x1); // boolean is true if LSB is 1 + // fall through to bputfield case Bytecodes::_fast_bputfield: __ stbx(R17_tos, Rclass_or_obj, Roffset); break; diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp --- a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -343,7 +343,7 @@ length.set_instruction(x->length()); length.load_item(); } - if (needs_store_check) { + if (needs_store_check || x->check_boolean()) { value.load_item(); } else { value.load_for_store(x->elt_type()); @@ -388,7 +388,8 @@ pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */, true /* do_load */, false /* patch */, NULL); } - __ move(value.result(), array_addr, null_check_info); + LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info); + __ move(result, array_addr, null_check_info); if (obj_store) { // Precise card mark post_barrier(LIR_OprFact::address(array_addr), value.result()); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/sparc/vm/cppInterpreter_sparc.cpp --- a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -539,6 +539,9 @@ __ cmp(G1_scratch, btos); __ br(Assembler::equal, true, Assembler::pt, xreturn_path); __ delayed()->ldsb(Otos_i, G3_scratch, Otos_i); + __ cmp(G1_scratch, ztos); + __ br(Assembler::equal, true, Assembler::pt, xreturn_path); + __ delayed()->ldsb(Otos_i, G3_scratch, Otos_i); __ should_not_reach_here(); #endif __ ldsb(Otos_i, G3_scratch, Otos_i); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/sparc/vm/interp_masm_sparc.cpp --- a/src/cpu/sparc/vm/interp_masm_sparc.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/sparc/vm/interp_masm_sparc.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -211,6 +211,7 @@ case atos: ld_ptr(oop_addr, Otos_l); st_ptr(G0, oop_addr); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: ld(val_addr, Otos_l1); break; @@ -459,9 +460,10 @@ interp_verify_oop(Otos_i, state, __FILE__, __LINE__); switch (state) { case atos: push_ptr(); break; - case btos: push_i(); break; - case ctos: - case stos: push_i(); break; + case btos: // fall through + case ztos: // fall through + case ctos: // fall through + case stos: // fall through case itos: push_i(); break; case ltos: push_l(); break; case ftos: push_f(); break; @@ -475,9 +477,10 @@ void InterpreterMacroAssembler::pop(TosState state) { switch (state) { case atos: pop_ptr(); break; - case btos: pop_i(); break; - case ctos: - case stos: pop_i(); break; + case btos: // fall through + case ztos: // fall through + case ctos: // fall through + case stos: // fall through case itos: pop_i(); break; case ltos: pop_l(); break; case ftos: pop_f(); break; @@ -1111,6 +1114,49 @@ interp_verify_oop(Otos_i, state, __FILE__, __LINE__); } +void InterpreterMacroAssembler::narrow(Register result) { + + ld_ptr(Address(Lmethod, Method::const_offset()), G3_scratch); + ldub(G3_scratch, in_bytes(ConstMethod::result_type_offset()), G3_scratch); + + Label notBool, notByte, notChar, done; + + // common case first + cmp(G3_scratch, T_INT); + br(Assembler::equal, true, pn, done); + delayed()->nop(); + + cmp(G3_scratch, T_BOOLEAN); + br(Assembler::notEqual, true, pn, notBool); + delayed()->cmp(G3_scratch, T_BYTE); + and3(result, 1, result); + ba(done); + delayed()->nop(); + + bind(notBool); + // cmp(G3_scratch, T_BYTE); + br(Assembler::notEqual, true, pn, notByte); + delayed()->cmp(G3_scratch, T_CHAR); + sll(result, 24, result); + sra(result, 24, result); + ba(done); + delayed()->nop(); + + bind(notByte); + // cmp(G3_scratch, T_CHAR); + sll(result, 16, result); + br(Assembler::notEqual, true, pn, done); + delayed()->sra(result, 16, result); + // sll(result, 16, result); + srl(result, 16, result); + + // bind(notChar); + // must be short, instructions already executed in delay slot + // sll(result, 16, result); + // sra(result, 16, result); + + bind(done); +} // remove activation // @@ -1146,6 +1192,7 @@ case ltos: mov(Otos_l2, Otos_l2->after_save()); // fall through // O1 -> I1 #endif case btos: // fall through + case ztos: // fall through case ctos: case stos: // fall through case atos: // fall through diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/sparc/vm/interp_masm_sparc.hpp --- a/src/cpu/sparc/vm/interp_masm_sparc.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/sparc/vm/interp_masm_sparc.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,6 +105,8 @@ void dispatch_via (TosState state, address* table); + void narrow(Register result); + // Removes the current activation (incl. unlocking of monitors). // Additionally this code is used for earlyReturn in which case we // want to skip throwing an exception and installing an exception. diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/sparc/vm/templateInterpreter_sparc.cpp --- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -711,6 +711,9 @@ __ cmp(G1_scratch, btos); __ br(Assembler::equal, true, Assembler::pt, xreturn_path); __ delayed()->ldsb(Otos_i, G3_scratch, Otos_i); + __ cmp(G1_scratch, ztos); + __ br(Assembler::equal, true, Assembler::pt, xreturn_path); + __ delayed()->ldsb(Otos_i, G3_scratch, Otos_i); __ should_not_reach_here(); #endif __ ldsb(Otos_i, G3_scratch, Otos_i); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/sparc/vm/templateTable_sparc.cpp --- a/src/cpu/sparc/vm/templateTable_sparc.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/sparc/vm/templateTable_sparc.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -167,6 +167,7 @@ switch (bc) { case Bytecodes::_fast_aputfield: case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_zputfield: case Bytecodes::_fast_cputfield: case Bytecodes::_fast_dputfield: case Bytecodes::_fast_fputfield: @@ -913,8 +914,20 @@ transition(itos, vtos); __ pop_i(O2); // index // Otos_i: val + // O2: index // O3: array __ index_check(O3, O2, 0, G3_scratch, O2); + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(O3, G4_scratch); + __ ld(G4_scratch, in_bytes(Klass::layout_helper_offset()), G4_scratch); + __ set(Klass::layout_helper_boolean_diffbit(), G3_scratch); + __ andcc(G3_scratch, G4_scratch, G0); + Label L_skip; + __ br(Assembler::zero, false, Assembler::pn, L_skip); + __ delayed()->nop(); + __ and3(Otos_i, 1, Otos_i); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); __ stb(Otos_i, O2, arrayOopDesc::base_offset_in_bytes(T_BYTE)); } @@ -1997,6 +2010,12 @@ __ bind(skip_register_finalizer); } + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + if (state == itos) { + __ narrow(Otos_i); + } __ remove_activation(state, /* throw_monitor_exception */ true); // The caller's SP was adjusted upon method entry to accomodate @@ -2216,7 +2235,7 @@ Label checkVolatile; // compute field type - Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj; + Label notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj; __ srl(Rflags, ConstantPoolCacheEntry::tos_state_shift, Rflags); // Make sure we don't need to mask Rflags after the above shift ConstantPoolCacheEntry::verify_tos_state_shift(); @@ -2271,7 +2290,7 @@ // cmp(Rflags, btos); __ br(Assembler::notEqual, false, Assembler::pt, notByte); - __ delayed() ->cmp(Rflags, ctos); + __ delayed() ->cmp(Rflags, ztos); // btos __ ldsb(Rclass, Roffset, Otos_i); @@ -2284,6 +2303,22 @@ __ bind(notByte); + // cmp(Rflags, ztos); + __ br(Assembler::notEqual, false, Assembler::pt, notBool); + __ delayed() ->cmp(Rflags, ctos); + + // ztos + __ ldsb(Rclass, Roffset, Otos_i); + __ push(itos); + if (!is_static) { + // use btos rewriting, no truncating to t/f bit is needed for getfield. + patch_bytecode(Bytecodes::_fast_bgetfield, G3_scratch, G4_scratch); + } + __ ba(checkVolatile); + __ delayed()->tst(Lscratch); + + __ bind(notBool); + // cmp(Rflags, ctos); __ br(Assembler::notEqual, false, Assembler::pt, notChar); __ delayed() ->cmp(Rflags, stos); @@ -2445,6 +2480,7 @@ switch (bytecode()) { // save tos values before call_VM() clobbers them case Bytecodes::_fast_aputfield: __ push_ptr(Otos_i); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ push_i(Otos_i); break; @@ -2462,6 +2498,7 @@ switch (bytecode()) { // restore tos values case Bytecodes::_fast_aputfield: __ pop_ptr(Otos_i); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ pop_i(Otos_i); break; @@ -2577,7 +2614,7 @@ ConstantPoolCacheEntry::verify_tos_state_shift(); // compute field type - Label notInt, notShort, notChar, notObj, notByte, notLong, notFloat; + Label notInt, notShort, notChar, notObj, notByte, notBool, notLong, notFloat; if (is_static) { // putstatic with object type most likely, check that first @@ -2645,7 +2682,7 @@ // cmp(Rflags, btos); __ br(Assembler::notEqual, false, Assembler::pt, notByte); - __ delayed()->cmp(Rflags, ltos); + __ delayed()->cmp(Rflags, ztos); // btos { @@ -2660,6 +2697,25 @@ } __ bind(notByte); + + // cmp(Rflags, btos); + __ br(Assembler::notEqual, false, Assembler::pt, notBool); + __ delayed()->cmp(Rflags, ltos); + + // ztos + { + __ pop_i(); + if (!is_static) pop_and_check_object(Rclass); + __ and3(Otos_i, 1, Otos_i); + __ stb(Otos_i, Rclass, Roffset); + if (!is_static) { + patch_bytecode(Bytecodes::_fast_zputfield, G3_scratch, G4_scratch, true, byte_no); + } + __ ba(checkVolatile); + __ delayed()->tst(Lscratch); + } + + __ bind(notBool); // cmp(Rflags, ltos); __ br(Assembler::notEqual, false, Assembler::pt, notLong); __ delayed()->cmp(Rflags, ctos); @@ -2783,6 +2839,7 @@ pop_and_check_object(Rclass); switch (bytecode()) { + case Bytecodes::_fast_zputfield: __ and3(Otos_i, 1, Otos_i); // fall through to bputfield case Bytecodes::_fast_bputfield: __ stb(Otos_i, Rclass, Roffset); break; case Bytecodes::_fast_cputfield: /* fall through */ case Bytecodes::_fast_sputfield: __ sth(Otos_i, Rclass, Roffset); break; diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/x86/vm/c1_LIRGenerator_x86.cpp --- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -283,7 +283,7 @@ length.load_item(); } - if (needs_store_check) { + if (needs_store_check || x->check_boolean()) { value.load_item(); } else { value.load_for_store(x->elt_type()); @@ -331,7 +331,8 @@ // Seems to be a precise post_barrier(LIR_OprFact::address(array_addr), value.result()); } else { - __ move(value.result(), array_addr, null_check_info); + LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info); + __ move(result, array_addr, null_check_info); } } diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/x86/vm/cppInterpreter_x86.cpp --- a/src/cpu/x86/vm/cppInterpreter_x86.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/x86/vm/cppInterpreter_x86.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -870,7 +870,7 @@ rdx, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); - Label notByte, notShort, notChar; + Label notByte, notBool, notShort, notChar; const Address field_address (rax, rcx, Address::times_1); // Need to differentiate between igetfield, agetfield, bgetfield etc. @@ -889,6 +889,11 @@ __ bind(notObj); #endif // _LP64 + __ cmpl(rdx, ztos); + __ jcc(Assembler::notEqual, notBool); + __ load_signed_byte(rax, field_address); + __ jmp(xreturn_path); + __ cmpl(rdx, btos); __ jcc(Assembler::notEqual, notByte); __ load_signed_byte(rax, field_address); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/x86/vm/interp_masm_x86.cpp --- a/src/cpu/x86/vm/interp_masm_x86.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/x86/vm/interp_masm_x86.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,54 @@ #include "interpreter/interpreter.hpp" #include "oops/methodData.hpp" + +// 8u does not have InterpreterMacroAssembler::load_earlyret_value here + +void InterpreterMacroAssembler::narrow(Register result) { + + // Get method->_constMethod->_result_type + movptr(rcx, Address(rbp, frame::interpreter_frame_method_offset * wordSize)); + movptr(rcx, Address(rcx, Method::const_offset())); + load_unsigned_byte(rcx, Address(rcx, ConstMethod::result_type_offset())); + + Label done, notBool, notByte, notChar; + + // common case first + cmpl(rcx, T_INT); + jcc(Assembler::equal, done); + + // mask integer result to narrower return type. + cmpl(rcx, T_BOOLEAN); + jcc(Assembler::notEqual, notBool); + andl(result, 0x1); + jmp(done); + + bind(notBool); + cmpl(rcx, T_BYTE); + jcc(Assembler::notEqual, notByte); + LP64_ONLY(movsbl(result, result);) + NOT_LP64(shll(result, 24);) // truncate upper 24 bits + NOT_LP64(sarl(result, 24);) // and sign-extend byte + jmp(done); + + bind(notByte); + cmpl(rcx, T_CHAR); + jcc(Assembler::notEqual, notChar); + LP64_ONLY(movzwl(result, result);) + NOT_LP64(andl(result, 0xFFFF);) // truncate upper 16 bits + jmp(done); + + bind(notChar); + // cmpl(rcx, T_SHORT); // all that's left + // jcc(Assembler::notEqual, done); + LP64_ONLY(movswl(result, result);) + NOT_LP64(shll(result, 16);) // truncate upper 16 bits + NOT_LP64(sarl(result, 16);) // and sign-extend short + + // Nothing to do for T_INT + bind(done); +} + #ifndef CC_INTERP void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) { Label update, next, none; diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/x86/vm/interp_masm_x86.hpp --- a/src/cpu/x86/vm/interp_masm_x86.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/x86/vm/interp_masm_x86.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,9 @@ Register _bcp_register; // register that contains the bcp public: + // narrow int return value + void narrow(Register result); + #ifndef CC_INTERP void profile_obj_type(Register obj, const Address& mdo_addr); void profile_arguments_type(Register mdp, Register callee, Register tmp, bool is_virtual); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/x86/vm/interp_masm_x86_32.cpp --- a/src/cpu/x86/vm/interp_masm_x86_32.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -151,6 +151,7 @@ case ltos: movl(rdx, val_addr1); // fall through case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: movl(rax, val_addr); break; @@ -362,6 +363,7 @@ switch (state) { case atos: pop_ptr(rax); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: pop_i(rax); break; @@ -405,6 +407,7 @@ switch (state) { case atos: push_ptr(rax); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: push_i(rax); break; diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/x86/vm/interp_masm_x86_64.cpp --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,6 +149,7 @@ verify_oop(rax, state); break; case ltos: movptr(rax, val_addr); break; case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: movl(rax, val_addr); break; @@ -387,6 +388,7 @@ switch (state) { case atos: pop_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: pop_i(); break; @@ -404,6 +406,7 @@ switch (state) { case atos: push_ptr(); break; case btos: + case ztos: case ctos: case stos: case itos: push_i(); break; diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/x86/vm/templateInterpreter_x86_32.cpp --- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -713,7 +713,7 @@ rdx, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); - Label notByte, notShort, notChar; + Label notByte, notBool, notShort, notChar; const Address field_address (rax, rcx, Address::times_1); // Need to differentiate between igetfield, agetfield, bgetfield etc. @@ -728,6 +728,12 @@ __ jmp(xreturn_path); __ bind(notByte); + __ cmpl(rdx, ztos); + __ jcc(Assembler::notEqual, notBool); + __ load_signed_byte(rax, field_address); + __ jmp(xreturn_path); + + __ bind(notBool); __ cmpl(rdx, stos); __ jcc(Assembler::notEqual, notShort); __ load_signed_short(rax, field_address); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -680,7 +680,7 @@ ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); - Label notObj, notInt, notByte, notShort; + Label notObj, notInt, notByte, notBool, notShort; const Address field_address(rax, rcx, Address::times_1); // Need to differentiate between igetfield, agetfield, bgetfield etc. @@ -711,6 +711,13 @@ __ jmp(xreturn_path); __ bind(notByte); + __ cmpl(rdx, ztos); + __ jcc(Assembler::notEqual, notBool); + // ztos + __ load_signed_byte(rax, field_address); + __ jmp(xreturn_path); + + __ bind(notBool); __ cmpl(rdx, stos); __ jcc(Assembler::notEqual, notShort); // stos diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/x86/vm/templateTable_x86_32.cpp --- a/src/cpu/x86/vm/templateTable_x86_32.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/x86/vm/templateTable_x86_32.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -212,6 +212,7 @@ switch (bc) { case Bytecodes::_fast_aputfield: case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_zputfield: case Bytecodes::_fast_cputfield: case Bytecodes::_fast_dputfield: case Bytecodes::_fast_fputfield: @@ -988,11 +989,21 @@ void TemplateTable::bastore() { transition(itos, vtos); __ pop_i(rbx); - // rax,: value + // rax: value + // rbx: index // rdx: array - index_check(rdx, rbx); // prefer index in rbx, - // rbx,: index - __ movb(Address(rdx, rbx, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), rax); + index_check(rdx, rbx); // prefer index in rbx + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(rcx, rdx); + __ movl(rcx, Address(rcx, Klass::layout_helper_offset())); + int diffbit = Klass::layout_helper_boolean_diffbit(); + __ testl(rcx, diffbit); + Label L_skip; + __ jccb(Assembler::zero, L_skip); + __ andl(rax, 1); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); + __ movb(Address(rdx, rbx, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), rax); } @@ -2037,7 +2048,14 @@ __ bind(skip_register_finalizer); } + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + if (state == itos) { + __ narrow(rax); + } __ remove_activation(state, rsi); + __ jmp(rsi); } @@ -2234,7 +2252,7 @@ const Address lo(obj, off, Address::times_1, 0*wordSize); const Address hi(obj, off, Address::times_1, 1*wordSize); - Label Done, notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; + Label Done, notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); assert(btos == 0, "change code, btos != 0"); @@ -2251,6 +2269,22 @@ __ jmp(Done); __ bind(notByte); + + __ cmpl(flags, ztos); + __ jcc(Assembler::notEqual, notBool); + + // ztos (same code as btos) + __ load_signed_byte(rax, lo); + __ push(ztos); + // Rewrite bytecode to be faster + if (!is_static) { + // use btos rewriting, no truncating to t/f bit is needed for getfield. + patch_bytecode(Bytecodes::_fast_bgetfield, rcx, rbx); + } + __ jmp(Done); + + __ bind(notBool); + // itos __ cmpl(flags, itos ); __ jcc(Assembler::notEqual, notInt); @@ -2450,7 +2484,7 @@ const Address lo(obj, off, Address::times_1, 0*wordSize); const Address hi(obj, off, Address::times_1, 1*wordSize); - Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; + Label notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); assert(btos == 0, "change code, btos != 0"); @@ -2469,6 +2503,22 @@ } __ bind(notByte); + __ cmpl(flags, ztos); + __ jcc(Assembler::notEqual, notBool); + + // ztos + { + __ pop(ztos); + if (!is_static) pop_and_check_object(obj); + __ andl(rax, 0x1); + __ movb(lo, rax); + if (!is_static) { + patch_bytecode(Bytecodes::_fast_zputfield, rcx, rbx, true, byte_no); + } + __ jmp(Done); + } + + __ bind(notBool); __ cmpl(flags, itos); __ jcc(Assembler::notEqual, notInt); @@ -2640,6 +2690,7 @@ switch (bytecode()) { // load values into the jvalue object case Bytecodes::_fast_aputfield: __ push_ptr(rax); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ push_i(rax); break; @@ -2662,6 +2713,7 @@ switch (bytecode()) { // restore tos values case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ pop_i(rax); break; @@ -2712,6 +2764,8 @@ // access field switch (bytecode()) { + case Bytecodes::_fast_zputfield: __ andl(rax, 0x1); // boolean is true if LSB is 1 + // fall through to bputfield case Bytecodes::_fast_bputfield: __ movb(lo, rax); break; case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: __ movw(lo, rax); break; @@ -2746,6 +2800,8 @@ // access field switch (bytecode()) { + case Bytecodes::_fast_zputfield: __ andl(rax, 0x1); // boolean is true if LSB is 1 + // fall through to bputfield case Bytecodes::_fast_bputfield: __ movb(lo, rax); break; case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: __ movw(lo, rax); break; diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/x86/vm/templateTable_x86_64.cpp --- a/src/cpu/x86/vm/templateTable_x86_64.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -215,6 +215,7 @@ switch (bc) { case Bytecodes::_fast_aputfield: case Bytecodes::_fast_bputfield: + case Bytecodes::_fast_zputfield: case Bytecodes::_fast_cputfield: case Bytecodes::_fast_dputfield: case Bytecodes::_fast_fputfield: @@ -1014,6 +1015,16 @@ // ebx: index // rdx: array index_check(rdx, rbx); // prefer index in ebx + // Need to check whether array is boolean or byte + // since both types share the bastore bytecode. + __ load_klass(rcx, rdx); + __ movl(rcx, Address(rcx, Klass::layout_helper_offset())); + int diffbit = Klass::layout_helper_boolean_diffbit(); + __ testl(rcx, diffbit); + Label L_skip; + __ jccb(Assembler::zero, L_skip); + __ andl(rax, 1); // if it is a T_BOOLEAN array, mask the stored value to 0/1 + __ bind(L_skip); __ movb(Address(rdx, rbx, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)), @@ -2067,7 +2078,14 @@ __ bind(skip_register_finalizer); } + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. + if (state == itos) { + __ narrow(rax); + } __ remove_activation(state, r13); + __ jmp(r13); } @@ -2285,7 +2303,7 @@ const Address field(obj, off, Address::times_1); - Label Done, notByte, notInt, notShort, notChar, + Label Done, notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); @@ -2304,6 +2322,20 @@ __ jmp(Done); __ bind(notByte); + __ cmpl(flags, ztos); + __ jcc(Assembler::notEqual, notBool); + + // ztos (same code as btos) + __ load_signed_byte(rax, field); + __ push(ztos); + // Rewrite bytecode to be faster + if (!is_static) { + // use btos rewriting, no truncating to t/f bit is needed for getfield. + patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx); + } + __ jmp(Done); + + __ bind(notBool); __ cmpl(flags, atos); __ jcc(Assembler::notEqual, notObj); // atos @@ -2493,7 +2525,7 @@ // field address const Address field(obj, off, Address::times_1); - Label notByte, notInt, notShort, notChar, + Label notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift); @@ -2514,6 +2546,22 @@ } __ bind(notByte); + __ cmpl(flags, ztos); + __ jcc(Assembler::notEqual, notBool); + + // ztos + { + __ pop(ztos); + if (!is_static) pop_and_check_object(obj); + __ andl(rax, 0x1); + __ movb(field, rax); + if (!is_static) { + patch_bytecode(Bytecodes::_fast_zputfield, bc, rbx, true, byte_no); + } + __ jmp(Done); + } + + __ bind(notBool); __ cmpl(flags, atos); __ jcc(Assembler::notEqual, notObj); @@ -2662,6 +2710,7 @@ switch (bytecode()) { // load values into the jvalue object case Bytecodes::_fast_aputfield: __ push_ptr(rax); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ push_i(rax); break; @@ -2687,6 +2736,7 @@ switch (bytecode()) { // restore tos values case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break; case Bytecodes::_fast_bputfield: // fall through + case Bytecodes::_fast_zputfield: // fall through case Bytecodes::_fast_sputfield: // fall through case Bytecodes::_fast_cputfield: // fall through case Bytecodes::_fast_iputfield: __ pop_i(rax); break; @@ -2742,6 +2792,9 @@ case Bytecodes::_fast_iputfield: __ movl(field, rax); break; + case Bytecodes::_fast_zputfield: + __ andl(rax, 0x1); // boolean is true if LSB is 1 + // fall through to bputfield case Bytecodes::_fast_bputfield: __ movb(field, rax); break; diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/zero/vm/cppInterpreter_zero.cpp --- a/src/cpu/zero/vm/cppInterpreter_zero.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -81,6 +81,30 @@ return 0; } +intptr_t narrow(BasicType type, intptr_t result) { + // mask integer result to narrower return type. + switch (type) { + case T_BOOLEAN: + return result&1; + case T_BYTE: + return (intptr_t)(jbyte)result; + case T_CHAR: + return (intptr_t)(uintptr_t)(jchar)result; + case T_SHORT: + return (intptr_t)(jshort)result; + case T_OBJECT: // nothing to do fall through + case T_ARRAY: + case T_LONG: + case T_INT: + case T_FLOAT: + case T_DOUBLE: + case T_VOID: + return result; + default : ShouldNotReachHere(); + } +} + + void CppInterpreter::main_loop(int recurse, TRAPS) { JavaThread *thread = (JavaThread *) THREAD; ZeroStack *stack = thread->zero_stack(); @@ -160,7 +184,7 @@ } else if (istate->msg() == BytecodeInterpreter::return_from_method) { // Copy the result into the caller's frame - result_slots = type2size[result_type_of(method)]; + result_slots = type2size[method->result_type()]; assert(result_slots >= 0 && result_slots <= 2, "what?"); result = istate->stack() + result_slots; break; @@ -194,8 +218,14 @@ stack->set_sp(stack->sp() + method->max_locals()); // Push our result - for (int i = 0; i < result_slots; i++) - stack->push(result[-i]); + for (int i = 0; i < result_slots; i++) { + // Adjust result to smaller + intptr_t res = result[-i]; + if (result_slots == 1) { + res = narrow(method->result_type(), res); + } + stack->push(res); + } } int CppInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { @@ -406,7 +436,7 @@ // Push our result if (!HAS_PENDING_EXCEPTION) { - BasicType type = result_type_of(method); + BasicType type = method->result_type(); stack->set_sp(stack->sp() - type2size[type]); switch (type) { @@ -528,6 +558,7 @@ break; case btos: + case ztos: SET_LOCALS_INT(object->byte_field_acquire(entry->f2_as_index()), 0); break; @@ -566,6 +597,7 @@ break; case btos: + case ztos: SET_LOCALS_INT(object->byte_field(entry->f2_as_index()), 0); break; @@ -764,26 +796,6 @@ return i; } -BasicType CppInterpreter::result_type_of(Method* method) { - BasicType t; - switch (method->result_index()) { - case 0 : t = T_BOOLEAN; break; - case 1 : t = T_CHAR; break; - case 2 : t = T_BYTE; break; - case 3 : t = T_SHORT; break; - case 4 : t = T_INT; break; - case 5 : t = T_LONG; break; - case 6 : t = T_VOID; break; - case 7 : t = T_FLOAT; break; - case 8 : t = T_DOUBLE; break; - case 9 : t = T_OBJECT; break; - default: ShouldNotReachHere(); - } - assert(AbstractInterpreter::BasicType_as_index(t) == method->result_index(), - "out of step with AbstractInterpreter::BasicType_as_index"); - return t; -} - address InterpreterGenerator::generate_empty_entry() { if (!UseFastEmptyMethods) return NULL; diff -r 49b8cecd1bbe -r 3f9a4c47edee src/cpu/zero/vm/cppInterpreter_zero.hpp --- a/src/cpu/zero/vm/cppInterpreter_zero.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/cpu/zero/vm/cppInterpreter_zero.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -49,8 +49,4 @@ static intptr_t* calculate_unwind_sp(ZeroStack* stack, oop method_handle); static void throw_exception(JavaThread* thread, Symbol* name,char *msg=NULL); - private: - // Fast result type determination - static BasicType result_type_of(Method* method); - #endif // CPU_ZERO_VM_CPPINTERPRETER_ZERO_HPP diff -r 49b8cecd1bbe -r 3f9a4c47edee src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/os/solaris/vm/os_solaris.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -178,75 +178,6 @@ static void unpackTime(timespec* absTime, bool isAbsolute, jlong time); -// Thread Local Storage -// This is common to all Solaris platforms so it is defined here, -// in this common file. -// The declarations are in the os_cpu threadLS*.hpp files. -// -// Static member initialization for TLS -Thread* ThreadLocalStorage::_get_thread_cache[ThreadLocalStorage::_pd_cache_size] = {NULL}; - -#ifndef PRODUCT -#define _PCT(n,d) ((100.0*(double)(n))/(double)(d)) - -int ThreadLocalStorage::_tcacheHit = 0; -int ThreadLocalStorage::_tcacheMiss = 0; - -void ThreadLocalStorage::print_statistics() { - int total = _tcacheMiss+_tcacheHit; - tty->print_cr("Thread cache hits %d misses %d total %d percent %f\n", - _tcacheHit, _tcacheMiss, total, _PCT(_tcacheHit, total)); -} -#undef _PCT -#endif // PRODUCT - -Thread* ThreadLocalStorage::get_thread_via_cache_slowly(uintptr_t raw_id, - int index) { - Thread *thread = get_thread_slow(); - if (thread != NULL) { - address sp = os::current_stack_pointer(); - guarantee(thread->_stack_base == NULL || - (sp <= thread->_stack_base && - sp >= thread->_stack_base - thread->_stack_size) || - is_error_reported(), - "sp must be inside of selected thread stack"); - - thread->set_self_raw_id(raw_id); // mark for quick retrieval - _get_thread_cache[ index ] = thread; - } - return thread; -} - - -static const double all_zero[ sizeof(Thread) / sizeof(double) + 1 ] = {0}; -#define NO_CACHED_THREAD ((Thread*)all_zero) - -void ThreadLocalStorage::pd_set_thread(Thread* thread) { - - // Store the new value before updating the cache to prevent a race - // between get_thread_via_cache_slowly() and this store operation. - os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); - - // Update thread cache with new thread if setting on thread create, - // or NO_CACHED_THREAD (zeroed) thread if resetting thread on exit. - uintptr_t raw = pd_raw_thread_id(); - int ix = pd_cache_index(raw); - _get_thread_cache[ix] = thread == NULL ? NO_CACHED_THREAD : thread; -} - -void ThreadLocalStorage::pd_init() { - for (int i = 0; i < _pd_cache_size; i++) { - _get_thread_cache[i] = NO_CACHED_THREAD; - } -} - -// Invalidate all the caches (happens to be the same as pd_init). -void ThreadLocalStorage::pd_invalidate_all() { pd_init(); } - -#undef NO_CACHED_THREAD - -// END Thread Local Storage - static inline size_t adjust_stack_size(address base, size_t size) { if ((ssize_t)size < 0) { // 4759953: Compensate for ridiculous stack size. @@ -1473,64 +1404,6 @@ return (int)(_initial_pid ? _initial_pid : getpid()); } -int os::allocate_thread_local_storage() { - // %%% in Win32 this allocates a memory segment pointed to by a - // register. Dan Stein can implement a similar feature in - // Solaris. Alternatively, the VM can do the same thing - // explicitly: malloc some storage and keep the pointer in a - // register (which is part of the thread's context) (or keep it - // in TLS). - // %%% In current versions of Solaris, thr_self and TSD can - // be accessed via short sequences of displaced indirections. - // The value of thr_self is available as %g7(36). - // The value of thr_getspecific(k) is stored in %g7(12)(4)(k*4-4), - // assuming that the current thread already has a value bound to k. - // It may be worth experimenting with such access patterns, - // and later having the parameters formally exported from a Solaris - // interface. I think, however, that it will be faster to - // maintain the invariant that %g2 always contains the - // JavaThread in Java code, and have stubs simply - // treat %g2 as a caller-save register, preserving it in a %lN. - thread_key_t tk; - if (thr_keycreate( &tk, NULL ) ) - fatal(err_msg("os::allocate_thread_local_storage: thr_keycreate failed " - "(%s)", strerror(errno))); - return int(tk); -} - -void os::free_thread_local_storage(int index) { - // %%% don't think we need anything here - // if ( pthread_key_delete((pthread_key_t) tk) ) - // fatal("os::free_thread_local_storage: pthread_key_delete failed"); -} - -#define SMALLINT 32 // libthread allocate for tsd_common is a version specific - // small number - point is NO swap space available -void os::thread_local_storage_at_put(int index, void* value) { - // %%% this is used only in threadLocalStorage.cpp - if (thr_setspecific((thread_key_t)index, value)) { - if (errno == ENOMEM) { - vm_exit_out_of_memory(SMALLINT, OOM_MALLOC_ERROR, - "thr_setspecific: out of swap space"); - } else { - fatal(err_msg("os::thread_local_storage_at_put: thr_setspecific failed " - "(%s)", strerror(errno))); - } - } else { - ThreadLocalStorage::set_thread_in_slot ((Thread *) value) ; - } -} - -// This function could be called before TLS is initialized, for example, when -// VM receives an async signal or when VM causes a fatal error during -// initialization. Return NULL if thr_getspecific() fails. -void* os::thread_local_storage_at(int index) { - // %%% this is used only in threadLocalStorage.cpp - void* r = NULL; - return thr_getspecific((thread_key_t)index, &r) != 0 ? NULL : r; -} - - // gethrtime() should be monotonic according to the documentation, // but some virtualized platforms are known to break this guarantee. // getTimeNanos() must be guaranteed not to move backwards, so we diff -r 49b8cecd1bbe -r 3f9a4c47edee src/os/solaris/vm/thread_solaris.inline.hpp --- a/src/os/solaris/vm/thread_solaris.inline.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/os/solaris/vm/thread_solaris.inline.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,19 +40,12 @@ // For SPARC, to avoid excessive register window spill-fill faults, // we aggressively inline these routines. -inline Thread* ThreadLocalStorage::thread() { - // don't use specialized code if +UseMallocOnly -- may confuse Purify et al. - debug_only(if (UseMallocOnly) return get_thread_slow();); +inline void ThreadLocalStorage::set_thread(Thread* thread) { + _thr_current = thread; +} - uintptr_t raw = pd_raw_thread_id(); - int ix = pd_cache_index(raw); - Thread* candidate = ThreadLocalStorage::_get_thread_cache[ix]; - if (candidate->self_raw_id() == raw) { - // hit - return candidate; - } else { - return ThreadLocalStorage::get_thread_via_cache_slowly(raw, ix); - } +inline Thread* ThreadLocalStorage::thread() { + return _thr_current; } #endif // OS_SOLARIS_VM_THREAD_SOLARIS_INLINE_HPP diff -r 49b8cecd1bbe -r 3f9a4c47edee src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp --- a/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * 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,19 +26,26 @@ #include "runtime/thread.inline.hpp" #include "runtime/threadLocalStorage.hpp" -// Provides an entry point we can link against and -// a buffer we can emit code into. The buffer is -// filled by ThreadLocalStorage::generate_code_for_get_thread -// and called from ThreadLocalStorage::thread() +// True thread-local variable +__thread Thread * ThreadLocalStorage::_thr_current = NULL; + +// Implementations needed to support the shared API -#include +void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do -// The portable TLS mechanism (get_thread_via_cache) is enough on SPARC. -// There is no need for hand-assembling a special function. -void ThreadLocalStorage::generate_code_for_get_thread() { +bool ThreadLocalStorage::_initialized = false; + +void ThreadLocalStorage::init() { + _initialized = true; } -void ThreadLocalStorage::set_thread_in_slot (Thread * self) {} +bool ThreadLocalStorage::is_initialized() { + return _initialized; +} + +Thread* ThreadLocalStorage::get_thread_slow() { + return thread(); +} extern "C" Thread* get_thread() { return ThreadLocalStorage::thread(); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp --- a/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,47 +25,15 @@ #ifndef OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP #define OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP -public: - // Java Thread - force inlining - static inline Thread* thread() ; +// Solaris specific implementation involves simple, direct use +// of a compiler-based thread-local variable private: - static Thread* _get_thread_cache[]; // index by [(raw_id>>9)^(raw_id>>20) % _pd_cache_size] - static Thread* get_thread_via_cache_slowly(uintptr_t raw_id, int index); + static __thread Thread * _thr_current; - NOT_PRODUCT(static int _tcacheHit;) - NOT_PRODUCT(static int _tcacheMiss;) + static bool _initialized; // needed for shared API public: - - // Print cache hit/miss statistics - static void print_statistics() PRODUCT_RETURN; - - enum Constants { - _pd_cache_size = 256*2 // projected typical # of threads * 2 - }; - - static void set_thread_in_slot (Thread *) ; - - static uintptr_t pd_raw_thread_id() { - return _raw_thread_id(); - } - - static int pd_cache_index(uintptr_t raw_id) { - // Hash function: From email from Dave: - // The hash function deserves an explanation. %g7 points to libthread's - // "thread" structure. On T1 the thread structure is allocated on the - // user's stack (yes, really!) so the ">>20" handles T1 where the JVM's - // stack size is usually >= 1Mb. The ">>9" is for T2 where Roger allocates - // globs of thread blocks contiguously. The "9" has to do with the - // expected size of the T2 thread structure. If these constants are wrong - // the worst thing that'll happen is that the hit rate for heavily threaded - // apps won't be as good as it could be. If you want to burn another - // shift+xor you could mix together _all of the %g7 bits to form the hash, - // but I think that's excessive. Making the change above changed the - // T$ miss rate on SpecJBB (on a 16X system) from about 3% to imperceptible. - uintptr_t ix = (int) (((raw_id >> 9) ^ (raw_id >> 20)) % _pd_cache_size); - return ix; - } + static inline Thread* thread(); #endif // OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP diff -r 49b8cecd1bbe -r 3f9a4c47edee src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp --- a/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * 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 @@ */ #include "precompiled.hpp" -#include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" #include "runtime/os.hpp" #include "runtime/threadLocalStorage.hpp" - +#include "runtime/thread.inline.hpp" void MacroAssembler::int3() { push(rax); @@ -39,98 +38,32 @@ pop(rax); } -#define __ _masm-> -#ifndef _LP64 -static void slow_call_thr_specific(MacroAssembler* _masm, Register thread) { - - // slow call to of thr_getspecific - // int thr_getspecific(thread_key_t key, void **value); - // Consider using pthread_getspecific instead. - -__ push(0); // allocate space for return value - if (thread != rax) __ push(rax); // save rax, if caller still wants it -__ push(rcx); // save caller save -__ push(rdx); // save caller save +// This is simply a call to ThreadLocalStorage::thread() +void MacroAssembler::get_thread(Register thread) { if (thread != rax) { -__ lea(thread, Address(rsp, 3 * sizeof(int))); // address of return value - } else { -__ lea(thread, Address(rsp, 2 * sizeof(int))); // address of return value + push(rax); } -__ push(thread); // and pass the address -__ push(ThreadLocalStorage::thread_index()); // the key -__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, thr_getspecific))); -__ increment(rsp, 2 * wordSize); -__ pop(rdx); -__ pop(rcx); - if (thread != rax) __ pop(rax); -__ pop(thread); - -} -#else -static void slow_call_thr_specific(MacroAssembler* _masm, Register thread) { - // slow call to of thr_getspecific - // int thr_getspecific(thread_key_t key, void **value); - // Consider using pthread_getspecific instead. + push(rdi); + push(rsi); + push(rdx); + push(rcx); + push(r8); + push(r9); + push(r10); + push(r11); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, ThreadLocalStorage::thread))); + + pop(r11); + pop(r10); + pop(r9); + pop(r8); + pop(rcx); + pop(rdx); + pop(rsi); + pop(rdi); if (thread != rax) { -__ push(rax); - } -__ push(0); // space for return value -__ push(rdi); -__ push(rsi); -__ lea(rsi, Address(rsp, 16)); // pass return value address -__ push(rdx); -__ push(rcx); -__ push(r8); -__ push(r9); -__ push(r10); - // XXX -__ mov(r10, rsp); -__ andptr(rsp, -16); -__ push(r10); -__ push(r11); - -__ movl(rdi, ThreadLocalStorage::thread_index()); -__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, thr_getspecific))); - -__ pop(r11); -__ pop(rsp); -__ pop(r10); -__ pop(r9); -__ pop(r8); -__ pop(rcx); -__ pop(rdx); -__ pop(rsi); -__ pop(rdi); -__ pop(thread); // load return value - if (thread != rax) { -__ pop(rax); + movl(thread, rax); + pop(rax); } } -#endif //LP64 - -void MacroAssembler::get_thread(Register thread) { - - int segment = NOT_LP64(Assembler::GS_segment) LP64_ONLY(Assembler::FS_segment); - // Try to emit a Solaris-specific fast TSD/TLS accessor. - ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_getTlsAccessMode (); - if (tlsMode == ThreadLocalStorage::pd_tlsAccessIndirect) { // T1 - // Use thread as a temporary: mov r, gs:[0]; mov r, [r+tlsOffset] - emit_int8 (segment); - // ExternalAddress doesn't work because it can't take NULL - AddressLiteral null(0, relocInfo::none); - movptr (thread, null); - movptr(thread, Address(thread, ThreadLocalStorage::pd_getTlsOffset())) ; - return ; - } else - if (tlsMode == ThreadLocalStorage::pd_tlsAccessDirect) { // T2 - // mov r, gs:[tlsOffset] - emit_int8 (segment); - AddressLiteral tls_off((address)ThreadLocalStorage::pd_getTlsOffset(), relocInfo::none); - movptr (thread, tls_off); - return ; - } - - slow_call_thr_specific(this, thread); - -} diff -r 49b8cecd1bbe -r 3f9a4c47edee src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp --- a/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * 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,167 +26,27 @@ #include "runtime/thread.inline.hpp" #include "runtime/threadLocalStorage.hpp" -#ifdef AMD64 -extern "C" Thread* fs_load(ptrdiff_t tlsOffset); -extern "C" intptr_t fs_thread(); -#else -// From solaris_i486.s -extern "C" Thread* gs_load(ptrdiff_t tlsOffset); -extern "C" intptr_t gs_thread(); -#endif // AMD64 +// True thread-local variable +__thread Thread * ThreadLocalStorage::_thr_current = NULL; + +// Implementations needed to support the shared API -// tlsMode encoding: -// -// pd_tlsAccessUndefined : uninitialized -// pd_tlsAccessSlow : not available -// pd_tlsAccessIndirect : -// old-style indirect access - present in "T1" libthread. -// use thr_slot_sync_allocate() to attempt to allocate a slot. -// pd_tlsAccessDirect : -// new-style direct access - present in late-model "T2" libthread. -// Allocate the offset (slot) via _thr_slot_offset() or by -// defining an IE- or LE-mode TLS/TSD slot in the launcher and then passing -// that offset into libjvm.so. -// See http://sac.eng/Archives/CaseLog/arc/PSARC/2003/159/. -// -// Note that we have a capability gap - some early model T2 forms -// (e.g., unpatched S9) have neither _thr_slot_sync_allocate() nor -// _thr_slot_offset(). In that case we revert to the usual -// thr_getspecific accessor. -// +void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do -static ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_tlsAccessUndefined ; -static ptrdiff_t tlsOffset = 0 ; -static thread_key_t tlsKey ; - -typedef int (*TSSA_Entry) (ptrdiff_t *, int, int) ; -typedef ptrdiff_t (*TSO_Entry) (int) ; +bool ThreadLocalStorage::_initialized = false; -ThreadLocalStorage::pd_tlsAccessMode ThreadLocalStorage::pd_getTlsAccessMode () -{ - guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ; - return tlsMode ; -} - -ptrdiff_t ThreadLocalStorage::pd_getTlsOffset () { - guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ; - return tlsOffset ; +void ThreadLocalStorage::init() { + _initialized = true; } -// TODO: Consider the following improvements: -// -// 1. Convert from thr_*specific* to pthread_*specific*. -// The pthread_ forms are slightly faster. Also, the -// pthread_ forms have a pthread_key_delete() API which -// would aid in clean JVM shutdown and the eventual goal -// of permitting a JVM to reinstantiate itself withing a process. -// -// 2. See ThreadLocalStorage::init(). We end up allocating -// two TLS keys during VM startup. That's benign, but we could collapse -// down to one key without too much trouble. -// -// 3. MacroAssembler::get_thread() currently emits calls to thr_getspecific(). -// Modify get_thread() to call Thread::current() instead. -// -// 4. Thread::current() currently uses a cache keyed by %gs:[0]. -// (The JVM has PSARC permission to use %g7/%gs:[0] -// as an opaque temporally unique thread identifier). -// For C++ access to a thread's reflexive "self" pointer we -// should consider using one of the following: -// a. a radix tree keyed by %esp - as in EVM. -// This requires two loads (the 2nd dependent on the 1st), but -// is easily inlined and doesn't require a "miss" slow path. -// b. a fast TLS/TSD slot allocated by _thr_slot_offset -// or _thr_slot_sync_allocate. -// -// 5. 'generate_code_for_get_thread' is a misnomer. -// We should change it to something more general like -// pd_ThreadSelf_Init(), for instance. -// - -static void AllocateTLSOffset () -{ - int rslt ; - TSSA_Entry tssa ; - TSO_Entry tso ; - ptrdiff_t off ; - - guarantee (tlsMode == ThreadLocalStorage::pd_tlsAccessUndefined, "tlsMode not set") ; - tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ; - tlsOffset = 0 ; -#ifndef AMD64 - - tssa = (TSSA_Entry) dlsym (RTLD_DEFAULT, "thr_slot_sync_allocate") ; - if (tssa != NULL) { - off = -1 ; - rslt = (*tssa)(&off, NULL, NULL) ; // (off,dtor,darg) - if (off != -1) { - tlsOffset = off ; - tlsMode = ThreadLocalStorage::pd_tlsAccessIndirect ; - return ; - } - } - - rslt = thr_keycreate (&tlsKey, NULL) ; - if (rslt != 0) { - tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ; // revert to slow mode - return ; - } - - tso = (TSO_Entry) dlsym (RTLD_DEFAULT, "_thr_slot_offset") ; - if (tso != NULL) { - off = (*tso)(tlsKey) ; - if (off >= 0) { - tlsOffset = off ; - tlsMode = ThreadLocalStorage::pd_tlsAccessDirect ; - return ; - } - } - - // Failure: Too bad ... we've allocated a TLS slot we don't need and there's - // no provision in the ABI for returning the slot. - // - // If we didn't find a slot then then: - // 1. We might be on liblwp. - // 2. We might be on T2 libthread, but all "fast" slots are already - // consumed - // 3. We might be on T1, and all TSD (thr_slot_sync_allocate) slots are - // consumed. - // 4. We might be on T2 libthread, but it's be re-architected - // so that fast slots are no longer g7-relative. - // - - tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ; - return ; -#endif // AMD64 +bool ThreadLocalStorage::is_initialized() { + return _initialized; } -void ThreadLocalStorage::generate_code_for_get_thread() { - AllocateTLSOffset() ; +Thread* ThreadLocalStorage::get_thread_slow() { + return thread(); } -void ThreadLocalStorage::set_thread_in_slot(Thread *thread) { - guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ; - if (tlsMode == pd_tlsAccessIndirect) { -#ifdef AMD64 - intptr_t tbase = fs_thread(); -#else - intptr_t tbase = gs_thread(); -#endif // AMD64 - *((Thread**) (tbase + tlsOffset)) = thread ; - } else - if (tlsMode == pd_tlsAccessDirect) { - thr_setspecific (tlsKey, (void *) thread) ; - // set with thr_setspecific and then readback with gs_load to validate. -#ifdef AMD64 - guarantee (thread == fs_load(tlsOffset), "tls readback failure") ; -#else - guarantee (thread == gs_load(tlsOffset), "tls readback failure") ; -#endif // AMD64 - } -} - - extern "C" Thread* get_thread() { return ThreadLocalStorage::thread(); } diff -r 49b8cecd1bbe -r 3f9a4c47edee src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp --- a/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,61 +25,15 @@ #ifndef OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP #define OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP -// Processor dependent parts of ThreadLocalStorage +// Solaris specific implementation involves simple, direct use +// of a compiler-based thread-local variable private: - static Thread* _get_thread_cache[]; // index by [(raw_id>>9)^(raw_id>>20) % _pd_cache_size] - static Thread* get_thread_via_cache_slowly(uintptr_t raw_id, int index); + static __thread Thread * _thr_current; - NOT_PRODUCT(static int _tcacheHit;) - NOT_PRODUCT(static int _tcacheMiss;) + static bool _initialized; // needed for shared API public: - // Cache hit/miss statistics - static void print_statistics() PRODUCT_RETURN; - - enum Constants { -#ifdef AMD64 - _pd_cache_size = 256*2 // projected typical # of threads * 2 -#else - _pd_cache_size = 128*2 // projected typical # of threads * 2 -#endif // AMD64 - }; - - enum pd_tlsAccessMode { - pd_tlsAccessUndefined = -1, - pd_tlsAccessSlow = 0, - pd_tlsAccessIndirect = 1, - pd_tlsAccessDirect = 2 - } ; - - static void set_thread_in_slot (Thread *) ; - - static pd_tlsAccessMode pd_getTlsAccessMode () ; - static ptrdiff_t pd_getTlsOffset () ; - - static uintptr_t pd_raw_thread_id() { -#ifdef _GNU_SOURCE -#ifdef AMD64 - uintptr_t rv; - __asm__ __volatile__ ("movq %%fs:0, %0" : "=r"(rv)); - return rv; -#else - return gs_thread(); -#endif // AMD64 -#else //_GNU_SOURCE - return _raw_thread_id(); -#endif //_GNU_SOURCE - } - - static int pd_cache_index(uintptr_t raw_id) { - // Copied from the sparc version. Dave said it should also work fine - // for solx86. - int ix = (int) (((raw_id >> 9) ^ (raw_id >> 20)) % _pd_cache_size); - return ix; - } - - // Java Thread static inline Thread* thread(); #endif // OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/c1/c1_Canonicalizer.cpp --- a/src/share/vm/c1/c1_Canonicalizer.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/c1/c1_Canonicalizer.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -265,7 +265,8 @@ // limit this optimization to current block if (value != NULL && in_current_block(conv)) { set_canonical(new StoreIndexed(x->array(), x->index(), x->length(), - x->elt_type(), value, x->state_before())); + x->elt_type(), value, x->state_before(), + x->check_boolean())); return; } } diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/c1/c1_GraphBuilder.cpp --- a/src/share/vm/c1/c1_GraphBuilder.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -975,7 +975,19 @@ (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) { length = append(new ArrayLength(array, state_before)); } - StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before); + ciType* array_type = array->declared_type(); + bool check_boolean = false; + if (array_type != NULL) { + if (array_type->is_loaded() && + array_type->as_array_klass()->element_type()->basic_type() == T_BOOLEAN) { + assert(type == T_BYTE, "boolean store uses bastore"); + Value mask = append(new Constant(new IntConstant(1))); + value = append(new LogicOp(Bytecodes::_iand, value, mask)); + } + } else if (type == T_BYTE) { + check_boolean = true; + } + StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before, check_boolean); append(result); _memory->store_value(value); @@ -1440,6 +1452,36 @@ need_mem_bar = true; } + BasicType bt = method()->return_type()->basic_type(); + switch (bt) { + case T_BYTE: + { + Value shift = append(new Constant(new IntConstant(24))); + x = append(new ShiftOp(Bytecodes::_ishl, x, shift)); + x = append(new ShiftOp(Bytecodes::_ishr, x, shift)); + break; + } + case T_SHORT: + { + Value shift = append(new Constant(new IntConstant(16))); + x = append(new ShiftOp(Bytecodes::_ishl, x, shift)); + x = append(new ShiftOp(Bytecodes::_ishr, x, shift)); + break; + } + case T_CHAR: + { + Value mask = append(new Constant(new IntConstant(0xFFFF))); + x = append(new LogicOp(Bytecodes::_iand, x, mask)); + break; + } + case T_BOOLEAN: + { + Value mask = append(new Constant(new IntConstant(1))); + x = append(new LogicOp(Bytecodes::_iand, x, mask)); + break; + } + } + // Check to see whether we are inlining. If so, Return // instructions become Gotos to the continuation point. if (continuation() != NULL) { @@ -1587,6 +1629,10 @@ if (state_before == NULL) { state_before = copy_state_for_exception(); } + if (field->type()->basic_type() == T_BOOLEAN) { + Value mask = append(new Constant(new IntConstant(1))); + val = append(new LogicOp(Bytecodes::_iand, val, mask)); + } append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching)); } break; @@ -1657,6 +1703,10 @@ if (state_before == NULL) { state_before = copy_state_for_exception(); } + if (field->type()->basic_type() == T_BOOLEAN) { + Value mask = append(new Constant(new IntConstant(1))); + val = append(new LogicOp(Bytecodes::_iand, val, mask)); + } StoreField* store = new StoreField(obj, offset, field, val, false, state_before, needs_patching); if (!needs_patching) store = _memory->store(store); if (store != NULL) { @@ -4222,7 +4272,12 @@ #ifndef _LP64 offset = append(new Convert(Bytecodes::_l2i, offset, as_ValueType(T_INT))); #endif - Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, args->at(3), is_volatile)); + Value val = args->at(3); + if (t == T_BOOLEAN) { + Value mask = append(new Constant(new IntConstant(1))); + val = append(new LogicOp(Bytecodes::_iand, val, mask)); + } + Instruction* op = append(new UnsafePutObject(t, args->at(1), offset, val, is_volatile)); compilation()->set_has_unsafe_access(true); kill_all(); } diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/c1/c1_Instruction.hpp --- a/src/share/vm/c1/c1_Instruction.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/c1/c1_Instruction.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -976,11 +976,13 @@ ciMethod* _profiled_method; int _profiled_bci; + bool _check_boolean; + public: // creation - StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* state_before) + StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value, ValueStack* state_before, bool check_boolean) : AccessIndexed(array, index, length, elt_type, state_before) - , _value(value), _profiled_method(NULL), _profiled_bci(0) + , _value(value), _profiled_method(NULL), _profiled_bci(0), _check_boolean(check_boolean) { set_flag(NeedsWriteBarrierFlag, (as_ValueType(elt_type)->is_object())); set_flag(NeedsStoreCheckFlag, (as_ValueType(elt_type)->is_object())); @@ -992,6 +994,7 @@ Value value() const { return _value; } bool needs_write_barrier() const { return check_flag(NeedsWriteBarrierFlag); } bool needs_store_check() const { return check_flag(NeedsStoreCheckFlag); } + bool check_boolean() const { return _check_boolean; } // Helpers for MethodData* profiling void set_should_profile(bool value) { set_flag(ProfileMDOFlag, value); } void set_profiled_method(ciMethod* method) { _profiled_method = method; } diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/c1/c1_LIRGenerator.cpp --- a/src/share/vm/c1/c1_LIRGenerator.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3646,3 +3646,26 @@ } } } + +LIR_Opr LIRGenerator::maybe_mask_boolean(StoreIndexed* x, LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info) { + if (x->check_boolean()) { + LIR_Opr value_fixed = rlock_byte(T_BYTE); + if (TwoOperandLIRForm) { + __ move(value, value_fixed); + __ logical_and(value_fixed, LIR_OprFact::intConst(1), value_fixed); + } else { + __ logical_and(value, LIR_OprFact::intConst(1), value_fixed); + } + LIR_Opr klass = new_register(T_METADATA); + __ move(new LIR_Address(array, oopDesc::klass_offset_in_bytes(), T_ADDRESS), klass, null_check_info); + null_check_info = NULL; + LIR_Opr layout = new_register(T_INT); + __ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout); + int diffbit = Klass::layout_helper_boolean_diffbit(); + __ logical_and(layout, LIR_OprFact::intConst(diffbit), layout); + __ cmp(lir_cond_notEqual, layout, LIR_OprFact::intConst(0)); + __ cmove(lir_cond_notEqual, value_fixed, value, value_fixed, T_BYTE); + value = value_fixed; + } + return value; +} diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/c1/c1_LIRGenerator.hpp --- a/src/share/vm/c1/c1_LIRGenerator.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/c1/c1_LIRGenerator.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -445,6 +445,7 @@ void profile_arguments(ProfileCall* x); void profile_parameters(Base* x); void profile_parameters_at_call(ProfileCall* x); + LIR_Opr maybe_mask_boolean(StoreIndexed* x, LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info); public: Compilation* compilation() const { return _compilation; } diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/classfile/classFileParser.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2417,11 +2417,9 @@ m->set_constants(_cp); m->set_name_index(name_index); m->set_signature_index(signature_index); -#ifdef CC_INTERP - // hmm is there a gc issue here?? + ResultTypeFinder rtf(_cp->symbol_at(signature_index)); - m->set_result_index(rtf.type()); -#endif + m->constMethod()->set_result_type(rtf.type()); if (args_size >= 0) { m->set_size_of_parameters(args_size); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/classfile/defaultMethods.cpp --- a/src/share/vm/classfile/defaultMethods.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/classfile/defaultMethods.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -892,10 +892,8 @@ m->set_constants(NULL); // This will get filled in later m->set_name_index(cp->utf8(name)); m->set_signature_index(cp->utf8(sig)); -#ifdef CC_INTERP ResultTypeFinder rtf(sig); - m->set_result_index(rtf.type()); -#endif + m->constMethod()->set_result_type(rtf.type()); m->set_size_of_parameters(params); m->set_max_stack(max_stack); m->set_max_locals(params); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/interpreter/bytecodeInterpreter.cpp --- a/src/share/vm/interpreter/bytecodeInterpreter.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1780,8 +1780,19 @@ ((objArrayOop) arrObj)->obj_at_put(index, rhsObject); UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3); } - CASE(_bastore): - ARRAY_STOREFROM32(T_BYTE, jbyte, "%d", STACK_INT, 0); + CASE(_bastore): { + ARRAY_INTRO(-3); + int item = STACK_INT(-1); + // if it is a T_BOOLEAN array, mask the stored value to 0/1 + if (arrObj->klass() == Universe::boolArrayKlassObj()) { + item &= 1; + } else { + assert(arrObj->klass() == Universe::byteArrayKlassObj(), + "should be byte array otherwise"); + } + ((typeArrayOop)arrObj)->byte_at_put(index, item); + UPDATE_PC_AND_TOS_AND_CONTINUE(1, -3); + } CASE(_castore): ARRAY_STOREFROM32(T_CHAR, jchar, "%d", STACK_INT, 0); CASE(_sastore): @@ -2012,7 +2023,7 @@ } else if (tos_type == ltos) { SET_STACK_LONG(obj->long_field_acquire(field_offset), 0); MORE_STACK(1); - } else if (tos_type == btos) { + } else if (tos_type == btos || tos_type == ztos) { SET_STACK_INT(obj->byte_field_acquire(field_offset), -1); } else if (tos_type == ctos) { SET_STACK_INT(obj->char_field_acquire(field_offset), -1); @@ -2033,7 +2044,7 @@ } else if (tos_type == ltos) { SET_STACK_LONG(obj->long_field(field_offset), 0); MORE_STACK(1); - } else if (tos_type == btos) { + } else if (tos_type == btos || tos_type == ztos) { SET_STACK_INT(obj->byte_field(field_offset), -1); } else if (tos_type == ctos) { SET_STACK_INT(obj->char_field(field_offset), -1); @@ -2122,6 +2133,9 @@ obj->release_obj_field_put(field_offset, STACK_OBJECT(-1)); } else if (tos_type == btos) { obj->release_byte_field_put(field_offset, STACK_INT(-1)); + } else if (tos_type == ztos) { + int bool_field = STACK_INT(-1); // only store LSB + obj->release_byte_field_put(field_offset, (bool_field & 1)); } else if (tos_type == ltos) { obj->release_long_field_put(field_offset, STACK_LONG(-1)); } else if (tos_type == ctos) { @@ -2142,6 +2156,9 @@ obj->obj_field_put(field_offset, STACK_OBJECT(-1)); } else if (tos_type == btos) { obj->byte_field_put(field_offset, STACK_INT(-1)); + } else if (tos_type == ztos) { + int bool_field = STACK_INT(-1); // only store LSB + obj->byte_field_put(field_offset, (bool_field & 1)); } else if (tos_type == ltos) { obj->long_field_put(field_offset, STACK_LONG(-1)); } else if (tos_type == ctos) { diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/interpreter/bytecodes.cpp --- a/src/share/vm/interpreter/bytecodes.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/interpreter/bytecodes.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -513,6 +513,7 @@ def(_fast_aputfield , "fast_aputfield" , "bJJ" , NULL , T_OBJECT , 0, true , _putfield ); def(_fast_bputfield , "fast_bputfield" , "bJJ" , NULL , T_INT , 0, true , _putfield ); + def(_fast_zputfield , "fast_zputfield" , "bJJ" , NULL , T_INT , 0, true , _putfield ); def(_fast_cputfield , "fast_cputfield" , "bJJ" , NULL , T_CHAR , 0, true , _putfield ); def(_fast_dputfield , "fast_dputfield" , "bJJ" , NULL , T_DOUBLE , 0, true , _putfield ); def(_fast_fputfield , "fast_fputfield" , "bJJ" , NULL , T_FLOAT , 0, true , _putfield ); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/interpreter/bytecodes.hpp --- a/src/share/vm/interpreter/bytecodes.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/interpreter/bytecodes.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -256,6 +256,7 @@ _fast_aputfield , _fast_bputfield , + _fast_zputfield , _fast_cputfield , _fast_dputfield , _fast_fputfield , diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/interpreter/interpreterRuntime.cpp --- a/src/share/vm/interpreter/interpreterRuntime.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/interpreter/interpreterRuntime.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1016,6 +1016,7 @@ switch(cp_entry->flag_state()) { case btos: // fall through + case ztos: // fall through case ctos: // fall through case stos: // fall through case itos: // fall through @@ -1052,7 +1053,8 @@ char sig_type = '\0'; switch(cp_entry->flag_state()) { - case btos: sig_type = 'Z'; break; + case btos: sig_type = 'B'; break; + case ztos: sig_type = 'Z'; break; case ctos: sig_type = 'C'; break; case stos: sig_type = 'S'; break; case itos: sig_type = 'I'; break; diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/interpreter/templateInterpreter.cpp --- a/src/share/vm/interpreter/templateInterpreter.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/interpreter/templateInterpreter.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,8 +61,9 @@ // Implementation of EntryPoint EntryPoint::EntryPoint() { - assert(number_of_states == 9, "check the code below"); + assert(number_of_states == 10, "check the code below"); _entry[btos] = NULL; + _entry[ztos] = NULL; _entry[ctos] = NULL; _entry[stos] = NULL; _entry[atos] = NULL; @@ -74,9 +75,10 @@ } -EntryPoint::EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) { - assert(number_of_states == 9, "check the code below"); +EntryPoint::EntryPoint(address bentry, address zentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry) { + assert(number_of_states == 10, "check the code below"); _entry[btos] = bentry; + _entry[ztos] = zentry; _entry[ctos] = centry; _entry[stos] = sentry; _entry[atos] = aentry; @@ -127,6 +129,7 @@ return EntryPoint( _table[btos][i], + _table[ztos][i], _table[ctos][i], _table[stos][i], _table[atos][i], @@ -141,8 +144,9 @@ void DispatchTable::set_entry(int i, EntryPoint& entry) { assert(0 <= i && i < length, "index out of bounds"); - assert(number_of_states == 9, "check the code below"); + assert(number_of_states == 10, "check the code below"); _table[btos][i] = entry.entry(btos); + _table[ztos][i] = entry.entry(ztos); _table[ctos][i] = entry.entry(ctos); _table[stos][i] = entry.entry(stos); _table[atos][i] = entry.entry(atos); @@ -225,6 +229,7 @@ Interpreter::_trace_code = EntryPoint( generate_trace_code(btos), + generate_trace_code(ztos), generate_trace_code(ctos), generate_trace_code(stos), generate_trace_code(atos), @@ -245,6 +250,7 @@ generate_return_entry_for(itos, i, index_size), generate_return_entry_for(itos, i, index_size), generate_return_entry_for(itos, i, index_size), + generate_return_entry_for(itos, i, index_size), generate_return_entry_for(atos, i, index_size), generate_return_entry_for(itos, i, index_size), generate_return_entry_for(ltos, i, index_size), @@ -256,13 +262,16 @@ } { CodeletMark cm(_masm, "invoke return entry points"); - const TosState states[] = {itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos}; + // These states are in order specified in TosState, except btos/ztos/ctos/stos are + // really the same as itos since there is no top of stack optimization for these types + const TosState states[] = {itos, itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos, ilgl}; const int invoke_length = Bytecodes::length_for(Bytecodes::_invokestatic); const int invokeinterface_length = Bytecodes::length_for(Bytecodes::_invokeinterface); const int invokedynamic_length = Bytecodes::length_for(Bytecodes::_invokedynamic); for (int i = 0; i < Interpreter::number_of_return_addrs; i++) { TosState state = states[i]; + assert(state != ilgl, "states array is wrong above"); Interpreter::_invoke_return_entry[i] = generate_return_entry_for(state, invoke_length, sizeof(u2)); Interpreter::_invokeinterface_return_entry[i] = generate_return_entry_for(state, invokeinterface_length, sizeof(u2)); Interpreter::_invokedynamic_return_entry[i] = generate_return_entry_for(state, invokedynamic_length, sizeof(u4)); @@ -273,6 +282,7 @@ Interpreter::_earlyret_entry = EntryPoint( generate_earlyret_entry_for(btos), + generate_earlyret_entry_for(ztos), generate_earlyret_entry_for(ctos), generate_earlyret_entry_for(stos), generate_earlyret_entry_for(atos), @@ -291,6 +301,7 @@ generate_deopt_entry_for(itos, i), generate_deopt_entry_for(itos, i), generate_deopt_entry_for(itos, i), + generate_deopt_entry_for(itos, i), generate_deopt_entry_for(atos, i), generate_deopt_entry_for(itos, i), generate_deopt_entry_for(ltos, i), @@ -318,6 +329,7 @@ Interpreter::_continuation_entry = EntryPoint( generate_continuation_for(btos), + generate_continuation_for(ztos), generate_continuation_for(ctos), generate_continuation_for(stos), generate_continuation_for(atos), @@ -333,6 +345,7 @@ Interpreter::_safept_entry = EntryPoint( generate_safept_entry_for(btos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), + generate_safept_entry_for(ztos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(ctos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(stos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), @@ -436,7 +449,7 @@ void TemplateInterpreterGenerator::set_unimplemented(int i) { address e = _unimplemented_bytecode; - EntryPoint entry(e, e, e, e, e, e, e, e, e); + EntryPoint entry(e, e, e, e, e, e, e, e, e, e); Interpreter::_normal_table.set_entry(i, entry); Interpreter::_wentry_point[i] = _unimplemented_bytecode; } @@ -448,6 +461,7 @@ assert(_unimplemented_bytecode != NULL, "should have been generated before"); assert(_illegal_bytecode_sequence != NULL, "should have been generated before"); address bep = _illegal_bytecode_sequence; + address zep = _illegal_bytecode_sequence; address cep = _illegal_bytecode_sequence; address sep = _illegal_bytecode_sequence; address aep = _illegal_bytecode_sequence; @@ -469,7 +483,7 @@ set_wide_entry_point(t, wep); } // set entry points - EntryPoint entry(bep, cep, sep, aep, iep, lep, fep, dep, vep); + EntryPoint entry(bep, zep, cep, sep, aep, iep, lep, fep, dep, vep); Interpreter::_normal_table.set_entry(code, entry); Interpreter::_wentry_point[code] = wep; } @@ -486,6 +500,7 @@ assert(t->is_valid(), "template must exist"); switch (t->tos_in()) { case btos: + case ztos: case ctos: case stos: ShouldNotReachHere(); // btos/ctos/stos should use itos. diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/interpreter/templateInterpreter.hpp --- a/src/share/vm/interpreter/templateInterpreter.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/interpreter/templateInterpreter.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ public: // Construction EntryPoint(); - EntryPoint(address bentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry); + EntryPoint(address bentry, address zentry, address centry, address sentry, address aentry, address ientry, address lentry, address fentry, address dentry, address ventry); // Attributes address entry(TosState state) const; // return target address for a given tosca state diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/interpreter/templateTable.cpp --- a/src/share/vm/interpreter/templateTable.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/interpreter/templateTable.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -493,6 +493,7 @@ def(Bytecodes::_fast_aputfield , ubcp|____|____|____, atos, vtos, fast_storefield , atos ); def(Bytecodes::_fast_bputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); + def(Bytecodes::_fast_zputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); def(Bytecodes::_fast_cputfield , ubcp|____|____|____, itos, vtos, fast_storefield , itos ); def(Bytecodes::_fast_dputfield , ubcp|____|____|____, dtos, vtos, fast_storefield , dtos ); def(Bytecodes::_fast_fputfield , ubcp|____|____|____, ftos, vtos, fast_storefield , ftos ); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/oops/constMethod.cpp --- a/src/share/vm/oops/constMethod.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/oops/constMethod.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,6 +65,7 @@ set_max_locals(0); set_method_idnum(0); set_size_of_parameters(0); + set_result_type(T_VOID); } // Accessor that copies to metadata. diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/oops/constMethod.hpp --- a/src/share/vm/oops/constMethod.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/oops/constMethod.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -211,6 +211,7 @@ int _constMethod_size; u2 _flags; + u1 _result_type; // BasicType of result // Size of Java bytecodes allocated immediately after Method*. u2 _code_size; @@ -469,6 +470,8 @@ static ByteSize size_of_parameters_offset() { return byte_offset_of(ConstMethod, _size_of_parameters); } + static ByteSize result_type_offset() + { return byte_offset_of(ConstMethod, _result_type); } // Unique id for the method static const u2 MAX_IDNUM; @@ -491,6 +494,8 @@ int size_of_parameters() const { return _size_of_parameters; } void set_size_of_parameters(int size) { _size_of_parameters = size; } + void set_result_type(BasicType rt) { assert(rt < 16, "result type too large"); + _result_type = (u1)rt; } // Deallocation for RedefineClasses void deallocate_contents(ClassLoaderData* loader_data); bool is_klass() const { return false; } diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/oops/cpCache.hpp --- a/src/share/vm/oops/cpCache.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/oops/cpCache.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,18 +77,19 @@ // f2 flag true if f2 contains an oop (e.g., virtual final method) // fv flag true if invokeinterface used for method in class Object // -// The flags 31, 30, 29, 28 together build a 4 bit number 0 to 8 with the +// The flags 31, 30, 29, 28 together build a 4 bit number 0 to 16 with the // following mapping to the TosState states: // // btos: 0 -// ctos: 1 -// stos: 2 -// itos: 3 -// ltos: 4 -// ftos: 5 -// dtos: 6 -// atos: 7 -// vtos: 8 +// ztos: 1 +// ctos: 2 +// stos: 3 +// itos: 4 +// ltos: 5 +// ftos: 6 +// dtos: 7 +// atos: 8 +// vtos: 9 // // Entry specific: field entries: // _indices = get (b1 section) and put (b2 section) bytecodes, original constant pool index @@ -351,14 +352,8 @@ bool has_method_type() const { return (!is_f1_null()) && (_flags & (1 << has_method_type_shift)) != 0; } bool is_method_entry() const { return (_flags & (1 << is_field_entry_shift)) == 0; } bool is_field_entry() const { return (_flags & (1 << is_field_entry_shift)) != 0; } - bool is_byte() const { return flag_state() == btos; } - bool is_char() const { return flag_state() == ctos; } - bool is_short() const { return flag_state() == stos; } - bool is_int() const { return flag_state() == itos; } bool is_long() const { return flag_state() == ltos; } - bool is_float() const { return flag_state() == ftos; } bool is_double() const { return flag_state() == dtos; } - bool is_object() const { return flag_state() == atos; } TosState flag_state() const { assert((uint)number_of_states <= (uint)tos_state_mask+1, ""); return (TosState)((_flags >> tos_state_shift) & tos_state_mask); } diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/oops/klass.hpp --- a/src/share/vm/oops/klass.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/oops/klass.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -370,6 +370,21 @@ assert(btvalue >= T_BOOLEAN && btvalue <= T_OBJECT, "sanity"); return (BasicType) btvalue; } + + // Want a pattern to quickly diff against layout header in register + // find something less clever! + static int layout_helper_boolean_diffbit() { + jint zlh = array_layout_helper(T_BOOLEAN); + jint blh = array_layout_helper(T_BYTE); + assert(zlh != blh, "array layout helpers must differ"); + int diffbit = 1; + while ((diffbit & (zlh ^ blh)) == 0 && (diffbit & zlh) == 0) { + diffbit <<= 1; + assert(diffbit != 0, "make sure T_BOOLEAN has a different bit than T_BYTE"); + } + return diffbit; + } + static int layout_helper_log2_element_size(jint lh) { assert(lh < (jint)_lh_neutral_value, "must be array"); int l2esz = (lh >> _lh_log2_element_size_shift) & _lh_log2_element_size_mask; diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/oops/method.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,9 +84,6 @@ set_constMethod(xconst); set_access_flags(access_flags); set_method_size(size); -#ifdef CC_INTERP - set_result_index(T_VOID); -#endif set_intrinsic_id(vmIntrinsics::_none); set_jfr_towrite(false); set_force_inline(false); @@ -417,12 +414,6 @@ set_size_of_parameters(asc.size() + (is_static() ? 0 : 1)); } -#ifdef CC_INTERP -void Method::set_result_index(BasicType type) { - _result_index = Interpreter::BasicType_as_index(type); -} -#endif - BasicType Method::result_type() const { ResultTypeFinder rtf(signature()); return rtf.type(); @@ -1140,10 +1131,8 @@ m->set_signature_index(_imcp_invoke_signature); assert(MethodHandles::is_signature_polymorphic_name(m->name()), ""); assert(m->signature() == signature, ""); -#ifdef CC_INTERP ResultTypeFinder rtf(signature); - m->set_result_index(rtf.type()); -#endif + m->constMethod()->set_result_type(rtf.type()); m->compute_size_of_parameters(THREAD); m->init_intrinsic_id(); assert(m->is_method_handle_intrinsic(), ""); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/oops/method.hpp --- a/src/share/vm/oops/method.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/oops/method.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -104,9 +104,6 @@ AccessFlags _access_flags; // Access flags int _vtable_index; // vtable index of this method (see VtableIndexFlag) // note: can have vtables with >2**16 elements (because of inheritance) -#ifdef CC_INTERP - int _result_index; // C++ interpreter needs for converting results to/from stack -#endif u2 _method_size; // size of this object u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) u1 _jfr_towrite : 1, // Flags @@ -201,11 +198,6 @@ return constMethod()->type_annotations(); } -#ifdef CC_INTERP - void set_result_index(BasicType type); - int result_index() { return _result_index; } -#endif - // Helper routine: get klass name + "." + method name + signature as // C string, for the purpose of providing more useful NoSuchMethodErrors // and fatal error handling. The string is allocated in resource @@ -564,7 +556,6 @@ void compute_size_of_parameters(Thread *thread); // word size of parameters (receiver if any + arguments) Symbol* klass_name() const; // returns the name of the method holder BasicType result_type() const; // type of the method result - int result_type_index() const; // type index of the method result bool is_returning_oop() const { BasicType r = result_type(); return (r == T_OBJECT || r == T_ARRAY); } bool is_returning_fp() const { BasicType r = result_type(); return (r == T_FLOAT || r == T_DOUBLE); } @@ -657,9 +648,6 @@ // interpreter support static ByteSize const_offset() { return byte_offset_of(Method, _constMethod ); } static ByteSize access_flags_offset() { return byte_offset_of(Method, _access_flags ); } -#ifdef CC_INTERP - static ByteSize result_index_offset() { return byte_offset_of(Method, _result_index ); } -#endif /* CC_INTERP */ static ByteSize from_compiled_offset() { return byte_offset_of(Method, _from_compiled_entry); } static ByteSize code_offset() { return byte_offset_of(Method, _code); } static ByteSize method_data_offset() { diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/oops/oop.inline.hpp --- a/src/share/vm/oops/oop.inline.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/oops/oop.inline.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -342,7 +342,7 @@ inline void oopDesc::byte_field_put(int offset, jbyte contents) { *byte_field_addr(offset) = (jint) contents; } inline jboolean oopDesc::bool_field(int offset) const { return (jboolean) *bool_field_addr(offset); } -inline void oopDesc::bool_field_put(int offset, jboolean contents) { *bool_field_addr(offset) = (jint) contents; } +inline void oopDesc::bool_field_put(int offset, jboolean contents) { *bool_field_addr(offset) = (( (jint) contents) & 1); } inline jchar oopDesc::char_field(int offset) const { return (jchar) *char_field_addr(offset); } inline void oopDesc::char_field_put(int offset, jchar contents) { *char_field_addr(offset) = (jint) contents; } @@ -382,7 +382,7 @@ inline void oopDesc::release_byte_field_put(int offset, jbyte contents) { OrderAccess::release_store(byte_field_addr(offset), contents); } inline jboolean oopDesc::bool_field_acquire(int offset) const { return OrderAccess::load_acquire(bool_field_addr(offset)); } -inline void oopDesc::release_bool_field_put(int offset, jboolean contents) { OrderAccess::release_store(bool_field_addr(offset), contents); } +inline void oopDesc::release_bool_field_put(int offset, jboolean contents) { OrderAccess::release_store(bool_field_addr(offset), (contents & 1)); } inline jchar oopDesc::char_field_acquire(int offset) const { return OrderAccess::load_acquire(char_field_addr(offset)); } inline void oopDesc::release_char_field_put(int offset, jchar contents) { OrderAccess::release_store(char_field_addr(offset), contents); } diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/oops/typeArrayOop.hpp --- a/src/share/vm/oops/typeArrayOop.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/oops/typeArrayOop.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -96,7 +96,7 @@ void byte_at_put(int which, jbyte contents) { *byte_at_addr(which) = contents; } jboolean bool_at(int which) const { return *bool_at_addr(which); } - void bool_at_put(int which, jboolean contents) { *bool_at_addr(which) = contents; } + void bool_at_put(int which, jboolean contents) { *bool_at_addr(which) = (((jint)contents) & 1); } jchar char_at(int which) const { return *char_at_addr(which); } void char_at_put(int which, jchar contents) { *char_at_addr(which) = contents; } diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/opto/memnode.cpp --- a/src/share/vm/opto/memnode.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/opto/memnode.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2370,7 +2370,7 @@ ctl != NULL, "raw memory operations should have control edge"); switch (bt) { - case T_BOOLEAN: + case T_BOOLEAN: val = gvn.transform(new (C) AndINode(val, gvn.intcon(0x1))); // Fall through to T_BYTE case case T_BYTE: return new (C) StoreBNode(ctl, mem, adr, adr_type, val, mo); case T_INT: return new (C) StoreINode(ctl, mem, adr, adr_type, val, mo); case T_CHAR: diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/opto/parse1.cpp --- a/src/share/vm/opto/parse1.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/opto/parse1.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -717,6 +717,27 @@ #endif } +static Node* mask_int_value(Node* v, BasicType bt, PhaseGVN* gvn) { + Compile* C = gvn->C; + switch (bt) { + case T_BYTE: + v = gvn->transform(new (C) LShiftINode(v, gvn->intcon(24))); + v = gvn->transform(new (C) RShiftINode(v, gvn->intcon(24))); + break; + case T_SHORT: + v = gvn->transform(new (C) LShiftINode(v, gvn->intcon(16))); + v = gvn->transform(new (C) RShiftINode(v, gvn->intcon(16))); + break; + case T_CHAR: + v = gvn->transform(new (C) AndINode(v, gvn->intcon(0xFFFF))); + break; + case T_BOOLEAN: + v = gvn->transform(new (C) AndINode(v, gvn->intcon(0x1))); + break; + } + return v; +} + //-------------------------------build_exits---------------------------------- // Build normal and exceptional exit merge points. void Parse::build_exits() { @@ -741,6 +762,16 @@ // Add a return value to the exit state. (Do not push it yet.) if (tf()->range()->cnt() > TypeFunc::Parms) { const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms); + if (ret_type->isa_int()) { + BasicType ret_bt = method()->return_type()->basic_type(); + if (ret_bt == T_BOOLEAN || + ret_bt == T_CHAR || + ret_bt == T_BYTE || + ret_bt == T_SHORT) { + ret_type = TypeInt::INT; + } + } + // Don't "bind" an unloaded return klass to the ret_phi. If the klass // becomes loaded during the subsequent parsing, the loaded and unloaded // types will not join when we transform and push in do_exits(). @@ -958,6 +989,10 @@ const Type* ret_type = tf()->range()->field_at(TypeFunc::Parms); Node* ret_phi = _gvn.transform( _exits.argument(0) ); assert(_exits.control()->is_top() || !_gvn.type(ret_phi)->empty(), "return value must be well defined"); + if (ret_type->isa_int()) { + BasicType ret_bt = method()->return_type()->basic_type(); + ret_phi = mask_int_value(ret_phi, ret_bt, &_gvn); + } _exits.push_node(ret_type->basic_type(), ret_phi); } diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/opto/parse2.cpp --- a/src/share/vm/opto/parse2.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/opto/parse2.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,11 +57,15 @@ //--------------------------------array_store---------------------------------- void Parse::array_store(BasicType elem_type) { - Node* adr = array_addressing(elem_type, 1); + const Type* elem = Type::TOP; + Node* adr = array_addressing(elem_type, 1, &elem); if (stopped()) return; // guaranteed null or range check Node* val = pop(); dec_sp(2); // Pop array and index const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(elem_type); + if (elem == TypeInt::BOOL) { + elem_type = T_BOOLEAN; + } store_to_memory(control(), adr, val, elem_type, adr_type, StoreNode::release_if_reference(elem_type)); } diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/opto/type.cpp --- a/src/share/vm/opto/type.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/opto/type.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1767,13 +1767,15 @@ break; case T_OBJECT: case T_ARRAY: + case T_FLOAT: + case T_INT: + field_array[pos++] = get_const_type(type); + break; case T_BOOLEAN: case T_CHAR: - case T_FLOAT: case T_BYTE: case T_SHORT: - case T_INT: - field_array[pos++] = get_const_type(type); + field_array[pos++] = TypeInt::INT; break; default: ShouldNotReachHere(); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/prims/jni.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -1121,7 +1121,14 @@ protected: va_list _ap; - inline void get_bool() { _arguments->push_int(va_arg(_ap, jint)); } // bool is coerced to int when using va_arg + inline void get_bool() { + // Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and + // 0 to JNI_FALSE. Boolean return values from native are normalized the same in + // TemplateInterpreterGenerator::generate_result_handler_for and + // SharedRuntime::generate_native_wrapper. + jboolean b = va_arg(_ap, jint); + _arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE)); + } inline void get_char() { _arguments->push_int(va_arg(_ap, jint)); } // char is coerced to int when using va_arg inline void get_short() { _arguments->push_int(va_arg(_ap, jint)); } // short is coerced to int when using va_arg inline void get_byte() { _arguments->push_int(va_arg(_ap, jint)); } // byte is coerced to int when using va_arg @@ -1167,9 +1174,17 @@ while ( 1 ) { switch ( fingerprint & parameter_feature_mask ) { case bool_parm: + get_bool(); + break; case char_parm: + get_char(); + break; case short_parm: + get_short(); + break; case byte_parm: + get_byte(); + break; case int_parm: get_int(); break; @@ -1203,7 +1218,14 @@ protected: const jvalue *_ap; - inline void get_bool() { _arguments->push_int((jint)(_ap++)->z); } + inline void get_bool() { + // Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and + // 0 to JNI_FALSE. Boolean return values from native are normalized the same in + // TemplateInterpreterGenerator::generate_result_handler_for and + // SharedRuntime::generate_native_wrapper. + jboolean b = (_ap++)->z; + _arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE)); + } inline void get_char() { _arguments->push_int((jint)(_ap++)->c); } inline void get_short() { _arguments->push_int((jint)(_ap++)->s); } inline void get_byte() { _arguments->push_int((jint)(_ap++)->b); } @@ -2828,6 +2850,7 @@ field_value.unionType = value; \ o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \ } \ + if (SigType == 'Z') { value = ((jboolean)value) & 1; } \ o->Fieldname##_field_put(offset, value); \ ReturnProbe; \ JNI_END @@ -3132,6 +3155,7 @@ field_value.unionType = value; \ JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \ } \ + if (SigType == 'Z') { value = ((jboolean)value) & 1; } \ id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \ ReturnProbe;\ JNI_END diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/prims/jvmtiEnvBase.cpp --- a/src/share/vm/prims/jvmtiEnvBase.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/prims/jvmtiEnvBase.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1348,7 +1348,7 @@ ResultTypeFinder rtf(signature); TosState fr_tos = as_TosState(rtf.type()); if (fr_tos != tos) { - if (tos != itos || (fr_tos != btos && fr_tos != ctos && fr_tos != stos)) { + if (tos != itos || (fr_tos != btos && fr_tos != ztos && fr_tos != ctos && fr_tos != stos)) { return JVMTI_ERROR_TYPE_MISMATCH; } } diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/prims/jvmtiExport.cpp --- a/src/share/vm/prims/jvmtiExport.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/prims/jvmtiExport.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1593,7 +1593,7 @@ address location, KlassHandle field_klass, Handle object, jfieldID field, char sig_type, jvalue *value) { - if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'C' || sig_type == 'S') { + if (sig_type == 'I' || sig_type == 'Z' || sig_type == 'B' || sig_type == 'C' || sig_type == 'S') { // 'I' instructions are used for byte, char, short and int. // determine which it really is, and convert fieldDescriptor fd; diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/prims/unsafe.cpp --- a/src/share/vm/prims/unsafe.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/prims/unsafe.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -156,13 +156,22 @@ ///// Data in the Java heap. +#define truncate_jboolean(x) ((x) & 1) +#define truncate_jbyte(x) (x) +#define truncate_jshort(x) (x) +#define truncate_jchar(x) (x) +#define truncate_jint(x) (x) +#define truncate_jlong(x) (x) +#define truncate_jfloat(x) (x) +#define truncate_jdouble(x) (x) + #define GET_FIELD(obj, offset, type_name, v) \ oop p = JNIHandles::resolve(obj); \ type_name v = *(type_name*)index_oop_from_field_offset_long(p, offset) #define SET_FIELD(obj, offset, type_name, x) \ oop p = JNIHandles::resolve(obj); \ - *(type_name*)index_oop_from_field_offset_long(p, offset) = x + *(type_name*)index_oop_from_field_offset_long(p, offset) = truncate_##type_name(x) #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \ oop p = JNIHandles::resolve(obj); \ @@ -173,7 +182,7 @@ #define SET_FIELD_VOLATILE(obj, offset, type_name, x) \ oop p = JNIHandles::resolve(obj); \ - OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x); + OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), truncate_##type_name(x)); // Macros for oops that check UseCompressedOops diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/runtime/deoptimization.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -852,13 +852,25 @@ _obj->int_field_put(offset, (jint)*((jint*)&val)); break; - case T_SHORT: case T_CHAR: // 2 bytes + case T_SHORT: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); _obj->short_field_put(offset, (jshort)*((jint*)&val)); break; - case T_BOOLEAN: case T_BYTE: // 1 byte + case T_CHAR: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + _obj->char_field_put(offset, (jchar)*((jint*)&val)); + break; + + case T_BYTE: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + _obj->byte_field_put(offset, (jbyte)*((jint*)&val)); + break; + + case T_BOOLEAN: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); _obj->bool_field_put(offset, (jboolean)*((jint*)&val)); @@ -904,13 +916,25 @@ obj->int_at_put(index, (jint)*((jint*)&val)); break; - case T_SHORT: case T_CHAR: // 2 bytes + case T_SHORT: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->short_at_put(index, (jshort)*((jint*)&val)); break; - case T_BOOLEAN: case T_BYTE: // 1 byte + case T_CHAR: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->char_at_put(index, (jchar)*((jint*)&val)); + break; + + case T_BYTE: + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->byte_at_put(index, (jbyte)*((jint*)&val)); + break; + + case T_BOOLEAN: assert(value->type() == T_INT, "Agreement."); val = value->get_int(); obj->bool_at_put(index, (jboolean)*((jint*)&val)); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/runtime/reflection.cpp --- a/src/share/vm/runtime/reflection.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/runtime/reflection.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1101,7 +1101,7 @@ void Reflection::narrow(jvalue* value, BasicType narrow_type, TRAPS) { switch (narrow_type) { case T_BOOLEAN: - value->z = (jboolean) value->i; + value->z = (jboolean) (value->i & 1); return; case T_BYTE: value->b = (jbyte) value->i; diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/runtime/threadLocalStorage.cpp --- a/src/share/vm/runtime/threadLocalStorage.cpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/runtime/threadLocalStorage.cpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,11 @@ # include "os_bsd.inline.hpp" #endif +// Solaris no longer has this kind of ThreadLocalStorage implementation. +// This will be removed from all platforms in the near future. + +#ifndef SOLARIS + // static member initialization int ThreadLocalStorage::_thread_index = -1; @@ -65,3 +70,5 @@ bool ThreadLocalStorage::is_initialized() { return (thread_index() != -1); } + +#endif // SOLARIS diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/runtime/threadLocalStorage.hpp --- a/src/share/vm/runtime/threadLocalStorage.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/runtime/threadLocalStorage.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -38,10 +38,14 @@ extern "C" uintptr_t _raw_thread_id(); class ThreadLocalStorage : AllStatic { + + // Exported API public: static void set_thread(Thread* thread); static Thread* get_thread_slow(); static void invalidate_all() { pd_invalidate_all(); } + static void init(); + static bool is_initialized(); // Machine dependent stuff #ifdef TARGET_OS_ARCH_linux_x86 @@ -81,17 +85,12 @@ # include "threadLS_bsd_zero.hpp" #endif - +#ifndef SOLARIS public: // Accessor static inline int thread_index() { return _thread_index; } static inline void set_thread_index(int index) { _thread_index = index; } - // Initialization - // Called explicitly from VMThread::activate_system instead of init_globals. - static void init(); - static bool is_initialized(); - private: static int _thread_index; @@ -100,6 +99,9 @@ // Processor dependent parts of set_thread and initialization static void pd_set_thread(Thread* thread); static void pd_init(); + +#endif // SOLARIS + // Invalidate any thread cacheing or optimization schemes. static void pd_invalidate_all(); diff -r 49b8cecd1bbe -r 3f9a4c47edee src/share/vm/utilities/globalDefinitions.hpp --- a/src/share/vm/utilities/globalDefinitions.hpp Sun Apr 10 01:08:29 2016 +0100 +++ b/src/share/vm/utilities/globalDefinitions.hpp Wed Apr 20 03:43:26 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -804,14 +804,15 @@ enum TosState { // describes the tos cache contents btos = 0, // byte, bool tos cached - ctos = 1, // char tos cached - stos = 2, // short tos cached - itos = 3, // int tos cached - ltos = 4, // long tos cached - ftos = 5, // float tos cached - dtos = 6, // double tos cached - atos = 7, // object cached - vtos = 8, // tos not cached + ztos = 1, // byte, bool tos cached + ctos = 2, // char tos cached + stos = 3, // short tos cached + itos = 4, // int tos cached + ltos = 5, // long tos cached + ftos = 6, // float tos cached + dtos = 7, // double tos cached + atos = 8, // object cached + vtos = 9, // tos not cached number_of_states, ilgl // illegal state: should not occur }; @@ -820,7 +821,7 @@ inline TosState as_TosState(BasicType type) { switch (type) { case T_BYTE : return btos; - case T_BOOLEAN: return btos; // FIXME: Add ztos + case T_BOOLEAN: return ztos; case T_CHAR : return ctos; case T_SHORT : return stos; case T_INT : return itos; @@ -836,8 +837,8 @@ inline BasicType as_BasicType(TosState state) { switch (state) { - //case ztos: return T_BOOLEAN;//FIXME case btos : return T_BYTE; + case ztos : return T_BOOLEAN; case ctos : return T_CHAR; case stos : return T_SHORT; case itos : return T_INT; diff -r 49b8cecd1bbe -r 3f9a4c47edee test/compiler/loopopts/CountedLoopProblem.java --- a/test/compiler/loopopts/CountedLoopProblem.java Sun Apr 10 01:08:29 2016 +0100 +++ b/test/compiler/loopopts/CountedLoopProblem.java Wed Apr 20 03:43:26 2016 +0100 @@ -36,18 +36,22 @@ public static void main(String[] args) throws Exception { Random r = new Random(42); int x = 0; - StringBuilder sb = new StringBuilder(); - for(int i = 0; i < 1000000; ++i) { - int v = Math.abs(r.nextInt()); - sb.append('+').append(v).append('\n'); - x += v; - // To trigger the problem we must OSR in the following loop - // To make the problem 100% reproducible run with -XX:-TieredCompilation -XX:OSROnlyBCI=62 - while(x < 0) x += 1000000000; - sb.append('=').append(x).append('\n'); - } - if (sb.toString().hashCode() != 0xaba94591) { - throw new Exception("Unexpected result"); + try { + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < 1000000; ++i) { + int v = Math.abs(r.nextInt()); + sb.append('+').append(v).append('\n'); + x += v; + // To trigger the problem we must OSR in the following loop + // To make the problem 100% reproducible run with -XX:-TieredCompilation -XX:OSROnlyBCI=62 + while(x < 0) x += 1000000000; + sb.append('=').append(x).append('\n'); + } + if (sb.toString().hashCode() != 0xaba94591) { + throw new Exception("Unexpected result"); + } + } catch(OutOfMemoryError e) { + // small heap, ignore } } } diff -r 49b8cecd1bbe -r 3f9a4c47edee test/gc/TestSoftReferencesBehaviorOnOOME.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/TestSoftReferencesBehaviorOnOOME.java Wed Apr 20 03:43:26 2016 +0100 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test TestSoftReferencesBehaviorOnOOME + * @key gc + * @summary Tests that all SoftReferences has been cleared at time of OOM. + * @library /testlibrary + * @build TestSoftReferencesBehaviorOnOOME + * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 512 2k + * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 128k 256k + * @run main/othervm -Xmx128m TestSoftReferencesBehaviorOnOOME 2k 32k 10 + */ +import java.util.*; +import com.oracle.java.testlibrary.Utils; +import java.lang.ref.SoftReference; +import java.util.LinkedList; + +public class TestSoftReferencesBehaviorOnOOME { + + private static final Random rndGenerator = new Random(); + + public static void main(String[] args) { + int semiRefAllocFrequency = DEFAULT_FREQUENCY; + long minSize = DEFAULT_MIN_SIZE, + maxSize = DEFAULT_MAX_SIZE; + + if ( args.length >= 3 ) { + semiRefAllocFrequency = Integer.parseInt(args[2]); + } + + if ( args.length >= 2) { + maxSize = getBytesCount(args[1]); + } + + if ( args.length >= 1) { + minSize = getBytesCount(args[0]); + } + + new TestSoftReferencesBehaviorOnOOME().softReferencesOom(minSize, maxSize, semiRefAllocFrequency); + } + + /** + * Test that all SoftReferences has been cleared at time of OOM. + */ + void softReferencesOom(long minSize, long maxSize, int semiRefAllocFrequency) { + System.out.format( "minSize = %d, maxSize = %d, freq = %d%n", minSize, maxSize, semiRefAllocFrequency ); + long counter = 0; + + long multiplier = maxSize - minSize; + LinkedList arrSoftRefs = new LinkedList(); + LinkedList arrObjects = new LinkedList(); + long numberOfNotNulledObjects = 0; + long oomSoftArraySize = 0; + + try { + while (true) { + // Keep every Xth object to make sure we hit OOM pretty fast + if (counter % semiRefAllocFrequency != 0) { + long allocationSize = ((int) (rndGenerator.nextDouble() * multiplier)) + + minSize; + arrObjects.add(new byte[(int)allocationSize]); + } else { + arrSoftRefs.add(new SoftReference(new Object())); + } + + counter++; + if (counter == Long.MAX_VALUE) { + counter = 0; + } + } + } catch (OutOfMemoryError oome) { + // Clear allocated ballast, so we don't get another OOM. + + arrObjects = null; + + // Get the number of soft refs first, so we don't trigger + // another OOM. + oomSoftArraySize = arrSoftRefs.size(); + + for (SoftReference sr : arrSoftRefs) { + Object o = sr.get(); + + if (o != null) { + numberOfNotNulledObjects++; + } + } + + // Make sure we clear all refs before we return failure + arrSoftRefs = null; + + if (numberOfNotNulledObjects > 0) { + throw new RuntimeException(numberOfNotNulledObjects + " out of " + + oomSoftArraySize + " SoftReferences was not " + + "null at time of OutOfMemoryError"); + } + } finally { + arrSoftRefs = null; + arrObjects = null; + } + } + + private static final long getBytesCount(String arg) { + String postfixes = "kMGT"; + long mod = 1; + + if (arg.trim().length() >= 2) { + mod = postfixes.indexOf( + arg.trim().charAt(arg.length() - 1) + ); + + if (mod != -1) { + mod = (long) Math.pow(1024, mod+1); + arg = arg.substring(0, arg.length() - 1); + } else { + mod = 1; // 10^0 + } + } + + return Long.parseLong(arg) * mod; + } + + private static final long DEFAULT_MIN_SIZE = 512; + private static final long DEFAULT_MAX_SIZE = 1024; + private static final int DEFAULT_FREQUENCY = 4; +} diff -r 49b8cecd1bbe -r 3f9a4c47edee test/runtime/NMT/JcmdWithNMTDisabled.java --- a/test/runtime/NMT/JcmdWithNMTDisabled.java Sun Apr 10 01:08:29 2016 +0100 +++ b/test/runtime/NMT/JcmdWithNMTDisabled.java Wed Apr 20 03:43:26 2016 +0100 @@ -26,10 +26,7 @@ * @key nmt jcmd * @summary Verify that jcmd correctly reports that NMT is not enabled * @library /testlibrary - * First run without enabling NMT - * @run main/othervm JcmdWithNMTDisabled - * Then run with explicitly disabling NMT, should not be any difference - * @run main/othervm -XX:NativeMemoryTracking=off JcmdWithNMTDisabled + * @run main JcmdWithNMTDisabled 1 */ import com.oracle.java.testlibrary.*; @@ -39,6 +36,27 @@ static String pid; public static void main(String args[]) throws Exception { + + // This test explicitly needs to be run with the exact command lines below, not passing on + // arguments from the parent VM is a conscious choice to avoid NMT being turned on. + if (args.length > 0) { + ProcessBuilder pb; + OutputAnalyzer output; + String testjdkPath = System.getProperty("test.jdk"); + + // First run without enabling NMT + pb = ProcessTools.createJavaProcessBuilder("-Dtest.jdk=" + testjdkPath, "JcmdWithNMTDisabled"); + output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + + // Then run with explicitly disabling NMT, should not be any difference + pb = ProcessTools.createJavaProcessBuilder("-Dtest.jdk=" + testjdkPath, "-XX:NativeMemoryTracking=off", "JcmdWithNMTDisabled"); + output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + + return; + } + // Grab my own PID pid = Integer.toString(ProcessTools.getProcessId());