# HG changeset patch # User amurillo # Date 1396023341 25200 # Node ID a6e433ebd892027b42e18987dce9a90095f3f6eb # Parent 5c9e34b1d8840a906229ca64ba989f3b3a1327fd# Parent 9df17c84daccb1bd1144e77489b51781a8de4185 Merge diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m --- a/hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m Fri Mar 28 09:15:41 2014 -0700 @@ -95,7 +95,9 @@ #define CHECK_EXCEPTION_CLEAR_(value) if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionClear(env); return value; } static void throw_new_debugger_exception(JNIEnv* env, const char* errMsg) { - (*env)->ThrowNew(env, (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"), errMsg); + jclass exceptionClass = (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"); + CHECK_EXCEPTION; + (*env)->ThrowNew(env, exceptionClass, errMsg); } static struct ps_prochandle* get_proc_handle(JNIEnv* env, jobject this_obj) { @@ -129,6 +131,7 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) { symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J"); + CHECK_EXCEPTION; taskID = (*env)->GetFieldID(env, cls, "task", "J"); CHECK_EXCEPTION; @@ -236,13 +239,16 @@ (JNIEnv *env, jobject this_obj, jlong addr) { uintptr_t offset; const char* sym = NULL; + jstring sym_string; struct ps_prochandle* ph = get_proc_handle(env, this_obj); if (ph != NULL && ph->core != NULL) { sym = symbol_for_pc(ph, (uintptr_t) addr, &offset); if (sym == NULL) return 0; + sym_string = (*env)->NewStringUTF(env, sym); + CHECK_EXCEPTION_(0); return (*env)->CallObjectMethod(env, this_obj, createClosestSymbol_ID, - (*env)->NewStringUTF(env, sym), (jlong)offset); + sym_string, (jlong)offset); } return 0; } @@ -749,11 +755,14 @@ const char* name; jobject loadObject; jobject loadObjectList; + jstring nameString; base = get_lib_base(ph, i); name = get_lib_name(ph, i); + nameString = (*env)->NewStringUTF(env, name); + CHECK_EXCEPTION; loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID, - (*env)->NewStringUTF(env, name), (jlong)0, (jlong)base); + nameString, (jlong)0, (jlong)base); CHECK_EXCEPTION; loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID); CHECK_EXCEPTION; diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/make/Makefile --- a/hotspot/make/Makefile Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/make/Makefile Fri Mar 28 09:15:41 2014 -0700 @@ -287,8 +287,43 @@ @$(ECHO) "Error: trying to build a minimal target but JVM_VARIANT_MINIMAL1 is not true." endif +remove_old_debuginfo: +ifeq ($(JVM_VARIANT_CLIENT), true) + ifeq ($(ZIP_DEBUGINFO_FILES),1) + ifeq ($(OSNAME), windows) + $(RM) -f $(EXPORT_CLIENT_DIR)/jvm.map $(EXPORT_CLIENT_DIR)/jvm.pdb + else + $(RM) -f $(EXPORT_CLIENT_DIR)/libjvm.debuginfo + endif + else + $(RM) -f $(EXPORT_CLIENT_DIR)/libjvm.diz + endif +endif +ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) + ifeq ($(ZIP_DEBUGINFO_FILES),1) + ifeq ($(OSNAME), windows) + $(RM) -f $(EXPORT_SERVER_DIR)/jvm.map $(EXPORT_SERVER_DIR)/jvm.pdb + else + ifeq ($(OS_VENDOR), Darwin) + $(RM) -rf $(EXPORT_SERVER_DIR)/libjvm.dylib.dSYM + else + $(RM) -f $(EXPORT_SERVER_DIR)/libjvm.debuginfo + endif + endif + else + $(RM) -f $(EXPORT_SERVER_DIR)/libjvm.diz + endif +endif +ifeq ($(JVM_VARIANT_MINIMAL1),true) + ifeq ($(ZIP_DEBUGINFO_FILES),1) + $(RM) -f $(EXPORT_MINIMAL_DIR)/libjvm.debuginfo + else + $(RM) -f $(EXPORT_MINIMAL_DIR)/libjvm.diz + endif +endif + # Export file rule -generic_export: $(EXPORT_LIST) +generic_export: $(EXPORT_LIST) remove_old_debuginfo export_product: $(MAKE) BUILD_FLAVOR=$(@:export_%=%) generic_export @@ -841,4 +876,4 @@ export_jdk_product export_jdk_fastdebug export_jdk_debug \ create_jdk copy_jdk update_jdk test_jdk \ copy_product_jdk copy_fastdebug_jdk copy_debug_jdk \ - $(HS_ALT_MAKE)/Makefile.make + $(HS_ALT_MAKE)/Makefile.make remove_old_debuginfo diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/make/aix/makefiles/vm.make --- a/hotspot/make/aix/makefiles/vm.make Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/make/aix/makefiles/vm.make Fri Mar 28 09:15:41 2014 -0700 @@ -101,7 +101,7 @@ # This is VERY important! The version define must only be supplied to vm_version.o # If not, ccache will not re-use the cache at all, since the version string might contain # a time and date. -vm_version.o: CXXFLAGS += ${JRE_VERSION} +CXXFLAGS/vm_version.o += ${JRE_VERSION} CXXFLAGS/BYFILE = $(CXXFLAGS/$@) diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/ppc/vm/assembler_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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 @@ -24,7 +24,6 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" #include "asm/assembler.inline.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "interpreter/interpreter.hpp" @@ -37,6 +36,7 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/macros.hpp" #if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" @@ -384,10 +384,10 @@ bool load_xa = (xa != 0) || (xb < 0); bool return_xd = false; - if (load_xa) lis(tmp, xa); - if (xc) lis(d, xc); + if (load_xa) { lis(tmp, xa); } + if (xc) { lis(d, xc); } if (load_xa) { - if (xb) ori(tmp, tmp, xb); // No addi, we support tmp == R0. + if (xb) { ori(tmp, tmp, (unsigned short)xb); } // No addi, we support tmp == R0. } else { li(tmp, xb); // non-negative } @@ -409,18 +409,18 @@ // opt 4: avoid adding 0 if (xa) { // Highest 16-bit needed? lis(d, xa); - if (xb) addi(d, d, xb); + if (xb) { addi(d, d, xb); } } else { li(d, xb); } sldi(d, d, 32); - if (xc) addis(d, d, xc); + if (xc) { addis(d, d, xc); } } // opt 5: Return offset to be inserted into following instruction. if (return_simm16_rest) return xd; - if (xd) addi(d, d, xd); + if (xd) { addi(d, d, xd); } return 0; } @@ -696,4 +696,5 @@ tty->print_cr("\ntest_asm disassembly (0x%lx 0x%lx):", code()->insts_begin(), code()->insts_end()); code()->decode(); } + #endif // !PRODUCT diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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 @@ -139,7 +139,8 @@ inline void Assembler::cmplw( ConditionRegister crx, Register a, Register b) { Assembler::cmpl( crx, 0, a, b); } inline void Assembler::cmpld( ConditionRegister crx, Register a, Register b) { Assembler::cmpl( crx, 1, a, b); } -inline void Assembler::isel(Register d, Register a, Register b, int c) { emit_int32(ISEL_OPCODE | rt(d) | ra(a) | rb(b) | bc(c)); } +inline void Assembler::isel(Register d, Register a, Register b, int c) { guarantee(VM_Version::has_isel(), "opcode not supported on this hardware"); + emit_int32(ISEL_OPCODE | rt(d) | ra(a) | rb(b) | bc(c)); } // PPC 1, section 3.3.11, Fixed-Point Logical Instructions inline void Assembler::andi_( Register a, Register s, int ui16) { emit_int32(ANDI_OPCODE | rta(a) | rs(s) | uimm(ui16, 16)); } @@ -531,9 +532,12 @@ //inline void Assembler::mffgpr( FloatRegister d, Register b) { emit_int32( MFFGPR_OPCODE | frt(d) | rb(b) | rc(0)); } //inline void Assembler::mftgpr( Register d, FloatRegister b) { emit_int32( MFTGPR_OPCODE | rt(d) | frb(b) | rc(0)); } // add cmpb and popcntb to detect ppc power version. -inline void Assembler::cmpb( Register a, Register s, Register b) { emit_int32( CMPB_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } -inline void Assembler::popcntb(Register a, Register s) { emit_int32( POPCNTB_OPCODE | rta(a) | rs(s)); }; -inline void Assembler::popcntw(Register a, Register s) { emit_int32( POPCNTW_OPCODE | rta(a) | rs(s)); }; +inline void Assembler::cmpb( Register a, Register s, Register b) { guarantee(VM_Version::has_cmpb(), "opcode not supported on this hardware"); + emit_int32( CMPB_OPCODE | rta(a) | rs(s) | rb(b) | rc(0)); } +inline void Assembler::popcntb(Register a, Register s) { guarantee(VM_Version::has_popcntb(), "opcode not supported on this hardware"); + emit_int32( POPCNTB_OPCODE | rta(a) | rs(s)); }; +inline void Assembler::popcntw(Register a, Register s) { guarantee(VM_Version::has_popcntw(), "opcode not supported on this hardware"); + emit_int32( POPCNTW_OPCODE | rta(a) | rs(s)); }; inline void Assembler::popcntd(Register a, Register s) { emit_int32( POPCNTD_OPCODE | rta(a) | rs(s)); }; inline void Assembler::fneg( FloatRegister d, FloatRegister b) { emit_int32( FNEG_OPCODE | frt(d) | frb(b) | rc(0)); } @@ -568,14 +572,17 @@ inline void Assembler::fctiw( FloatRegister d, FloatRegister b) { emit_int32( FCTIW_OPCODE | frt(d) | frb(b) | rc(0)); } inline void Assembler::fctiwz(FloatRegister d, FloatRegister b) { emit_int32( FCTIWZ_OPCODE | frt(d) | frb(b) | rc(0)); } inline void Assembler::fcfid( FloatRegister d, FloatRegister b) { emit_int32( FCFID_OPCODE | frt(d) | frb(b) | rc(0)); } -inline void Assembler::fcfids(FloatRegister d, FloatRegister b) { emit_int32( FCFIDS_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fcfids(FloatRegister d, FloatRegister b) { guarantee(VM_Version::has_fcfids(), "opcode not supported on this hardware"); + emit_int32( FCFIDS_OPCODE | frt(d) | frb(b) | rc(0)); } // PPC 1, section 4.6.7 Floating-Point Compare Instructions inline void Assembler::fcmpu( ConditionRegister crx, FloatRegister a, FloatRegister b) { emit_int32( FCMPU_OPCODE | bf(crx) | fra(a) | frb(b)); } // PPC 1, section 5.2.1 Floating-Point Arithmetic Instructions -inline void Assembler::fsqrt( FloatRegister d, FloatRegister b) { emit_int32( FSQRT_OPCODE | frt(d) | frb(b) | rc(0)); } -inline void Assembler::fsqrts(FloatRegister d, FloatRegister b) { emit_int32( FSQRTS_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fsqrt( FloatRegister d, FloatRegister b) { guarantee(VM_Version::has_fsqrt(), "opcode not supported on this hardware"); + emit_int32( FSQRT_OPCODE | frt(d) | frb(b) | rc(0)); } +inline void Assembler::fsqrts(FloatRegister d, FloatRegister b) { guarantee(VM_Version::has_fsqrts(), "opcode not supported on this hardware"); + emit_int32( FSQRTS_OPCODE | frt(d) | frb(b) | rc(0)); } // Vector instructions for >= Power6. inline void Assembler::lvebx( VectorRegister d, Register s1, Register s2) { emit_int32( LVEBX_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } @@ -703,7 +710,8 @@ inline void Assembler::vcmpgtub_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUB_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); } inline void Assembler::vcmpgtuh_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUH_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); } inline void Assembler::vcmpgtuw_(VectorRegister d,VectorRegister a, VectorRegister b) { emit_int32( VCMPGTUW_OPCODE | vrt(d) | vra(a) | vrb(b) | vcmp_rc(1)); } -inline void Assembler::vand( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VAND_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vand( VectorRegister d, VectorRegister a, VectorRegister b) { guarantee(VM_Version::has_vand(), "opcode not supported on this hardware"); + emit_int32( VAND_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vandc( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VANDC_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vnor( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VNOR_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vor( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VOR_OPCODE | vrt(d) | vra(a) | vrb(b)); } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/c2_globals_ppc.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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 @@ -87,7 +87,7 @@ define_pd_global(uintx, CodeCacheMinBlockLength, 4); define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); -define_pd_global(bool, TrapBasedRangeChecks, false); +define_pd_global(bool, TrapBasedRangeChecks, true); // Heap related flags define_pd_global(uintx,MetaspaceSize, ScaleForWordSize(16*M)); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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 @@ -24,8 +24,6 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" -#include "asm/assembler.inline.hpp" #include "asm/macroAssembler.inline.hpp" #include "compiler/disassembler.hpp" #include "gc_interface/collectedHeap.inline.hpp" @@ -1120,7 +1118,7 @@ } return _last_calls_return_pc; } -#endif +#endif // ABI_ELFv2 void MacroAssembler::call_VM_base(Register oop_result, Register last_java_sp, @@ -1794,7 +1792,7 @@ cmpwi(cr_reg, temp_reg, markOopDesc::biased_lock_pattern); bne(cr_reg, cas_label); - load_klass_with_trap_null_check(temp_reg, obj_reg); + load_klass(temp_reg, obj_reg); load_const_optimized(temp2_reg, ~((int) markOopDesc::age_mask_in_place)); ld(temp_reg, in_bytes(Klass::prototype_header_offset()), temp_reg); @@ -1891,7 +1889,7 @@ // the bias from one thread to another directly in this situation. andi(temp_reg, mark_reg, markOopDesc::age_mask_in_place); orr(temp_reg, R16_thread, temp_reg); - load_klass_with_trap_null_check(temp2_reg, obj_reg); + load_klass(temp2_reg, obj_reg); ld(temp2_reg, in_bytes(Klass::prototype_header_offset()), temp2_reg); orr(temp_reg, temp_reg, temp2_reg); @@ -1927,7 +1925,7 @@ // that another thread raced us for the privilege of revoking the // bias of this particular object, so it's okay to continue in the // normal locking code. - load_klass_with_trap_null_check(temp_reg, obj_reg); + load_klass(temp_reg, obj_reg); ld(temp_reg, in_bytes(Klass::prototype_header_offset()), temp_reg); andi(temp2_reg, mark_reg, markOopDesc::age_mask_in_place); orr(temp_reg, temp_reg, temp2_reg); @@ -2213,8 +2211,7 @@ stbx(R0, Rtmp, Robj); } -#ifndef SERIALGC - +#if INCLUDE_ALL_GCS // General G1 pre-barrier generator. // Goal: record the previous value if it is not null. void MacroAssembler::g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val, @@ -2328,14 +2325,17 @@ // Get the address of the card. lbzx(/*card value*/ Rtmp3, Rbase, Rcard_addr); - - assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code"); - cmpwi(CCR0, Rtmp3 /* card value */, 0); + cmpwi(CCR0, Rtmp3, (int)G1SATBCardTableModRefBS::g1_young_card_val()); + beq(CCR0, filtered); + + membar(Assembler::StoreLoad); + lbzx(/*card value*/ Rtmp3, Rbase, Rcard_addr); // Reload after membar. + cmpwi(CCR0, Rtmp3 /* card value */, CardTableModRefBS::dirty_card_val()); beq(CCR0, filtered); // Storing a region crossing, non-NULL oop, card is clean. // Dirty card and log. - li(Rtmp3, 0); // dirty + li(Rtmp3, CardTableModRefBS::dirty_card_val()); //release(); // G1: oops are allowed to get visible after dirty marking. stbx(Rtmp3, Rbase, Rcard_addr); @@ -2362,7 +2362,7 @@ bind(filtered_int); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Values for last_Java_pc, and last_Java_sp must comply to the rules // in frame_ppc64.hpp. @@ -2453,7 +2453,8 @@ void MacroAssembler::encode_klass_not_null(Register dst, Register src) { Register current = (src != noreg) ? src : dst; // Klass is in dst if no src provided. if (Universe::narrow_klass_base() != 0) { - load_const(R0, Universe::narrow_klass_base(), (dst != current) ? dst : noreg); // Use dst as temp if it is free. + // Use dst as temp if it is free. + load_const(R0, Universe::narrow_klass_base(), (dst != current && dst != R0) ? dst : noreg); sub(dst, current, R0); current = dst; } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -514,14 +514,14 @@ void card_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp); void card_table_write(jbyte* byte_map_base, Register Rtmp, Register Robj); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // General G1 pre-barrier generator. void g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val, Register Rtmp1, Register Rtmp2, bool needs_frame = false); // General G1 post-barrier generator void g1_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp1, Register Rtmp2, Register Rtmp3, Label *filtered_ext = NULL); -#endif // SERIALGC +#endif // Support for managing the JavaThread pointer (i.e.; the reference to // thread-local information). diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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 @@ -119,6 +119,7 @@ void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register target, Register temp, bool for_compiler_entry) { + Label L_no_such_method; assert(method == R19_method, "interpreter calling convention"); assert_different_registers(method, target, temp); @@ -131,17 +132,31 @@ __ lwz(temp, in_bytes(JavaThread::interp_only_mode_offset()), R16_thread); __ cmplwi(CCR0, temp, 0); __ beq(CCR0, run_compiled_code); + // Null method test is replicated below in compiled case, + // it might be able to address across the verify_thread() + __ cmplwi(CCR0, R19_method, 0); + __ beq(CCR0, L_no_such_method); __ ld(target, in_bytes(Method::interpreter_entry_offset()), R19_method); __ mtctr(target); __ bctr(); __ BIND(run_compiled_code); } + // Compiled case, either static or fall-through from runtime conditional + __ cmplwi(CCR0, R19_method, 0); + __ beq(CCR0, L_no_such_method); + const ByteSize entry_offset = for_compiler_entry ? Method::from_compiled_offset() : Method::from_interpreted_offset(); __ ld(target, in_bytes(entry_offset), R19_method); __ mtctr(target); __ bctr(); + + __ bind(L_no_such_method); + assert(StubRoutines::throw_AbstractMethodError_entry() != NULL, "not yet generated!"); + __ load_const_optimized(target, StubRoutines::throw_AbstractMethodError_entry()); + __ mtctr(target); + __ bctr(); } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/ppc/vm/ppc.ad --- a/hotspot/src/cpu/ppc/vm/ppc.ad Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/ppc.ad Fri Mar 28 09:15:41 2014 -0700 @@ -891,6 +891,13 @@ // This is a block of C++ code which provides values, functions, and // definitions necessary in the rest of the architecture description. source_hpp %{ + // Header information of the source block. + // Method declarations/definitions which are used outside + // the ad-scope can conveniently be defined here. + // + // To keep related declarations/definitions/uses close together, + // we switch between source %{ }% and source_hpp %{ }% freely as needed. + // Returns true if Node n is followed by a MemBar node that // will do an acquire. If so, this node must not do the acquire // operation. @@ -1114,6 +1121,40 @@ //============================================================================= +%} // interrupt source + +source_hpp %{ // Header information of the source block. + +//-------------------------------------------------------------- +//---< Used for optimization in Compile::Shorten_branches >--- +//-------------------------------------------------------------- + +const uint trampoline_stub_size = 6 * BytesPerInstWord; + +class CallStubImpl { + + public: + + static void emit_trampoline_stub(MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset); + + // Size of call trampoline stub. + // This doesn't need to be accurate to the byte, but it + // must be larger than or equal to the real size of the stub. + static uint size_call_trampoline() { + return trampoline_stub_size; + } + + // number of relocations needed by a call trampoline stub + static uint reloc_call_trampoline() { + return 5; + } + +}; + +%} // end source_hpp + +source %{ + // Emit a trampoline stub for a call to a target which is too far away. // // code sequences: @@ -1125,9 +1166,7 @@ // load the call target from the constant pool // branch via CTR (LR/link still points to the call-site above) -const uint trampoline_stub_size = 6 * BytesPerInstWord; - -void emit_trampoline_stub(MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset) { +void CallStubImpl::emit_trampoline_stub(MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset) { // Start the stub. address stub = __ start_a_stub(Compile::MAX_stubs_size/2); if (stub == NULL) { @@ -1170,19 +1209,6 @@ __ end_a_stub(); } -// Size of trampoline stub, this doesn't need to be accurate but it must -// be larger or equal to the real size of the stub. -// Used for optimization in Compile::Shorten_branches. -uint size_call_trampoline() { - return trampoline_stub_size; -} - -// Number of relocation entries needed by trampoline stub. -// Used for optimization in Compile::Shorten_branches. -uint reloc_call_trampoline() { - return 5; -} - //============================================================================= // Emit an inline branch-and-link call and a related trampoline stub. @@ -1221,7 +1247,7 @@ const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr); // Emit the trampoline stub which will be related to the branch-and-link below. - emit_trampoline_stub(_masm, entry_point_toc_offset, offsets.insts_call_instruction_offset); + CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, offsets.insts_call_instruction_offset); __ relocate(rtype); } @@ -2023,17 +2049,34 @@ //============================================================================= -uint size_exception_handler() { - // The exception_handler is a b64_patchable. - return MacroAssembler::b64_patchable_size; -} - -uint size_deopt_handler() { - // The deopt_handler is a bl64_patchable. - return MacroAssembler::bl64_patchable_size; -} - -int emit_exception_handler(CodeBuffer &cbuf) { +%} // interrupt source + +source_hpp %{ // Header information of the source block. + +class HandlerImpl { + + public: + + static int emit_exception_handler(CodeBuffer &cbuf); + static int emit_deopt_handler(CodeBuffer& cbuf); + + static uint size_exception_handler() { + // The exception_handler is a b64_patchable. + return MacroAssembler::b64_patchable_size; + } + + static uint size_deopt_handler() { + // The deopt_handler is a bl64_patchable. + return MacroAssembler::bl64_patchable_size; + } + +}; + +%} // end source_hpp + +source %{ + +int HandlerImpl::emit_exception_handler(CodeBuffer &cbuf) { MacroAssembler _masm(&cbuf); address base = __ start_a_stub(size_exception_handler()); @@ -2050,7 +2093,7 @@ // The deopt_handler is like the exception handler, but it calls to // the deoptimization blob instead of jumping to the exception blob. -int emit_deopt_handler(CodeBuffer& cbuf) { +int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) { MacroAssembler _masm(&cbuf); address base = __ start_a_stub(size_deopt_handler()); @@ -3438,7 +3481,7 @@ const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr); // Emit the trampoline stub which will be related to the branch-and-link below. - emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset); + CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset); __ relocate(_optimized_virtual ? relocInfo::opt_virtual_call_type : relocInfo::static_call_type); } @@ -3481,7 +3524,7 @@ const int entry_point_toc_offset = __ offset_to_method_toc(entry_point_toc_addr); // Emit the trampoline stub which will be related to the branch-and-link below. - emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset); + CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset); assert(_optimized_virtual, "methodHandle call should be a virtual call"); __ relocate(relocInfo::opt_virtual_call_type); } @@ -3531,7 +3574,7 @@ const address entry_point = !($meth$$method) ? 0 : (address)$meth$$method; const address entry_point_const = __ address_constant(entry_point, RelocationHolder::none); const int entry_point_const_toc_offset = __ offset_to_method_toc(entry_point_const); - emit_trampoline_stub(_masm, entry_point_const_toc_offset, __ offset()); + CallStubImpl::emit_trampoline_stub(_masm, entry_point_const_toc_offset, __ offset()); if (ra_->C->env()->failing()) return; @@ -8755,6 +8798,7 @@ // Single-precision sqrt. instruct sqrtF_reg(regF dst, regF src) %{ match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); + predicate(VM_Version::has_fsqrts()); ins_cost(DEFAULT_COST); format %{ "FSQRTS $dst, $src" %} @@ -11550,8 +11594,7 @@ // effect no longer needs to be mentioned, since r0 is not contained // in a reg_class. - format %{ "LD R12, addr of polling page\n\t" - "LD R0, #0, R12 \t// Safepoint poll for GC" %} + format %{ "LD R0, #0, R12 \t// Safepoint poll for GC" %} ins_encode( enc_poll(0x0, poll) ); ins_pipe(pipe_class_default); %} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -34,6 +34,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/vframeArray.hpp" #include "vmreg_ppc.inline.hpp" +#include "adfiles/ad_ppc_64.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" #endif @@ -52,10 +53,6 @@ #define BIND(label) bind(label); BLOCK_COMMENT(#label ":") -// Used by generate_deopt_blob. Defined in .ad file. -extern uint size_deopt_handler(); - - class RegisterSaver { // Used for saving volatile registers. public: @@ -2782,7 +2779,7 @@ // We can't grab a free register here, because all registers may // contain live values, so let the RegisterSaver do the adjustment // of the return pc. - const int return_pc_adjustment_no_exception = -size_deopt_handler(); + const int return_pc_adjustment_no_exception = -HandlerImpl::size_deopt_handler(); // Push the "unpack frame" // Save everything in sight. diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp --- a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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,17 +23,6 @@ * */ -#include "precompiled.hpp" -#include "runtime/deoptimization.hpp" -#include "runtime/frame.inline.hpp" -#include "runtime/stubRoutines.hpp" -#ifdef TARGET_OS_FAMILY_aix -# include "thread_aix.inline.hpp" -#endif -#ifdef TARGET_OS_FAMILY_linux -# include "thread_linux.inline.hpp" -#endif - // Implementation of the platform-specific part of StubRoutines - for // a description of how to extend it, see the stubRoutines.hpp file. diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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 @@ -402,6 +402,9 @@ CodeBuffer cb("detect_cpu_features", code_size, 0); MacroAssembler* a = new MacroAssembler(&cb); + // Must be set to true so we can generate the test code. + _features = VM_Version::all_features_m; + // Emit code. void (*test)(address addr, uint64_t offset)=(void(*)(address addr, uint64_t offset))(void *)a->function_entry(); uint32_t *code = (uint32_t *)a->pc(); @@ -409,14 +412,15 @@ // Keep R3_ARG1 unmodified, it contains &field (see below). // Keep R4_ARG2 unmodified, it contains offset = 0 (see below). a->fsqrt(F3, F4); // code[0] -> fsqrt_m - a->isel(R7, R5, R6, 0); // code[1] -> isel_m - a->ldarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[2] -> lxarx_m - a->cmpb(R7, R5, R6); // code[3] -> bcmp - //a->mftgpr(R7, F3); // code[4] -> mftgpr - a->popcntb(R7, R5); // code[5] -> popcntb - a->popcntw(R7, R5); // code[6] -> popcntw - a->fcfids(F3, F4); // code[7] -> fcfids - a->vand(VR0, VR0, VR0); // code[8] -> vand + a->fsqrts(F3, F4); // code[1] -> fsqrts_m + a->isel(R7, R5, R6, 0); // code[2] -> isel_m + a->ldarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[3] -> lxarx_m + a->cmpb(R7, R5, R6); // code[4] -> bcmp + //a->mftgpr(R7, F3); // code[5] -> mftgpr + a->popcntb(R7, R5); // code[6] -> popcntb + a->popcntw(R7, R5); // code[7] -> popcntw + a->fcfids(F3, F4); // code[8] -> fcfids + a->vand(VR0, VR0, VR0); // code[9] -> vand a->blr(); // Emit function to set one cache line to zero. Emit function descriptor and get pointer to it. @@ -426,6 +430,7 @@ uint32_t *code_end = (uint32_t *)a->pc(); a->flush(); + _features = VM_Version::unknown_m; // Print the detection code. if (PrintAssembly) { @@ -450,6 +455,7 @@ // determine which instructions are legal. int feature_cntr = 0; if (code[feature_cntr++]) features |= fsqrt_m; + if (code[feature_cntr++]) features |= fsqrts_m; if (code[feature_cntr++]) features |= isel_m; if (code[feature_cntr++]) features |= lxarxeh_m; if (code[feature_cntr++]) features |= cmpb_m; diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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 @@ -33,6 +33,7 @@ protected: enum Feature_Flag { fsqrt, + fsqrts, isel, lxarxeh, cmpb, @@ -46,6 +47,7 @@ enum Feature_Flag_Set { unknown_m = 0, fsqrt_m = (1 << fsqrt ), + fsqrts_m = (1 << fsqrts ), isel_m = (1 << isel ), lxarxeh_m = (1 << lxarxeh), cmpb_m = (1 << cmpb ), @@ -72,6 +74,7 @@ static bool is_determine_features_test_running() { return _is_determine_features_test_running; } // CPU instruction support static bool has_fsqrt() { return (_features & fsqrt_m) != 0; } + static bool has_fsqrts() { return (_features & fsqrts_m) != 0; } static bool has_isel() { return (_features & isel_m) != 0; } static bool has_lxarxeh() { return (_features & lxarxeh_m) !=0; } static bool has_cmpb() { return (_features & cmpb_m) != 0; } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp --- a/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/ppc/vm/vtableStubs_ppc_64.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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 @@ -79,7 +79,7 @@ address npe_addr = __ pc(); // npe = null pointer exception __ load_klass_with_trap_null_check(rcvr_klass, R3); - // Set methodOop (in case of interpreted method), and destination address. + // Set method (in case of interpreted method), and destination address. int entry_offset = InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); #ifndef PRODUCT @@ -161,8 +161,6 @@ address npe_addr = __ pc(); // npe = null pointer exception __ load_klass_with_trap_null_check(rcvr_klass, R3_ARG1); - //__ ld(rcvr_klass, oopDesc::klass_offset_in_bytes(), R3_ARG1); - BLOCK_COMMENT("Load start of itable entries into itable_entry."); __ lwz(vtable_len, InstanceKlass::vtable_length_offset() * wordSize, rcvr_klass); __ slwi(vtable_len, vtable_len, exact_log2(vtableEntry::size() * wordSize)); @@ -199,7 +197,7 @@ itable_offset_search_inc; __ lwz(vtable_offset, vtable_offset_offset, itable_entry_addr); - // Compute itableMethodEntry and get methodOop and entry point for compiler. + // Compute itableMethodEntry and get method and entry point for compiler. const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes(); @@ -211,7 +209,7 @@ Label ok; __ cmpd(CCR0, R19_method, 0); __ bne(CCR0, ok); - __ stop("methodOop is null", 103); + __ stop("method is null", 103); __ bind(ok); } #endif diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -3320,7 +3320,7 @@ // if tmp is invalid, then the function being called doesn't destroy the thread if (tmp->is_valid()) { - __ save_thread(tmp->as_register()); + __ save_thread(tmp->as_pointer_register()); } __ call(dest, relocInfo::runtime_call_type); __ delayed()->nop(); @@ -3328,7 +3328,7 @@ add_call_info_here(info); } if (tmp->is_valid()) { - __ restore_thread(tmp->as_register()); + __ restore_thread(tmp->as_pointer_register()); } #ifdef ASSERT diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -69,7 +69,7 @@ LIR_Opr LIRGenerator::exceptionOopOpr() { return FrameMap::Oexception_opr; } LIR_Opr LIRGenerator::exceptionPcOpr() { return FrameMap::Oissuing_pc_opr; } LIR_Opr LIRGenerator::syncTempOpr() { return new_register(T_OBJECT); } -LIR_Opr LIRGenerator::getThreadTemp() { return rlock_callee_saved(T_INT); } +LIR_Opr LIRGenerator::getThreadTemp() { return rlock_callee_saved(NOT_LP64(T_INT) LP64_ONLY(T_LONG)); } LIR_Opr LIRGenerator::result_register_for(ValueType* type, bool callee) { LIR_Opr opr; diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/sparc/vm/c1_globals_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/c1_globals_sparc.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/sparc/vm/c1_globals_sparc.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -66,6 +66,4 @@ define_pd_global(bool, CSEArrayLength, true ); define_pd_global(bool, TwoOperandLIRForm, false); -define_pd_global(intx, SafepointPollOffset, 0 ); - #endif // CPU_SPARC_VM_C1_GLOBALS_SPARC_HPP diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/sparc/vm/sparc.ad --- a/hotspot/src/cpu/sparc/vm/sparc.ad Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/sparc/vm/sparc.ad Fri Mar 28 09:15:41 2014 -0700 @@ -457,6 +457,13 @@ // This is a block of C++ code which provides values, functions, and // definitions necessary in the rest of the architecture description source_hpp %{ +// Header information of the source block. +// Method declarations/definitions which are used outside +// the ad-scope can conveniently be defined here. +// +// To keep related declarations/definitions/uses close together, +// we switch between source %{ }% and source_hpp %{ }% freely as needed. + // Must be visible to the DFA in dfa_sparc.cpp extern bool can_branch_register( Node *bol, Node *cmp ); @@ -468,6 +475,46 @@ #define LONG_HI_REG(x) (x) #define LONG_LO_REG(x) (x) +class CallStubImpl { + + //-------------------------------------------------------------- + //---< Used for optimization in Compile::Shorten_branches >--- + //-------------------------------------------------------------- + + public: + // Size of call trampoline stub. + static uint size_call_trampoline() { + return 0; // no call trampolines on this platform + } + + // number of relocations needed by a call trampoline stub + static uint reloc_call_trampoline() { + return 0; // no call trampolines on this platform + } +}; + +class HandlerImpl { + + public: + + static int emit_exception_handler(CodeBuffer &cbuf); + static int emit_deopt_handler(CodeBuffer& cbuf); + + static uint size_exception_handler() { + if (TraceJumps) { + return (400); // just a guess + } + return ( NativeJump::instruction_size ); // sethi;jmp;nop + } + + static uint size_deopt_handler() { + if (TraceJumps) { + return (400); // just a guess + } + return ( 4+ NativeJump::instruction_size ); // save;sethi;jmp;restore + } +}; + %} source %{ @@ -1710,22 +1757,9 @@ //============================================================================= -uint size_exception_handler() { - if (TraceJumps) { - return (400); // just a guess - } - return ( NativeJump::instruction_size ); // sethi;jmp;nop -} - -uint size_deopt_handler() { - if (TraceJumps) { - return (400); // just a guess - } - return ( 4+ NativeJump::instruction_size ); // save;sethi;jmp;restore -} // Emit exception handler code. -int emit_exception_handler(CodeBuffer& cbuf) { +int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) { Register temp_reg = G3; AddressLiteral exception_blob(OptoRuntime::exception_blob()->entry_point()); MacroAssembler _masm(&cbuf); @@ -1746,7 +1780,7 @@ return offset; } -int emit_deopt_handler(CodeBuffer& cbuf) { +int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) { // Can't use any of the current frame's registers as we may have deopted // at a poll and everything (including G3) can be live. Register temp_reg = L0; diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/assembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1112,7 +1112,6 @@ } void Assembler::bsrl(Register dst, Register src) { - assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT"); int encode = prefix_and_encode(dst->encoding(), src->encoding()); emit_int8(0x0F); emit_int8((unsigned char)0xBD); @@ -2343,6 +2342,11 @@ emit_int8(imm8); } +void Assembler::pause() { + emit_int8((unsigned char)0xF3); + emit_int8((unsigned char)0x90); +} + void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) { assert(VM_Version::supports_sse4_2(), ""); InstructionMark im(this); @@ -2667,6 +2671,11 @@ } } +void Assembler::rdtsc() { + emit_int8((unsigned char)0x0F); + emit_int8((unsigned char)0x31); +} + // copies data from [esi] to [edi] using rcx pointer sized words // generic void Assembler::rep_mov() { @@ -2976,6 +2985,11 @@ emit_simd_arith_nonds(0x2E, dst, src, VEX_SIMD_NONE); } +void Assembler::xabort(int8_t imm8) { + emit_int8((unsigned char)0xC6); + emit_int8((unsigned char)0xF8); + emit_int8((unsigned char)(imm8 & 0xFF)); +} void Assembler::xaddl(Address dst, Register src) { InstructionMark im(this); @@ -2985,6 +2999,24 @@ emit_operand(src, dst); } +void Assembler::xbegin(Label& abort, relocInfo::relocType rtype) { + InstructionMark im(this); + relocate(rtype); + if (abort.is_bound()) { + address entry = target(abort); + assert(entry != NULL, "abort entry NULL"); + intptr_t offset = entry - pc(); + emit_int8((unsigned char)0xC7); + emit_int8((unsigned char)0xF8); + emit_int32(offset - 6); // 2 opcode + 4 address + } else { + abort.add_patch_at(code(), locator()); + emit_int8((unsigned char)0xC7); + emit_int8((unsigned char)0xF8); + emit_int32(0); + } +} + void Assembler::xchgl(Register dst, Address src) { // xchg InstructionMark im(this); prefix(src, dst); @@ -2998,6 +3030,12 @@ emit_int8((unsigned char)(0xC0 | encode)); } +void Assembler::xend() { + emit_int8((unsigned char)0x0F); + emit_int8((unsigned char)0x01); + emit_int8((unsigned char)0xD5); +} + void Assembler::xgetbv() { emit_int8(0x0F); emit_int8(0x01); @@ -4938,7 +4976,6 @@ } void Assembler::bsrq(Register dst, Register src) { - assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT"); int encode = prefixq_and_encode(dst->encoding(), src->encoding()); emit_int8(0x0F); emit_int8((unsigned char)0xBD); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/assembler_x86.hpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -1451,6 +1451,8 @@ // Pemutation of 64bit words void vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256); + void pause(); + // SSE4.2 string instructions void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8); void pcmpestri(XMMRegister xmm1, Address src, int imm8); @@ -1535,6 +1537,8 @@ void rclq(Register dst, int imm8); + void rdtsc(); + void ret(int imm16); void sahf(); @@ -1632,16 +1636,22 @@ void ucomiss(XMMRegister dst, Address src); void ucomiss(XMMRegister dst, XMMRegister src); + void xabort(int8_t imm8); + void xaddl(Address dst, Register src); void xaddq(Address dst, Register src); + void xbegin(Label& abort, relocInfo::relocType rtype = relocInfo::none); + void xchgl(Register reg, Address adr); void xchgl(Register dst, Register src); void xchgq(Register reg, Address adr); void xchgq(Register dst, Register src); + void xend(); + // Get Value of Extended Control Register void xgetbv(); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -604,8 +604,7 @@ // Note: we do not need to round double result; float result has the right precision // the poll sets the condition code, but no data registers - AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()), - relocInfo::poll_return_type); + AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_return_type); if (Assembler::is_polling_page_far()) { __ lea(rscratch1, polling_page); @@ -619,8 +618,7 @@ int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) { - AddressLiteral polling_page(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()), - relocInfo::poll_type); + AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_type); guarantee(info != NULL, "Shouldn't be NULL"); int offset = __ offset(); if (Assembler::is_polling_page_far()) { diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/c1_globals_x86.hpp --- a/hotspot/src/cpu/x86/vm/c1_globals_x86.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/c1_globals_x86.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -65,6 +65,4 @@ define_pd_global(bool, CSEArrayLength, false); define_pd_global(bool, TwoOperandLIRForm, true ); -define_pd_global(intx, SafepointPollOffset, 256 ); - #endif // CPU_X86_VM_C1_GLOBALS_X86_HPP diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/globals_x86.hpp --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -129,6 +129,42 @@ product(bool, UseFastStosb, false, \ "Use fast-string operation for zeroing: rep stosb") \ \ + /* Use Restricted Transactional Memory for lock eliding */ \ + product(bool, UseRTMLocking, false, \ + "Enable RTM lock eliding for inflated locks in compiled code") \ + \ + experimental(bool, UseRTMForStackLocks, false, \ + "Enable RTM lock eliding for stack locks in compiled code") \ + \ + product(bool, UseRTMDeopt, false, \ + "Perform deopt and recompilation based on RTM abort ratio") \ + \ + product(uintx, RTMRetryCount, 5, \ + "Number of RTM retries on lock abort or busy") \ + \ + experimental(intx, RTMSpinLoopCount, 100, \ + "Spin count for lock to become free before RTM retry") \ + \ + experimental(intx, RTMAbortThreshold, 1000, \ + "Calculate abort ratio after this number of aborts") \ + \ + experimental(intx, RTMLockingThreshold, 10000, \ + "Lock count at which to do RTM lock eliding without " \ + "abort ratio calculation") \ + \ + experimental(intx, RTMAbortRatio, 50, \ + "Lock abort ratio at which to stop use RTM lock eliding") \ + \ + experimental(intx, RTMTotalCountIncrRate, 64, \ + "Increment total RTM attempted lock count once every n times") \ + \ + experimental(intx, RTMLockingCalculationDelay, 0, \ + "Number of milliseconds to wait before start calculating aborts " \ + "for RTM locking") \ + \ + experimental(bool, UseRTMXendForLockBusy, false, \ + "Use RTM Xend instead of Xabort when lock busy") \ + \ /* assembler */ \ product(bool, Use486InstrsOnly, false, \ "Use 80486 Compliant instruction subset") \ diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -301,7 +301,9 @@ mov_literal32(dst, (int32_t)obj, metadata_Relocation::spec_for_immediate()); } -void MacroAssembler::movptr(Register dst, AddressLiteral src) { +void MacroAssembler::movptr(Register dst, AddressLiteral src, Register scratch) { + // scratch register is not used, + // it is defined to match parameters of 64-bit version of this method. if (src.is_lval()) { mov_literal32(dst, (intptr_t)src.target(), src.rspec()); } else { @@ -613,6 +615,15 @@ /* else */ { subq(dst, value) ; return; } } +void MacroAssembler::incrementq(AddressLiteral dst) { + if (reachable(dst)) { + incrementq(as_Address(dst)); + } else { + lea(rscratch1, dst); + incrementq(Address(rscratch1, 0)); + } +} + void MacroAssembler::incrementq(Register reg, int value) { if (value == min_jint) { addq(reg, value); return; } if (value < 0) { decrementq(reg, -value); return; } @@ -681,15 +692,15 @@ movq(dst, rscratch1); } -void MacroAssembler::movptr(Register dst, AddressLiteral src) { +void MacroAssembler::movptr(Register dst, AddressLiteral src, Register scratch) { if (src.is_lval()) { mov_literal64(dst, (intptr_t)src.target(), src.rspec()); } else { if (reachable(src)) { movq(dst, as_Address(src)); } else { - lea(rscratch1, src); - movq(dst, Address(rscratch1,0)); + lea(scratch, src); + movq(dst, Address(scratch, 0)); } } } @@ -988,20 +999,37 @@ LP64_ONLY(andq(dst, imm32)) NOT_LP64(andl(dst, imm32)); } -void MacroAssembler::atomic_incl(AddressLiteral counter_addr) { - pushf(); +void MacroAssembler::atomic_incl(Address counter_addr) { + if (os::is_MP()) + lock(); + incrementl(counter_addr); +} + +void MacroAssembler::atomic_incl(AddressLiteral counter_addr, Register scr) { if (reachable(counter_addr)) { - if (os::is_MP()) - lock(); - incrementl(as_Address(counter_addr)); + atomic_incl(as_Address(counter_addr)); } else { - lea(rscratch1, counter_addr); - if (os::is_MP()) - lock(); - incrementl(Address(rscratch1, 0)); - } - popf(); -} + lea(scr, counter_addr); + atomic_incl(Address(scr, 0)); + } +} + +#ifdef _LP64 +void MacroAssembler::atomic_incq(Address counter_addr) { + if (os::is_MP()) + lock(); + incrementq(counter_addr); +} + +void MacroAssembler::atomic_incq(AddressLiteral counter_addr, Register scr) { + if (reachable(counter_addr)) { + atomic_incq(as_Address(counter_addr)); + } else { + lea(scr, counter_addr); + atomic_incq(Address(scr, 0)); + } +} +#endif // Writes to stack successive pages until offset reached to check for // stack overflow + shadow pages. This clobbers tmp. @@ -1274,6 +1302,325 @@ } #ifdef COMPILER2 + +#if INCLUDE_RTM_OPT + +// Update rtm_counters based on abort status +// input: abort_status +// rtm_counters (RTMLockingCounters*) +// flags are killed +void MacroAssembler::rtm_counters_update(Register abort_status, Register rtm_counters) { + + atomic_incptr(Address(rtm_counters, RTMLockingCounters::abort_count_offset())); + if (PrintPreciseRTMLockingStatistics) { + for (int i = 0; i < RTMLockingCounters::ABORT_STATUS_LIMIT; i++) { + Label check_abort; + testl(abort_status, (1< 0) { + // Delay calculation + movptr(tmpReg, ExternalAddress((address) RTMLockingCounters::rtm_calculation_flag_addr()), tmpReg); + testptr(tmpReg, tmpReg); + jccb(Assembler::equal, L_done); + } + // Abort ratio calculation only if abort_count > RTMAbortThreshold + // Aborted transactions = abort_count * 100 + // All transactions = total_count * RTMTotalCountIncrRate + // Set no_rtm bit if (Aborted transactions >= All transactions * RTMAbortRatio) + + movptr(tmpReg, Address(rtm_counters_Reg, RTMLockingCounters::abort_count_offset())); + cmpptr(tmpReg, RTMAbortThreshold); + jccb(Assembler::below, L_check_always_rtm2); + imulptr(tmpReg, tmpReg, 100); + + Register scrReg = rtm_counters_Reg; + movptr(scrReg, Address(rtm_counters_Reg, RTMLockingCounters::total_count_offset())); + imulptr(scrReg, scrReg, RTMTotalCountIncrRate); + imulptr(scrReg, scrReg, RTMAbortRatio); + cmpptr(tmpReg, scrReg); + jccb(Assembler::below, L_check_always_rtm1); + if (method_data != NULL) { + // set rtm_state to "no rtm" in MDO + mov_metadata(tmpReg, method_data); + if (os::is_MP()) { + lock(); + } + orl(Address(tmpReg, MethodData::rtm_state_offset_in_bytes()), NoRTM); + } + jmpb(L_done); + bind(L_check_always_rtm1); + // Reload RTMLockingCounters* address + lea(rtm_counters_Reg, ExternalAddress((address)rtm_counters)); + bind(L_check_always_rtm2); + movptr(tmpReg, Address(rtm_counters_Reg, RTMLockingCounters::total_count_offset())); + cmpptr(tmpReg, RTMLockingThreshold / RTMTotalCountIncrRate); + jccb(Assembler::below, L_done); + if (method_data != NULL) { + // set rtm_state to "always rtm" in MDO + mov_metadata(tmpReg, method_data); + if (os::is_MP()) { + lock(); + } + orl(Address(tmpReg, MethodData::rtm_state_offset_in_bytes()), UseRTM); + } + bind(L_done); +} + +// Update counters and perform abort ratio calculation +// input: abort_status_Reg +// rtm_counters_Reg, flags are killed +void MacroAssembler::rtm_profiling(Register abort_status_Reg, + Register rtm_counters_Reg, + RTMLockingCounters* rtm_counters, + Metadata* method_data, + bool profile_rtm) { + + assert(rtm_counters != NULL, "should not be NULL when profiling RTM"); + // update rtm counters based on rax value at abort + // reads abort_status_Reg, updates flags + lea(rtm_counters_Reg, ExternalAddress((address)rtm_counters)); + rtm_counters_update(abort_status_Reg, rtm_counters_Reg); + if (profile_rtm) { + // Save abort status because abort_status_Reg is used by following code. + if (RTMRetryCount > 0) { + push(abort_status_Reg); + } + assert(rtm_counters != NULL, "should not be NULL when profiling RTM"); + rtm_abort_ratio_calculation(abort_status_Reg, rtm_counters_Reg, rtm_counters, method_data); + // restore abort status + if (RTMRetryCount > 0) { + pop(abort_status_Reg); + } + } +} + +// Retry on abort if abort's status is 0x6: can retry (0x2) | memory conflict (0x4) +// inputs: retry_count_Reg +// : abort_status_Reg +// output: retry_count_Reg decremented by 1 +// flags are killed +void MacroAssembler::rtm_retry_lock_on_abort(Register retry_count_Reg, Register abort_status_Reg, Label& retryLabel) { + Label doneRetry; + assert(abort_status_Reg == rax, ""); + // The abort reason bits are in eax (see all states in rtmLocking.hpp) + // 0x6 = conflict on which we can retry (0x2) | memory conflict (0x4) + // if reason is in 0x6 and retry count != 0 then retry + andptr(abort_status_Reg, 0x6); + jccb(Assembler::zero, doneRetry); + testl(retry_count_Reg, retry_count_Reg); + jccb(Assembler::zero, doneRetry); + pause(); + decrementl(retry_count_Reg); + jmp(retryLabel); + bind(doneRetry); +} + +// Spin and retry if lock is busy, +// inputs: box_Reg (monitor address) +// : retry_count_Reg +// output: retry_count_Reg decremented by 1 +// : clear z flag if retry count exceeded +// tmp_Reg, scr_Reg, flags are killed +void MacroAssembler::rtm_retry_lock_on_busy(Register retry_count_Reg, Register box_Reg, + Register tmp_Reg, Register scr_Reg, Label& retryLabel) { + Label SpinLoop, SpinExit, doneRetry; + // Clean monitor_value bit to get valid pointer + int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value; + + testl(retry_count_Reg, retry_count_Reg); + jccb(Assembler::zero, doneRetry); + decrementl(retry_count_Reg); + movptr(scr_Reg, RTMSpinLoopCount); + + bind(SpinLoop); + pause(); + decrementl(scr_Reg); + jccb(Assembler::lessEqual, SpinExit); + movptr(tmp_Reg, Address(box_Reg, owner_offset)); + testptr(tmp_Reg, tmp_Reg); + jccb(Assembler::notZero, SpinLoop); + + bind(SpinExit); + jmp(retryLabel); + bind(doneRetry); + incrementl(retry_count_Reg); // clear z flag +} + +// Use RTM for normal stack locks +// Input: objReg (object to lock) +void MacroAssembler::rtm_stack_locking(Register objReg, Register tmpReg, Register scrReg, + Register retry_on_abort_count_Reg, + RTMLockingCounters* stack_rtm_counters, + Metadata* method_data, bool profile_rtm, + Label& DONE_LABEL, Label& IsInflated) { + assert(UseRTMForStackLocks, "why call this otherwise?"); + assert(!UseBiasedLocking, "Biased locking is not supported with RTM locking"); + assert(tmpReg == rax, ""); + assert(scrReg == rdx, ""); + Label L_rtm_retry, L_decrement_retry, L_on_abort; + + if (RTMRetryCount > 0) { + movl(retry_on_abort_count_Reg, RTMRetryCount); // Retry on abort + bind(L_rtm_retry); + } + if (!UseRTMXendForLockBusy) { + movptr(tmpReg, Address(objReg, 0)); + testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased + jcc(Assembler::notZero, IsInflated); + } + if (PrintPreciseRTMLockingStatistics || profile_rtm) { + Label L_noincrement; + if (RTMTotalCountIncrRate > 1) { + // tmpReg, scrReg and flags are killed + branch_on_random_using_rdtsc(tmpReg, scrReg, (int)RTMTotalCountIncrRate, L_noincrement); + } + assert(stack_rtm_counters != NULL, "should not be NULL when profiling RTM"); + atomic_incptr(ExternalAddress((address)stack_rtm_counters->total_count_addr()), scrReg); + bind(L_noincrement); + } + xbegin(L_on_abort); + movptr(tmpReg, Address(objReg, 0)); // fetch markword + andptr(tmpReg, markOopDesc::biased_lock_mask_in_place); // look at 3 lock bits + cmpptr(tmpReg, markOopDesc::unlocked_value); // bits = 001 unlocked + jcc(Assembler::equal, DONE_LABEL); // all done if unlocked + + Register abort_status_Reg = tmpReg; // status of abort is stored in RAX + if (UseRTMXendForLockBusy) { + xend(); + movptr(tmpReg, Address(objReg, 0)); + testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased + jcc(Assembler::notZero, IsInflated); + movptr(abort_status_Reg, 0x1); // Set the abort status to 1 (as xabort does) + jmp(L_decrement_retry); + } + else { + xabort(0); + } + bind(L_on_abort); + if (PrintPreciseRTMLockingStatistics || profile_rtm) { + rtm_profiling(abort_status_Reg, scrReg, stack_rtm_counters, method_data, profile_rtm); + } + bind(L_decrement_retry); + if (RTMRetryCount > 0) { + // retry on lock abort if abort status is 'can retry' (0x2) or 'memory conflict' (0x4) + rtm_retry_lock_on_abort(retry_on_abort_count_Reg, abort_status_Reg, L_rtm_retry); + } +} + +// Use RTM for inflating locks +// inputs: objReg (object to lock) +// boxReg (on-stack box address (displaced header location) - KILLED) +// tmpReg (ObjectMonitor address + 2(monitor_value)) +void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Register tmpReg, + Register scrReg, Register retry_on_busy_count_Reg, + Register retry_on_abort_count_Reg, + RTMLockingCounters* rtm_counters, + Metadata* method_data, bool profile_rtm, + Label& DONE_LABEL) { + assert(UseRTMLocking, "why call this otherwise?"); + assert(tmpReg == rax, ""); + assert(scrReg == rdx, ""); + Label L_rtm_retry, L_decrement_retry, L_on_abort; + // Clean monitor_value bit to get valid pointer + int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value; + + // Without cast to int32_t a movptr will destroy r10 which is typically obj + movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())); + movptr(boxReg, tmpReg); // Save ObjectMonitor address + + if (RTMRetryCount > 0) { + movl(retry_on_busy_count_Reg, RTMRetryCount); // Retry on lock busy + movl(retry_on_abort_count_Reg, RTMRetryCount); // Retry on abort + bind(L_rtm_retry); + } + if (PrintPreciseRTMLockingStatistics || profile_rtm) { + Label L_noincrement; + if (RTMTotalCountIncrRate > 1) { + // tmpReg, scrReg and flags are killed + branch_on_random_using_rdtsc(tmpReg, scrReg, (int)RTMTotalCountIncrRate, L_noincrement); + } + assert(rtm_counters != NULL, "should not be NULL when profiling RTM"); + atomic_incptr(ExternalAddress((address)rtm_counters->total_count_addr()), scrReg); + bind(L_noincrement); + } + xbegin(L_on_abort); + movptr(tmpReg, Address(objReg, 0)); + movptr(tmpReg, Address(tmpReg, owner_offset)); + testptr(tmpReg, tmpReg); + jcc(Assembler::zero, DONE_LABEL); + if (UseRTMXendForLockBusy) { + xend(); + jmp(L_decrement_retry); + } + else { + xabort(0); + } + bind(L_on_abort); + Register abort_status_Reg = tmpReg; // status of abort is stored in RAX + if (PrintPreciseRTMLockingStatistics || profile_rtm) { + rtm_profiling(abort_status_Reg, scrReg, rtm_counters, method_data, profile_rtm); + } + if (RTMRetryCount > 0) { + // retry on lock abort if abort status is 'can retry' (0x2) or 'memory conflict' (0x4) + rtm_retry_lock_on_abort(retry_on_abort_count_Reg, abort_status_Reg, L_rtm_retry); + } + + movptr(tmpReg, Address(boxReg, owner_offset)) ; + testptr(tmpReg, tmpReg) ; + jccb(Assembler::notZero, L_decrement_retry) ; + + // Appears unlocked - try to swing _owner from null to non-null. + // Invariant: tmpReg == 0. tmpReg is EAX which is the implicit cmpxchg comparand. +#ifdef _LP64 + Register threadReg = r15_thread; +#else + get_thread(scrReg); + Register threadReg = scrReg; +#endif + if (os::is_MP()) { + lock(); + } + cmpxchgptr(threadReg, Address(boxReg, owner_offset)); // Updates tmpReg + + if (RTMRetryCount > 0) { + // success done else retry + jccb(Assembler::equal, DONE_LABEL) ; + bind(L_decrement_retry); + // Spin and retry if lock is busy. + rtm_retry_lock_on_busy(retry_on_busy_count_Reg, boxReg, tmpReg, scrReg, L_rtm_retry); + } + else { + bind(L_decrement_retry); + } +} + +#endif // INCLUDE_RTM_OPT + // Fast_Lock and Fast_Unlock used by C2 // Because the transitions from emitted code to the runtime @@ -1350,17 +1697,26 @@ // box: on-stack box address (displaced header location) - KILLED // rax,: tmp -- KILLED // scr: tmp -- KILLED -void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg, Register scrReg, BiasedLockingCounters* counters) { +void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg, + Register scrReg, Register cx1Reg, Register cx2Reg, + BiasedLockingCounters* counters, + RTMLockingCounters* rtm_counters, + RTMLockingCounters* stack_rtm_counters, + Metadata* method_data, + bool use_rtm, bool profile_rtm) { // Ensure the register assignents are disjoint - guarantee (objReg != boxReg, ""); - guarantee (objReg != tmpReg, ""); - guarantee (objReg != scrReg, ""); - guarantee (boxReg != tmpReg, ""); - guarantee (boxReg != scrReg, ""); - guarantee (tmpReg == rax, ""); + assert(tmpReg == rax, ""); + + if (use_rtm) { + assert_different_registers(objReg, boxReg, tmpReg, scrReg, cx1Reg, cx2Reg); + } else { + assert(cx1Reg == noreg, ""); + assert(cx2Reg == noreg, ""); + assert_different_registers(objReg, boxReg, tmpReg, scrReg); + } if (counters != NULL) { - atomic_incl(ExternalAddress((address)counters->total_entry_count_addr())); + atomic_incl(ExternalAddress((address)counters->total_entry_count_addr()), scrReg); } if (EmitSync & 1) { // set box->dhw = unused_mark (3) @@ -1419,12 +1775,20 @@ biased_locking_enter(boxReg, objReg, tmpReg, scrReg, true, DONE_LABEL, NULL, counters); } +#if INCLUDE_RTM_OPT + if (UseRTMForStackLocks && use_rtm) { + rtm_stack_locking(objReg, tmpReg, scrReg, cx2Reg, + stack_rtm_counters, method_data, profile_rtm, + DONE_LABEL, IsInflated); + } +#endif // INCLUDE_RTM_OPT + movptr(tmpReg, Address(objReg, 0)); // [FETCH] - testl (tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased - jccb (Assembler::notZero, IsInflated); + testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased + jccb(Assembler::notZero, IsInflated); // Attempt stack-locking ... - orptr (tmpReg, 0x1); + orptr (tmpReg, markOopDesc::unlocked_value); movptr(Address(boxReg, 0), tmpReg); // Anticipate successful CAS if (os::is_MP()) { lock(); @@ -1434,19 +1798,32 @@ cond_inc32(Assembler::equal, ExternalAddress((address)counters->fast_path_entry_count_addr())); } - jccb(Assembler::equal, DONE_LABEL); - - // Recursive locking + jcc(Assembler::equal, DONE_LABEL); // Success + + // Recursive locking. + // The object is stack-locked: markword contains stack pointer to BasicLock. + // Locked by current thread if difference with current SP is less than one page. subptr(tmpReg, rsp); + // Next instruction set ZFlag == 1 (Success) if difference is less then one page. andptr(tmpReg, (int32_t) (NOT_LP64(0xFFFFF003) LP64_ONLY(7 - os::vm_page_size())) ); movptr(Address(boxReg, 0), tmpReg); if (counters != NULL) { cond_inc32(Assembler::equal, ExternalAddress((address)counters->fast_path_entry_count_addr())); } - jmpb(DONE_LABEL); + jmp(DONE_LABEL); bind(IsInflated); + // The object is inflated. tmpReg contains pointer to ObjectMonitor* + 2(monitor_value) + +#if INCLUDE_RTM_OPT + // Use the same RTM locking code in 32- and 64-bit VM. + if (use_rtm) { + rtm_inflated_locking(objReg, boxReg, tmpReg, scrReg, cx1Reg, cx2Reg, + rtm_counters, method_data, profile_rtm, DONE_LABEL); + } else { +#endif // INCLUDE_RTM_OPT + #ifndef _LP64 // The object is inflated. // @@ -1576,7 +1953,7 @@ // Without cast to int32_t a movptr will destroy r10 which is typically obj movptr(Address(boxReg, 0), (int32_t)intptr_t(markOopDesc::unused_mark())); - mov (boxReg, tmpReg); + movptr (boxReg, tmpReg); movptr (tmpReg, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)); testptr(tmpReg, tmpReg); jccb (Assembler::notZero, DONE_LABEL); @@ -1587,9 +1964,11 @@ } cmpxchgptr(r15_thread, Address(boxReg, ObjectMonitor::owner_offset_in_bytes()-2)); // Intentional fall-through into DONE_LABEL ... - +#endif // _LP64 + +#if INCLUDE_RTM_OPT + } // use_rtm() #endif - // DONE_LABEL is a hot target - we'd really like to place it at the // start of cache line by padding with NOPs. // See the AMD and Intel software optimization manuals for the @@ -1631,11 +2010,9 @@ // should not be unlocked by "normal" java-level locking and vice-versa. The specification // doesn't specify what will occur if a program engages in such mixed-mode locking, however. -void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpReg) { - guarantee (objReg != boxReg, ""); - guarantee (objReg != tmpReg, ""); - guarantee (boxReg != tmpReg, ""); - guarantee (boxReg == rax, ""); +void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpReg, bool use_rtm) { + assert(boxReg == rax, ""); + assert_different_registers(objReg, boxReg, tmpReg); if (EmitSync & 4) { // Disable - inhibit all inlining. Force control through the slow-path @@ -1667,14 +2044,41 @@ biased_locking_exit(objReg, tmpReg, DONE_LABEL); } +#if INCLUDE_RTM_OPT + if (UseRTMForStackLocks && use_rtm) { + assert(!UseBiasedLocking, "Biased locking is not supported with RTM locking"); + Label L_regular_unlock; + movptr(tmpReg, Address(objReg, 0)); // fetch markword + andptr(tmpReg, markOopDesc::biased_lock_mask_in_place); // look at 3 lock bits + cmpptr(tmpReg, markOopDesc::unlocked_value); // bits = 001 unlocked + jccb(Assembler::notEqual, L_regular_unlock); // if !HLE RegularLock + xend(); // otherwise end... + jmp(DONE_LABEL); // ... and we're done + bind(L_regular_unlock); + } +#endif + cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD); // Examine the displaced header + jcc (Assembler::zero, DONE_LABEL); // 0 indicates recursive stack-lock movptr(tmpReg, Address(objReg, 0)); // Examine the object's markword - jccb (Assembler::zero, DONE_LABEL); // 0 indicates recursive stack-lock - - testptr(tmpReg, 0x02); // Inflated? + testptr(tmpReg, markOopDesc::monitor_value); // Inflated? jccb (Assembler::zero, Stacked); // It's inflated. +#if INCLUDE_RTM_OPT + if (use_rtm) { + Label L_regular_inflated_unlock; + // Clean monitor_value bit to get valid pointer + int owner_offset = ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value; + movptr(boxReg, Address(tmpReg, owner_offset)); + testptr(boxReg, boxReg); + jccb(Assembler::notZero, L_regular_inflated_unlock); + xend(); + jmpb(DONE_LABEL); + bind(L_regular_inflated_unlock); + } +#endif + // Despite our balanced locking property we still check that m->_owner == Self // as java routines or native JNI code called by this thread might // have released the lock. @@ -2448,7 +2852,9 @@ Condition negated_cond = negate_condition(cond); Label L; jcc(negated_cond, L); + pushf(); // Preserve flags atomic_incl(counter_addr); + popf(); bind(L); } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -27,6 +27,7 @@ #include "asm/assembler.hpp" #include "utilities/macros.hpp" +#include "runtime/rtmLocking.hpp" // MacroAssembler extends Assembler by frequently used macros. @@ -111,7 +112,8 @@ op == 0xE9 /* jmp */ || op == 0xEB /* short jmp */ || (op & 0xF0) == 0x70 /* short jcc */ || - op == 0x0F && (branch[1] & 0xF0) == 0x80 /* jcc */, + op == 0x0F && (branch[1] & 0xF0) == 0x80 /* jcc */ || + op == 0xC7 && branch[1] == 0xF8 /* xbegin */, "Invalid opcode at patch point"); if (op == 0xEB || (op & 0xF0) == 0x70) { @@ -121,7 +123,7 @@ guarantee(this->is8bit(imm8), "Short forward jump exceeds 8-bit offset"); *disp = imm8; } else { - int* disp = (int*) &branch[(op == 0x0F)? 2: 1]; + int* disp = (int*) &branch[(op == 0x0F || op == 0xC7)? 2: 1]; int imm32 = target - (address) &disp[1]; *disp = imm32; } @@ -161,7 +163,6 @@ void incrementq(Register reg, int value = 1); void incrementq(Address dst, int value = 1); - // Support optimal SSE move instructions. void movflt(XMMRegister dst, XMMRegister src) { if (UseXmmRegToRegMoveAll) { movaps(dst, src); return; } @@ -187,6 +188,8 @@ void incrementl(AddressLiteral dst); void incrementl(ArrayAddress dst); + void incrementq(AddressLiteral dst); + // Alignment void align(int modulus); @@ -654,8 +657,36 @@ #ifdef COMPILER2 // Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file. // See full desription in macroAssembler_x86.cpp. - void fast_lock(Register obj, Register box, Register tmp, Register scr, BiasedLockingCounters* counters); - void fast_unlock(Register obj, Register box, Register tmp); + void fast_lock(Register obj, Register box, Register tmp, + Register scr, Register cx1, Register cx2, + BiasedLockingCounters* counters, + RTMLockingCounters* rtm_counters, + RTMLockingCounters* stack_rtm_counters, + Metadata* method_data, + bool use_rtm, bool profile_rtm); + void fast_unlock(Register obj, Register box, Register tmp, bool use_rtm); +#if INCLUDE_RTM_OPT + void rtm_counters_update(Register abort_status, Register rtm_counters); + void branch_on_random_using_rdtsc(Register tmp, Register scr, int count, Label& brLabel); + void rtm_abort_ratio_calculation(Register tmp, Register rtm_counters_reg, + RTMLockingCounters* rtm_counters, + Metadata* method_data); + void rtm_profiling(Register abort_status_Reg, Register rtm_counters_Reg, + RTMLockingCounters* rtm_counters, Metadata* method_data, bool profile_rtm); + void rtm_retry_lock_on_abort(Register retry_count, Register abort_status, Label& retryLabel); + void rtm_retry_lock_on_busy(Register retry_count, Register box, Register tmp, Register scr, Label& retryLabel); + void rtm_stack_locking(Register obj, Register tmp, Register scr, + Register retry_on_abort_count, + RTMLockingCounters* stack_rtm_counters, + Metadata* method_data, bool profile_rtm, + Label& DONE_LABEL, Label& IsInflated); + void rtm_inflated_locking(Register obj, Register box, Register tmp, + Register scr, Register retry_on_busy_count, + Register retry_on_abort_count, + RTMLockingCounters* rtm_counters, + Metadata* method_data, bool profile_rtm, + Label& DONE_LABEL); +#endif #endif Condition negate_condition(Condition cond); @@ -721,6 +752,7 @@ void imulptr(Register dst, Register src) { LP64_ONLY(imulq(dst, src)) NOT_LP64(imull(dst, src)); } + void imulptr(Register dst, Register src, int imm32) { LP64_ONLY(imulq(dst, src, imm32)) NOT_LP64(imull(dst, src, imm32)); } void negptr(Register dst) { LP64_ONLY(negq(dst)) NOT_LP64(negl(dst)); } @@ -762,7 +794,14 @@ // Conditionally (atomically, on MPs) increments passed counter address, preserving condition codes. void cond_inc32(Condition cond, AddressLiteral counter_addr); // Unconditional atomic increment. - void atomic_incl(AddressLiteral counter_addr); + void atomic_incl(Address counter_addr); + void atomic_incl(AddressLiteral counter_addr, Register scr = rscratch1); +#ifdef _LP64 + void atomic_incq(Address counter_addr); + void atomic_incq(AddressLiteral counter_addr, Register scr = rscratch1); +#endif + void atomic_incptr(AddressLiteral counter_addr, Register scr = rscratch1) { LP64_ONLY(atomic_incq(counter_addr, scr)) NOT_LP64(atomic_incl(counter_addr, scr)) ; } + void atomic_incptr(Address counter_addr) { LP64_ONLY(atomic_incq(counter_addr)) NOT_LP64(atomic_incl(counter_addr)) ; } void lea(Register dst, AddressLiteral adr); void lea(Address dst, AddressLiteral adr); @@ -1074,7 +1113,11 @@ void movptr(Register dst, Address src); - void movptr(Register dst, AddressLiteral src); +#ifdef _LP64 + void movptr(Register dst, AddressLiteral src, Register scratch=rscratch1); +#else + void movptr(Register dst, AddressLiteral src, Register scratch=noreg); // Scratch reg is ignored in 32-bit +#endif void movptr(Register dst, intptr_t src); void movptr(Register dst, Register src); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/rtmLocking.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/cpu/x86/vm/rtmLocking.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,60 @@ +/* + * 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. + * + */ + +#include "precompiled.hpp" +#include "memory/allocation.inline.hpp" +#include "runtime/task.hpp" +#include "runtime/rtmLocking.hpp" + +// One-shot PeriodicTask subclass for enabling RTM locking +uintx RTMLockingCounters::_calculation_flag = 0; + +class RTMLockingCalculationTask : public PeriodicTask { + public: + RTMLockingCalculationTask(size_t interval_time) : PeriodicTask(interval_time){ } + + virtual void task() { + RTMLockingCounters::_calculation_flag = 1; + // Reclaim our storage and disenroll ourself + delete this; + } +}; + +void RTMLockingCounters::init() { + if (UseRTMLocking && RTMLockingCalculationDelay > 0) { + RTMLockingCalculationTask* task = new RTMLockingCalculationTask(RTMLockingCalculationDelay); + task->enroll(); + } else { + _calculation_flag = 1; + } +} + +//------------------------------print_on------------------------------- +void RTMLockingCounters::print_on(outputStream* st) { + tty->print_cr("# rtm locks total (estimated): " UINTX_FORMAT, _total_count * RTMTotalCountIncrRate); + tty->print_cr("# rtm lock aborts : " UINTX_FORMAT, _abort_count); + for (int i = 0; i < ABORT_STATUS_LIMIT; i++) { + tty->print_cr("# rtm lock aborts %d: " UINTX_FORMAT, i, _abortX_count[i]); + } +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1817,6 +1817,13 @@ // Frame is now completed as far as size and linkage. int frame_complete = ((intptr_t)__ pc()) - start; + if (UseRTMLocking) { + // Abort RTM transaction before calling JNI + // because critical section will be large and will be + // aborted anyway. Also nmethod could be deoptimized. + __ xabort(0); + } + // Calculate the difference between rsp and rbp,. We need to know it // after the native call because on windows Java Natives will pop // the arguments and it is painful to do rsp relative addressing @@ -3170,6 +3177,12 @@ }; address start = __ pc(); + + if (UseRTMLocking) { + // Abort RTM transaction before possible nmethod deoptimization. + __ xabort(0); + } + // Push self-frame. __ subptr(rsp, return_off*wordSize); // Epilog! @@ -3355,6 +3368,14 @@ address call_pc = NULL; bool cause_return = (poll_type == POLL_AT_RETURN); bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP); + + if (UseRTMLocking) { + // Abort RTM transaction before calling runtime + // because critical section will be large and will be + // aborted anyway. Also nmethod could be deoptimized. + __ xabort(0); + } + // If cause_return is true we are at a poll_return and there is // the return address on the stack to the caller on the nmethod // that is safepoint. We can leave this return on the stack and diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -2012,6 +2012,13 @@ // Frame is now completed as far as size and linkage. int frame_complete = ((intptr_t)__ pc()) - start; + if (UseRTMLocking) { + // Abort RTM transaction before calling JNI + // because critical section will be large and will be + // aborted anyway. Also nmethod could be deoptimized. + __ xabort(0); + } + #ifdef ASSERT { Label L; @@ -3612,6 +3619,11 @@ address start = __ pc(); + if (UseRTMLocking) { + // Abort RTM transaction before possible nmethod deoptimization. + __ xabort(0); + } + // Push self-frame. We get here with a return address on the // stack, so rsp is 8-byte aligned until we allocate our frame. __ subptr(rsp, SimpleRuntimeFrame::return_off << LogBytesPerInt); // Epilog! @@ -3792,6 +3804,13 @@ bool cause_return = (poll_type == POLL_AT_RETURN); bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP); + if (UseRTMLocking) { + // Abort RTM transaction before calling runtime + // because critical section will be large and will be + // aborted anyway. Also nmethod could be deoptimized. + __ xabort(0); + } + // Make room for return address (or push it again) if (!cause_return) { __ push(rbx); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/vm_version_x86.cpp --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -50,8 +50,13 @@ const char* VM_Version::_features_str = ""; VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, }; +// Address of instruction which causes SEGV +address VM_Version::_cpuinfo_segv_addr = 0; +// Address of instruction after the one which causes SEGV +address VM_Version::_cpuinfo_cont_addr = 0; + static BufferBlob* stub_blob; -static const int stub_size = 550; +static const int stub_size = 600; extern "C" { typedef void (*getPsrInfo_stub_t)(void*); @@ -234,9 +239,9 @@ // Check if OS has enabled XGETBV instruction to access XCR0 // (OSXSAVE feature flag) and CPU supports AVX // - __ andl(rcx, 0x18000000); + __ andl(rcx, 0x18000000); // cpuid1 bits osxsave | avx __ cmpl(rcx, 0x18000000); - __ jccb(Assembler::notEqual, sef_cpuid); + __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported // // XCR0, XFEATURE_ENABLED_MASK register @@ -247,6 +252,47 @@ __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rdx); + __ andl(rax, 0x6); // xcr0 bits sse | ymm + __ cmpl(rax, 0x6); + __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported + + // + // Some OSs have a bug when upper 128bits of YMM + // registers are not restored after a signal processing. + // Generate SEGV here (reference through NULL) + // and check upper YMM bits after it. + // + VM_Version::set_avx_cpuFeatures(); // Enable temporary to pass asserts + + // load value into all 32 bytes of ymm7 register + __ movl(rcx, VM_Version::ymm_test_value()); + + __ movdl(xmm0, rcx); + __ pshufd(xmm0, xmm0, 0x00); + __ vinsertf128h(xmm0, xmm0, xmm0); + __ vmovdqu(xmm7, xmm0); +#ifdef _LP64 + __ vmovdqu(xmm8, xmm0); + __ vmovdqu(xmm15, xmm0); +#endif + + __ xorl(rsi, rsi); + VM_Version::set_cpuinfo_segv_addr( __ pc() ); + // Generate SEGV + __ movl(rax, Address(rsi, 0)); + + VM_Version::set_cpuinfo_cont_addr( __ pc() ); + // Returns here after signal. Save xmm0 to check it later. + __ lea(rsi, Address(rbp, in_bytes(VM_Version::ymm_save_offset()))); + __ vmovdqu(Address(rsi, 0), xmm0); + __ vmovdqu(Address(rsi, 32), xmm7); +#ifdef _LP64 + __ vmovdqu(Address(rsi, 64), xmm8); + __ vmovdqu(Address(rsi, 96), xmm15); +#endif + + VM_Version::clean_cpuFeatures(); + // // cpuid(0x7) Structured Extended Features // @@ -429,7 +475,7 @@ } char buf[256]; - jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", cores_per_cpu(), threads_per_core(), cpu_family(), _model, _stepping, (supports_cmov() ? ", cmov" : ""), @@ -446,8 +492,9 @@ (supports_avx() ? ", avx" : ""), (supports_avx2() ? ", avx2" : ""), (supports_aes() ? ", aes" : ""), - (supports_clmul() ? ", clmul" : ""), + (supports_clmul() ? ", clmul" : ""), (supports_erms() ? ", erms" : ""), + (supports_rtm() ? ", rtm" : ""), (supports_mmx_ext() ? ", mmxext" : ""), (supports_3dnow_prefetch() ? ", 3dnowpref" : ""), (supports_lzcnt() ? ", lzcnt": ""), @@ -488,7 +535,7 @@ } } else if (UseAES) { if (!FLAG_IS_DEFAULT(UseAES)) - warning("AES instructions not available on this CPU"); + warning("AES instructions are not available on this CPU"); FLAG_SET_DEFAULT(UseAES, false); } @@ -521,10 +568,57 @@ } } else if (UseAESIntrinsics) { if (!FLAG_IS_DEFAULT(UseAESIntrinsics)) - warning("AES intrinsics not available on this CPU"); + warning("AES intrinsics are not available on this CPU"); FLAG_SET_DEFAULT(UseAESIntrinsics, false); } + // Adjust RTM (Restricted Transactional Memory) flags + if (!supports_rtm() && UseRTMLocking) { + // Can't continue because UseRTMLocking affects UseBiasedLocking flag + // setting during arguments processing. See use_biased_locking(). + // VM_Version_init() is executed after UseBiasedLocking is used + // in Thread::allocate(). + vm_exit_during_initialization("RTM instructions are not available on this CPU"); + } + +#if INCLUDE_RTM_OPT + if (UseRTMLocking) { + if (!FLAG_IS_CMDLINE(UseRTMLocking)) { + // RTM locking should be used only for applications with + // high lock contention. For now we do not use it by default. + vm_exit_during_initialization("UseRTMLocking flag should be only set on command line"); + } + if (!is_power_of_2(RTMTotalCountIncrRate)) { + warning("RTMTotalCountIncrRate must be a power of 2, resetting it to 64"); + FLAG_SET_DEFAULT(RTMTotalCountIncrRate, 64); + } + if (RTMAbortRatio < 0 || RTMAbortRatio > 100) { + warning("RTMAbortRatio must be in the range 0 to 100, resetting it to 50"); + FLAG_SET_DEFAULT(RTMAbortRatio, 50); + } + } else { // !UseRTMLocking + if (UseRTMForStackLocks) { + if (!FLAG_IS_DEFAULT(UseRTMForStackLocks)) { + warning("UseRTMForStackLocks flag should be off when UseRTMLocking flag is off"); + } + FLAG_SET_DEFAULT(UseRTMForStackLocks, false); + } + if (UseRTMDeopt) { + FLAG_SET_DEFAULT(UseRTMDeopt, false); + } + if (PrintPreciseRTMLockingStatistics) { + FLAG_SET_DEFAULT(PrintPreciseRTMLockingStatistics, false); + } + } +#else + if (UseRTMLocking) { + // Only C2 does RTM locking optimization. + // Can't continue because UseRTMLocking affects UseBiasedLocking flag + // setting during arguments processing. See use_biased_locking(). + vm_exit_during_initialization("RTM locking optimization is not supported in this VM"); + } +#endif + #ifdef COMPILER2 if (UseFPUForSpilling) { if (UseSSE < 2) { @@ -540,14 +634,28 @@ if (MaxVectorSize > 32) { FLAG_SET_DEFAULT(MaxVectorSize, 32); } - if (MaxVectorSize > 16 && UseAVX == 0) { - // Only supported with AVX+ + if (MaxVectorSize > 16 && (UseAVX == 0 || !os_supports_avx_vectors())) { + // 32 bytes vectors (in YMM) are only supported with AVX+ FLAG_SET_DEFAULT(MaxVectorSize, 16); } if (UseSSE < 2) { - // Only supported with SSE2+ + // Vectors (in XMM) are only supported with SSE2+ FLAG_SET_DEFAULT(MaxVectorSize, 0); } +#ifdef ASSERT + if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) { + tty->print_cr("State of YMM registers after signal handle:"); + int nreg = 2 LP64_ONLY(+2); + const char* ymm_name[4] = {"0", "7", "8", "15"}; + for (int i = 0; i < nreg; i++) { + tty->print("YMM%s:", ymm_name[i]); + for (int j = 7; j >=0; j--) { + tty->print(" %x", _cpuid_info.ymm_save[i*8 + j]); + } + tty->cr(); + } + } +#endif } #endif @@ -678,14 +786,6 @@ } } } -#if defined(COMPILER2) && defined(_ALLBSD_SOURCE) - if (MaxVectorSize > 16) { - // Limit vectors size to 16 bytes on BSD until it fixes - // restoring upper 128bit of YMM registers on return - // from signal handler. - FLAG_SET_DEFAULT(MaxVectorSize, 16); - } -#endif // COMPILER2 // Use count leading zeros count instruction if available. if (supports_lzcnt()) { @@ -814,6 +914,11 @@ if (UseAES) { tty->print(" UseAES=1"); } +#ifdef COMPILER2 + if (MaxVectorSize > 0) { + tty->print(" MaxVectorSize=%d", MaxVectorSize); + } +#endif tty->cr(); tty->print("Allocation"); if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) { @@ -856,6 +961,27 @@ #endif // !PRODUCT } +bool VM_Version::use_biased_locking() { +#if INCLUDE_RTM_OPT + // RTM locking is most useful when there is high lock contention and + // low data contention. With high lock contention the lock is usually + // inflated and biased locking is not suitable for that case. + // RTM locking code requires that biased locking is off. + // Note: we can't switch off UseBiasedLocking in get_processor_features() + // because it is used by Thread::allocate() which is called before + // VM_Version::initialize(). + if (UseRTMLocking && UseBiasedLocking) { + if (FLAG_IS_DEFAULT(UseBiasedLocking)) { + FLAG_SET_DEFAULT(UseBiasedLocking, false); + } else { + warning("Biased locking is not supported with RTM locking; ignoring UseBiasedLocking flag." ); + UseBiasedLocking = false; + } + } +#endif + return UseBiasedLocking; +} + void VM_Version::initialize() { ResourceMark rm; // Making this stub must be FIRST use of assembler diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/vm_version_x86.hpp --- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -207,7 +207,9 @@ : 2, bmi2 : 1, erms : 1, - : 22; + : 1, + rtm : 1, + : 20; } bits; }; @@ -229,6 +231,9 @@ // 0 if this instruction is not available static const char* _features_str; + static address _cpuinfo_segv_addr; // address of instruction which causes SEGV + static address _cpuinfo_cont_addr; // address of instruction after the one which causes SEGV + enum { CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX) CPU_CMOV = (1 << 1), @@ -254,7 +259,8 @@ CPU_ERMS = (1 << 20), // enhanced 'rep movsb/stosb' instructions CPU_CLMUL = (1 << 21), // carryless multiply for CRC CPU_BMI1 = (1 << 22), - CPU_BMI2 = (1 << 23) + CPU_BMI2 = (1 << 23), + CPU_RTM = (1 << 24) // Restricted Transactional Memory instructions } cpuFeatureFlags; enum { @@ -361,6 +367,9 @@ // extended control register XCR0 (the XFEATURE_ENABLED_MASK register) XemXcr0Eax xem_xcr0_eax; uint32_t xem_xcr0_edx; // reserved + + // Space to save ymm registers after signal handle + int ymm_save[8*4]; // Save ymm0, ymm7, ymm8, ymm15 }; // The actual cpuid info block @@ -438,6 +447,8 @@ result |= CPU_ERMS; if (_cpuid_info.std_cpuid1_ecx.bits.clmul != 0) result |= CPU_CLMUL; + if (_cpuid_info.sef_cpuid7_ebx.bits.rtm != 0) + result |= CPU_RTM; // AMD features. if (is_amd()) { @@ -460,6 +471,21 @@ return result; } + static bool os_supports_avx_vectors() { + if (!supports_avx()) { + return false; + } + // Verify that OS save/restore all bits of AVX registers + // during signal processing. + int nreg = 2 LP64_ONLY(+2); + for (int i = 0; i < 8 * nreg; i++) { // 32 bytes per ymm register + if (_cpuid_info.ymm_save[i] != ymm_test_value()) { + return false; + } + } + return true; + } + static void get_processor_features(); public: @@ -476,10 +502,26 @@ static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); } static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); } static ByteSize xem_xcr0_offset() { return byte_offset_of(CpuidInfo, xem_xcr0_eax); } + static ByteSize ymm_save_offset() { return byte_offset_of(CpuidInfo, ymm_save); } + + // The value used to check ymm register after signal handle + static int ymm_test_value() { return 0xCAFEBABE; } + + static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; } + static bool is_cpuinfo_segv_addr(address pc) { return _cpuinfo_segv_addr == pc; } + static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; } + static address cpuinfo_cont_addr() { return _cpuinfo_cont_addr; } + + static void clean_cpuFeatures() { _cpuFeatures = 0; } + static void set_avx_cpuFeatures() { _cpuFeatures = (CPU_SSE | CPU_SSE2 | CPU_AVX); } + // Initialization static void initialize(); + // Override Abstract_VM_Version implementation + static bool use_biased_locking(); + // Asserts static void assert_is_initialized() { assert(_cpuid_info.std_cpuid1_eax.bits.family != 0, "VM_Version not initialized"); @@ -572,6 +614,7 @@ static bool supports_aes() { return (_cpuFeatures & CPU_AES) != 0; } static bool supports_erms() { return (_cpuFeatures & CPU_ERMS) != 0; } static bool supports_clmul() { return (_cpuFeatures & CPU_CLMUL) != 0; } + static bool supports_rtm() { return (_cpuFeatures & CPU_RTM) != 0; } static bool supports_bmi1() { return (_cpuFeatures & CPU_BMI1) != 0; } static bool supports_bmi2() { return (_cpuFeatures & CPU_BMI2) != 0; } // Intel features diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/x86.ad --- a/hotspot/src/cpu/x86/vm/x86.ad Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/x86.ad Fri Mar 28 09:15:41 2014 -0700 @@ -474,7 +474,125 @@ %} + +//----------SOURCE BLOCK------------------------------------------------------- +// This is a block of C++ code which provides values, functions, and +// definitions necessary in the rest of the architecture description + +source_hpp %{ +// Header information of the source block. +// Method declarations/definitions which are used outside +// the ad-scope can conveniently be defined here. +// +// To keep related declarations/definitions/uses close together, +// we switch between source %{ }% and source_hpp %{ }% freely as needed. + +class CallStubImpl { + + //-------------------------------------------------------------- + //---< Used for optimization in Compile::shorten_branches >--- + //-------------------------------------------------------------- + + public: + // Size of call trampoline stub. + static uint size_call_trampoline() { + return 0; // no call trampolines on this platform + } + + // number of relocations needed by a call trampoline stub + static uint reloc_call_trampoline() { + return 0; // no call trampolines on this platform + } +}; + +class HandlerImpl { + + public: + + static int emit_exception_handler(CodeBuffer &cbuf); + static int emit_deopt_handler(CodeBuffer& cbuf); + + static uint size_exception_handler() { + // NativeCall instruction size is the same as NativeJump. + // exception handler starts out as jump and can be patched to + // a call be deoptimization. (4932387) + // Note that this value is also credited (in output.cpp) to + // the size of the code section. + return NativeJump::instruction_size; + } + +#ifdef _LP64 + static uint size_deopt_handler() { + // three 5 byte instructions + return 15; + } +#else + static uint size_deopt_handler() { + // NativeCall instruction size is the same as NativeJump. + // exception handler starts out as jump and can be patched to + // a call be deoptimization. (4932387) + // Note that this value is also credited (in output.cpp) to + // the size of the code section. + return 5 + NativeJump::instruction_size; // pushl(); jmp; + } +#endif +}; + +%} // end source_hpp + source %{ + +// Emit exception handler code. +// Stuff framesize into a register and call a VM stub routine. +int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) { + + // Note that the code buffer's insts_mark is always relative to insts. + // That's why we must use the macroassembler to generate a handler. + MacroAssembler _masm(&cbuf); + address base = __ start_a_stub(size_exception_handler()); + if (base == NULL) return 0; // CodeBuffer::expand failed + int offset = __ offset(); + __ jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point())); + assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); + __ end_a_stub(); + return offset; +} + +// Emit deopt handler code. +int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) { + + // Note that the code buffer's insts_mark is always relative to insts. + // That's why we must use the macroassembler to generate a handler. + MacroAssembler _masm(&cbuf); + address base = __ start_a_stub(size_deopt_handler()); + if (base == NULL) return 0; // CodeBuffer::expand failed + int offset = __ offset(); + +#ifdef _LP64 + address the_pc = (address) __ pc(); + Label next; + // push a "the_pc" on the stack without destroying any registers + // as they all may be live. + + // push address of "next" + __ call(next, relocInfo::none); // reloc none is fine since it is a disp32 + __ bind(next); + // adjust it so it matches "the_pc" + __ subptr(Address(rsp, 0), __ offset() - offset); +#else + InternalAddress here(__ pc()); + __ pushptr(here.addr()); +#endif + + __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); + assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); + __ end_a_stub(); + return offset; +} + + +//============================================================================= + // Float masks come from different places depending on platform. #ifdef _LP64 static address float_signmask() { return StubRoutines::x86::float_sign_mask(); } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/x86_32.ad --- a/hotspot/src/cpu/x86/vm/x86_32.ad Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/x86_32.ad Fri Mar 28 09:15:41 2014 -0700 @@ -1297,59 +1297,6 @@ //============================================================================= -uint size_exception_handler() { - // NativeCall instruction size is the same as NativeJump. - // exception handler starts out as jump and can be patched to - // a call be deoptimization. (4932387) - // Note that this value is also credited (in output.cpp) to - // the size of the code section. - return NativeJump::instruction_size; -} - -// Emit exception handler code. Stuff framesize into a register -// and call a VM stub routine. -int emit_exception_handler(CodeBuffer& cbuf) { - - // Note that the code buffer's insts_mark is always relative to insts. - // That's why we must use the macroassembler to generate a handler. - MacroAssembler _masm(&cbuf); - address base = - __ start_a_stub(size_exception_handler()); - if (base == NULL) return 0; // CodeBuffer::expand failed - int offset = __ offset(); - __ jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point())); - assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); - __ end_a_stub(); - return offset; -} - -uint size_deopt_handler() { - // NativeCall instruction size is the same as NativeJump. - // exception handler starts out as jump and can be patched to - // a call be deoptimization. (4932387) - // Note that this value is also credited (in output.cpp) to - // the size of the code section. - return 5 + NativeJump::instruction_size; // pushl(); jmp; -} - -// Emit deopt handler code. -int emit_deopt_handler(CodeBuffer& cbuf) { - - // Note that the code buffer's insts_mark is always relative to insts. - // That's why we must use the macroassembler to generate a handler. - MacroAssembler _masm(&cbuf); - address base = - __ start_a_stub(size_exception_handler()); - if (base == NULL) return 0; // CodeBuffer::expand failed - int offset = __ offset(); - InternalAddress here(__ pc()); - __ pushptr(here.addr()); - - __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); - assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); - __ end_a_stub(); - return offset; -} int Matcher::regnum_to_fpu_offset(int regnum) { return regnum - 32; // The FP registers are in the second chunk @@ -12925,13 +12872,31 @@ // inlined locking and unlocking +instruct cmpFastLockRTM(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eDXRegI scr, rRegI cx1, rRegI cx2) %{ + predicate(Compile::current()->use_rtm()); + match(Set cr (FastLock object box)); + effect(TEMP tmp, TEMP scr, TEMP cx1, TEMP cx2, USE_KILL box); + ins_cost(300); + format %{ "FASTLOCK $object,$box\t! kills $box,$tmp,$scr,$cx1,$cx2" %} + ins_encode %{ + __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, + $scr$$Register, $cx1$$Register, $cx2$$Register, + _counters, _rtm_counters, _stack_rtm_counters, + ((Method*)(ra_->C->method()->constant_encoding()))->method_data(), + true, ra_->C->profile_rtm()); + %} + ins_pipe(pipe_slow); +%} + instruct cmpFastLock(eFlagsReg cr, eRegP object, eBXRegP box, eAXRegI tmp, eRegP scr) %{ + predicate(!Compile::current()->use_rtm()); match(Set cr (FastLock object box)); effect(TEMP tmp, TEMP scr, USE_KILL box); ins_cost(300); format %{ "FASTLOCK $object,$box\t! kills $box,$tmp,$scr" %} ins_encode %{ - __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, $scr$$Register, _counters); + __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, + $scr$$Register, noreg, noreg, _counters, NULL, NULL, NULL, false, false); %} ins_pipe(pipe_slow); %} @@ -12942,7 +12907,7 @@ ins_cost(300); format %{ "FASTUNLOCK $object,$box\t! kills $box,$tmp" %} ins_encode %{ - __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register); + __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register, ra_->C->use_rtm()); %} ins_pipe(pipe_slow); %} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/cpu/x86/vm/x86_64.ad --- a/hotspot/src/cpu/x86/vm/x86_64.ad Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/cpu/x86/vm/x86_64.ad Fri Mar 28 09:15:41 2014 -0700 @@ -1439,66 +1439,9 @@ return MachNode::size(ra_); // too many variables; just compute it // the hard way } - + //============================================================================= -uint size_exception_handler() -{ - // NativeCall instruction size is the same as NativeJump. - // Note that this value is also credited (in output.cpp) to - // the size of the code section. - return NativeJump::instruction_size; -} - -// Emit exception handler code. -int emit_exception_handler(CodeBuffer& cbuf) -{ - - // Note that the code buffer's insts_mark is always relative to insts. - // That's why we must use the macroassembler to generate a handler. - MacroAssembler _masm(&cbuf); - address base = - __ start_a_stub(size_exception_handler()); - if (base == NULL) return 0; // CodeBuffer::expand failed - int offset = __ offset(); - __ jump(RuntimeAddress(OptoRuntime::exception_blob()->entry_point())); - assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); - __ end_a_stub(); - return offset; -} - -uint size_deopt_handler() -{ - // three 5 byte instructions - return 15; -} - -// Emit deopt handler code. -int emit_deopt_handler(CodeBuffer& cbuf) -{ - - // Note that the code buffer's insts_mark is always relative to insts. - // That's why we must use the macroassembler to generate a handler. - MacroAssembler _masm(&cbuf); - address base = - __ start_a_stub(size_deopt_handler()); - if (base == NULL) return 0; // CodeBuffer::expand failed - int offset = __ offset(); - address the_pc = (address) __ pc(); - Label next; - // push a "the_pc" on the stack without destroying any registers - // as they all may be live. - - // push address of "next" - __ call(next, relocInfo::none); // reloc none is fine since it is a disp32 - __ bind(next); - // adjust it so it matches "the_pc" - __ subptr(Address(rsp, 0), __ offset() - offset); - __ jump(RuntimeAddress(SharedRuntime::deopt_blob()->unpack())); - assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); - __ end_a_stub(); - return offset; -} int Matcher::regnum_to_fpu_offset(int regnum) { @@ -11387,13 +11330,31 @@ // ============================================================================ // inlined locking and unlocking +instruct cmpFastLockRTM(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rdx_RegI scr, rRegI cx1, rRegI cx2) %{ + predicate(Compile::current()->use_rtm()); + match(Set cr (FastLock object box)); + effect(TEMP tmp, TEMP scr, TEMP cx1, TEMP cx2, USE_KILL box); + ins_cost(300); + format %{ "fastlock $object,$box\t! kills $box,$tmp,$scr,$cx1,$cx2" %} + ins_encode %{ + __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, + $scr$$Register, $cx1$$Register, $cx2$$Register, + _counters, _rtm_counters, _stack_rtm_counters, + ((Method*)(ra_->C->method()->constant_encoding()))->method_data(), + true, ra_->C->profile_rtm()); + %} + ins_pipe(pipe_slow); +%} + instruct cmpFastLock(rFlagsReg cr, rRegP object, rbx_RegP box, rax_RegI tmp, rRegP scr) %{ + predicate(!Compile::current()->use_rtm()); match(Set cr (FastLock object box)); effect(TEMP tmp, TEMP scr, USE_KILL box); ins_cost(300); format %{ "fastlock $object,$box\t! kills $box,$tmp,$scr" %} ins_encode %{ - __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, $scr$$Register, _counters); + __ fast_lock($object$$Register, $box$$Register, $tmp$$Register, + $scr$$Register, noreg, noreg, _counters, NULL, NULL, NULL, false, false); %} ins_pipe(pipe_slow); %} @@ -11404,7 +11365,7 @@ ins_cost(300); format %{ "fastunlock $object,$box\t! kills $box,$tmp" %} ins_encode %{ - __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register); + __ fast_unlock($object$$Register, $box$$Register, $tmp$$Register, ra_->C->use_rtm()); %} ins_pipe(pipe_slow); %} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/os/aix/vm/mutex_aix.inline.hpp --- a/hotspot/src/os/aix/vm/mutex_aix.inline.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/os/aix/vm/mutex_aix.inline.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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 @@ -28,6 +28,6 @@ #include "os_aix.inline.hpp" #include "runtime/interfaceSupport.hpp" -#include "thread_aix.inline.hpp" +#include "runtime/thread.inline.hpp" #endif // OS_AIX_VM_MUTEX_AIX_INLINE_HPP diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/os/aix/vm/os_aix.cpp --- a/hotspot/src/os/aix/vm/os_aix.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/os/aix/vm/os_aix.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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,10 +61,10 @@ #include "runtime/statSampler.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/threadCritical.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/timer.hpp" #include "services/attachListener.hpp" #include "services/runtimeService.hpp" -#include "thread_aix.inline.hpp" #include "utilities/decoder.hpp" #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/os/aix/vm/threadCritical_aix.cpp --- a/hotspot/src/os/aix/vm/threadCritical_aix.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/os/aix/vm/threadCritical_aix.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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,7 +25,7 @@ #include "precompiled.hpp" #include "runtime/threadCritical.hpp" -#include "thread_aix.inline.hpp" +#include "runtime/thread.inline.hpp" // put OS-includes here # include diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/os/linux/vm/os_linux.cpp --- a/hotspot/src/os/linux/vm/os_linux.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -109,6 +109,8 @@ #define MAX_PATH (2 * K) +#define MAX_SECS 100000000 + // for timer info max values which include all bits #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) @@ -2434,7 +2436,6 @@ sem_t _semaphore; }; - Semaphore::Semaphore() { sem_init(&_semaphore, 0, 0); } @@ -2456,8 +2457,22 @@ } bool Semaphore::timedwait(unsigned int sec, int nsec) { + struct timespec ts; - unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); + // Semaphore's are always associated with CLOCK_REALTIME + os::Linux::clock_gettime(CLOCK_REALTIME, &ts); + // see unpackTime for discussion on overflow checking + if (sec >= MAX_SECS) { + ts.tv_sec += MAX_SECS; + ts.tv_nsec = 0; + } else { + ts.tv_sec += sec; + ts.tv_nsec += nsec; + if (ts.tv_nsec >= NANOSECS_PER_SEC) { + ts.tv_nsec -= NANOSECS_PER_SEC; + ++ts.tv_sec; // note: this must be <= max_secs + } + } while (1) { int result = sem_timedwait(&_semaphore, &ts); @@ -5661,7 +5676,6 @@ * is no need to track notifications. */ -#define MAX_SECS 100000000 /* * This code is common to linux and solaris and will be moved to a * common place in dolphin. diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/os/windows/vm/os_windows.cpp --- a/hotspot/src/os/windows/vm/os_windows.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/os/windows/vm/os_windows.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -2425,6 +2425,12 @@ } } + if ((exception_code == EXCEPTION_ACCESS_VIOLATION) && + VM_Version::is_cpuinfo_segv_addr(pc)) { + // Verify that OS save/restore AVX registers. + return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr()); + } + if (t != NULL && t->is_Java_thread()) { JavaThread* thread = (JavaThread*) t; bool in_java = thread->thread_state() == _thread_in_Java; diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp --- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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 @@ -49,8 +49,8 @@ #include "runtime/osThread.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/timer.hpp" -#include "thread_aix.inline.hpp" #include "utilities/events.hpp" #include "utilities/vmError.hpp" #ifdef COMPILER1 diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp --- a/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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,14 +25,14 @@ #include "precompiled.hpp" #include "runtime/threadLocalStorage.hpp" -#include "thread_aix.inline.hpp" +#include "runtime/thread.hpp" void ThreadLocalStorage::generate_code_for_get_thread() { - // nothing we can do here for user-level thread + // Nothing we can do here for user-level thread. } void ThreadLocalStorage::pd_init() { - // Nothing to do + // Nothing to do. } void ThreadLocalStorage::pd_set_thread(Thread* thread) { diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp --- a/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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 @@ -24,8 +24,8 @@ */ #include "precompiled.hpp" -#include "runtime/frame.inline.hpp" -#include "thread_aix.inline.hpp" +#include "runtime/frame.hpp" +#include "runtime/thread.hpp" // Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Aix/PPC. bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) { diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp --- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -492,6 +492,11 @@ } } + if ((sig == SIGSEGV || sig == SIGBUS) && VM_Version::is_cpuinfo_segv_addr(pc)) { + // Verify that OS save/restore AVX registers. + stub = VM_Version::cpuinfo_cont_addr(); + } + // We test if stub is already set (by the stack overflow code // above) so it is not overwritten by the code that follows. This // check is not required on other platforms, because on other diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/os_cpu/linux_ppc/vm/thread_linux_ppc.cpp --- a/hotspot/src/os_cpu/linux_ppc/vm/thread_linux_ppc.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/os_cpu/linux_ppc/vm/thread_linux_ppc.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright 2012, 2014 SAP AG. 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 @@ -24,8 +24,8 @@ */ #include "precompiled.hpp" -#include "runtime/frame.inline.hpp" -#include "thread_linux.inline.hpp" +#include "runtime/frame.hpp" +#include "runtime/thread.hpp" // Forte Analyzer AsyncGetCallTrace profiling support is not implemented on Linux/PPC. bool JavaThread::pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, bool isInJava) { diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -338,6 +338,11 @@ } } + if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) { + // Verify that OS save/restore AVX registers. + stub = VM_Version::cpuinfo_cont_addr(); + } + if (thread->thread_state() == _thread_in_Java) { // Java thread running in Java code => find exception handler if any // a fault inside compiled code, the interpreter, or a stub diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -459,6 +459,11 @@ } } + if ((sig == SIGSEGV) && VM_Version::is_cpuinfo_segv_addr(pc)) { + // Verify that OS save/restore AVX registers. + stub = VM_Version::cpuinfo_cont_addr(); + } + if (thread->thread_state() == _thread_in_vm) { if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) { stub = StubRoutines::handler_for_unsafe_access(); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/adlc/output_c.cpp --- a/hotspot/src/share/vm/adlc/output_c.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/adlc/output_c.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1582,6 +1582,8 @@ if( node->is_ideal_fastlock() && new_inst->is_ideal_fastlock() ) { fprintf(fp, " ((MachFastLockNode*)n%d)->_counters = _counters;\n",cnt); + fprintf(fp, " ((MachFastLockNode*)n%d)->_rtm_counters = _rtm_counters;\n",cnt); + fprintf(fp, " ((MachFastLockNode*)n%d)->_stack_rtm_counters = _stack_rtm_counters;\n",cnt); } // Fill in the bottom_type where requested @@ -3963,6 +3965,8 @@ } if( inst->is_ideal_fastlock() ) { fprintf(fp_cpp, "%s node->_counters = _leaf->as_FastLock()->counters();\n", indent); + fprintf(fp_cpp, "%s node->_rtm_counters = _leaf->as_FastLock()->rtm_counters();\n", indent); + fprintf(fp_cpp, "%s node->_stack_rtm_counters = _leaf->as_FastLock()->stack_rtm_counters();\n", indent); } } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/c1/c1_LIRGenerator.cpp --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -2526,7 +2526,7 @@ // need to free up storage used for OSR entry point LIR_Opr osrBuffer = block()->next()->operand(); BasicTypeList signature; - signature.append(T_INT); + signature.append(NOT_LP64(T_INT) LP64_ONLY(T_LONG)); // pass a pointer to osrBuffer CallingConvention* cc = frame_map()->c_calling_convention(&signature); __ move(osrBuffer, cc->args()->at(0)); __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_end), diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/c1/c1_globals.hpp --- a/hotspot/src/share/vm/c1/c1_globals.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/c1/c1_globals.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -308,9 +308,6 @@ develop(intx, InstructionCountCutoff, 37000, \ "If GraphBuilder adds this many instructions, bails out") \ \ - product_pd(intx, SafepointPollOffset, \ - "Offset added to polling address (Intel only)") \ - \ develop(bool, ComputeExactFPURegisterUsage, true, \ "Compute additional live set for fpu registers to simplify fpu stack merge (Intel only)") \ \ diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/ci/ciEnv.cpp --- a/hotspot/src/share/vm/ci/ciEnv.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/ci/ciEnv.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -961,7 +961,8 @@ AbstractCompiler* compiler, int comp_level, bool has_unsafe_access, - bool has_wide_vectors) { + bool has_wide_vectors, + RTMState rtm_state) { VM_ENTRY_MARK; nmethod* nm = NULL; { @@ -1002,6 +1003,15 @@ methodHandle method(THREAD, target->get_Method()); +#if INCLUDE_RTM_OPT + if (!failing() && (rtm_state != NoRTM) && + (method()->method_data() != NULL) && + (method()->method_data()->rtm_state() != rtm_state)) { + // Preemptive decompile if rtm state was changed. + record_failure("RTM state change invalidated rtm code"); + } +#endif + if (failing()) { // While not a true deoptimization, it is a preemptive decompile. MethodData* mdo = method()->method_data(); @@ -1028,13 +1038,15 @@ frame_words, oop_map_set, handler_table, inc_table, compiler, comp_level); - // Free codeBlobs code_buffer->free_blob(); if (nm != NULL) { nm->set_has_unsafe_access(has_unsafe_access); nm->set_has_wide_vectors(has_wide_vectors); +#if INCLUDE_RTM_OPT + nm->set_rtm_state(rtm_state); +#endif // Record successful registration. // (Put nm into the task handle *before* publishing to the Java heap.) diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/ci/ciEnv.hpp --- a/hotspot/src/share/vm/ci/ciEnv.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/ci/ciEnv.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -365,7 +365,8 @@ AbstractCompiler* compiler, int comp_level, bool has_unsafe_access, - bool has_wide_vectors); + bool has_wide_vectors, + RTMState rtm_state = NoRTM); // Access to certain well known ciObjects. diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/ci/ciMethodData.hpp --- a/hotspot/src/share/vm/ci/ciMethodData.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/ci/ciMethodData.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -478,6 +478,18 @@ int invocation_count() { return _invocation_counter; } int backedge_count() { return _backedge_counter; } + +#if INCLUDE_RTM_OPT + // return cached value + int rtm_state() { + if (is_empty()) { + return NoRTM; + } else { + return get_MethodData()->rtm_state(); + } + } +#endif + // Transfer information about the method to MethodData*. // would_profile means we would like to profile this method, // meaning it's not trivial. diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/code/nmethod.cpp --- a/hotspot/src/share/vm/code/nmethod.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/code/nmethod.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -460,7 +460,9 @@ _scavenge_root_link = NULL; _scavenge_root_state = 0; _compiler = NULL; - +#if INCLUDE_RTM_OPT + _rtm_state = NoRTM; +#endif #ifdef HAVE_DTRACE_H _trap_offset = 0; #endif // def HAVE_DTRACE_H diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/code/nmethod.hpp --- a/hotspot/src/share/vm/code/nmethod.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/code/nmethod.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -193,6 +193,12 @@ jbyte _scavenge_root_state; +#if INCLUDE_RTM_OPT + // RTM state at compile time. Used during deoptimization to decide + // whether to restart collecting RTM locking abort statistic again. + RTMState _rtm_state; +#endif + // Nmethod Flushing lock. If non-zero, then the nmethod is not removed // and is not made into a zombie. However, once the nmethod is made into // a zombie, it will be locked one final time if CompiledMethodUnload @@ -414,6 +420,12 @@ bool is_zombie() const { return _state == zombie; } bool is_unloaded() const { return _state == unloaded; } +#if INCLUDE_RTM_OPT + // rtm state accessing and manipulating + RTMState rtm_state() const { return _rtm_state; } + void set_rtm_state(RTMState state) { _rtm_state = state; } +#endif + // Make the nmethod non entrant. The nmethod will continue to be // alive. It is used when an uncommon trap happens. Returns true // if this thread changed the state of the nmethod or false if diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -793,53 +793,6 @@ } } -// Apply the given closure to each oop in the space \intersect memory region. -void CompactibleFreeListSpace::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) { - assert_lock_strong(freelistLock()); - if (is_empty()) { - return; - } - MemRegion cur = MemRegion(bottom(), end()); - mr = mr.intersection(cur); - if (mr.is_empty()) { - return; - } - if (mr.equals(cur)) { - oop_iterate(cl); - return; - } - assert(mr.end() <= end(), "just took an intersection above"); - HeapWord* obj_addr = block_start(mr.start()); - HeapWord* t = mr.end(); - - SpaceMemRegionOopsIterClosure smr_blk(cl, mr); - if (block_is_obj(obj_addr)) { - // Handle first object specially. - oop obj = oop(obj_addr); - obj_addr += adjustObjectSize(obj->oop_iterate(&smr_blk)); - } else { - FreeChunk* fc = (FreeChunk*)obj_addr; - obj_addr += fc->size(); - } - while (obj_addr < t) { - HeapWord* obj = obj_addr; - obj_addr += block_size(obj_addr); - // If "obj_addr" is not greater than top, then the - // entire object "obj" is within the region. - if (obj_addr <= t) { - if (block_is_obj(obj)) { - oop(obj)->oop_iterate(cl); - } - } else { - // "obj" extends beyond end of region - if (block_is_obj(obj)) { - oop(obj)->oop_iterate(&smr_blk); - } - break; - } - } -} - // NOTE: In the following methods, in order to safely be able to // apply the closure to an object, we need to be sure that the // object has been initialized. We are guaranteed that an object diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -351,7 +351,6 @@ Mutex* freelistLock() const { return &_freelistLock; } // Iteration support - void oop_iterate(MemRegion mr, ExtendedOopClosure* cl); void oop_iterate(ExtendedOopClosure* cl); void object_iterate(ObjectClosure* blk); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -3164,16 +3164,6 @@ } void -ConcurrentMarkSweepGeneration::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) { - if (freelistLock()->owned_by_self()) { - Generation::oop_iterate(mr, cl); - } else { - MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag); - Generation::oop_iterate(mr, cl); - } -} - -void ConcurrentMarkSweepGeneration::oop_iterate(ExtendedOopClosure* cl) { if (freelistLock()->owned_by_self()) { Generation::oop_iterate(cl); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -1285,7 +1285,6 @@ void save_sweep_limit(); // More iteration support - virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl); virtual void oop_iterate(ExtendedOopClosure* cl); virtual void safe_object_iterate(ObjectClosure* cl); virtual void object_iterate(ObjectClosure* cl); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -2018,8 +2018,8 @@ // that calculated by walking the marking bitmap. // Bitmaps to hold expected values - BitMap expected_region_bm(_region_bm.size(), false); - BitMap expected_card_bm(_card_bm.size(), false); + BitMap expected_region_bm(_region_bm.size(), true); + BitMap expected_card_bm(_card_bm.size(), true); G1ParVerifyFinalCountTask g1_par_verify_task(g1h, &_region_bm, diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -550,7 +550,8 @@ if (PrintTenuringDistribution) { gclog_or_tty->cr(); - gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold %u (max %u)", + gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold " + UINTX_FORMAT " (max threshold " UINTX_FORMAT ")", size_policy->calculated_survivor_size_in_bytes(), _tenuring_threshold, MaxTenuringThreshold); } @@ -829,10 +830,10 @@ void PSScavenge::initialize() { // Arguments must have been parsed - if (AlwaysTenure) { - _tenuring_threshold = 0; - } else if (NeverTenure) { - _tenuring_threshold = markOopDesc::max_age + 1; + if (AlwaysTenure || NeverTenure) { + assert(MaxTenuringThreshold == 0 || MaxTenuringThreshold == markOopDesc::max_age + 1, + err_msg("MaxTenuringThreshold should be 0 or markOopDesc::max_age + 1, but is ", MaxTenuringThreshold)); + _tenuring_threshold = MaxTenuringThreshold; } else { // We want to smooth out our startup times for the AdaptiveSizePolicy _tenuring_threshold = (UseAdaptiveSizePolicy) ? InitialTenuringThreshold : diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/shared/ageTable.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,28 +80,37 @@ uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) { size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100); - size_t total = 0; - uint age = 1; - assert(sizes[0] == 0, "no objects with age zero should be recorded"); - while (age < table_size) { - total += sizes[age]; - // check if including objects of age 'age' made us pass the desired - // size, if so 'age' is the new threshold - if (total > desired_survivor_size) break; - age++; + uint result; + + if (AlwaysTenure || NeverTenure) { + assert(MaxTenuringThreshold == 0 || MaxTenuringThreshold == markOopDesc::max_age + 1, + err_msg("MaxTenuringThreshold should be 0 or markOopDesc::max_age + 1, but is ", MaxTenuringThreshold)); + result = MaxTenuringThreshold; + } else { + size_t total = 0; + uint age = 1; + assert(sizes[0] == 0, "no objects with age zero should be recorded"); + while (age < table_size) { + total += sizes[age]; + // check if including objects of age 'age' made us pass the desired + // size, if so 'age' is the new threshold + if (total > desired_survivor_size) break; + age++; + } + result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold; } - uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold; if (PrintTenuringDistribution || UsePerfData) { if (PrintTenuringDistribution) { gclog_or_tty->cr(); - gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold %u (max %u)", + gclog_or_tty->print_cr("Desired survivor size " SIZE_FORMAT " bytes, new threshold " + UINTX_FORMAT " (max threshold " UINTX_FORMAT ")", desired_survivor_size*oopSize, result, MaxTenuringThreshold); } - total = 0; - age = 1; + size_t total = 0; + uint age = 1; while (age < table_size) { total += sizes[age]; if (sizes[age] > 0) { diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/memory/genCollectedHeap.cpp --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -837,12 +837,6 @@ } } -void GenCollectedHeap::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) { - for (int i = 0; i < _n_gens; i++) { - _gens[i]->oop_iterate(mr, cl); - } -} - void GenCollectedHeap::object_iterate(ObjectClosure* cl) { for (int i = 0; i < _n_gens; i++) { _gens[i]->object_iterate(cl); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/memory/genCollectedHeap.hpp --- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -212,7 +212,6 @@ // Iteration functions. void oop_iterate(ExtendedOopClosure* cl); - void oop_iterate(MemRegion mr, ExtendedOopClosure* cl); void object_iterate(ObjectClosure* cl); void safe_object_iterate(ObjectClosure* cl); Space* space_containing(const void* addr) const; diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/memory/generation.cpp --- a/hotspot/src/share/vm/memory/generation.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/memory/generation.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -295,22 +295,16 @@ class GenerationOopIterateClosure : public SpaceClosure { public: - ExtendedOopClosure* cl; - MemRegion mr; + ExtendedOopClosure* _cl; virtual void do_space(Space* s) { - s->oop_iterate(mr, cl); + s->oop_iterate(_cl); } - GenerationOopIterateClosure(ExtendedOopClosure* _cl, MemRegion _mr) : - cl(_cl), mr(_mr) {} + GenerationOopIterateClosure(ExtendedOopClosure* cl) : + _cl(cl) {} }; void Generation::oop_iterate(ExtendedOopClosure* cl) { - GenerationOopIterateClosure blk(cl, _reserved); - space_iterate(&blk); -} - -void Generation::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) { - GenerationOopIterateClosure blk(cl, mr); + GenerationOopIterateClosure blk(cl); space_iterate(&blk); } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/memory/generation.hpp --- a/hotspot/src/share/vm/memory/generation.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/memory/generation.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -543,10 +543,6 @@ // generation, calling "cl.do_oop" on each. virtual void oop_iterate(ExtendedOopClosure* cl); - // Same as above, restricted to the intersection of a memory region and - // the generation. - virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl); - // Iterate over all objects in the generation, calling "cl.do_object" on // each. virtual void object_iterate(ObjectClosure* cl); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/memory/metaspace.cpp --- a/hotspot/src/share/vm/memory/metaspace.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/memory/metaspace.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -3343,37 +3343,22 @@ } void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) { - if (SafepointSynchronize::is_at_safepoint()) { - assert(Thread::current()->is_VM_thread(), "should be the VM thread"); - // Don't take Heap_lock - MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag); - if (word_size < TreeChunk >::min_size()) { - // Dark matter. Too small for dictionary. + assert(!SafepointSynchronize::is_at_safepoint() + || Thread::current()->is_VM_thread(), "should be the VM thread"); + + MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag); + + if (word_size < TreeChunk >::min_size()) { + // Dark matter. Too small for dictionary. #ifdef ASSERT - Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5); + Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5); #endif - return; - } - if (is_class && using_class_space()) { - class_vsm()->deallocate(ptr, word_size); - } else { - vsm()->deallocate(ptr, word_size); - } + return; + } + if (is_class && using_class_space()) { + class_vsm()->deallocate(ptr, word_size); } else { - MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag); - - if (word_size < TreeChunk >::min_size()) { - // Dark matter. Too small for dictionary. -#ifdef ASSERT - Copy::fill_to_words((HeapWord*)ptr, word_size, 0xf5f5f5f5); -#endif - return; - } - if (is_class && using_class_space()) { - class_vsm()->deallocate(ptr, word_size); - } else { - vsm()->deallocate(ptr, word_size); - } + vsm()->deallocate(ptr, word_size); } } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/memory/sharedHeap.hpp --- a/hotspot/src/share/vm/memory/sharedHeap.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/memory/sharedHeap.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -163,9 +163,6 @@ // Iteration functions. void oop_iterate(ExtendedOopClosure* cl) = 0; - // Same as above, restricted to a memory region. - virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl) = 0; - // Iterate over all spaces in use in the heap, in an undefined order. virtual void space_iterate(SpaceClosure* cl) = 0; diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/memory/space.cpp --- a/hotspot/src/share/vm/memory/space.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/memory/space.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -42,9 +42,6 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" -void SpaceMemRegionOopsIterClosure::do_oop(oop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); } -void SpaceMemRegionOopsIterClosure::do_oop(narrowOop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); } - HeapWord* DirtyCardToOopClosure::get_actual_top(HeapWord* top, HeapWord* top_obj) { if (top_obj != NULL) { @@ -686,43 +683,6 @@ } } -void ContiguousSpace::oop_iterate(MemRegion mr, ExtendedOopClosure* blk) { - if (is_empty()) { - return; - } - MemRegion cur = MemRegion(bottom(), top()); - mr = mr.intersection(cur); - if (mr.is_empty()) { - return; - } - if (mr.equals(cur)) { - oop_iterate(blk); - return; - } - assert(mr.end() <= top(), "just took an intersection above"); - HeapWord* obj_addr = block_start(mr.start()); - HeapWord* t = mr.end(); - - // Handle first object specially. - oop obj = oop(obj_addr); - SpaceMemRegionOopsIterClosure smr_blk(blk, mr); - obj_addr += obj->oop_iterate(&smr_blk); - while (obj_addr < t) { - oop obj = oop(obj_addr); - assert(obj->is_oop(), "expected an oop"); - obj_addr += obj->size(); - // If "obj_addr" is not greater than top, then the - // entire object "obj" is within the region. - if (obj_addr <= t) { - obj->oop_iterate(blk); - } else { - // "obj" extends beyond end of region - obj->oop_iterate(&smr_blk); - break; - } - }; -} - void ContiguousSpace::object_iterate(ObjectClosure* blk) { if (is_empty()) return; WaterMark bm = bottom_mark(); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/memory/space.hpp --- a/hotspot/src/share/vm/memory/space.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/memory/space.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -81,31 +81,6 @@ class CardTableRS; class DirtyCardToOopClosure; -// An oop closure that is circumscribed by a filtering memory region. -class SpaceMemRegionOopsIterClosure: public ExtendedOopClosure { - private: - ExtendedOopClosure* _cl; - MemRegion _mr; - protected: - template void do_oop_work(T* p) { - if (_mr.contains(p)) { - _cl->do_oop(p); - } - } - public: - SpaceMemRegionOopsIterClosure(ExtendedOopClosure* cl, MemRegion mr): - _cl(cl), _mr(mr) {} - virtual void do_oop(oop* p); - virtual void do_oop(narrowOop* p); - virtual bool do_metadata() { - // _cl is of type ExtendedOopClosure instead of OopClosure, so that we can check this. - assert(!_cl->do_metadata(), "I've checked all call paths, this shouldn't happen."); - return false; - } - virtual void do_klass(Klass* k) { ShouldNotReachHere(); } - virtual void do_class_loader_data(ClassLoaderData* cld) { ShouldNotReachHere(); } -}; - // A Space describes a heap area. Class Space is an abstract // base class. // @@ -221,11 +196,6 @@ // applications of the closure are not included in the iteration. virtual void oop_iterate(ExtendedOopClosure* cl); - // Same as above, restricted to the intersection of a memory region and - // the space. Fields in objects allocated by applications of the closure - // are not included in the iteration. - virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl) = 0; - // Iterate over all objects in the space, calling "cl.do_object" on // each. Objects allocated by applications of the closure are not // included in the iteration. @@ -866,7 +836,6 @@ // Iteration void oop_iterate(ExtendedOopClosure* cl); - void oop_iterate(MemRegion mr, ExtendedOopClosure* cl); void object_iterate(ObjectClosure* blk); // For contiguous spaces this method will iterate safely over objects // in the space (i.e., between bottom and top) when at a safepoint. diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/oops/method.cpp --- a/hotspot/src/share/vm/oops/method.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/oops/method.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -273,7 +273,7 @@ } address Method::bcp_from(int bci) const { - assert((is_native() && bci == 0) || (!is_native() && 0 <= bci && bci < code_size()), "illegal bci"); + assert((is_native() && bci == 0) || (!is_native() && 0 <= bci && bci < code_size()), err_msg("illegal bci: %d", bci)); address bcp = code_base() + bci; assert(is_native() && bcp == code_base() || contains(bcp), "bcp doesn't belong to this method"); return bcp; diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/oops/methodData.cpp --- a/hotspot/src/share/vm/oops/methodData.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/oops/methodData.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" +#include "compiler/compilerOracle.hpp" #include "interpreter/bytecode.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/linkResolver.hpp" @@ -1153,6 +1154,21 @@ _highest_osr_comp_level = 0; _would_profile = true; +#if INCLUDE_RTM_OPT + _rtm_state = NoRTM; // No RTM lock eliding by default + if (UseRTMLocking && + !CompilerOracle::has_option_string(_method, "NoRTMLockEliding")) { + if (CompilerOracle::has_option_string(_method, "UseRTMLockEliding") || !UseRTMDeopt) { + // Generate RTM lock eliding code without abort ratio calculation code. + _rtm_state = UseRTM; + } else if (UseRTMDeopt) { + // Generate RTM lock eliding code and include abort ratio calculation + // code if UseRTMDeopt is on. + _rtm_state = ProfileRTM; + } + } +#endif + // Initialize flags and trap history. _nof_decompiles = 0; _nof_overflow_recompiles = 0; diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/oops/methodData.hpp --- a/hotspot/src/share/vm/oops/methodData.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/oops/methodData.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -2052,7 +2052,7 @@ // Whole-method sticky bits and flags enum { - _trap_hist_limit = 18, // decoupled from Deoptimization::Reason_LIMIT + _trap_hist_limit = 19, // decoupled from Deoptimization::Reason_LIMIT _trap_hist_mask = max_jubyte, _extra_data_count = 4 // extra DataLayout headers, for trap history }; // Public flag values @@ -2083,6 +2083,12 @@ // Counter values at the time profiling started. int _invocation_counter_start; int _backedge_counter_start; + +#if INCLUDE_RTM_OPT + // State of RTM code generation during compilation of the method + int _rtm_state; +#endif + // Number of loops and blocks is computed when compiling the first // time with C1. It is used to determine if method is trivial. short _num_loops; @@ -2246,6 +2252,22 @@ InvocationCounter* invocation_counter() { return &_invocation_counter; } InvocationCounter* backedge_counter() { return &_backedge_counter; } +#if INCLUDE_RTM_OPT + int rtm_state() const { + return _rtm_state; + } + void set_rtm_state(RTMState rstate) { + _rtm_state = (int)rstate; + } + void atomic_set_rtm_state(RTMState rstate) { + Atomic::store((int)rstate, &_rtm_state); + } + + static int rtm_state_offset_in_bytes() { + return offset_of(MethodData, _rtm_state); + } +#endif + void set_would_profile(bool p) { _would_profile = p; } bool would_profile() const { return _would_profile; } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/c2_globals.hpp --- a/hotspot/src/share/vm/opto/c2_globals.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/c2_globals.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -446,6 +446,9 @@ diagnostic(bool, PrintPreciseBiasedLockingStatistics, false, \ "Print per-lock-site statistics of biased locking in JVM") \ \ + diagnostic(bool, PrintPreciseRTMLockingStatistics, false, \ + "Print per-lock-site statistics of rtm locking in JVM") \ + \ notproduct(bool, PrintEliminateLocks, false, \ "Print out when locks are eliminated") \ \ diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/classes.hpp --- a/hotspot/src/share/vm/opto/classes.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/classes.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -198,6 +198,7 @@ macro(NeverBranch) macro(Opaque1) macro(Opaque2) +macro(Opaque3) macro(OrI) macro(OrL) macro(OverflowAddI) diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/compile.cpp --- a/hotspot/src/share/vm/opto/compile.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/compile.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -694,9 +694,10 @@ set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining)); set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics")); - if (ProfileTraps) { + if (ProfileTraps RTM_OPT_ONLY( || UseRTMLocking )) { // Make sure the method being compiled gets its own MDO, // so we can at least track the decompile_count(). + // Need MDO to record RTM code generation state. method()->ensure_method_data(); } @@ -907,7 +908,8 @@ compiler, env()->comp_level(), has_unsafe_access(), - SharedRuntime::is_wide_vector(max_vector_size()) + SharedRuntime::is_wide_vector(max_vector_size()), + rtm_state() ); if (log() != NULL) // Print code cache state into compiler log @@ -1073,7 +1075,23 @@ set_do_scheduling(OptoScheduling); set_do_count_invocations(false); set_do_method_data_update(false); - + set_rtm_state(NoRTM); // No RTM lock eliding by default +#if INCLUDE_RTM_OPT + if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) { + int rtm_state = method()->method_data()->rtm_state(); + if (method_has_option("NoRTMLockEliding") || ((rtm_state & NoRTM) != 0)) { + // Don't generate RTM lock eliding code. + set_rtm_state(NoRTM); + } else if (method_has_option("UseRTMLockEliding") || ((rtm_state & UseRTM) != 0) || !UseRTMDeopt) { + // Generate RTM lock eliding code without abort ratio calculation code. + set_rtm_state(UseRTM); + } else if (UseRTMDeopt) { + // Generate RTM lock eliding code and include abort ratio calculation + // code if UseRTMDeopt is on. + set_rtm_state(ProfileRTM); + } + } +#endif if (debug_info()->recording_non_safepoints()) { set_node_note_array(new(comp_arena()) GrowableArray (comp_arena(), 8, 0, NULL)); @@ -2581,6 +2599,7 @@ break; case Op_Opaque1: // Remove Opaque Nodes before matching case Op_Opaque2: // Remove Opaque Nodes before matching + case Op_Opaque3: n->subsume_by(n->in(1), this); break; case Op_CallStaticJava: diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/compile.hpp --- a/hotspot/src/share/vm/opto/compile.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/compile.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -319,9 +319,9 @@ bool _trace_opto_output; bool _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing #endif - // JSR 292 bool _has_method_handle_invokes; // True if this method has MethodHandle invokes. + RTMState _rtm_state; // State of Restricted Transactional Memory usage // Compilation environment. Arena _comp_arena; // Arena with lifetime equivalent to Compile @@ -591,6 +591,10 @@ void set_print_inlining(bool z) { _print_inlining = z; } bool print_intrinsics() const { return _print_intrinsics; } void set_print_intrinsics(bool z) { _print_intrinsics = z; } + RTMState rtm_state() const { return _rtm_state; } + void set_rtm_state(RTMState s) { _rtm_state = s; } + bool use_rtm() const { return (_rtm_state & NoRTM) == 0; } + bool profile_rtm() const { return _rtm_state == ProfileRTM; } // check the CompilerOracle for special behaviours for this compile bool method_has_option(const char * option) { return method() != NULL && method()->has_option(option); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/connode.hpp --- a/hotspot/src/share/vm/opto/connode.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/connode.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -642,6 +642,19 @@ virtual const Type *bottom_type() const { return TypeInt::INT; } }; +//------------------------------Opaque3Node------------------------------------ +// A node to prevent unwanted optimizations. Will be optimized only during +// macro nodes expansion. +class Opaque3Node : public Opaque2Node { + int _opt; // what optimization it was used for +public: + enum { RTM_OPT }; + Opaque3Node(Compile* C, Node *n, int opt) : Opaque2Node(C, n), _opt(opt) {} + virtual int Opcode() const; + bool rtm_opt() const { return (_opt == RTM_OPT); } +}; + + //----------------------PartialSubtypeCheckNode-------------------------------- // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass // array for an instance of the superklass. Set a hidden internal cache on a diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/graphKit.cpp --- a/hotspot/src/share/vm/opto/graphKit.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/graphKit.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1125,6 +1125,17 @@ } return _gvn.transform( new (C) ConvI2LNode(offset)); } + +Node* GraphKit::ConvI2UL(Node* offset) { + juint offset_con = (juint) find_int_con(offset, Type::OffsetBot); + if (offset_con != (juint) Type::OffsetBot) { + return longcon((julong) offset_con); + } + Node* conv = _gvn.transform( new (C) ConvI2LNode(offset)); + Node* mask = _gvn.transform( ConLNode::make(C, (julong) max_juint) ); + return _gvn.transform( new (C) AndLNode(conv, mask) ); +} + Node* GraphKit::ConvL2I(Node* offset) { // short-circuit a common case jlong offset_con = find_long_con(offset, (jlong)Type::OffsetBot); @@ -3151,10 +3162,14 @@ Node* mem = reset_memory(); FastLockNode * flock = _gvn.transform(new (C) FastLockNode(0, obj, box) )->as_FastLock(); - if (PrintPreciseBiasedLockingStatistics) { + if (UseBiasedLocking && PrintPreciseBiasedLockingStatistics) { // Create the counters for this fast lock. flock->create_lock_counter(sync_jvms()); // sync_jvms used to get current bci } + + // Create the rtm counters for this fast lock if needed. + flock->create_rtm_lock_counter(sync_jvms()); // sync_jvms used to get current bci + // Add monitor to debug info for the slow path. If we block inside the // slow path and de-opt, we need the monitor hanging around map()->push_monitor( flock ); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/graphKit.hpp --- a/hotspot/src/share/vm/opto/graphKit.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/graphKit.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -338,6 +338,7 @@ // Convert between int and long, and size_t. // (See macros ConvI2X, etc., in type.hpp for ConvI2X, etc.) Node* ConvI2L(Node* offset); + Node* ConvI2UL(Node* offset); Node* ConvL2I(Node* offset); // Find out the klass of an object. Node* load_object_klass(Node* object); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/library_call.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -2600,7 +2600,7 @@ case T_ADDRESS: // Cast to an int type. p = _gvn.transform(new (C) CastP2XNode(NULL, p)); - p = ConvX2L(p); + p = ConvX2UL(p); break; default: fatal(err_msg_res("unexpected type %d: %s", type, type2name(type))); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/locknode.cpp --- a/hotspot/src/share/vm/opto/locknode.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/locknode.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -136,6 +136,8 @@ //-----------------------------hash-------------------------------------------- uint FastLockNode::hash() const { return NO_HASH; } +uint FastLockNode::size_of() const { return sizeof(*this); } + //------------------------------cmp-------------------------------------------- uint FastLockNode::cmp( const Node &n ) const { return (&n == this); // Always fail except on self @@ -159,6 +161,22 @@ _counters = blnc->counters(); } +void FastLockNode::create_rtm_lock_counter(JVMState* state) { +#if INCLUDE_RTM_OPT + Compile* C = Compile::current(); + if (C->profile_rtm() || (PrintPreciseRTMLockingStatistics && C->use_rtm())) { + RTMLockingNamedCounter* rlnc = (RTMLockingNamedCounter*) + OptoRuntime::new_named_counter(state, NamedCounter::RTMLockingCounter); + _rtm_counters = rlnc->counters(); + if (UseRTMForStackLocks) { + rlnc = (RTMLockingNamedCounter*) + OptoRuntime::new_named_counter(state, NamedCounter::RTMLockingCounter); + _stack_rtm_counters = rlnc->counters(); + } + } +#endif +} + //============================================================================= //------------------------------do_monitor_enter------------------------------- void Parse::do_monitor_enter() { diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/locknode.hpp --- a/hotspot/src/share/vm/opto/locknode.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/locknode.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -92,13 +92,17 @@ //------------------------------FastLockNode----------------------------------- class FastLockNode: public CmpNode { private: - BiasedLockingCounters* _counters; + BiasedLockingCounters* _counters; + RTMLockingCounters* _rtm_counters; // RTM lock counters for inflated locks + RTMLockingCounters* _stack_rtm_counters; // RTM lock counters for stack locks public: FastLockNode(Node *ctrl, Node *oop, Node *box) : CmpNode(oop,box) { init_req(0,ctrl); init_class_id(Class_FastLock); _counters = NULL; + _rtm_counters = NULL; + _stack_rtm_counters = NULL; } Node* obj_node() const { return in(1); } Node* box_node() const { return in(2); } @@ -107,13 +111,17 @@ // FastLock and FastUnlockNode do not hash, we need one for each correspoding // LockNode/UnLockNode to avoid creating Phi's. virtual uint hash() const ; // { return NO_HASH; } + virtual uint size_of() const; virtual uint cmp( const Node &n ) const ; // Always fail, except on self virtual int Opcode() const; virtual const Type *Value( PhaseTransform *phase ) const { return TypeInt::CC; } const Type *sub(const Type *t1, const Type *t2) const { return TypeInt::CC;} void create_lock_counter(JVMState* s); - BiasedLockingCounters* counters() const { return _counters; } + void create_rtm_lock_counter(JVMState* state); + BiasedLockingCounters* counters() const { return _counters; } + RTMLockingCounters* rtm_counters() const { return _rtm_counters; } + RTMLockingCounters* stack_rtm_counters() const { return _stack_rtm_counters; } }; diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/loopTransform.cpp --- a/hotspot/src/share/vm/opto/loopTransform.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/loopTransform.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -617,6 +617,15 @@ case Op_AryEq: { return false; } +#if INCLUDE_RTM_OPT + case Op_FastLock: + case Op_FastUnlock: { + // Don't unroll RTM locking code because it is large. + if (UseRTMLocking) { + return false; + } + } +#endif } // switch } @@ -722,6 +731,15 @@ // String intrinsics are large and have loops. return false; } +#if INCLUDE_RTM_OPT + case Op_FastLock: + case Op_FastUnlock: { + // Don't unroll RTM locking code because it is large. + if (UseRTMLocking) { + return false; + } + } +#endif } // switch } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/machnode.hpp --- a/hotspot/src/share/vm/opto/machnode.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/machnode.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -53,6 +53,7 @@ class Matcher; class PhaseRegAlloc; class RegMask; +class RTMLockingCounters; class State; //---------------------------MachOper------------------------------------------ @@ -714,8 +715,9 @@ class MachFastLockNode : public MachNode { virtual uint size_of() const { return sizeof(*this); } // Size is bigger public: - BiasedLockingCounters* _counters; - + BiasedLockingCounters* _counters; + RTMLockingCounters* _rtm_counters; // RTM lock counters for inflated locks + RTMLockingCounters* _stack_rtm_counters; // RTM lock counters for stack locks MachFastLockNode() : MachNode() {} }; diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/macro.cpp --- a/hotspot/src/share/vm/opto/macro.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/macro.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -2439,6 +2439,7 @@ } } // Next, attempt to eliminate allocations + _has_locks = false; progress = true; while (progress) { progress = false; @@ -2457,11 +2458,13 @@ case Node::Class_Lock: case Node::Class_Unlock: assert(!n->as_AbstractLock()->is_eliminated(), "sanity"); + _has_locks = true; break; default: assert(n->Opcode() == Op_LoopLimit || n->Opcode() == Op_Opaque1 || - n->Opcode() == Op_Opaque2, "unknown node type in macro list"); + n->Opcode() == Op_Opaque2 || + n->Opcode() == Op_Opaque3, "unknown node type in macro list"); } assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); progress = progress || success; @@ -2502,6 +2505,30 @@ } else if (n->Opcode() == Op_Opaque1 || n->Opcode() == Op_Opaque2) { _igvn.replace_node(n, n->in(1)); success = true; +#if INCLUDE_RTM_OPT + } else if ((n->Opcode() == Op_Opaque3) && ((Opaque3Node*)n)->rtm_opt()) { + assert(C->profile_rtm(), "should be used only in rtm deoptimization code"); + assert((n->outcnt() == 1) && n->unique_out()->is_Cmp(), ""); + Node* cmp = n->unique_out(); +#ifdef ASSERT + // Validate graph. + assert((cmp->outcnt() == 1) && cmp->unique_out()->is_Bool(), ""); + BoolNode* bol = cmp->unique_out()->as_Bool(); + assert((bol->outcnt() == 1) && bol->unique_out()->is_If() && + (bol->_test._test == BoolTest::ne), ""); + IfNode* ifn = bol->unique_out()->as_If(); + assert((ifn->outcnt() == 2) && + ifn->proj_out(1)->is_uncommon_trap_proj(Deoptimization::Reason_rtm_state_change), ""); +#endif + Node* repl = n->in(1); + if (!_has_locks) { + // Remove RTM state check if there are no locks in the code. + // Replace input to compare the same value. + repl = (cmp->in(1) == n) ? cmp->in(2) : cmp->in(1); + } + _igvn.replace_node(n, repl); + success = true; +#endif } assert(success == (C->macro_count() < old_macro_count), "elimination reduces macro count"); progress = progress || success; diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/macro.hpp --- a/hotspot/src/share/vm/opto/macro.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/macro.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -76,6 +76,8 @@ ProjNode *_memproj_catchall; ProjNode *_resproj; + // Additional data collected during macro expansion + bool _has_locks; void expand_allocate(AllocateNode *alloc); void expand_allocate_array(AllocateArrayNode *alloc); @@ -118,7 +120,7 @@ Node* length); public: - PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn) { + PhaseMacroExpand(PhaseIterGVN &igvn) : Phase(Macro_Expand), _igvn(igvn), _has_locks(false) { _igvn.set_delay_transform(true); } void eliminate_macro_nodes(); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/output.cpp --- a/hotspot/src/share/vm/opto/output.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/output.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -42,18 +42,12 @@ #include "runtime/handles.inline.hpp" #include "utilities/xmlstream.hpp" -extern uint size_exception_handler(); -extern uint size_deopt_handler(); - #ifndef PRODUCT #define DEBUG_ARG(x) , x #else #define DEBUG_ARG(x) #endif -extern int emit_exception_handler(CodeBuffer &cbuf); -extern int emit_deopt_handler(CodeBuffer &cbuf); - // Convert Nodes to instruction bits and pass off to the VM void Compile::Output() { // RootNode goes @@ -394,6 +388,11 @@ blk_size += (mach->alignment_required() - 1) * relocInfo::addr_unit(); // assume worst case padding reloc_size += mach->reloc(); if (mach->is_MachCall()) { + // add size information for trampoline stub + // class CallStubImpl is platform-specific and defined in the *.ad files. + stub_size += CallStubImpl::size_call_trampoline(); + reloc_size += CallStubImpl::reloc_call_trampoline(); + MachCallNode *mcall = mach->as_MachCall(); // This destination address is NOT PC-relative @@ -1133,10 +1132,9 @@ shorten_branches(blk_starts, code_req, locs_req, stub_req); // nmethod and CodeBuffer count stubs & constants as part of method's code. - int exception_handler_req = size_exception_handler(); - int deopt_handler_req = size_deopt_handler(); - exception_handler_req += MAX_stubs_size; // add marginal slop for handler - deopt_handler_req += MAX_stubs_size; // add marginal slop for handler + // class HandlerImpl is platform-specific and defined in the *.ad files. + int exception_handler_req = HandlerImpl::size_exception_handler() + MAX_stubs_size; // add marginal slop for handler + int deopt_handler_req = HandlerImpl::size_deopt_handler() + MAX_stubs_size; // add marginal slop for handler stub_req += MAX_stubs_size; // ensure per-stub margin code_req += MAX_inst_size; // ensure per-instruction margin @@ -1622,17 +1620,18 @@ FillExceptionTables(inct_cnt, call_returns, inct_starts, blk_labels); // Only java methods have exception handlers and deopt handlers + // class HandlerImpl is platform-specific and defined in the *.ad files. if (_method) { // Emit the exception handler code. - _code_offsets.set_value(CodeOffsets::Exceptions, emit_exception_handler(*cb)); + _code_offsets.set_value(CodeOffsets::Exceptions, HandlerImpl::emit_exception_handler(*cb)); // Emit the deopt handler code. - _code_offsets.set_value(CodeOffsets::Deopt, emit_deopt_handler(*cb)); + _code_offsets.set_value(CodeOffsets::Deopt, HandlerImpl::emit_deopt_handler(*cb)); // Emit the MethodHandle deopt handler code (if required). if (has_method_handle_invokes()) { // We can use the same code as for the normal deopt handler, we // just need a different entry point address. - _code_offsets.set_value(CodeOffsets::DeoptMH, emit_deopt_handler(*cb)); + _code_offsets.set_value(CodeOffsets::DeoptMH, HandlerImpl::emit_deopt_handler(*cb)); } } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/parse.hpp --- a/hotspot/src/share/vm/opto/parse.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/parse.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -486,6 +486,8 @@ // Helper function to compute array addressing Node* array_addressing(BasicType type, int vals, const Type* *result2=NULL); + void rtm_deopt(); + // Pass current map to exits void return_current(Node* value); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/parse1.cpp --- a/hotspot/src/share/vm/opto/parse1.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/parse1.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -567,6 +567,10 @@ set_map(entry_map); do_method_entry(); } + if (depth() == 1) { + // Add check to deoptimize the nmethod if RTM state was changed + rtm_deopt(); + } // Check for bailouts during method entry. if (failing()) { @@ -2006,6 +2010,42 @@ set_control( _gvn.transform(result_rgn) ); } +// Add check to deoptimize if RTM state is not ProfileRTM +void Parse::rtm_deopt() { +#if INCLUDE_RTM_OPT + if (C->profile_rtm()) { + assert(C->method() != NULL, "only for normal compilations"); + assert(!C->method()->method_data()->is_empty(), "MDO is needed to record RTM state"); + assert(depth() == 1, "generate check only for main compiled method"); + + // Set starting bci for uncommon trap. + set_parse_bci(is_osr_parse() ? osr_bci() : 0); + + // Load the rtm_state from the MethodData. + const TypePtr* adr_type = TypeMetadataPtr::make(C->method()->method_data()); + Node* mdo = makecon(adr_type); + int offset = MethodData::rtm_state_offset_in_bytes(); + Node* adr_node = basic_plus_adr(mdo, mdo, offset); + Node* rtm_state = make_load(control(), adr_node, TypeInt::INT, T_INT, adr_type, MemNode::unordered); + + // Separate Load from Cmp by Opaque. + // In expand_macro_nodes() it will be replaced either + // with this load when there are locks in the code + // or with ProfileRTM (cmp->in(2)) otherwise so that + // the check will fold. + Node* profile_state = makecon(TypeInt::make(ProfileRTM)); + Node* opq = _gvn.transform( new (C) Opaque3Node(C, rtm_state, Opaque3Node::RTM_OPT) ); + Node* chk = _gvn.transform( new (C) CmpINode(opq, profile_state) ); + Node* tst = _gvn.transform( new (C) BoolNode(chk, BoolTest::eq) ); + // Branch to failure if state was changed + { BuildCutout unless(this, tst, PROB_ALWAYS); + uncommon_trap(Deoptimization::Reason_rtm_state_change, + Deoptimization::Action_make_not_entrant); + } + } +#endif +} + //------------------------------return_current--------------------------------- // Append current _map to _exit_return void Parse::return_current(Node* value) { diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/runtime.cpp --- a/hotspot/src/share/vm/opto/runtime.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/runtime.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1310,6 +1310,14 @@ tty->print_cr("%s", c->name()); blc->print_on(tty); } +#if INCLUDE_RTM_OPT + } else if (c->tag() == NamedCounter::RTMLockingCounter) { + RTMLockingCounters* rlc = ((RTMLockingNamedCounter*)c)->counters(); + if (rlc->nonzero()) { + tty->print_cr("%s", c->name()); + rlc->print_on(tty); + } +#endif } c = c->next(); } @@ -1349,6 +1357,8 @@ NamedCounter* c; if (tag == NamedCounter::BiasedLockingCounter) { c = new BiasedLockingNamedCounter(strdup(st.as_string())); + } else if (tag == NamedCounter::RTMLockingCounter) { + c = new RTMLockingNamedCounter(strdup(st.as_string())); } else { c = new NamedCounter(strdup(st.as_string()), tag); } @@ -1357,6 +1367,7 @@ // add counters so this is safe. NamedCounter* head; do { + c->set_next(NULL); head = _named_counters; c->set_next(head); } while (Atomic::cmpxchg_ptr(c, &_named_counters, head) != head); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/runtime.hpp --- a/hotspot/src/share/vm/opto/runtime.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/runtime.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -29,6 +29,7 @@ #include "opto/machnode.hpp" #include "opto/type.hpp" #include "runtime/biasedLocking.hpp" +#include "runtime/rtmLocking.hpp" #include "runtime/deoptimization.hpp" #include "runtime/vframe.hpp" @@ -61,7 +62,8 @@ NoTag, LockCounter, EliminatedLockCounter, - BiasedLockingCounter + BiasedLockingCounter, + RTMLockingCounter }; private: @@ -85,7 +87,7 @@ NamedCounter* next() const { return _next; } void set_next(NamedCounter* next) { - assert(_next == NULL, "already set"); + assert(_next == NULL || next == NULL, "already set"); _next = next; } @@ -102,6 +104,18 @@ BiasedLockingCounters* counters() { return &_counters; } }; + +class RTMLockingNamedCounter : public NamedCounter { + private: + RTMLockingCounters _counters; + + public: + RTMLockingNamedCounter(const char *n) : + NamedCounter(n, RTMLockingCounter), _counters() {} + + RTMLockingCounters* counters() { return &_counters; } +}; + typedef const TypeFunc*(*TypeFunc_generator)(); class OptoRuntime : public AllStatic { diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/type.cpp --- a/hotspot/src/share/vm/opto/type.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/type.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -4380,7 +4380,7 @@ // else fall through: case TopPTR: case AnyNull: { - return make(ptr, NULL, offset); + return make(ptr, _metadata, offset); } case BotPTR: case NotNull: diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/opto/type.hpp --- a/hotspot/src/share/vm/opto/type.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/opto/type.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -1716,6 +1716,7 @@ #define ConvL2X(x) (x) #define ConvX2I(x) ConvL2I(x) #define ConvX2L(x) (x) +#define ConvX2UL(x) (x) #else @@ -1760,6 +1761,7 @@ #define ConvL2X(x) ConvL2I(x) #define ConvX2I(x) (x) #define ConvX2L(x) ConvI2L(x) +#define ConvX2UL(x) ConvI2UL(x) #endif diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/prims/whitebox.cpp --- a/hotspot/src/share/vm/prims/whitebox.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/prims/whitebox.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -500,6 +500,54 @@ c = *p; WB_END +WB_ENTRY(jstring, WB_GetCPUFeatures(JNIEnv* env, jobject o)) + const char* cpu_features = VM_Version::cpu_features(); + ThreadToNativeFromVM ttn(thread); + jstring features_string = env->NewStringUTF(cpu_features); + + CHECK_JNI_EXCEPTION_(env, NULL); + + return features_string; +WB_END + + +WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr)) + ResourceMark rm(THREAD); + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION_(env, NULL); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code(); + jobjectArray result = NULL; + if (code == NULL) { + return result; + } + int insts_size = code->insts_size(); + + ThreadToNativeFromVM ttn(thread); + jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string()); + CHECK_JNI_EXCEPTION_(env, NULL); + result = env->NewObjectArray(2, clazz, NULL); + if (result == NULL) { + return result; + } + + clazz = env->FindClass(vmSymbols::java_lang_Integer()->as_C_string()); + CHECK_JNI_EXCEPTION_(env, NULL); + jmethodID constructor = env->GetMethodID(clazz, vmSymbols::object_initializer_name()->as_C_string(), vmSymbols::int_void_signature()->as_C_string()); + CHECK_JNI_EXCEPTION_(env, NULL); + jobject obj = env->NewObject(clazz, constructor, code->comp_level()); + CHECK_JNI_EXCEPTION_(env, NULL); + env->SetObjectArrayElement(result, 0, obj); + + jbyteArray insts = env->NewByteArray(insts_size); + CHECK_JNI_EXCEPTION_(env, NULL); + env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin()); + env->SetObjectArrayElement(result, 1, insts); + + return result; +WB_END + + //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, Symbol* signature_symbol) { @@ -611,6 +659,9 @@ {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable }, {CC"fullGC", CC"()V", (void*)&WB_FullGC }, {CC"readReservedMemory", CC"()V", (void*)&WB_ReadReservedMemory }, + {CC"getCPUFeatures", CC"()Ljava/lang/String;", (void*)&WB_GetCPUFeatures }, + {CC"getNMethod", CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;", + (void*)&WB_GetNMethod }, }; #undef CC diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/prims/whitebox.hpp --- a/hotspot/src/share/vm/prims/whitebox.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/prims/whitebox.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -40,7 +40,6 @@ do { \ JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \ if (HAS_PENDING_EXCEPTION) { \ - CLEAR_PENDING_EXCEPTION; \ return(value); \ } \ } while (0) @@ -49,7 +48,6 @@ do { \ JavaThread* THREAD = JavaThread::thread_from_jni_environment(env); \ if (HAS_PENDING_EXCEPTION) { \ - CLEAR_PENDING_EXCEPTION; \ return; \ } \ } while (0) diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/runtime/arguments.cpp --- a/hotspot/src/share/vm/runtime/arguments.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -301,6 +301,7 @@ { "UseMPSS", JDK_Version::jdk(8), JDK_Version::jdk(9) }, { "UseStringCache", JDK_Version::jdk(8), JDK_Version::jdk(9) }, { "UseOldInlining", JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "SafepointPollOffset", JDK_Version::jdk(9), JDK_Version::jdk(10) }, #ifdef PRODUCT { "DesiredMethodLimit", JDK_Version::jdk_update(7, 2), JDK_Version::jdk(8) }, @@ -1186,11 +1187,6 @@ FLAG_SET_DEFAULT(OldPLABSize, (intx)1024); } - // AlwaysTenure flag should make ParNew promote all at first collection. - // See CR 6362902. - if (AlwaysTenure) { - FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, 0); - } // When using compressed oops, we use local overflow stacks, // rather than using a global overflow list chained through // the klass word of the object's pre-image. @@ -2343,10 +2339,8 @@ status = status && verify_percentage(YoungGenerationSizeSupplement, "YoungGenerationSizeSupplement"); status = status && verify_percentage(TenuredGenerationSizeSupplement, "TenuredGenerationSizeSupplement"); - // the "age" field in the oop header is 4 bits; do not want to pull in markOop.hpp - // just for that, so hardcode here. - status = status && verify_interval(MaxTenuringThreshold, 0, 15, "MaxTenuringThreshold"); - status = status && verify_interval(InitialTenuringThreshold, 0, MaxTenuringThreshold, "MaxTenuringThreshold"); + status = status && verify_interval(MaxTenuringThreshold, 0, markOopDesc::max_age + 1, "MaxTenuringThreshold"); + status = status && verify_interval(InitialTenuringThreshold, 0, MaxTenuringThreshold, "InitialTenuringThreshold"); status = status && verify_percentage(TargetSurvivorRatio, "TargetSurvivorRatio"); status = status && verify_percentage(MarkSweepDeadRatio, "MarkSweepDeadRatio"); @@ -3072,14 +3066,31 @@ // but disallow DR and offlining (5008695). FLAG_SET_CMDLINE(bool, BindGCTaskThreadsToCPUs, true); + // Need to keep consistency of MaxTenuringThreshold and AlwaysTenure/NeverTenure; + // and the last option wins. } else if (match_option(option, "-XX:+NeverTenure", &tail)) { - // The last option must always win. + FLAG_SET_CMDLINE(bool, NeverTenure, true); FLAG_SET_CMDLINE(bool, AlwaysTenure, false); - FLAG_SET_CMDLINE(bool, NeverTenure, true); + FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, markOopDesc::max_age + 1); } else if (match_option(option, "-XX:+AlwaysTenure", &tail)) { - // The last option must always win. FLAG_SET_CMDLINE(bool, NeverTenure, false); FLAG_SET_CMDLINE(bool, AlwaysTenure, true); + FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, 0); + } else if (match_option(option, "-XX:MaxTenuringThreshold=", &tail)) { + uintx max_tenuring_thresh = 0; + if(!parse_uintx(tail, &max_tenuring_thresh, 0)) { + jio_fprintf(defaultStream::error_stream(), + "Invalid MaxTenuringThreshold: %s\n", option->optionString); + } + FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, max_tenuring_thresh); + + if (MaxTenuringThreshold == 0) { + FLAG_SET_CMDLINE(bool, NeverTenure, false); + FLAG_SET_CMDLINE(bool, AlwaysTenure, true); + } else { + FLAG_SET_CMDLINE(bool, NeverTenure, false); + FLAG_SET_CMDLINE(bool, AlwaysTenure, false); + } } else if (match_option(option, "-XX:+CMSPermGenSweepingEnabled", &tail) || match_option(option, "-XX:-CMSPermGenSweepingEnabled", &tail)) { jio_fprintf(defaultStream::error_stream(), @@ -3779,9 +3790,6 @@ #endif // CC_INTERP #ifdef COMPILER2 - if (!UseBiasedLocking || EmitSync != 0) { - UseOptoBiasInlining = false; - } if (!EliminateLocks) { EliminateNestedLocks = false; } @@ -3842,6 +3850,11 @@ UseBiasedLocking = false; } } +#ifdef COMPILER2 + if (!UseBiasedLocking || EmitSync != 0) { + UseOptoBiasInlining = false; + } +#endif return JNI_OK; } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/runtime/deoptimization.cpp --- a/hotspot/src/share/vm/runtime/deoptimization.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -1288,7 +1288,8 @@ gather_statistics(reason, action, trap_bc); // Ensure that we can record deopt. history: - bool create_if_missing = ProfileTraps; + // Need MDO to record RTM code generation state. + bool create_if_missing = ProfileTraps RTM_OPT_ONLY( || UseRTMLocking ); MethodData* trap_mdo = get_method_data(thread, trap_method, create_if_missing); @@ -1569,6 +1570,17 @@ if (tstate1 != tstate0) pdata->set_trap_state(tstate1); } + +#if INCLUDE_RTM_OPT + // Restart collecting RTM locking abort statistic if the method + // is recompiled for a reason other than RTM state change. + // Assume that in new recompiled code the statistic could be different, + // for example, due to different inlining. + if ((reason != Reason_rtm_state_change) && (trap_mdo != NULL) && + UseRTMDeopt && (nm->rtm_state() != ProfileRTM)) { + trap_mdo->atomic_set_rtm_state(ProfileRTM); + } +#endif } if (inc_recompile_count) { @@ -1826,7 +1838,8 @@ "age", "predicate", "loop_limit_check", - "speculate_class_check" + "speculate_class_check", + "rtm_state_change" }; const char* Deoptimization::_trap_action_name[Action_LIMIT] = { // Note: Keep this in sync. with enum DeoptAction. diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/runtime/deoptimization.hpp --- a/hotspot/src/share/vm/runtime/deoptimization.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/runtime/deoptimization.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -60,6 +60,7 @@ Reason_predicate, // compiler generated predicate failed Reason_loop_limit_check, // compiler generated loop limits check failed Reason_speculate_class_check, // saw unexpected object class from type speculation + Reason_rtm_state_change, // rtm state change detected Reason_LIMIT, // Note: Keep this enum in sync. with _trap_reason_name. Reason_RECORDED_LIMIT = Reason_bimorphic // some are not recorded per bc diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/runtime/frame.cpp --- a/hotspot/src/share/vm/runtime/frame.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/runtime/frame.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -531,13 +531,16 @@ // Number of elements on the interpreter expression stack // Callers should span by stackElementWords int element_size = Interpreter::stackElementWords; + size_t stack_size = 0; if (frame::interpreter_frame_expression_stack_direction() < 0) { - return (interpreter_frame_expression_stack() - - interpreter_frame_tos_address() + 1)/element_size; + stack_size = (interpreter_frame_expression_stack() - + interpreter_frame_tos_address() + 1)/element_size; } else { - return (interpreter_frame_tos_address() - - interpreter_frame_expression_stack() + 1)/element_size; + stack_size = (interpreter_frame_tos_address() - + interpreter_frame_expression_stack() + 1)/element_size; } + assert( stack_size <= (size_t)max_jint, "stack size too big"); + return ((jint)stack_size); } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/runtime/java.cpp --- a/hotspot/src/share/vm/runtime/java.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/runtime/java.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -265,7 +265,7 @@ os::print_statistics(); } - if (PrintLockStatistics || PrintPreciseBiasedLockingStatistics) { + if (PrintLockStatistics || PrintPreciseBiasedLockingStatistics || PrintPreciseRTMLockingStatistics) { OptoRuntime::print_named_counters(); } @@ -387,7 +387,7 @@ } #ifdef COMPILER2 - if (PrintPreciseBiasedLockingStatistics) { + if (PrintPreciseBiasedLockingStatistics || PrintPreciseRTMLockingStatistics) { OptoRuntime::print_named_counters(); } #endif diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/runtime/rtmLocking.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/runtime/rtmLocking.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,113 @@ +/* + * 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. + * + */ + +#ifndef SHARE_VM_RUNTIME_RTMLOCKING_HPP +#define SHARE_VM_RUNTIME_RTMLOCKING_HPP + +// Generate RTM (Restricted Transactional Memory) locking code for all inflated +// locks when "UseRTMLocking" option is on with normal locking mechanism as fall back +// handler. +// +// On abort/lock busy the lock will be retried a fixed number of times under RTM +// as specified by "RTMRetryCount" option. The locks which abort too often +// can be auto tuned or manually tuned. +// +// Auto-tuning can be done on an option like UseRTMDeopt and it will need abort +// ratio calculation for each lock. The abort ratio will be calculated after +// "RTMAbortThreshold" number of aborts is reached. The formulas are: +// +// Aborted transactions = abort_count * 100 +// All transactions = total_count * RTMTotalCountIncrRate +// +// Aborted transactions >= All transactions * RTMAbortRatio +// +// If "UseRTMDeopt" is on and the aborts ratio reaches "RTMAbortRatio" +// the method containing the lock will be deoptimized and recompiled with +// all locks as normal locks. If the abort ratio continues to remain low after +// "RTMLockingThreshold" locks are attempted, then the method will be deoptimized +// and recompiled with all locks as RTM locks without abort ratio calculation code. +// The abort ratio calculation can be delayed by specifying flag +// -XX:RTMLockingCalculationDelay in millisecond. +// +// For manual tuning the abort statistics for each lock needs to be provided +// to the user on some JVM option like "PrintPreciseRTMLockingStatistics". +// Based on the abort statistics users can create a .hotspot_compiler file +// or use -XX:CompileCommand=option,class::method,NoRTMLockEliding +// to specify for which methods to disable RTM locking. +// +// When UseRTMForStackLocks option is enabled along with UseRTMLocking option, +// the RTM locking code is generated for stack locks too. +// The retries, auto-tuning support and rtm locking statistics are all +// supported for stack locks just like inflated locks. + +// RTM locking counters +class RTMLockingCounters VALUE_OBJ_CLASS_SPEC { + private: + uintx _total_count; // Total RTM locks count + uintx _abort_count; // Total aborts count + + public: + enum { ABORT_STATUS_LIMIT = 6 }; + // Counters per RTM Abort Status. Incremented with +PrintPreciseRTMLockingStatistics + // RTM uses the EAX register to communicate abort status to software. + // Following an RTM abort the EAX register has the following definition. + // + // EAX register bit position Meaning + // 0 Set if abort caused by XABORT instruction. + // 1 If set, the transaction may succeed on a retry. This bit is always clear if bit 0 is set. + // 2 Set if another logical processor conflicted with a memory address that was part of the transaction that aborted. + // 3 Set if an internal buffer overflowed. + // 4 Set if a debug breakpoint was hit. + // 5 Set if an abort occurred during execution of a nested transaction. + private: + uintx _abortX_count[ABORT_STATUS_LIMIT]; + + public: + static uintx _calculation_flag; + static uintx* rtm_calculation_flag_addr() { return &_calculation_flag; } + + static void init(); + + RTMLockingCounters() : _total_count(0), _abort_count(0) { + for (int i = 0; i < ABORT_STATUS_LIMIT; i++) { + _abortX_count[i] = 0; + } + } + + uintx* total_count_addr() { return &_total_count; } + uintx* abort_count_addr() { return &_abort_count; } + uintx* abortX_count_addr() { return &_abortX_count[0]; } + + static int total_count_offset() { return (int)offset_of(RTMLockingCounters, _total_count); } + static int abort_count_offset() { return (int)offset_of(RTMLockingCounters, _abort_count); } + static int abortX_count_offset() { return (int)offset_of(RTMLockingCounters, _abortX_count[0]); } + + + bool nonzero() { return (_abort_count + _total_count) > 0; } + + void print_on(outputStream* st); + void print() { print_on(tty); } +}; + +#endif // SHARE_VM_RUNTIME_RTMLOCKING_HPP diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/runtime/task.cpp --- a/hotspot/src/share/vm/runtime/task.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/runtime/task.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -105,7 +105,6 @@ _counter(0), _interval((int) interval_time) { // Sanity check the interval time assert(_interval >= PeriodicTask::min_interval && - _interval <= PeriodicTask::max_interval && _interval % PeriodicTask::interval_gran == 0, "improper PeriodicTask interval time"); } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/runtime/thread.cpp --- a/hotspot/src/share/vm/runtime/thread.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/runtime/thread.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -107,6 +107,9 @@ #include "opto/c2compiler.hpp" #include "opto/idealGraphPrinter.hpp" #endif +#if INCLUDE_RTM_OPT +#include "runtime/rtmLocking.hpp" +#endif #ifdef DTRACE_ENABLED @@ -3622,6 +3625,10 @@ BiasedLocking::init(); +#if INCLUDE_RTM_OPT + RTMLockingCounters::init(); +#endif + if (JDK_Version::current().post_vm_init_hook_enabled()) { call_postVMInitHook(THREAD); // The Java side of PostVMInitHook.run must deal with all diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/services/management.cpp --- a/hotspot/src/share/vm/services/management.cpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/services/management.cpp Fri Mar 28 09:15:41 2014 -0700 @@ -152,11 +152,14 @@ // Load and initialize the sun.management.Agent class // invoke startAgent method to start the management server Handle loader = Handle(THREAD, SystemDictionary::java_system_loader()); - Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), + Klass* k = SystemDictionary::resolve_or_null(vmSymbols::sun_management_Agent(), loader, Handle(), - true, - CHECK); + THREAD); + if (k == NULL) { + vm_exit_during_initialization("Management agent initialization failure: " + "class sun.management.Agent not found."); + } instanceKlassHandle ik (THREAD, k); JavaValue result(T_VOID); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/src/share/vm/utilities/globalDefinitions.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Fri Mar 28 09:15:41 2014 -0700 @@ -373,6 +373,21 @@ // Machine dependent stuff +#if defined(X86) && defined(COMPILER2) && !defined(JAVASE_EMBEDDED) +// Include Restricted Transactional Memory lock eliding optimization +#define INCLUDE_RTM_OPT 1 +#define RTM_OPT_ONLY(code) code +#else +#define INCLUDE_RTM_OPT 0 +#define RTM_OPT_ONLY(code) +#endif +// States of Restricted Transactional Memory usage. +enum RTMState { + NoRTM = 0x2, // Don't use RTM + UseRTM = 0x1, // Use RTM + ProfileRTM = 0x0 // Use RTM with abort ratio calculation +}; + #ifdef TARGET_ARCH_x86 # include "globalDefinitions_x86.hpp" #endif diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/6792161/Test6792161.java --- a/hotspot/test/compiler/6792161/Test6792161.java Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/test/compiler/6792161/Test6792161.java Fri Mar 28 09:15:41 2014 -0700 @@ -27,7 +27,7 @@ * @bug 6792161 * @summary assert("No dead instructions after post-alloc") * - * @run main/othervm/timeout=300 -Xcomp -XX:MaxInlineSize=120 Test6792161 + * @run main/othervm/timeout=600 -Xcomp -XX:MaxInlineSize=120 Test6792161 */ import java.lang.reflect.Constructor; diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/arguments/BMICommandLineOptionTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/arguments/BMICommandLineOptionTestBase.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,68 @@ +/* + * 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. + */ + +import com.oracle.java.testlibrary.cli.*; + +/** + * Base class for all X86 bit manipulation related command line options. + */ +public abstract class BMICommandLineOptionTestBase + extends CPUSpecificCommandLineOptionTest { + + public static final String LZCNT_WARNING = + "lzcnt instruction is not available on this CPU"; + public static final String TZCNT_WARNING = + "tzcnt instruction is not available on this CPU"; + public static final String BMI1_WARNING = + "BMI1 instructions are not available on this CPU"; + + protected final String optionName; + protected final String warningMessage; + protected final String errorMessage; + + /** + * Construct new test on {@code optionName} option. + * + * @param optionName Name of the option to be tested + * without -XX:[+-] prefix. + * @param warningMessage Message that can occur in VM output + * if CPU on test box does not support + * features required by the option. + * @param supportedCPUFeatures CPU features requires by the option, + * that should be supported on test box. + * @param unsupportedCPUFeatures CPU features requires by the option, + * that should not be supported on test box. + */ + public BMICommandLineOptionTestBase(String optionName, + String warningMessage, + String supportedCPUFeatures[], + String unsupportedCPUFeatures[]) { + super(".*", supportedCPUFeatures, unsupportedCPUFeatures); + this.optionName = optionName; + this.warningMessage = warningMessage; + this.errorMessage = CommandLineOptionTest. + UNRECOGNIZED_OPTION_ERROR_FORMAT.format(optionName); + } + +} + diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/arguments/BMISupportedCPUTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/arguments/BMISupportedCPUTest.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; + +/** + * Test on bit manipulation related command line options, + * that should be executed on CPU that supports all required + * features. + */ +public class BMISupportedCPUTest extends BMICommandLineOptionTestBase { + + /** + * Construct new test on {@code optionName} option. + * + * @param optionName Name of the option to be tested + * without -XX:[+-] prefix. + * @param warningMessage Message that can occur in VM output + * if CPU on test box does not support + * features required by the option. + * @param cpuFeatures CPU features requires by the option. + */ + public BMISupportedCPUTest(String optionName, + String warningMessage, + String... cpuFeatures) { + super(optionName, warningMessage, cpuFeatures, null); + } + + @Override + public void runTestCases() throws Throwable { + // verify that VM will succesfully start up whithout warnings + CommandLineOptionTest. + verifyJVMStartup("-XX:+" + optionName, + null, new String[] { warningMessage }, + ExitCode.OK); + + // verify that VM will succesfully start up whithout warnings + CommandLineOptionTest. + verifyJVMStartup("-XX:-" + optionName, + null, new String[] { warningMessage }, + ExitCode.OK); + + // verify that on appropriate CPU option in on by default + CommandLineOptionTest.verifyOptionValue(optionName, "true"); + + // verify that option could be explicitly turned off + CommandLineOptionTest.verifyOptionValue(optionName, "false", + "-XX:-" + optionName); + } +} + diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/arguments/BMIUnsupportedCPUTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/arguments/BMIUnsupportedCPUTest.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,114 @@ +/* + * 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. + */ + +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; + +/** + * Test on bit manipulation related command line options, + * that should be executed on CPU that does not support + * required features. + */ +public class BMIUnsupportedCPUTest extends BMICommandLineOptionTestBase { + + /** + * Construct new test on {@code optionName} option. + * + * @param optionName Name of the option to be tested + * without -XX:[+-] prefix. + * @param warningMessage Message that can occur in VM output + * if CPU on test box does not support + * features required by the option. + * @param cpuFeatures CPU features requires by the option. + */ + public BMIUnsupportedCPUTest(String optionName, + String warningMessage, + String... cpuFeatures) { + super(optionName, warningMessage, null, cpuFeatures); + } + + @Override + public void runTestCases() throws Throwable { + if (Platform.isX86() || Platform.isX64()) { + unsupportedX86CPUTestCases(); + } else { + unsupportedNonX86CPUTestCases(); + } + } + + /** + * Run test cases common for all bit manipulation related VM options + * targeted to X86 CPU that does not support required features. + * + * @throws Throwable if test failed. + */ + public void unsupportedX86CPUTestCases() throws Throwable { + + // verify that VM will succesfully start up, but output will + // contain a warning + CommandLineOptionTest. + verifyJVMStartup("-XX:+" + optionName, + new String[] { warningMessage }, + new String[] { errorMessage }, + ExitCode.OK); + + // verify that VM will succesfully startup without any warnings + CommandLineOptionTest. + verifyJVMStartup("-XX:-" + optionName, + null, + new String[] { warningMessage, errorMessage }, + ExitCode.OK); + + // verify that on unsupported CPUs option is off by default + CommandLineOptionTest.verifyOptionValue(optionName, "false"); + + // verify that on unsupported CPUs option will be off even if + // it was explicitly turned on by uset + CommandLineOptionTest.verifyOptionValue(optionName, "false", + "-XX:+" + optionName); + + } + + /** + * Run test cases common for all bit manipulation related VM options + * targeted to non-X86 CPU that does not support required features. + * + * @throws Throwable if test failed. + */ + public void unsupportedNonX86CPUTestCases() throws Throwable { + + // verify that VM known nothing about tested option + CommandLineOptionTest. + verifyJVMStartup("-XX:+" + optionName, + new String[] { errorMessage }, + null, + ExitCode.FAIL); + + CommandLineOptionTest. + verifyJVMStartup("-XX:-" + optionName, + new String[] { errorMessage }, + null, + ExitCode.FAIL); + } +} + diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8031321 + * @summary Verify processing of UseBMI1Instructions option on CPU with + * BMI1 feature support. + * @library /testlibrary /testlibrary/whitebox + * @build TestUseBMI1InstructionsOnSupportedCPU + * BMISupportedCPUTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseBMI1InstructionsOnSupportedCPU + */ + +import sun.hotspot.cpuinfo.CPUInfo; +import com.oracle.java.testlibrary.*; + +public class TestUseBMI1InstructionsOnSupportedCPU + extends BMISupportedCPUTest { + + public TestUseBMI1InstructionsOnSupportedCPU() { + super("UseBMI1Instructions", BMI1_WARNING, "bmi1"); + } + + public static void main(String args[]) throws Throwable { + new TestUseBMI1InstructionsOnSupportedCPU().test(); + } +} + diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8031321 + * @summary Verify processing of UseBMI1Instructions option on CPU without + * BMI1 feature support. + * @library /testlibrary /testlibrary/whitebox + * @build TestUseBMI1InstructionsOnUnsupportedCPU + * BMIUnsupportedCPUTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestUseBMI1InstructionsOnUnsupportedCPU + */ + +import sun.hotspot.cpuinfo.CPUInfo; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; + +public class TestUseBMI1InstructionsOnUnsupportedCPU + extends BMIUnsupportedCPUTest { + + public TestUseBMI1InstructionsOnUnsupportedCPU() { + super("UseBMI1Instructions", BMI1_WARNING, "bmi1"); + } + + public static void main(String args[]) throws Throwable { + new TestUseBMI1InstructionsOnUnsupportedCPU().test(); + } +} + diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8031321 + * @summary Verify processing of UseCountLeadingZerosInstruction option + * on CPU with LZCNT support. + * @library /testlibrary /testlibrary/whitebox + * @build TestUseCountLeadingZerosInstructionOnSupportedCPU + * BMISupportedCPUTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestUseCountLeadingZerosInstructionOnSupportedCPU + */ + +import sun.hotspot.cpuinfo.CPUInfo; +import com.oracle.java.testlibrary.*; + +public class TestUseCountLeadingZerosInstructionOnSupportedCPU + extends BMISupportedCPUTest { + + public TestUseCountLeadingZerosInstructionOnSupportedCPU() { + super("UseCountLeadingZerosInstruction", LZCNT_WARNING, "lzcnt"); + } + + public static void main(String args[]) throws Throwable { + new TestUseCountLeadingZerosInstructionOnSupportedCPU().test(); + } +} + diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8031321 + * @summary Verify processing of UseCountLeadingZerosInstruction option + * on CPU without LZCNT support. + * @library /testlibrary /testlibrary/whitebox + * @build TestUseCountLeadingZerosInstructionOnUnsupportedCPU + * BMIUnsupportedCPUTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestUseCountLeadingZerosInstructionOnUnsupportedCPU + */ + +import sun.hotspot.cpuinfo.CPUInfo; +import com.oracle.java.testlibrary.*; + +public class TestUseCountLeadingZerosInstructionOnUnsupportedCPU + extends BMIUnsupportedCPUTest { + + public TestUseCountLeadingZerosInstructionOnUnsupportedCPU() { + super("UseCountLeadingZerosInstruction", LZCNT_WARNING, "lzcnt"); + } + + public static void main(String args[]) throws Throwable { + new TestUseCountLeadingZerosInstructionOnUnsupportedCPU().test(); + } +} + diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8031321 + * @summary Verify processing of UseCountTrailingZerosInstruction option + * on CPU with TZCNT (BMI1 feature) support. + * @library /testlibrary /testlibrary/whitebox + * @build TestUseCountTrailingZerosInstructionOnSupportedCPU + * BMISupportedCPUTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestUseCountTrailingZerosInstructionOnSupportedCPU + */ + +import sun.hotspot.cpuinfo.CPUInfo; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; + +public class TestUseCountTrailingZerosInstructionOnSupportedCPU + extends BMISupportedCPUTest { + + public TestUseCountTrailingZerosInstructionOnSupportedCPU() { + super("UseCountTrailingZerosInstruction", TZCNT_WARNING, "bmi1"); + } + + @Override + public void runTestCases() throws Throwable { + + super.runTestCases(); + + // verify that option will be disabled if all BMI1 instuctions + // are explicitly disabled + CommandLineOptionTest. + verifyOptionValue("UseCountTrailingZerosInstruction", "false", + "-XX:-UseBMI1Instructions"); + + // verify that option could be turned on even if other BMI1 + // instructions were turned off + CommandLineOptionTest. + verifyOptionValue("UseCountTrailingZerosInstruction", "true", + "-XX:-UseBMI1Instructions", + "-XX:+UseCountTrailingZerosInstruction"); + } + + public static void main(String args[]) throws Throwable { + new TestUseCountTrailingZerosInstructionOnSupportedCPU().test(); + } +} + diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8031321 + * @summary Verify processing of UseCountTrailingZerosInstruction option + * on CPU without TZCNT instuction (BMI1 feature) support. + * @library /testlibrary /testlibrary/whitebox + * @build TestUseCountTrailingZerosInstructionOnUnsupportedCPU + * BMIUnsupportedCPUTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * TestUseCountTrailingZerosInstructionOnUnsupportedCPU + */ + +import sun.hotspot.cpuinfo.CPUInfo; +import com.oracle.java.testlibrary.*; +import com.oracle.java.testlibrary.cli.*; + +public class TestUseCountTrailingZerosInstructionOnUnsupportedCPU + extends BMIUnsupportedCPUTest { + + public TestUseCountTrailingZerosInstructionOnUnsupportedCPU() { + super("UseCountTrailingZerosInstruction", TZCNT_WARNING, "bmi1"); + } + + @Override + public void unsupportedX86CPUTestCases() throws Throwable { + + super.unsupportedX86CPUTestCases(); + + // verify that option will not be turned on during + // UseBMI1Instuctions processing + CommandLineOptionTest. + verifyOptionValue("UseCountTrailingZerosInstruction", "false", + "-XX:+UseBMI1Instructions"); + + CommandLineOptionTest. + verifyOptionValue("UseCountTrailingZerosInstruction", "false", + "-XX:+UseCountTrailingZerosInstruction", + "-XX:+UseBMI1Instructions"); + } + + public static void main(String args[]) throws Throwable { + new TestUseCountTrailingZerosInstructionOnUnsupportedCPU().test(); + } +} + diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/BMITestRunner.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/BMITestRunner.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,442 @@ +/* + * 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. + * + */ + +import java.util.*; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.charset.StandardCharsets; + +import com.oracle.java.testlibrary.*; + +/** + * Test runner that invokes all methods implemented by particular Expr + * with random arguments in two different JVM processes and compares output. + * JVMs being started in different modes - one in int and other in comp + * with C2 and disabled tiered compilation. + */ +public class BMITestRunner { + + enum VMMode { + COMP, INT; + }; + + public static int DEFAULT_ITERATIONS_COUNT = 4000; + + /** + * Execute all methods implemented by expr in int and comp modes + * and compare output. + * Test pass only of output obtained with different VM modes is equal. + * To control behaviour of test following options could be passed: + *
    + *
  • -iterations=<N> each operation implemented by + * expr will be executed N times. Default value + * is 4000.
  • + *
  • -seed=<SEED> arguments for expr's methods + * obtained via RNG initiated with seed SEED. By default + * some random seed will be used.
  • + *
+ * + * @param expr operation that should be tested + * @param testOpts options to control test behaviour + * @param additionalVMOpts additional options for VM + * + * @throws Throwable if test failed. + */ + public static void runTests(Class expr, + String testOpts[], + String... additionalVMOpts) + throws Throwable { + + int seed = new Random().nextInt(); + int iterations = DEFAULT_ITERATIONS_COUNT; + + for (String testOption : testOpts) { + if (testOption.startsWith("-iterations=")) { + iterations = Integer.valueOf(testOption. + replace("-iterations=", "")); + } else if (testOption.startsWith("-seed=")) { + seed = Integer.valueOf(testOption.replace("-seed=", "")); + } + } + + System.out.println("Running test with seed: " + seed); + + OutputAnalyzer intOutput = runTest(expr, VMMode.INT, + additionalVMOpts, + seed, iterations); + OutputAnalyzer compOutput = runTest(expr, VMMode.COMP, + additionalVMOpts, + seed, iterations); + + dumpOutput(intOutput, "int"); + dumpOutput(compOutput, "comp"); + + Asserts.assertStringsEqual(intOutput.getStdout(), + compOutput.getStdout(), + "Results obtained in -Xint and " + + "-Xcomp should be the same."); + } + + /** + * Execute tests on methods implemented by expr in new VM + * started in testVMMode mode. + * + * @param expr operation that should be tested + * @param testVMMode VM mode for test + * @param additionalVMOpts additional options for VM + * @param seed for RNG used it tests + * @param iterations that will be used to invoke expr's methods. + * + * @return OutputAnalyzer for executed test. + * @throws Throwable when something goes wrong. + */ + public static OutputAnalyzer runTest(Class expr, + VMMode testVMMode, + String additionalVMOpts[], + int seed, int iterations) + throws Throwable { + + List vmOpts = new LinkedList(); + + Collections.addAll(vmOpts, additionalVMOpts); + + //setup mode-specific options + switch (testVMMode) { + case INT: + Collections.addAll(vmOpts, new String[] { "-Xint" }); + break; + case COMP: + Collections.addAll(vmOpts, new String[] { + "-Xcomp", + "-XX:-TieredCompilation", + String.format("-XX:CompileCommand=compileonly,%s::*", + expr.getName()) + }); + break; + } + + Collections.addAll(vmOpts, new String[] { + "-XX:+DisplayVMOutputToStderr", + Executor.class.getName(), + expr.getName(), + new Integer(seed).toString(), + new Integer(iterations).toString() + }); + + OutputAnalyzer outputAnalyzer = ProcessTools. + executeTestJvm(vmOpts.toArray(new String[vmOpts.size()])); + + outputAnalyzer.shouldHaveExitValue(0); + + return outputAnalyzer; + } + + /** + * Dump stdout and stderr of test process to prefix.test.out + * and prefix.test.err respectively. + * + * @param outputAnalyzer OutputAnalyzer whom output should be dumped + * @param prefix Prefix that will be used in file names. + * @throws IOException if unable to dump output to file. + */ + protected static void dumpOutput(OutputAnalyzer outputAnalyzer, + String prefix) + throws IOException { + Files.write(Paths.get(prefix + ".test.out"), + outputAnalyzer.getStdout().getBytes()); + + Files.write(Paths.get(prefix + ".test.err"), + outputAnalyzer.getStderr().getBytes()); + } + + + /** + * Executor that invoke all methods implemented by particular + * Expr instance. + */ + public static class Executor { + + /** + * Usage: BMITestRunner$Executor + */ + public static void main(String args[]) throws Exception { + @SuppressWarnings("unchecked") + Class exprClass = + (Class)Class.forName(args[0]); + Expr expr = exprClass.getConstructor().newInstance(); + Random rng = new Random(Integer.valueOf(args[1])); + int iterations = Integer.valueOf(args[2]); + runTests(expr, iterations, rng); + } + + + public static int[] getIntBitShifts() { + //SIZE+1 shift is for zero. + int data[] = new int[Integer.SIZE+1]; + for (int s = 0; s < data.length; s++) { + data[s] = 1< 0X%x", + value, expr.intExpr(value)); + } + + for (int i = 0; i < iterations; i++) { + int value = rng.nextInt(); + log("UnaryIntReg(0X%x) -> 0X%x", + value, expr.intExpr(value)); + } + } + + public static void runUnaryIntMemTest(Expr expr, int iterations, + Random rng) { + if (!(expr.isUnaryArgumentSupported() + && expr.isIntExprSupported() + && expr.isMemExprSupported())) { + return; + } + + for (int value : getIntBitShifts()) { + log("UnaryIntMem(0X%x) -> 0X%x", + value, expr.intExpr(new Expr.MemI(value))); + } + + for (int i = 0; i < iterations; i++) { + int value = rng.nextInt(); + log("UnaryIntMem(0X%x) -> 0X%x", + value, expr.intExpr(new Expr.MemI(value))); + } + } + + public static void runUnaryLongRegTest(Expr expr, int iterations, + Random rng) { + if (!(expr.isUnaryArgumentSupported() + && expr.isLongExprSupported())) { + return; + } + + for (long value : getLongBitShifts()) { + log("UnaryLongReg(0X%x) -> 0X%x", + value, expr.longExpr(value)); + } + + for (int i = 0; i < iterations; i++) { + long value = rng.nextLong(); + log("UnaryLongReg(0X%x) -> 0X%x", + value, expr.longExpr(value)); + } + } + + public static void runUnaryLongMemTest(Expr expr, int iterations, + Random rng) { + if (!(expr.isUnaryArgumentSupported() + && expr.isLongExprSupported() + && expr.isMemExprSupported())) { + return; + } + + for (long value : getLongBitShifts()) { + log("UnaryLongMem(0X%x) -> 0X%x", + value, expr.longExpr(new Expr.MemL(value))); + } + + for (int i = 0; i < iterations; i++) { + long value = rng.nextLong(); + log("UnaryLongMem(0X%x) -> 0X%x", + value, expr.longExpr(new Expr.MemL(value))); + } + } + + public static void runBinaryRegRegIntTest(Expr expr, int iterations, + Random rng) { + if (!(expr.isIntExprSupported() + && expr.isBinaryArgumentSupported())) { + return; + } + + for (int i = 0; i < iterations; i++) { + int aValue = rng.nextInt(); + int bValue = rng.nextInt(); + log("BinaryIntRegReg(0X%x, 0X%x) -> 0X%x", + aValue, bValue, expr.intExpr(aValue, bValue)); + } + } + + public static void runBinaryRegMemIntTest(Expr expr, int iterations, + Random rng) { + if (!(expr.isIntExprSupported() + && expr.isBinaryArgumentSupported() + && expr.isMemExprSupported())) { + return; + } + + for (int i = 0; i < iterations; i++) { + int aValue = rng.nextInt(); + int bValue = rng.nextInt(); + log("BinaryIntRegMem(0X%x, 0X%x) -> 0X%x", aValue, bValue, + expr.intExpr(aValue, new Expr.MemI(bValue))); + } + } + + public static void runBinaryMemRegIntTest(Expr expr, int iterations, + Random rng) { + if (!(expr.isIntExprSupported() + && expr.isBinaryArgumentSupported() + && expr.isMemExprSupported())) { + return; + } + + for (int i = 0; i < iterations; i++) { + int aValue = rng.nextInt(); + int bValue = rng.nextInt(); + log("BinaryIntMemReg(0X%x, 0X%x) -> 0X%x", aValue, bValue, + expr.intExpr(new Expr.MemI(aValue), bValue)); + } + } + + public static void runBinaryMemMemIntTest(Expr expr, int iterations, + Random rng) { + if (!(expr.isIntExprSupported() + && expr.isBinaryArgumentSupported() + && expr.isMemExprSupported())) { + return; + } + + for (int i = 0; i < iterations; i++) { + int aValue = rng.nextInt(); + int bValue = rng.nextInt(); + log("BinaryIntMemMem(0X%x, 0X%x) -> 0X%x", aValue, bValue, + expr.intExpr(new Expr.MemI(aValue), + new Expr.MemI(bValue))); + } + } + + public static void runBinaryRegRegLongTest(Expr expr, + int iterations, + Random rng) { + if (!(expr.isLongExprSupported() + && expr.isBinaryArgumentSupported())) { + return; + } + + for (int i = 0; i < iterations; i++) { + long aValue = rng.nextLong(); + long bValue = rng.nextLong(); + log("BinaryLongRegReg(0X%x, 0X%x) -> 0X%x", aValue, bValue, + expr.longExpr(aValue, bValue)); + } + } + + public static void runBinaryRegMemLongTest(Expr expr, + int iterations, + Random rng) { + if (!(expr.isLongExprSupported() + && expr.isBinaryArgumentSupported() + && expr.isMemExprSupported())) { + return; + } + + for (int i = 0; i < iterations; i++) { + long aValue = rng.nextLong(); + long bValue = rng.nextLong(); + log("BinaryLongRegMem(0X%x, 0X%x) -> 0X%x", aValue, bValue, + expr.longExpr(aValue, new Expr.MemL(bValue))); + } + } + + public static void runBinaryMemRegLongTest(Expr expr, + int iterations, + Random rng) { + if (!(expr.isLongExprSupported() + && expr.isBinaryArgumentSupported() + && expr.isMemExprSupported())) { + return; + } + + for (int i = 0; i < iterations; i++) { + long aValue = rng.nextLong(); + long bValue = rng.nextLong(); + log("BinaryLongMemReg(0X%x, 0X%x) -> 0X%x", aValue, bValue, + expr.longExpr(new Expr.MemL(aValue), bValue)); + } + } + + public static void runBinaryMemMemLongTest(Expr expr, + int iterations, + Random rng) { + if (!(expr.isLongExprSupported() + && expr.isBinaryArgumentSupported() + && expr.isMemExprSupported())) { + return; + } + + for (int i = 0; i < iterations; i++) { + long aValue = rng.nextLong(); + long bValue = rng.nextLong(); + log("BinaryLongMemMem(0X%x, 0X%x) -> 0X%x", aValue, bValue, + expr.longExpr(new Expr.MemL(aValue), + new Expr.MemL(bValue))); + } + } + } +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/Expr.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/Expr.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,178 @@ +/* + * 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. + * + */ + +/** + * Expression that should be replaced by particular instrinsic + * or intruction during compilation. + */ + +public abstract class Expr { + + public static class MemI { + public MemI(int i) { + this.value = i; + } + + public int value; + } + + public static class MemL { + public MemL(long l) { + this.value = l; + } + + public long value; + } + + public boolean isUnaryArgumentSupported() { + return false; + } + + public boolean isIntExprSupported() { + return false; + } + + public boolean isBinaryArgumentSupported() { + return false; + } + + public boolean isLongExprSupported() { + return false; + } + + public boolean isMemExprSupported() { + return false; + } + + public int intExpr(int reg) { + throw new UnsupportedOperationException(); + } + + public int intExpr(MemI mem) { + throw new UnsupportedOperationException(); + } + + public int intExpr(int a, int b) { + throw new UnsupportedOperationException(); + } + + public int intExpr(int a, MemI b) { + throw new UnsupportedOperationException(); + } + + public int intExpr(MemI a, int b) { + throw new UnsupportedOperationException(); + } + + public int intExpr(MemI a, MemI b) { + throw new UnsupportedOperationException(); + } + + public long longExpr(long reg) { + throw new UnsupportedOperationException(); + } + + public long longExpr(MemL mem) { + throw new UnsupportedOperationException(); + } + + public long longExpr(long a, long b) { + throw new UnsupportedOperationException(); + } + + public long longExpr(long a, MemL b) { + throw new UnsupportedOperationException(); + } + + public long longExpr(MemL a, long b) { + throw new UnsupportedOperationException(); + } + + public long longExpr(MemL a, MemL b) { + throw new UnsupportedOperationException(); + } + + public static class BMIExpr extends Expr { + + public boolean isMemExprSupported() { + return true; + } + } + + public static class BMIBinaryExpr extends BMIExpr { + + public boolean isBinaryArgumentSupported() { + return true; + } + + } + + public static class BMIUnaryExpr extends BMIExpr { + public boolean isUnaryArgumentSupported() { + return true; + } + } + + public static class BMIBinaryIntExpr extends BMIBinaryExpr { + public boolean isIntExprSupported() { + return true; + } + } + + public static class BMIBinaryLongExpr extends BMIBinaryExpr { + public boolean isLongExprSupported() { + return true; + } + } + + public static class BMIUnaryIntExpr extends BMIUnaryExpr { + public boolean isIntExprSupported() { + return true; + } + } + + public static class BMIUnaryLongExpr extends BMIUnaryExpr { + public boolean isLongExprSupported() { + return true; + } + } + + public static class BitCountingExpr extends Expr { + public boolean isUnaryArgumentSupported() { + return true; + } + } + + public static class BitCountingIntExpr extends BitCountingExpr { + public boolean isIntExprSupported() { + return true; + } + } + + public static class BitCountingLongExpr extends BitCountingExpr { + public boolean isLongExprSupported() { + return true; + } + } +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/TestAndnI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031321 + * @summary Verify that results of computations are the same w/ + * and w/o usage of ANDN instruction + * @library /testlibrary /testlibrary/whitebox + * @build TestAndnI BMITestRunner Expr + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestAndnI + */ + +import sun.hotspot.cpuinfo.CPUInfo; + +public class TestAndnI { + + public static void main(String args[]) throws Throwable { + if (!CPUInfo.hasFeature("bmi1")) { + System.out.println("CPU does not support bmi1 feature. "+ + "Test skipped."); + return; + } + + BMITestRunner.runTests(AndnIExpr.class, args, + "-XX:+UseBMI1Instructions"); + BMITestRunner.runTests(AndnICommutativeExpr.class, args, + "-XX:+UseBMI1Instructions"); + } + + public static class AndnIExpr extends Expr.BMIBinaryIntExpr { + + public int intExpr(int src1, int src2) { + return ~src1 & src2; + } + + public int intExpr(int src1, Expr.MemI src2) { + return ~src1 & src2.value; + } + + public int intExpr(Expr.MemI src1, int src2) { + return ~src1.value & src2; + } + + public int intExpr(Expr.MemI src1, Expr.MemI src2) { + return ~src1.value & src2.value; + } + } + + public static class AndnICommutativeExpr extends Expr.BMIBinaryIntExpr { + + public int intExpr(int src1, int src2) { + return src1 & ~src2; + } + + public int intExpr(int src1, Expr.MemI src2) { + return src1 & ~src2.value; + } + + public int intExpr(Expr.MemI src1, int src2) { + return src1.value & ~src2; + } + + public int intExpr(Expr.MemI src1, Expr.MemI src2) { + return src1.value & ~src2.value; + } + } +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/TestAndnL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031321 + * @summary Verify that results of computations are the same w/ + * and w/o usage of ANDN instruction + * @library /testlibrary /testlibrary/whitebox + * @build TestAndnL BMITestRunner Expr + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestAndnL + */ + +import sun.hotspot.cpuinfo.CPUInfo; + +public class TestAndnL { + + public static void main(String args[]) throws Throwable { + if (!CPUInfo.hasFeature("bmi1")) { + System.out.println("CPU does not support bmi1 feature. " + + "Test skipped."); + return; + } + + BMITestRunner.runTests(AndnLExpr.class, args, + "-XX:+UseBMI1Instructions"); + BMITestRunner.runTests(AndnLCommutativeExpr.class, args, + "-XX:+UseBMI1Instructions"); + } + + public static class AndnLExpr extends Expr.BMIBinaryLongExpr { + + public long longExpr(long src1, long src2) { + return ~src1 & src2; + } + + public long longExpr(long src1, Expr.MemL src2) { + return ~src1 & src2.value; + } + + public long longExpr(Expr.MemL src1, long src2) { + return ~src1.value & src2; + } + + public long longExpr(Expr.MemL src1, Expr.MemL src2) { + return ~src1.value & src2.value; + } + + + } + + public static class AndnLCommutativeExpr extends Expr.BMIBinaryLongExpr { + + public long longExpr(long src1, long src2) { + return src1 & ~src2; + } + + public long longExpr(long src1, Expr.MemL src2) { + return src1 & ~src2.value; + } + + public long longExpr(Expr.MemL src1, long src2) { + return src1.value & ~src2; + } + + public long longExpr(Expr.MemL src1, Expr.MemL src2) { + return src1.value & ~src2.value; + } + + } + +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031321 + * @summary Verify that results of computations are the same w/ + * and w/o usage of BLSI instruction + * @library /testlibrary /testlibrary/whitebox + * @build TestBlsiI BMITestRunner Expr + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestBlsiI + */ + +import sun.hotspot.cpuinfo.CPUInfo; + +public class TestBlsiI { + + public static void main(String args[]) throws Throwable { + if (!CPUInfo.hasFeature("bmi1")) { + System.out.println("CPU does not support bmi1 feature. " + + "Test skipped."); + return; + } + + BMITestRunner.runTests(BlsiIExpr.class, args, + "-XX:+UseBMI1Instructions"); + BMITestRunner.runTests(BlsiICommutativeExpr.class, args, + "-XX:+UseBMI1Instructions"); + } + + public static class BlsiIExpr extends Expr.BMIUnaryIntExpr { + + public int intExpr(int src) { + return -src & src; + } + + public int intExpr(Expr.MemI src) { + return -src.value & src.value; + } + + } + + public static class BlsiICommutativeExpr extends Expr.BMIUnaryIntExpr { + + public int intExpr(int src) { + return src & -src; + } + + public int intExpr(Expr.MemI src) { + return src.value & -src.value; + } + + } + +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031321 + * @summary Verify that results of computations are the same w/ + * and w/o usage of BLSI instruction + * @library /testlibrary /testlibrary/whitebox + * @build TestBlsiL BMITestRunner Expr + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestBlsiL + */ + +import sun.hotspot.cpuinfo.CPUInfo; + +public class TestBlsiL { + + public static void main(String args[]) throws Throwable { + if (!CPUInfo.hasFeature("bmi1")) { + System.out.println("CPU does not support bmi1 feature. " + + "Test skipped."); + return; + } + + BMITestRunner.runTests(BlsiLExpr.class, args, + "-XX:+UseBMI1Instructions"); + BMITestRunner.runTests(BlsiLCommutativeExpr.class, args, + "-XX:+UseBMI1Instructions"); + } + + public static class BlsiLExpr extends Expr.BMIUnaryLongExpr { + + public long longExpr(long src) { + return -src & src; + } + + public long longExpr(Expr.MemL src) { + return -src.value & src.value; + } + + } + + public static class BlsiLCommutativeExpr extends Expr.BMIUnaryLongExpr { + + public long longExpr(long src) { + return src & -src; + } + + public long longExpr(Expr.MemL src) { + return src.value & -src.value; + } + + } + +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031321 + * @summary Verify that results of computations are the same w/ + * and w/o usage of BLSMSK instruction + * @library /testlibrary /testlibrary/whitebox + * @build TestBlsmskI BMITestRunner Expr + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestBlsmskI + */ + +import sun.hotspot.cpuinfo.CPUInfo; + +public class TestBlsmskI { + + public static void main(String args[]) throws Throwable { + if (!CPUInfo.hasFeature("bmi1")) { + System.out.println("CPU does not support bmi1 feature. " + + "Test skipped."); + return; + } + + BMITestRunner.runTests(BlsmskIExpr.class, args, + "-XX:+UseBMI1Instructions"); + BMITestRunner.runTests(BlsmskICommutativeExpr.class, args, + "-XX:+UseBMI1Instructions"); + } + + public static class BlsmskIExpr extends Expr.BMIUnaryIntExpr { + + public int intExpr(int src) { + return (src - 1) ^ src; + } + + public int intExpr(Expr.MemI src) { + return (src.value - 1) ^ src.value; + } + + } + + public static class BlsmskICommutativeExpr extends Expr.BMIUnaryIntExpr { + + public int intExpr(int src) { + return src ^ (src - 1); + } + + public int intExpr(Expr.MemI src) { + return src.value ^ (src.value - 1); + } + + } + +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031321 + * @summary Verify that results of computations are the same w/ + * and w/o usage of BLSMSK instruction + * @library /testlibrary /testlibrary/whitebox + * @build TestBlsmskL BMITestRunner Expr + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestBlsmskL + */ + +import sun.hotspot.cpuinfo.CPUInfo; + +public class TestBlsmskL { + + public static void main(String args[]) throws Throwable { + if (!CPUInfo.hasFeature("bmi1")) { + System.out.println("CPU does not support bmi1 feature. " + + "Test skipped."); + return; + } + + BMITestRunner.runTests(BlsmskLExpr.class, args, + "-XX:+UseBMI1Instructions"); + BMITestRunner.runTests(BlsmskLCommutativeExpr.class, args, + "-XX:+UseBMI1Instructions"); + } + + public static class BlsmskLExpr + extends Expr.BMIUnaryLongExpr { + + public long longExpr(long src) { + return (src - 1) ^ src; + } + + public long longExpr(Expr.MemL src) { + return (src.value - 1) ^ src.value; + } + + } + + public static class BlsmskLCommutativeExpr + extends Expr.BMIUnaryLongExpr { + + public long longExpr(long src) { + return src ^ (src - 1); + } + + public long longExpr(Expr.MemL src) { + return src.value ^ (src.value - 1); + } + + } + +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031321 + * @summary Verify that results of computations are the same w/ + * and w/o usage of BLSR instruction + * @library /testlibrary /testlibrary/whitebox + * @build TestBlsrI BMITestRunner Expr + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestBlsrI + */ + +import sun.hotspot.cpuinfo.CPUInfo; + +public class TestBlsrI { + + public static void main(String args[]) throws Throwable { + if (!CPUInfo.hasFeature("bmi1")) { + System.out.println("CPU does not support bmi1 feature. " + + "Test skipped."); + return; + } + + BMITestRunner.runTests(BlsrIExpr.class, args, + "-XX:+UseBMI1Instructions"); + BMITestRunner.runTests(BlsrICommutativeExpr.class, args, + "-XX:+UseBMI1Instructions"); + } + + public static class BlsrIExpr extends Expr.BMIUnaryIntExpr { + + public int intExpr(int src) { + return (src - 1) & src; + } + + public int intExpr(Expr.MemI src) { + return (src.value - 1) & src.value; + } + + } + + public static class BlsrICommutativeExpr extends Expr.BMIUnaryIntExpr { + + public int intExpr(int src) { + return src & (src - 1); + } + + public int intExpr(Expr.MemI src) { + return src.value & (src.value - 1); + } + + } + +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031321 + * @summary Verify that results of computations are the same w/ + * and w/o usage of BLSR instruction + * @library /testlibrary /testlibrary/whitebox + * @build TestBlsrL BMITestRunner Expr + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestBlsrL + */ + +import sun.hotspot.cpuinfo.CPUInfo; + +public class TestBlsrL { + + public static void main(String args[]) throws Throwable { + if (!CPUInfo.hasFeature("bmi1")) { + System.out.println("CPU does not support bmi1 feature. " + + "Test skipped."); + return; + } + + BMITestRunner.runTests(BlsrLExpr.class, args, + "-XX:+UseBMI1Instructions"); + BMITestRunner.runTests(BlsrLCommutativeExpr.class, args, + "-XX:+UseBMI1Instructions"); + } + + public static class BlsrLExpr extends Expr.BMIUnaryLongExpr { + + public long longExpr(long src) { + return (src - 1) & src; + } + + public long longExpr(Expr.MemL src) { + return (src.value - 1) & src.value; + } + + } + + public static class BlsrLCommutativeExpr extends Expr.BMIUnaryLongExpr { + + public long longExpr(long src) { + return src & (src - 1); + } + + public long longExpr(Expr.MemL src) { + return src.value & (src.value - 1); + } + + } + +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031321 + * @summary Verify that results of computations are the same w/ + * and w/o usage of intrinsic + * @library /testlibrary /testlibrary/whitebox + * @build TestLzcntI BMITestRunner Expr + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestLzcntI + */ + +import sun.hotspot.cpuinfo.CPUInfo; + +public class TestLzcntI { + + public static void main(String args[]) throws Throwable { + if (!CPUInfo.hasFeature("lzcnt")) { + System.out.println("CPU does not support lzcnt feature. " + + "Test skipped."); + return; + } + + BMITestRunner.runTests(LzcntIExpr.class, args, + "-XX:+UseCountLeadingZerosInstruction"); + } + + public static class LzcntIExpr extends Expr.BitCountingIntExpr { + + public int intExpr(int src) { + return Integer.numberOfLeadingZeros(src); + } + + } + +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031321 + * @summary Verify that results of computations are the same w/ + * and w/o usage of intrinsic + * @library /testlibrary /testlibrary/whitebox + * @build TestLzcntL BMITestRunner Expr + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestLzcntL + */ + +import sun.hotspot.cpuinfo.CPUInfo; + +public class TestLzcntL { + + public static void main(String args[]) throws Throwable { + if (!CPUInfo.hasFeature("lzcnt")) { + System.out.println("CPU does not support lzcnt feature. " + + "Test skipped."); + return; + } + + BMITestRunner.runTests(LzcntLExpr.class, args, + "-XX:+UseCountLeadingZerosInstruction"); + } + + public static class LzcntLExpr extends Expr.BitCountingLongExpr { + + public long longExpr(long src) { + return Long.numberOfLeadingZeros(src); + } + + } + +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031321 + * @summary Verify that results of computations are the same w/ + * and w/o usage of intrinsic + * @library /testlibrary /testlibrary/whitebox + * @build TestTzcntI BMITestRunner Expr + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestTzcntI + */ + +import sun.hotspot.cpuinfo.CPUInfo; + +public class TestTzcntI { + + public static void main(String args[]) throws Throwable { + if (!CPUInfo.hasFeature("bmi1")) { + System.out.println("CPU does not support bmi1 feature. " + + "Test skipped."); + return; + } + + BMITestRunner.runTests(TzcntIExpr.class, args, + "-XX:+UseCountTrailingZerosInstruction"); + } + + public static class TzcntIExpr extends Expr.BitCountingIntExpr { + + public int intExpr(int src) { + return Integer.numberOfTrailingZeros(src); + } + + } + +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8031321 + * @summary Verify that results of computations are the same w/ + * and w/o usage of intrinsic + * @library /testlibrary /testlibrary/whitebox + * @build TestTzcntL BMITestRunner Expr + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI TestTzcntL + */ + +import sun.hotspot.cpuinfo.CPUInfo; + +public class TestTzcntL { + + public static void main(String args[]) throws Throwable { + if (!CPUInfo.hasFeature("bmi1")) { + System.out.println("CPU does not support bmi1 feature. " + + "Test skipped."); + return; + } + + BMITestRunner.runTests(TzcntLExpr.class, args, + "-XX:+UseCountTrailingZerosInstruction"); + } + + public static class TzcntLExpr extends Expr.BitCountingLongExpr { + + public long longExpr(long src) { + return Long.numberOfTrailingZeros(src); + } + + } + +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/intrinsics/unsafe/UnsafeGetAddressTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/unsafe/UnsafeGetAddressTest.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6653795 + * @summary C2 intrinsic for Unsafe.getAddress performs pointer sign extension on 32-bit systems + * @run main UnsafeGetAddressTest + * + */ + +import sun.misc.Unsafe; +import java.lang.reflect.*; + +public class UnsafeGetAddressTest { + private static Unsafe unsafe; + + public static void main(String[] args) throws Exception { + Class c = UnsafeGetAddressTest.class.getClassLoader().loadClass("sun.misc.Unsafe"); + Field f = c.getDeclaredField("theUnsafe"); + f.setAccessible(true); + unsafe = (Unsafe)f.get(c); + + long address = unsafe.allocateMemory(unsafe.addressSize()); + unsafe.putAddress(address, 0x0000000080000000L); + // from sun.misc.Unsafe.getAddress' documentation: + // "If the native pointer is less than 64 bits wide, it is + // extended as an unsigned number to a Java long." + result = unsafe.getAddress(address); + System.out.printf("1: was 0x%x, expected 0x%x\n", result, + 0x0000000080000000L); + for (int i = 0; i < 1000000; i++) { + result = unsafe.getAddress(address); + } + + // The code has got compiled, check the result now + System.out.printf("2: was 0x%x, expected 0x%x\n", result, + 0x0000000080000000L); + if (result != 0x0000000080000000L) { + System.out.println("Test Failed"); + System.exit(97); + } else { + System.out.println("Test Passed"); + } + } + static volatile long result; +} + diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java --- a/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java Fri Mar 28 09:15:41 2014 -0700 @@ -24,6 +24,7 @@ import com.sun.management.HotSpotDiagnosticMXBean; import com.sun.management.VMOption; import sun.hotspot.WhiteBox; +import sun.hotspot.code.NMethod; import sun.management.ManagementFactoryHelper; import java.lang.reflect.Constructor; @@ -278,7 +279,8 @@ } protected final int getCompLevel() { - return WHITE_BOX.getMethodCompilationLevel(method, testCase.isOsr()); + NMethod nm = NMethod.get(method, testCase.isOsr()); + return nm == null ? COMP_LEVEL_NONE : nm.comp_level; } protected final boolean isCompilable() { diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/compiler/whitebox/GetNMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/whitebox/GetNMethodTest.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,71 @@ +/* + * 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. + * + */ + +import sun.hotspot.code.NMethod; + +/* + * @test GetNMethodTest + * @bug 8038240 + * @library /testlibrary /testlibrary/whitebox + * @build GetNMethodTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* GetNMethodTest + * @summary testing of WB::getNMethod() + * @author igor.ignatyev@oracle.com + */ +public class GetNMethodTest extends CompilerWhiteBoxTest { + public static void main(String[] args) throws Exception { + CompilerWhiteBoxTest.main(GetNMethodTest::new, args); + } + + private GetNMethodTest(TestCase testCase) { + super(testCase); + // to prevent inlining of #method + WHITE_BOX.testSetDontInlineMethod(method, true); + } + + @Override + protected void test() throws Exception { + checkNotCompiled(); + + compile(); + checkCompiled(); + NMethod nmethod = NMethod.get(method, testCase.isOsr()); + if (IS_VERBOSE) { + System.out.println("nmethod = " + nmethod); + } + if (nmethod == null) { + throw new RuntimeException("nmethod of compiled method is null"); + } + if (nmethod.insts.length == 0) { + throw new RuntimeException("compiled method's instructions is empty"); + } + deoptimize(); + checkNotCompiled(); + nmethod = NMethod.get(method, testCase.isOsr()); + if (nmethod != null) { + throw new RuntimeException("nmethod of non-compiled method isn't null"); + } + } +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/gc/arguments/FlagsValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/arguments/FlagsValue.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,43 @@ +/* +* 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. +*/ + +import java.util.regex.*; + +public class FlagsValue { + public static boolean getFlagBoolValue(String flag, String where) { + Matcher m = Pattern.compile(flag + "\\s+:?= (true|false)").matcher(where); + if (!m.find()) { + throw new RuntimeException("Could not find value for flag " + flag + " in output string"); + } + return m.group(1).equals("true"); + } + + public static long getFlagLongValue(String flag, String where) { + Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where); + if (!m.find()) { + throw new RuntimeException("Could not find value for flag " + flag + " in output string"); + } + String match = m.group(); + return Long.parseLong(match.substring(match.lastIndexOf(" ") + 1, match.length())); + } +} \ No newline at end of file diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/gc/arguments/TestInitialTenuringThreshold.java --- a/hotspot/test/gc/arguments/TestInitialTenuringThreshold.java Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/test/gc/arguments/TestInitialTenuringThreshold.java Fri Mar 28 09:15:41 2014 -0700 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2013, 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 @@ -63,13 +63,13 @@ // successful tests runWithThresholds(0, 10, false); runWithThresholds(5, 5, false); + runWithThresholds(8, 16, false); // failing tests runWithThresholds(10, 0, true); runWithThresholds(9, 8, true); runWithThresholds(-1, 8, true); runWithThresholds(8, -1, true); - runWithThresholds(8, 16, true); runWithThresholds(16, 8, true); + runWithThresholds(8, 17, true); } -} - +} \ No newline at end of file diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/gc/arguments/TestObjectTenuringFlags.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/arguments/TestObjectTenuringFlags.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,215 @@ +/* +* 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 TestObjectTenuringFlags + * @key gc + * @bug 6521376 + * @summary Tests argument processing for NeverTenure, AlwaysTenure, + * and MaxTenuringThreshold + * @library /testlibrary + * @build TestObjectTenuringFlags FlagsValue + * @run main/othervm TestObjectTenuringFlags + */ + +import com.oracle.java.testlibrary.*; + +import java.util.*; + +public class TestObjectTenuringFlags { + public static void main(String args[]) throws Exception { + // default case + runTenuringFlagsConsistencyTest( + new String[]{}, + false /* shouldFail */, + new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 7, 15)); + + // valid cases + runTenuringFlagsConsistencyTest( + new String[]{"-XX:+NeverTenure"}, + false /* shouldFail */, + new ExpectedTenuringFlags(false /* alwaysTenure */, true /* neverTenure */, 7, 16)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:+AlwaysTenure"}, + false /* shouldFail */, + new ExpectedTenuringFlags(true /* alwaysTenure */, false /* neverTenure */, 0, 0)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:MaxTenuringThreshold=0"}, + false /* shouldFail */, + new ExpectedTenuringFlags(true /* alwaysTenure */, false /* neverTenure */, 0, 0)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:MaxTenuringThreshold=5"}, + false /* shouldFail */, + new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 5, 5)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:MaxTenuringThreshold=10"}, + false /* shouldFail */, + new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 7, 10)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:MaxTenuringThreshold=15"}, + false /* shouldFail */, + new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 7, 15)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:MaxTenuringThreshold=16"}, + false /* shouldFail */, + new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 7, 16)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:InitialTenuringThreshold=0"}, + false /* shouldFail */, + new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 0, 15)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:InitialTenuringThreshold=5"}, + false /* shouldFail */, + new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 5, 15)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:InitialTenuringThreshold=10"}, + false /* shouldFail */, + new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 10, 15)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:InitialTenuringThreshold=15"}, + false /* shouldFail */, + new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 15, 15)); + + // "Last option wins" cases + runTenuringFlagsConsistencyTest( + new String[]{"-XX:+AlwaysTenure", "-XX:+NeverTenure"}, + false /* shouldFail */, + new ExpectedTenuringFlags(false /* alwaysTenure */, true /* neverTenure */, 7, 16)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:+NeverTenure", "-XX:+AlwaysTenure"}, + false /* shouldFail */, + new ExpectedTenuringFlags(true /* alwaysTenure */, false /* neverTenure */, 0, 0)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:MaxTenuringThreshold=16", "-XX:+AlwaysTenure"}, + false /* shouldFail */, + new ExpectedTenuringFlags(true /* alwaysTenure */, false /* neverTenure */, 0, 0)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:+AlwaysTenure", "-XX:MaxTenuringThreshold=16"}, + false /* shouldFail */, + new ExpectedTenuringFlags(false /* alwaysTenure */, false /* neverTenure */, 7, 16)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:MaxTenuringThreshold=0", "-XX:+NeverTenure"}, + false /* shouldFail */, + new ExpectedTenuringFlags(false /* alwaysTenure */, true /* neverTenure */, 7, 16)); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:+NeverTenure", "-XX:MaxTenuringThreshold=0"}, + false /* shouldFail */, + new ExpectedTenuringFlags(true /* alwaysTenure */, false /* neverTenure */, 0, 0)); + + // Illegal cases + runTenuringFlagsConsistencyTest( + new String[]{"-XX:MaxTenuringThreshold=17"}, + true /* shouldFail */, + new ExpectedTenuringFlags()); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:InitialTenuringThreshold=16"}, + true /* shouldFail */, + new ExpectedTenuringFlags()); + + runTenuringFlagsConsistencyTest( + new String[]{"-XX:InitialTenuringThreshold=17"}, + true /* shouldFail */, + new ExpectedTenuringFlags()); + } + + private static void runTenuringFlagsConsistencyTest(String[] tenuringFlags, + boolean shouldFail, + ExpectedTenuringFlags expectedFlags) throws Exception { + List vmOpts = new ArrayList<>(); + if (tenuringFlags.length > 0) { + Collections.addAll(vmOpts, tenuringFlags); + } + Collections.addAll(vmOpts, "-XX:+PrintFlagsFinal", "-version"); + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(vmOpts.toArray(new String[vmOpts.size()])); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + if (shouldFail) { + output.shouldHaveExitValue(1); + } else { + output.shouldHaveExitValue(0); + String stdout = output.getStdout(); + checkTenuringFlagsConsistency(stdout, expectedFlags); + } + } + + private static void checkTenuringFlagsConsistency(String output, ExpectedTenuringFlags expectedFlags) { + if (expectedFlags.alwaysTenure != FlagsValue.getFlagBoolValue("AlwaysTenure", output)) { + throw new RuntimeException( + "Actual flag AlwaysTenure " + FlagsValue.getFlagBoolValue("AlwaysTenure", output) + + " is not equal to expected flag AlwaysTenure " + expectedFlags.alwaysTenure); + } + + if (expectedFlags.neverTenure != FlagsValue.getFlagBoolValue("NeverTenure", output)) { + throw new RuntimeException( + "Actual flag NeverTenure " + FlagsValue.getFlagBoolValue("NeverTenure", output) + + " is not equal to expected flag NeverTenure " + expectedFlags.neverTenure); + } + + if (expectedFlags.initialTenuringThreshold != FlagsValue.getFlagLongValue("InitialTenuringThreshold", output)) { + throw new RuntimeException( + "Actual flag InitialTenuringThreshold " + FlagsValue.getFlagLongValue("InitialTenuringThreshold", output) + + " is not equal to expected flag InitialTenuringThreshold " + expectedFlags.initialTenuringThreshold); + } + + if (expectedFlags.maxTenuringThreshold != FlagsValue.getFlagLongValue("MaxTenuringThreshold", output)) { + throw new RuntimeException( + "Actual flag MaxTenuringThreshold " + FlagsValue.getFlagLongValue("MaxTenuringThreshold", output) + + " is not equal to expected flag MaxTenuringThreshold " + expectedFlags.maxTenuringThreshold); + } + } +} + +class ExpectedTenuringFlags { + public boolean alwaysTenure; + public boolean neverTenure; + public long initialTenuringThreshold; + public long maxTenuringThreshold; + + public ExpectedTenuringFlags(boolean alwaysTenure, + boolean neverTenure, + long initialTenuringThreshold, + long maxTenuringThreshold) { + this.alwaysTenure = alwaysTenure; + this.neverTenure = neverTenure; + this.initialTenuringThreshold = initialTenuringThreshold; + this.maxTenuringThreshold = maxTenuringThreshold; + } + public ExpectedTenuringFlags() {} +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java --- a/hotspot/test/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/test/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java Fri Mar 28 09:15:41 2014 -0700 @@ -26,7 +26,7 @@ * @bug 8004924 * @summary Checks that jmap -heap contains the flag CompressedClassSpaceSize * @library /testlibrary - * @run main/othervm -XX:CompressedClassSpaceSize=50m CompressedClassSpaceSizeInJmapHeap + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:CompressedClassSpaceSize=50m CompressedClassSpaceSizeInJmapHeap */ import com.oracle.java.testlibrary.*; @@ -37,6 +37,11 @@ public class CompressedClassSpaceSizeInJmapHeap { public static void main(String[] args) throws Exception { + if (!Platform.is64bit()) { + // Compressed Class Space is only available on 64-bit JVMs + return; + } + String pid = Integer.toString(ProcessTools.getProcessId()); JDKToolLauncher jmap = JDKToolLauncher.create("jmap") diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/testlibrary/com/oracle/java/testlibrary/Asserts.java --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Asserts.java Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Asserts.java Fri Mar 28 09:15:41 2014 -0700 @@ -378,6 +378,64 @@ } } + /** + * Asserts that two strings are equal. + * + * If strings are not equals, then exception message + * will contain {@code msg} followed by list of mismatched lines. + * + * @param str1 First string to compare. + * @param str2 Second string to compare. + * @param msg A description of the assumption. + * @throws RuntimeException if strings are not equal. + */ + public static void assertStringsEqual(String str1, String str2, + String msg) { + String lineSeparator = System.getProperty("line.separator"); + String str1Lines[] = str1.split(lineSeparator); + String str2Lines[] = str2.split(lineSeparator); + + int minLength = Math.min(str1Lines.length, str2Lines.length); + String longestStringLines[] = ((str1Lines.length == minLength) ? + str2Lines : str1Lines); + + boolean stringsAreDifferent = false; + + StringBuilder messageBuilder = new StringBuilder(msg); + + messageBuilder.append("\n"); + + for (int line = 0; line < minLength; line++) { + if (!str1Lines[line].equals(str2Lines[line])) { + messageBuilder.append(String. + format("[line %d] '%s' differs " + + "from '%s'\n", + line, + str1Lines[line], + str2Lines[line])); + stringsAreDifferent = true; + } + } + + if (minLength < longestStringLines.length) { + String stringName = ((longestStringLines == str1Lines) ? + "first" : "second"); + messageBuilder.append(String.format("Only %s string contains " + + "following lines:\n", + stringName)); + stringsAreDifferent = true; + for(int line = minLength; line < longestStringLines.length; line++) { + messageBuilder.append(String. + format("[line %d] '%s'", line, + longestStringLines[line])); + } + } + + if (stringsAreDifferent) { + error(messageBuilder.toString()); + } + } + private static > int compare(T lhs, T rhs, String msg) { assertNotNull(lhs, msg); assertNotNull(rhs, msg); diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/testlibrary/com/oracle/java/testlibrary/ExitCode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/ExitCode.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,40 @@ +/* + * 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. + */ + +package com.oracle.java.testlibrary; + +/** + * Exit code values that could be returned by the JVM. + */ +public enum ExitCode { + OK(0), + FAIL(1), + CRASH(134); + + public final int value; + + ExitCode(int value) { + this.value = value; + } +} + diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java Fri Mar 28 09:15:41 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -108,6 +108,40 @@ } /** + * Returns the default JTReg arguments for a jvm running a test without + * options that matches regular expresions in {@code filters}. + * This is the combination of JTReg arguments test.vm.opts and test.java.opts. + * @param filters Regular expressions used to filter out options. + * @return An array of options, or an empty array if no opptions. + */ + public static String[] getFilteredTestJavaOpts(String... filters) { + String options[] = getTestJavaOpts(); + + if (filters.length == 0) { + return options; + } + + List filteredOptions = new ArrayList(options.length); + Pattern patterns[] = new Pattern[filters.length]; + for (int i = 0; i < filters.length; i++) { + patterns[i] = Pattern.compile(filters[i]); + } + + for (String option : options) { + boolean matched = false; + for (int i = 0; i < patterns.length && !matched; i++) { + Matcher matcher = patterns[i].matcher(option); + matched = matcher.find(); + } + if (!matched) { + filteredOptions.add(option); + } + } + + return filteredOptions.toArray(new String[filteredOptions.size()]); + } + + /** * Combines given arguments with default JTReg arguments for a jvm running a test. * This is the combination of JTReg arguments test.vm.opts and test.java.opts * @return The combination of JTReg test java options and user args. diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CPUSpecificCommandLineOptionTest.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,110 @@ +/* + * 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. + */ + +package com.oracle.java.testlibrary.cli; + +import sun.hotspot.cpuinfo.CPUInfo; +import com.oracle.java.testlibrary.*; + +/** + * Base class for command line options tests that + * requires specific CPU arch or specific CPU features. + */ +public abstract class CPUSpecificCommandLineOptionTest + extends CommandLineOptionTest { + + private String cpuArchPattern; + private String supportedCPUFeatures[]; + private String unsupportedCPUFeatures[]; + + /** + * Create new CPU specific test instance that does not + * require any CPU features. + * + * @param cpuArchPattern Regular expression that should + * match os.arch. + */ + public CPUSpecificCommandLineOptionTest(String cpuArchPattern) { + this(cpuArchPattern, null, null); + } + + /** + * Create new CPU specific test instance that does not + * require from CPU support of {@code supportedCPUFeatures} features + * and no support of {@code unsupportedCPUFeatures}. + * + * @param cpuArchPattern Regular expression that should + * match os.arch. + * @param supportedCPUFeatures Array with names of features that + * should be supported by CPU. If null, + * then no features have to be supported. + * @param unsupportedCPUFeatures Array with names of features that + * should not be supported by CPU. + * If null, then CPU may support any + * features. + */ + public CPUSpecificCommandLineOptionTest(String cpuArchPattern, + String supportedCPUFeatures[], + String unsupportedCPUFeatures[]) { + this.cpuArchPattern = cpuArchPattern; + this.supportedCPUFeatures = supportedCPUFeatures; + this.unsupportedCPUFeatures = unsupportedCPUFeatures; + } + + /** + * Check that CPU on test box has appropriate architecture, support all + * required features and does not support all features that should not be + * supported. + * + * @return true if CPU on test box fulfill all requirements. + */ + @Override + public boolean checkPreconditions() { + if (!Platform.getOsArch().matches(cpuArchPattern)) { + System.out.println("CPU arch does not match " + cpuArchPattern); + return false; + } + + if (supportedCPUFeatures != null) { + for (String feature : supportedCPUFeatures) { + if (!CPUInfo.hasFeature(feature)) { + System.out.println("CPU does not support " + feature + + " feature"); + return false; + } + } + } + + if (unsupportedCPUFeatures != null) { + for (String feature : unsupportedCPUFeatures) { + if (CPUInfo.hasFeature(feature)) { + System.out.println("CPU support " + feature + " feature"); + return false; + } + } + } + + return true; + } +} + diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,173 @@ +/* + * 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. + */ + +package com.oracle.java.testlibrary.cli; + +import java.util.List; +import java.util.ArrayList; +import java.util.Collections; + +import com.oracle.java.testlibrary.*; + +/** + * Base class for command line option tests. + */ +public abstract class CommandLineOptionTest { + + public static final String UNRECOGNIZED_OPTION_ERROR_FORMAT = + "Unrecognized VM option '[+-]?%s'"; + + public static final String printFlagsFinalFormat = "%s\\s*:?=\\s*%s"; + + /** + * Verify that JVM startup behaviour matches our expectations. + * + * @param option The option that should be passed to JVM + * @param excpectedMessages Array of patterns that should occur + * in JVM output. If null then + * JVM output could be empty. + * @param unexpectedMessages Array of patterns that should not + * occur in JVM output. If null then + * JVM output could be empty. + * @param exitCode expected exit code. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyJVMStartup(String option, + String expectedMessages[], + String unexpectedMessages[], + ExitCode exitCode) + throws Throwable { + + OutputAnalyzer outputAnalyzer = + ProcessTools.executeTestJvm(option, "-version"); + + outputAnalyzer.shouldHaveExitValue(exitCode.value); + + if (expectedMessages != null) { + for (String expectedMessage : expectedMessages) { + outputAnalyzer.shouldMatch(expectedMessage); + } + } + + if (unexpectedMessages != null) { + for (String unexpectedMessage : unexpectedMessages) { + outputAnalyzer.shouldNotMatch(unexpectedMessage); + } + } + } + + /** + * Verify that value of specified JVM option is the same as + * expected value. + * This method filter out option with {@code optionName} + * name from test java options. + * + * @param optionName Name of tested option. + * @param expectedValue Expected value of tested option. + * @param additionalVMOpts Additonal options that should be + * passed to JVM. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyOptionValue(String optionName, + String expectedValue, + String... additionalVMOpts) + throws Throwable { + verifyOptionValue(optionName, expectedValue, true, additionalVMOpts); + } + + /** + * Verify that value of specified JVM option is the same as + * expected value. + * This method filter out option with {@code optionName} + * name from test java options. + * + * @param optionName Name of tested option. + * @param expectedValue Expected value of tested option. + * @param addTestVmOptions If true, then test VM options + * will be used. + * @param additionalVMOpts Additonal options that should be + * passed to JVM. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyOptionValue(String optionName, + String expectedValue, + boolean addTestVmOptions, + String... additionalVMOpts) + throws Throwable { + + List vmOpts = new ArrayList(); + + if (addTestVmOptions) { + Collections.addAll(vmOpts, + Utils.getFilteredTestJavaOpts(optionName)); + } + Collections.addAll(vmOpts, additionalVMOpts); + Collections.addAll(vmOpts, new String[] { + "-XX:+PrintFlagsFinal", + "-version" + }); + + ProcessBuilder processBuilder = + ProcessTools. + createJavaProcessBuilder(vmOpts. + toArray(new String[vmOpts.size()])); + + OutputAnalyzer outputAnalyzer = + new OutputAnalyzer(processBuilder.start()); + + outputAnalyzer.shouldHaveExitValue(0); + outputAnalyzer.shouldMatch(String. + format(printFlagsFinalFormat, + optionName, + expectedValue)); + } + + + /** + * Run command line option test. + * + * @throws Throwable if test failed. + */ + public final void test() throws Throwable { + if (checkPreconditions()) { + runTestCases(); + } + } + + /** + * Check that all preconditions for test execution are met. + * + * @return true if test could be executed. + */ + public boolean checkPreconditions() { + return true; + } + + /** + * Run test cases. + * + * @throws Throwable if test failed. + */ + public abstract void runTestCases() throws Throwable; +} + diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java --- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Tue Mar 25 14:52:03 2014 -0700 +++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Fri Mar 28 09:15:41 2014 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -135,6 +135,7 @@ public native boolean enqueueMethodForCompilation(Executable method, int compLevel, int entry_bci); public native void clearMethodState(Executable method); public native int getMethodEntryBci(Executable method); + public native Object[] getNMethod(Executable method, boolean isOsr); // Intered strings public native boolean isInStringTable(String str); @@ -150,4 +151,7 @@ public native void runMemoryUnitTests(); public native void readFromNoaccessArea(); + // CPU features + public native String getCPUFeatures(); + } diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/testlibrary/whitebox/sun/hotspot/code/NMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/code/NMethod.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,51 @@ +/* + * 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. + * + */ + +package sun.hotspot.code; + +import java.lang.reflect.Executable; +import sun.hotspot.WhiteBox; + +public class NMethod { + private static final WhiteBox wb = WhiteBox.getWhiteBox(); + public static NMethod get(Executable method, boolean isOsr) { + Object[] obj = wb.getNMethod(method, isOsr); + return obj == null ? null : new NMethod(obj); + } + private NMethod(Object[] obj) { + assert obj.length == 2; + comp_level = (Integer) obj[0]; + insts = (byte[]) obj[1]; + } + public byte[] insts; + public int comp_level; + + @Override + public String toString() { + return "NMethod{" + + "insts=" + insts + + ", comp_level=" + comp_level + + '}'; + } +} diff -r 5c9e34b1d884 -r a6e433ebd892 hotspot/test/testlibrary/whitebox/sun/hotspot/cpuinfo/CPUInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/cpuinfo/CPUInfo.java Fri Mar 28 09:15:41 2014 -0700 @@ -0,0 +1,98 @@ +/* + * 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. + * + */ + +package sun.hotspot.cpuinfo; + +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +import sun.hotspot.WhiteBox; + +/** + * Information about CPU on test box. + * + * CPUInfo uses WhiteBox to gather information, + * so WhiteBox class should be added to bootclasspath + * and option -XX:+WhiteBoxAPI should expclicetly + * specified on command line. + */ +public class CPUInfo { + + private static final List features; + private static final String additionalCPUInfo; + + static { + WhiteBox wb = WhiteBox.getWhiteBox(); + + Pattern additionalCPUInfoRE = + Pattern.compile("([^(]*\\([^)]*\\)[^,]*),\\s*"); + + String cpuFeaturesString = wb.getCPUFeatures(); + Matcher matcher = additionalCPUInfoRE.matcher(cpuFeaturesString); + if (matcher.find()) { + additionalCPUInfo = matcher.group(1); + } else { + additionalCPUInfo = ""; + } + String splittedFeatures[] = matcher.replaceAll("").split("(, )| "); + + features = Collections.unmodifiableList(Arrays. + asList(splittedFeatures)); + } + + /** + * Get additional information about CPU. + * For example, on X86 in will be family/model/stepping + * and number of cores. + * + * @return additional CPU info + */ + public static String getAdditionalCPUInfo() { + return additionalCPUInfo; + } + + /** + * Get all known features supported by CPU. + * + * @return unmodifiable list with names of all known features + * supported by CPU. + */ + public static List getFeatures() { + return features; + } + + /** + * Check if some feature is supported by CPU. + * + * @param feature Name of feature to be tested. + * @return true if tested feature is supported by CPU. + */ + public static boolean hasFeature(String feature) { + return features.contains(feature.toLowerCase()); + } +}