Mercurial > hg > icedtea7-forest > hotspot
changeset 4604:482ff4e18ca3 hs24-b42
Merge
author | amurillo |
---|---|
date | Thu, 25 Apr 2013 08:49:05 -0700 |
parents | e0f1aa072185 (current diff) ab40cf42161d (diff) |
children | 34a398422e59 |
files | make/hotspot_version test/runtime/NMT/AllocTestType.java |
diffstat | 54 files changed, 1635 insertions(+), 701 deletions(-) [+] |
line wrap: on
line diff
--- a/make/hotspot_version Wed Apr 24 12:20:45 2013 -0700 +++ b/make/hotspot_version Thu Apr 25 08:49:05 2013 -0700 @@ -35,7 +35,7 @@ HS_MAJOR_VER=24 HS_MINOR_VER=0 -HS_BUILD_NUMBER=41 +HS_BUILD_NUMBER=42 JDK_MAJOR_VER=1 JDK_MINOR_VER=7
--- a/src/cpu/sparc/vm/sparc.ad Wed Apr 24 12:20:45 2013 -0700 +++ b/src/cpu/sparc/vm/sparc.ad Thu Apr 25 08:49:05 2013 -0700 @@ -1,5 +1,5 @@ // -// Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -8176,10 +8176,25 @@ format %{ "SUBcc $p,$q,$p\t! p' = p-q\n\t" "ADD $p,$y,$tmp\t! g3=p-q+y\n\t" "MOVlt $tmp,$p\t! p' < 0 ? p'+y : p'" %} - ins_encode( enc_cadd_cmpLTMask(p, q, y, tmp) ); - ins_pipe( cadd_cmpltmask ); -%} - + ins_encode(enc_cadd_cmpLTMask(p, q, y, tmp)); + ins_pipe(cadd_cmpltmask); +%} + +instruct and_cmpLTMask(iRegI p, iRegI q, iRegI y, flagsReg ccr) %{ + match(Set p (AndI (CmpLTMask p q) y)); + effect(KILL ccr); + ins_cost(DEFAULT_COST*3); + + format %{ "CMP $p,$q\n\t" + "MOV $y,$p\n\t" + "MOVge G0,$p" %} + ins_encode %{ + __ cmp($p$$Register, $q$$Register); + __ mov($y$$Register, $p$$Register); + __ movcc(Assembler::greaterEqual, false, Assembler::icc, G0, $p$$Register); + %} + ins_pipe(ialu_reg_reg_ialu); +%} //----------------------------------------------------------------- // Direct raw moves between float and general registers using VIS3.
--- a/src/cpu/x86/vm/assembler_x86.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/cpu/x86/vm/assembler_x86.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -10154,6 +10154,31 @@ pop_CPU_state(); } +void MacroAssembler::restore_cpu_control_state_after_jni() { + // Either restore the MXCSR register after returning from the JNI Call + // or verify that it wasn't changed (with -Xcheck:jni flag). + if (VM_Version::supports_sse()) { + if (RestoreMXCSROnJNICalls) { + ldmxcsr(ExternalAddress(StubRoutines::addr_mxcsr_std())); + } else if (CheckJNICalls) { + call(RuntimeAddress(StubRoutines::x86::verify_mxcsr_entry())); + } + } + if (VM_Version::supports_avx()) { + // Clear upper bits of YMM registers to avoid SSE <-> AVX transition penalty. + vzeroupper(); + } + +#ifndef _LP64 + // Either restore the x87 floating pointer control word after returning + // from the JNI call or verify that it wasn't changed. + if (CheckJNICalls) { + call(RuntimeAddress(StubRoutines::x86::verify_fpu_cntrl_wrd_entry())); + } +#endif // _LP64 +} + + void MacroAssembler::load_klass(Register dst, Register src) { #ifdef _LP64 if (UseCompressedOops) { @@ -11052,6 +11077,8 @@ addptr(result, stride2); subl(cnt2, stride2); jccb(Assembler::notZero, COMPARE_WIDE_VECTORS_LOOP); + // clean upper bits of YMM registers + vzeroupper(); // compare wide vectors tail bind(COMPARE_WIDE_TAIL); @@ -11065,6 +11092,8 @@ // Identifies the mismatching (higher or lower)16-bytes in the 32-byte vectors. bind(VECTOR_NOT_EQUAL); + // clean upper bits of YMM registers + vzeroupper(); lea(str1, Address(str1, result, scale)); lea(str2, Address(str2, result, scale)); jmp(COMPARE_16_CHARS); @@ -11321,6 +11350,10 @@ // That's it bind(DONE); + if (UseAVX >= 2) { + // clean upper bits of YMM registers + vzeroupper(); + } } void MacroAssembler::generate_fill(BasicType t, bool aligned, @@ -11450,6 +11483,10 @@ vmovdqu(Address(to, 0), xtmp); addptr(to, 32); subl(count, 8 << shift); + + BIND(L_check_fill_8_bytes); + // clean upper bits of YMM registers + vzeroupper(); } else { // Fill 32-byte chunks pshufd(xtmp, xtmp, 0); @@ -11473,8 +11510,9 @@ addptr(to, 32); subl(count, 8 << shift); jcc(Assembler::greaterEqual, L_fill_32_bytes_loop); + + BIND(L_check_fill_8_bytes); } - BIND(L_check_fill_8_bytes); addl(count, 8 << shift); jccb(Assembler::zero, L_exit); jmpb(L_fill_8_bytes);
--- a/src/cpu/x86/vm/assembler_x86.hpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/cpu/x86/vm/assembler_x86.hpp Thu Apr 25 08:49:05 2013 -0700 @@ -2315,6 +2315,9 @@ // only if +VerifyFPU void verify_FPU(int stack_depth, const char* s = "illegal FPU state"); + // Verify or restore cpu control state after JNI call + void restore_cpu_control_state_after_jni(); + // prints msg, dumps registers and stops execution void stop(const char* msg);
--- a/src/cpu/x86/vm/cppInterpreter_x86.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/cpu/x86/vm/cppInterpreter_x86.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -1295,25 +1295,8 @@ __ push(rdx); #endif // _LP64 - // Either restore the MXCSR register after returning from the JNI Call - // or verify that it wasn't changed. - if (VM_Version::supports_sse()) { - if (RestoreMXCSROnJNICalls) { - __ ldmxcsr(ExternalAddress(StubRoutines::addr_mxcsr_std())); - } - else if (CheckJNICalls ) { - __ call(RuntimeAddress(StubRoutines::x86::verify_mxcsr_entry())); - } - } - -#ifndef _LP64 - // Either restore the x87 floating pointer control word after returning - // from the JNI call or verify that it wasn't changed. - if (CheckJNICalls) { - __ call(RuntimeAddress(StubRoutines::x86::verify_fpu_cntrl_wrd_entry())); - } -#endif // _LP64 - + // Verify or restore cpu control state after JNI call + __ restore_cpu_control_state_after_jni(); // change thread state __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_native_trans);
--- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -2070,6 +2070,9 @@ __ call(RuntimeAddress(native_func)); + // Verify or restore cpu control state after JNI call + __ restore_cpu_control_state_after_jni(); + // WARNING - on Windows Java Natives use pascal calling convention and pop the // arguments off of the stack. We could just re-adjust the stack pointer here // and continue to do SP relative addressing but we instead switch to FP
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -2320,16 +2320,8 @@ __ call(RuntimeAddress(native_func)); - // Either restore the MXCSR register after returning from the JNI Call - // or verify that it wasn't changed. - if (RestoreMXCSROnJNICalls) { - __ ldmxcsr(ExternalAddress(StubRoutines::x86::mxcsr_std())); - - } - else if (CheckJNICalls ) { - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::x86::verify_mxcsr_entry()))); - } - + // Verify or restore cpu control state after JNI call + __ restore_cpu_control_state_after_jni(); // Unpack native results. switch (ret_type) {
--- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -864,6 +864,11 @@ __ BIND(L_copy_64_bytes); __ subl(qword_count, 8); __ jcc(Assembler::greaterEqual, L_copy_64_bytes_loop); + + if (UseUnalignedLoadStores && (UseAVX >= 2)) { + // clean upper bits of YMM registers + __ vzeroupper(); + } __ addl(qword_count, 8); __ jccb(Assembler::zero, L_exit); //
--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -1359,6 +1359,10 @@ } __ addptr(qword_count, 4); __ BIND(L_end); + if (UseAVX >= 2) { + // clean upper bits of YMM registers + __ vzeroupper(); + } } else { // Copy 32-bytes per iteration __ BIND(L_loop); @@ -1432,6 +1436,10 @@ } __ subptr(qword_count, 4); __ BIND(L_end); + if (UseAVX >= 2) { + // clean upper bits of YMM registers + __ vzeroupper(); + } } else { // Copy 32-bytes per iteration __ BIND(L_loop);
--- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -1080,22 +1080,8 @@ // result potentially in rdx:rax or ST0 - // Either restore the MXCSR register after returning from the JNI Call - // or verify that it wasn't changed. - if (VM_Version::supports_sse()) { - if (RestoreMXCSROnJNICalls) { - __ ldmxcsr(ExternalAddress(StubRoutines::addr_mxcsr_std())); - } - else if (CheckJNICalls ) { - __ call(RuntimeAddress(StubRoutines::x86::verify_mxcsr_entry())); - } - } - - // Either restore the x87 floating pointer control word after returning - // from the JNI call or verify that it wasn't changed. - if (CheckJNICalls) { - __ call(RuntimeAddress(StubRoutines::x86::verify_fpu_cntrl_wrd_entry())); - } + // Verify or restore cpu control state after JNI call + __ restore_cpu_control_state_after_jni(); // save potential result in ST(0) & rdx:rax // (if result handler is the T_FLOAT or T_DOUBLE handler, result must be in ST0 -
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -1081,15 +1081,8 @@ __ call(rax); // result potentially in rax or xmm0 - // Depending on runtime options, either restore the MXCSR - // register after returning from the JNI Call or verify that - // it wasn't changed during -Xcheck:jni. - if (RestoreMXCSROnJNICalls) { - __ ldmxcsr(ExternalAddress(StubRoutines::x86::mxcsr_std())); - } - else if (CheckJNICalls) { - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::x86::verify_mxcsr_entry()))); - } + // Verify or restore cpu control state after JNI call + __ restore_cpu_control_state_after_jni(); // NOTE: The order of these pushes is known to frame::interpreter_frame_result // in order to extract the result of a method call. If the order of these
--- a/src/cpu/x86/vm/x86_32.ad Wed Apr 24 12:20:45 2013 -0700 +++ b/src/cpu/x86/vm/x86_32.ad Thu Apr 25 08:49:05 2013 -0700 @@ -1,5 +1,5 @@ // -// Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -228,10 +228,16 @@ static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000)); // Offset hacking within calls. -static int pre_call_FPU_size() { - if (Compile::current()->in_24_bit_fp_mode()) - return 6; // fldcw - return 0; +static int pre_call_resets_size() { + int size = 0; + Compile* C = Compile::current(); + if (C->in_24_bit_fp_mode()) { + size += 6; // fldcw + } + if (C->max_vector_size() > 16) { + size += 3; // vzeroupper + } + return size; } static int preserve_SP_size() { @@ -242,21 +248,21 @@ // from the start of the call to the point where the return address // will point. int MachCallStaticJavaNode::ret_addr_offset() { - int offset = 5 + pre_call_FPU_size(); // 5 bytes from start of call to where return address points + int offset = 5 + pre_call_resets_size(); // 5 bytes from start of call to where return address points if (_method_handle_invoke) offset += preserve_SP_size(); return offset; } int MachCallDynamicJavaNode::ret_addr_offset() { - return 10 + pre_call_FPU_size(); // 10 bytes from start of call to where return address points + return 10 + pre_call_resets_size(); // 10 bytes from start of call to where return address points } static int sizeof_FFree_Float_Stack_All = -1; int MachCallRuntimeNode::ret_addr_offset() { assert(sizeof_FFree_Float_Stack_All != -1, "must have been emitted already"); - return sizeof_FFree_Float_Stack_All + 5 + pre_call_FPU_size(); + return sizeof_FFree_Float_Stack_All + 5 + pre_call_resets_size(); } // Indicate if the safepoint node needs the polling page as an input. @@ -272,7 +278,7 @@ // The address of the call instruction needs to be 4-byte aligned to // ensure that it does not span a cache line so that it can be patched. int CallStaticJavaDirectNode::compute_padding(int current_offset) const { - current_offset += pre_call_FPU_size(); // skip fldcw, if any + current_offset += pre_call_resets_size(); // skip fldcw, if any current_offset += 1; // skip call opcode byte return round_to(current_offset, alignment_required()) - current_offset; } @@ -280,7 +286,7 @@ // The address of the call instruction needs to be 4-byte aligned to // ensure that it does not span a cache line so that it can be patched. int CallStaticJavaHandleNode::compute_padding(int current_offset) const { - current_offset += pre_call_FPU_size(); // skip fldcw, if any + current_offset += pre_call_resets_size(); // skip fldcw, if any current_offset += preserve_SP_size(); // skip mov rbp, rsp current_offset += 1; // skip call opcode byte return round_to(current_offset, alignment_required()) - current_offset; @@ -289,7 +295,7 @@ // The address of the call instruction needs to be 4-byte aligned to // ensure that it does not span a cache line so that it can be patched. int CallDynamicJavaDirectNode::compute_padding(int current_offset) const { - current_offset += pre_call_FPU_size(); // skip fldcw, if any + current_offset += pre_call_resets_size(); // skip fldcw, if any current_offset += 5; // skip MOV instruction current_offset += 1; // skip call opcode byte return round_to(current_offset, alignment_required()) - current_offset; @@ -583,16 +589,20 @@ // Remove two words for return addr and rbp, framesize -= 2*wordSize; - if( C->in_24_bit_fp_mode() ) { + if (C->max_vector_size() > 16) { + st->print("VZEROUPPER"); + st->cr(); st->print("\t"); + } + if (C->in_24_bit_fp_mode()) { st->print("FLDCW standard control word"); st->cr(); st->print("\t"); } - if( framesize ) { + if (framesize) { st->print("ADD ESP,%d\t# Destroy frame",framesize); st->cr(); st->print("\t"); } st->print_cr("POPL EBP"); st->print("\t"); - if( do_polling() && C->is_method_compilation() ) { + if (do_polling() && C->is_method_compilation()) { st->print("TEST PollPage,EAX\t! Poll Safepoint"); st->cr(); st->print("\t"); } @@ -602,8 +612,14 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Compile *C = ra_->C; + if (C->max_vector_size() > 16) { + // Clear upper bits of YMM registers when current compiled code uses + // wide vectors to avoid AVX <-> SSE transition penalty during call. + MacroAssembler masm(&cbuf); + masm.vzeroupper(); + } // If method set FPU control word, restore to standard control word - if( C->in_24_bit_fp_mode() ) { + if (C->in_24_bit_fp_mode()) { MacroAssembler masm(&cbuf); masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); } @@ -615,12 +631,11 @@ // Note that VerifyStackAtCalls' Majik cookie does not change the frame size popped here - if( framesize >= 128 ) { + if (framesize >= 128) { emit_opcode(cbuf, 0x81); // add SP, #framesize emit_rm(cbuf, 0x3, 0x00, ESP_enc); emit_d32(cbuf, framesize); - } - else if( framesize ) { + } else if (framesize) { emit_opcode(cbuf, 0x83); // add SP, #framesize emit_rm(cbuf, 0x3, 0x00, ESP_enc); emit_d8(cbuf, framesize); @@ -628,7 +643,7 @@ emit_opcode(cbuf, 0x58 | EBP_enc); - if( do_polling() && C->is_method_compilation() ) { + if (do_polling() && C->is_method_compilation()) { cbuf.relocate(cbuf.insts_end(), relocInfo::poll_return_type, 0); emit_opcode(cbuf,0x85); emit_rm(cbuf, 0x0, EAX_enc, 0x5); // EAX @@ -640,7 +655,8 @@ Compile *C = ra_->C; // If method set FPU control word, restore to standard control word int size = C->in_24_bit_fp_mode() ? 6 : 0; - if( do_polling() && C->is_method_compilation() ) size += 6; + if (C->max_vector_size() > 16) size += 3; // vzeroupper + if (do_polling() && C->is_method_compilation()) size += 6; int framesize = C->frame_slots() << LogBytesPerInt; assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); @@ -649,7 +665,7 @@ size++; // popl rbp, - if( framesize >= 128 ) { + if (framesize >= 128) { size += 6; } else { size += framesize ? 3 : 0; @@ -1848,20 +1864,26 @@ %} - enc_class pre_call_FPU %{ + enc_class pre_call_resets %{ // If method sets FPU control word restore it here debug_only(int off0 = cbuf.insts_size()); - if( Compile::current()->in_24_bit_fp_mode() ) { - MacroAssembler masm(&cbuf); - masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); + if (ra_->C->in_24_bit_fp_mode()) { + MacroAssembler _masm(&cbuf); + __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); + } + if (ra_->C->max_vector_size() > 16) { + // Clear upper bits of YMM registers when current compiled code uses + // wide vectors to avoid AVX <-> SSE transition penalty during call. + MacroAssembler _masm(&cbuf); + __ vzeroupper(); } debug_only(int off1 = cbuf.insts_size()); - assert(off1 - off0 == pre_call_FPU_size(), "correct size prediction"); + assert(off1 - off0 == pre_call_resets_size(), "correct size prediction"); %} enc_class post_call_FPU %{ // If method sets FPU control word do it here also - if( Compile::current()->in_24_bit_fp_mode() ) { + if (Compile::current()->in_24_bit_fp_mode()) { MacroAssembler masm(&cbuf); masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_24())); } @@ -1872,17 +1894,17 @@ // who we intended to call. cbuf.set_insts_mark(); $$$emit8$primary; - if ( !_method ) { + if (!_method) { emit_d32_reloc(cbuf, ($meth$$method - (int)(cbuf.insts_end()) - 4), runtime_call_Relocation::spec(), RELOC_IMM32 ); - } else if(_optimized_virtual) { + } else if (_optimized_virtual) { emit_d32_reloc(cbuf, ($meth$$method - (int)(cbuf.insts_end()) - 4), opt_virtual_call_Relocation::spec(), RELOC_IMM32 ); } else { emit_d32_reloc(cbuf, ($meth$$method - (int)(cbuf.insts_end()) - 4), static_call_Relocation::spec(), RELOC_IMM32 ); } - if( _method ) { // Emit stub for static call + if (_method) { // Emit stub for static call emit_java_to_interp(cbuf); } %} @@ -2301,30 +2323,6 @@ emit_rm(cbuf, 0x3, $p$$reg, tmpReg); %} - enc_class enc_cmpLTP_mem(rRegI p, rRegI q, memory mem, eCXRegI tmp) %{ // cadd_cmpLT - int tmpReg = $tmp$$reg; - - // SUB $p,$q - emit_opcode(cbuf,0x2B); - emit_rm(cbuf, 0x3, $p$$reg, $q$$reg); - // SBB $tmp,$tmp - emit_opcode(cbuf,0x1B); - emit_rm(cbuf, 0x3, tmpReg, tmpReg); - // AND $tmp,$y - cbuf.set_insts_mark(); // Mark start of opcode for reloc info in mem operand - emit_opcode(cbuf,0x23); - int reg_encoding = tmpReg; - int base = $mem$$base; - int index = $mem$$index; - int scale = $mem$$scale; - int displace = $mem$$disp; - bool disp_is_oop = $mem->disp_is_oop(); - encode_RegMem(cbuf, reg_encoding, base, index, scale, displace, disp_is_oop); - // ADD $p,$tmp - emit_opcode(cbuf,0x03); - emit_rm(cbuf, 0x3, $p$$reg, tmpReg); - %} - enc_class shift_left_long( eRegL dst, eCXRegI shift ) %{ // TEST shift,32 emit_opcode(cbuf,0xF7); @@ -8906,9 +8904,9 @@ %} %} -instruct cmpLTMask( eCXRegI dst, ncxRegI p, ncxRegI q, eFlagsReg cr ) %{ +instruct cmpLTMask(eCXRegI dst, ncxRegI p, ncxRegI q, eFlagsReg cr) %{ match(Set dst (CmpLTMask p q)); - effect( KILL cr ); + effect(KILL cr); ins_cost(400); // SETlt can only use low byte of EAX,EBX, ECX, or EDX as destination @@ -8916,50 +8914,83 @@ "CMP $p,$q\n\t" "SETlt $dst\n\t" "NEG $dst" %} - ins_encode( OpcRegReg(0x33,dst,dst), - OpcRegReg(0x3B,p,q), - setLT_reg(dst), neg_reg(dst) ); - ins_pipe( pipe_slow ); -%} - -instruct cmpLTMask0( rRegI dst, immI0 zero, eFlagsReg cr ) %{ + ins_encode %{ + Register Rp = $p$$Register; + Register Rq = $q$$Register; + Register Rd = $dst$$Register; + Label done; + __ xorl(Rd, Rd); + __ cmpl(Rp, Rq); + __ setb(Assembler::less, Rd); + __ negl(Rd); + %} + + ins_pipe(pipe_slow); +%} + +instruct cmpLTMask0(rRegI dst, immI0 zero, eFlagsReg cr) %{ match(Set dst (CmpLTMask dst zero)); - effect( DEF dst, KILL cr ); + effect(DEF dst, KILL cr); ins_cost(100); - format %{ "SAR $dst,31" %} - opcode(0xC1, 0x7); /* C1 /7 ib */ - ins_encode( RegOpcImm( dst, 0x1F ) ); - ins_pipe( ialu_reg ); -%} - - -instruct cadd_cmpLTMask( ncxRegI p, ncxRegI q, ncxRegI y, eCXRegI tmp, eFlagsReg cr ) %{ + format %{ "SAR $dst,31\t# cmpLTMask0" %} + ins_encode %{ + __ sarl($dst$$Register, 31); + %} + ins_pipe(ialu_reg); +%} + +/* better to save a register than avoid a branch */ +instruct cadd_cmpLTMask(rRegI p, rRegI q, rRegI y, eFlagsReg cr) %{ match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q))); - effect( KILL tmp, KILL cr ); + effect(KILL cr); ins_cost(400); - // annoyingly, $tmp has no edges so you cant ask for it in - // any format or encoding - format %{ "SUB $p,$q\n\t" - "SBB ECX,ECX\n\t" - "AND ECX,$y\n\t" - "ADD $p,ECX" %} - ins_encode( enc_cmpLTP(p,q,y,tmp) ); - ins_pipe( pipe_cmplt ); + format %{ "SUB $p,$q\t# cadd_cmpLTMask\n\t" + "JGE done\n\t" + "ADD $p,$y\n" + "done: " %} + ins_encode %{ + Register Rp = $p$$Register; + Register Rq = $q$$Register; + Register Ry = $y$$Register; + Label done; + __ subl(Rp, Rq); + __ jccb(Assembler::greaterEqual, done); + __ addl(Rp, Ry); + __ bind(done); + %} + + ins_pipe(pipe_cmplt); +%} + +/* better to save a register than avoid a branch */ +instruct and_cmpLTMask(rRegI p, rRegI q, rRegI y, eFlagsReg cr) %{ + match(Set y (AndI (CmpLTMask p q) y)); + effect(KILL cr); + + ins_cost(300); + + format %{ "CMPL $p, $q\t# and_cmpLTMask\n\t" + "JLT done\n\t" + "XORL $y, $y\n" + "done: " %} + ins_encode %{ + Register Rp = $p$$Register; + Register Rq = $q$$Register; + Register Ry = $y$$Register; + Label done; + __ cmpl(Rp, Rq); + __ jccb(Assembler::less, done); + __ xorl(Ry, Ry); + __ bind(done); + %} + + ins_pipe(pipe_cmplt); %} /* If I enable this, I encourage spilling in the inner loop of compress. -instruct cadd_cmpLTMask_mem( ncxRegI p, ncxRegI q, memory y, eCXRegI tmp, eFlagsReg cr ) %{ +instruct cadd_cmpLTMask_mem(ncxRegI p, ncxRegI q, memory y, eCXRegI tmp, eFlagsReg cr) %{ match(Set p (AddI (AndI (CmpLTMask p q) (LoadI y)) (SubI p q))); - effect( USE_KILL tmp, KILL cr ); - ins_cost(400); - - format %{ "SUB $p,$q\n\t" - "SBB ECX,ECX\n\t" - "AND ECX,$y\n\t" - "ADD $p,ECX" %} - ins_encode( enc_cmpLTP_mem(p,q,y,tmp) ); -%} */ //----------Long Instructions------------------------------------------------ @@ -12817,7 +12848,7 @@ ins_cost(300); format %{ "CALL,static " %} opcode(0xE8); /* E8 cd */ - ins_encode( pre_call_FPU, + ins_encode( pre_call_resets, Java_Static_Call( meth ), call_epilog, post_call_FPU ); @@ -12838,7 +12869,7 @@ ins_cost(300); format %{ "CALL,static/MethodHandle " %} opcode(0xE8); /* E8 cd */ - ins_encode( pre_call_FPU, + ins_encode( pre_call_resets, preserve_SP, Java_Static_Call( meth ), restore_SP, @@ -12859,7 +12890,7 @@ format %{ "MOV EAX,(oop)-1\n\t" "CALL,dynamic" %} opcode(0xE8); /* E8 cd */ - ins_encode( pre_call_FPU, + ins_encode( pre_call_resets, Java_Dynamic_Call( meth ), call_epilog, post_call_FPU ); @@ -12876,7 +12907,7 @@ format %{ "CALL,runtime " %} opcode(0xE8); /* E8 cd */ // Use FFREEs to clear entries in float stack - ins_encode( pre_call_FPU, + ins_encode( pre_call_resets, FFree_Float_Stack_All, Java_To_Runtime( meth ), post_call_FPU ); @@ -12891,7 +12922,7 @@ ins_cost(300); format %{ "CALL_LEAF,runtime " %} opcode(0xE8); /* E8 cd */ - ins_encode( pre_call_FPU, + ins_encode( pre_call_resets, FFree_Float_Stack_All, Java_To_Runtime( meth ), Verify_FPU_For_Leaf, post_call_FPU );
--- a/src/cpu/x86/vm/x86_64.ad Wed Apr 24 12:20:45 2013 -0700 +++ b/src/cpu/x86/vm/x86_64.ad Thu Apr 25 08:49:05 2013 -0700 @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -399,6 +399,9 @@ static int preserve_SP_size() { return 3; // rex.w, op, rm(reg/reg) } +static int clear_avx_size() { + return (Compile::current()->max_vector_size() > 16) ? 3 : 0; // vzeroupper +} // !!!!! Special hack to get all types of calls to specify the byte offset // from the start of the call to the point where the return address @@ -406,6 +409,7 @@ int MachCallStaticJavaNode::ret_addr_offset() { int offset = 5; // 5 bytes from start of call to where return address points + offset += clear_avx_size(); if (_method_handle_invoke) offset += preserve_SP_size(); return offset; @@ -413,11 +417,16 @@ int MachCallDynamicJavaNode::ret_addr_offset() { - return 15; // 15 bytes from start of call to where return address points + int offset = 15; // 15 bytes from start of call to where return address points + offset += clear_avx_size(); + return offset; } -// In os_cpu .ad file -// int MachCallRuntimeNode::ret_addr_offset() +int MachCallRuntimeNode::ret_addr_offset() { + int offset = 13; // movq r10,#addr; callq (r10) + offset += clear_avx_size(); + return offset; +} // Indicate if the safepoint node needs the polling page as an input, // it does if the polling page is more than disp32 away. @@ -434,6 +443,7 @@ // ensure that it does not span a cache line so that it can be patched. int CallStaticJavaDirectNode::compute_padding(int current_offset) const { + current_offset += clear_avx_size(); // skip vzeroupper current_offset += 1; // skip call opcode byte return round_to(current_offset, alignment_required()) - current_offset; } @@ -443,6 +453,7 @@ int CallStaticJavaHandleNode::compute_padding(int current_offset) const { current_offset += preserve_SP_size(); // skip mov rbp, rsp + current_offset += clear_avx_size(); // skip vzeroupper current_offset += 1; // skip call opcode byte return round_to(current_offset, alignment_required()) - current_offset; } @@ -451,6 +462,7 @@ // ensure that it does not span a cache line so that it can be patched. int CallDynamicJavaDirectNode::compute_padding(int current_offset) const { + current_offset += clear_avx_size(); // skip vzeroupper current_offset += 11; // skip movq instruction + call opcode byte return round_to(current_offset, alignment_required()) - current_offset; } @@ -762,6 +774,11 @@ void MachEpilogNode::format(PhaseRegAlloc* ra_, outputStream* st) const { Compile* C = ra_->C; + if (C->max_vector_size() > 16) { + st->print("vzeroupper"); + st->cr(); st->print("\t"); + } + int framesize = C->frame_slots() << LogBytesPerInt; assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); // Remove word for return adr already pushed @@ -791,6 +808,13 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { Compile* C = ra_->C; + if (C->max_vector_size() > 16) { + // Clear upper bits of YMM registers when current compiled code uses + // wide vectors to avoid AVX <-> SSE transition penalty during call. + MacroAssembler _masm(&cbuf); + __ vzeroupper(); + } + int framesize = C->frame_slots() << LogBytesPerInt; assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); // Remove word for return adr already pushed @@ -2001,6 +2025,25 @@ __ bind(miss); %} + enc_class clear_avx %{ + debug_only(int off0 = cbuf.insts_size()); + if (ra_->C->max_vector_size() > 16) { + // Clear upper bits of YMM registers when current compiled code uses + // wide vectors to avoid AVX <-> SSE transition penalty during call. + MacroAssembler _masm(&cbuf); + __ vzeroupper(); + } + debug_only(int off1 = cbuf.insts_size()); + assert(off1 - off0 == clear_avx_size(), "correct size prediction"); + %} + + enc_class Java_To_Runtime(method meth) %{ + // No relocation needed + MacroAssembler _masm(&cbuf); + __ mov64(r10, (int64_t) $meth$$method); + __ call(r10); + %} + enc_class Java_To_Interpreter(method meth) %{ // CALL Java_To_Interpreter @@ -2203,12 +2246,6 @@ $$$emit32$src$$constant; %} - enc_class Con64(immL src) - %{ - // Output immediate - emit_d64($src$$constant); - %} - enc_class Con32F_as_bits(immF src) %{ // Output Float immediate bits @@ -7349,7 +7386,7 @@ ins_pipe( pipe_cmpxchg ); %} -instruct xaddL_no_res( memory mem, Universe dummy, immL add, rFlagsReg cr) %{ +instruct xaddL_no_res( memory mem, Universe dummy, immL32 add, rFlagsReg cr) %{ predicate(n->as_LoadStore()->result_not_used()); match(Set dummy (GetAndAddL mem add)); effect(KILL cr); @@ -9198,7 +9235,7 @@ match(Set dst (CmpLTMask p q)); effect(KILL cr); - ins_cost(400); // XXX + ins_cost(400); format %{ "cmpl $p, $q\t# cmpLTMask\n\t" "setlt $dst\n\t" "movzbl $dst, $dst\n\t" @@ -9216,37 +9253,63 @@ match(Set dst (CmpLTMask dst zero)); effect(KILL cr); - ins_cost(100); // XXX + ins_cost(100); format %{ "sarl $dst, #31\t# cmpLTMask0" %} - opcode(0xC1, 0x7); /* C1 /7 ib */ - ins_encode(reg_opc_imm(dst, 0x1F)); + ins_encode %{ + __ sarl($dst$$Register, 31); + %} ins_pipe(ialu_reg); %} - -instruct cadd_cmpLTMask(rRegI p, rRegI q, rRegI y, rRegI tmp, rFlagsReg cr) +/* Better to save a register than avoid a branch */ +instruct cadd_cmpLTMask(rRegI p, rRegI q, rRegI y, rFlagsReg cr) %{ match(Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q))); - effect(TEMP tmp, KILL cr); - - ins_cost(400); // XXX - format %{ "subl $p, $q\t# cadd_cmpLTMask1\n\t" - "sbbl $tmp, $tmp\n\t" - "andl $tmp, $y\n\t" - "addl $p, $tmp" %} + effect(KILL cr); + ins_cost(300); + format %{ "subl $p,$q\t# cadd_cmpLTMask\n\t" + "jge done\n\t" + "addl $p,$y\n" + "done: " %} ins_encode %{ Register Rp = $p$$Register; Register Rq = $q$$Register; Register Ry = $y$$Register; - Register Rt = $tmp$$Register; + Label done; __ subl(Rp, Rq); - __ sbbl(Rt, Rt); - __ andl(Rt, Ry); - __ addl(Rp, Rt); + __ jccb(Assembler::greaterEqual, done); + __ addl(Rp, Ry); + __ bind(done); %} ins_pipe(pipe_cmplt); %} +/* Better to save a register than avoid a branch */ +instruct and_cmpLTMask(rRegI p, rRegI q, rRegI y, rFlagsReg cr) +%{ + match(Set y (AndI (CmpLTMask p q) y)); + effect(KILL cr); + + ins_cost(300); + + format %{ "cmpl $p, $q\t# and_cmpLTMask\n\t" + "jlt done\n\t" + "xorl $y, $y\n" + "done: " %} + ins_encode %{ + Register Rp = $p$$Register; + Register Rq = $q$$Register; + Register Ry = $y$$Register; + Label done; + __ cmpl(Rp, Rq); + __ jccb(Assembler::less, done); + __ xorl(Ry, Ry); + __ bind(done); + %} + ins_pipe(pipe_cmplt); +%} + + //---------- FP Instructions------------------------------------------------ instruct cmpF_cc_reg(rFlagsRegU cr, regF src1, regF src2) @@ -11124,7 +11187,7 @@ ins_cost(300); format %{ "call,static " %} opcode(0xE8); /* E8 cd */ - ins_encode(Java_Static_Call(meth), call_epilog); + ins_encode(clear_avx, Java_Static_Call(meth), call_epilog); ins_pipe(pipe_slow); ins_alignment(4); %} @@ -11142,7 +11205,7 @@ ins_cost(300); format %{ "call,static/MethodHandle " %} opcode(0xE8); /* E8 cd */ - ins_encode(preserve_SP, + ins_encode(clear_avx, preserve_SP, Java_Static_Call(meth), restore_SP, call_epilog); @@ -11162,7 +11225,7 @@ format %{ "movq rax, #Universe::non_oop_word()\n\t" "call,dynamic " %} opcode(0xE8); /* E8 cd */ - ins_encode(Java_Dynamic_Call(meth), call_epilog); + ins_encode(clear_avx, Java_Dynamic_Call(meth), call_epilog); ins_pipe(pipe_slow); ins_alignment(4); %} @@ -11175,8 +11238,7 @@ ins_cost(300); format %{ "call,runtime " %} - opcode(0xE8); /* E8 cd */ - ins_encode(Java_To_Runtime(meth)); + ins_encode(clear_avx, Java_To_Runtime(meth)); ins_pipe(pipe_slow); %} @@ -11188,8 +11250,7 @@ ins_cost(300); format %{ "call_leaf,runtime " %} - opcode(0xE8); /* E8 cd */ - ins_encode(Java_To_Runtime(meth)); + ins_encode(clear_avx, Java_To_Runtime(meth)); ins_pipe(pipe_slow); %} @@ -11201,7 +11262,6 @@ ins_cost(300); format %{ "call_leaf_nofp,runtime " %} - opcode(0xE8); /* E8 cd */ ins_encode(Java_To_Runtime(meth)); ins_pipe(pipe_slow); %}
--- a/src/os/bsd/vm/os_bsd.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/os/bsd/vm/os_bsd.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -2667,17 +2667,118 @@ // Bsd(POSIX) specific hand shaking semaphore. #ifdef __APPLE__ -static semaphore_t sig_sem; +typedef semaphore_t os_semaphore_t; #define SEM_INIT(sem, value) semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO, value) -#define SEM_WAIT(sem) semaphore_wait(sem); -#define SEM_POST(sem) semaphore_signal(sem); +#define SEM_WAIT(sem) semaphore_wait(sem) +#define SEM_POST(sem) semaphore_signal(sem) +#define SEM_DESTROY(sem) semaphore_destroy(mach_task_self(), sem) #else -static sem_t sig_sem; +typedef sem_t os_semaphore_t; #define SEM_INIT(sem, value) sem_init(&sem, 0, value) -#define SEM_WAIT(sem) sem_wait(&sem); -#define SEM_POST(sem) sem_post(&sem); +#define SEM_WAIT(sem) sem_wait(&sem) +#define SEM_POST(sem) sem_post(&sem) +#define SEM_DESTROY(sem) sem_destroy(&sem) #endif +class Semaphore : public StackObj { + public: + Semaphore(); + ~Semaphore(); + void signal(); + void wait(); + bool trywait(); + bool timedwait(unsigned int sec, int nsec); + private: + jlong currenttime() const; + semaphore_t _semaphore; +}; + +Semaphore::Semaphore() : _semaphore(0) { + SEM_INIT(_semaphore, 0); +} + +Semaphore::~Semaphore() { + SEM_DESTROY(_semaphore); +} + +void Semaphore::signal() { + SEM_POST(_semaphore); +} + +void Semaphore::wait() { + SEM_WAIT(_semaphore); +} + +jlong Semaphore::currenttime() const { + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000); +} + +#ifdef __APPLE__ +bool Semaphore::trywait() { + return timedwait(0, 0); +} + +bool Semaphore::timedwait(unsigned int sec, int nsec) { + kern_return_t kr = KERN_ABORTED; + mach_timespec_t waitspec; + waitspec.tv_sec = sec; + waitspec.tv_nsec = nsec; + + jlong starttime = currenttime(); + + kr = semaphore_timedwait(_semaphore, waitspec); + while (kr == KERN_ABORTED) { + jlong totalwait = (sec * NANOSECS_PER_SEC) + nsec; + + jlong current = currenttime(); + jlong passedtime = current - starttime; + + if (passedtime >= totalwait) { + waitspec.tv_sec = 0; + waitspec.tv_nsec = 0; + } else { + jlong waittime = totalwait - (current - starttime); + waitspec.tv_sec = waittime / NANOSECS_PER_SEC; + waitspec.tv_nsec = waittime % NANOSECS_PER_SEC; + } + + kr = semaphore_timedwait(_semaphore, waitspec); + } + + return kr == KERN_SUCCESS; +} + +#else + +bool Semaphore::trywait() { + return sem_trywait(&_semaphore) == 0; +} + +bool Semaphore::timedwait(unsigned int sec, int nsec) { + struct timespec ts; + jlong endtime = unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); + + while (1) { + int result = sem_timedwait(&_semaphore, &ts); + if (result == 0) { + return true; + } else if (errno == EINTR) { + continue; + } else if (errno == ETIMEDOUT) { + return false; + } else { + return false; + } + } +} + +#endif // __APPLE__ + +static os_semaphore_t sig_sem; +static Semaphore sr_semaphore; + void os::signal_init_pd() { // Initialize signal structures ::memset((void*)pending_signals, 0, sizeof(pending_signals)); @@ -3791,12 +3892,14 @@ pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); sigdelset(&suspend_set, SR_signum); + sr_semaphore.signal(); // wait here until we are resumed while (1) { sigsuspend(&suspend_set); os::SuspendResume::State result = osthread->sr.running(); if (result == os::SuspendResume::SR_RUNNING) { + sr_semaphore.signal(); break; } else if (result != os::SuspendResume::SR_SUSPENDED) { ShouldNotReachHere(); @@ -3815,7 +3918,7 @@ } else if (current == os::SuspendResume::SR_WAKEUP_REQUEST) { // ignore } else { - ShouldNotReachHere(); + // ignore } errno = old_errno; @@ -3879,8 +3982,9 @@ // but this seems the normal response to library errors static bool do_suspend(OSThread* osthread) { assert(osthread->sr.is_running(), "thread should be running"); + assert(!sr_semaphore.trywait(), "semaphore has invalid state"); + // mark as suspended and send signal - if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) { // failed to switch, state wasn't running? ShouldNotReachHere(); @@ -3888,35 +3992,22 @@ } if (sr_notify(osthread) != 0) { - // try to cancel, switch to running - - os::SuspendResume::State result = osthread->sr.cancel_suspend(); - if (result == os::SuspendResume::SR_RUNNING) { - // cancelled - return false; - } else if (result == os::SuspendResume::SR_SUSPENDED) { - // somehow managed to suspend - return true; - } else { - ShouldNotReachHere(); - return false; - } + ShouldNotReachHere(); } // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED - - for (int n = 0; !osthread->sr.is_suspended(); n++) { - for (int i = 0; i < RANDOMLY_LARGE_INTEGER2 && !osthread->sr.is_suspended(); i++) { - os::yield_all(i); - } - - // timeout, try to cancel the request - if (n >= RANDOMLY_LARGE_INTEGER) { + while (true) { + if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { + break; + } else { + // timeout os::SuspendResume::State cancelled = osthread->sr.cancel_suspend(); if (cancelled == os::SuspendResume::SR_RUNNING) { return false; } else if (cancelled == os::SuspendResume::SR_SUSPENDED) { - return true; + // make sure that we consume the signal on the semaphore as well + sr_semaphore.wait(); + break; } else { ShouldNotReachHere(); return false; @@ -3930,6 +4021,7 @@ static void do_resume(OSThread* osthread) { assert(osthread->sr.is_suspended(), "thread should be suspended"); + assert(!sr_semaphore.trywait(), "invalid semaphore state"); if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) { // failed to switch to WAKEUP_REQUEST @@ -3937,11 +4029,11 @@ return; } - while (!osthread->sr.is_running()) { + while (true) { if (sr_notify(osthread) == 0) { - for (int n = 0; n < RANDOMLY_LARGE_INTEGER && !osthread->sr.is_running(); n++) { - for (int i = 0; i < 100 && !osthread->sr.is_running(); i++) { - os::yield_all(i); + if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { + if (osthread->sr.is_running()) { + return; } } } else { @@ -5936,3 +6028,4 @@ return n; } +
--- a/src/os/bsd/vm/os_bsd.hpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/os/bsd/vm/os_bsd.hpp Thu Apr 25 08:49:05 2013 -0700 @@ -304,7 +304,7 @@ int TryPark () ; int park (jlong millis) ; void SetAssociation (Thread * a) { _Assoc = a ; } -} ; +}; class PlatformParker : public CHeapObj<mtInternal> { protected: @@ -322,6 +322,6 @@ status = pthread_mutex_init (_mutex, NULL); assert_status(status == 0, status, "mutex_init"); } -} ; +}; #endif // OS_BSD_VM_OS_BSD_HPP
--- a/src/os/linux/vm/os_linux.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/os/linux/vm/os_linux.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -163,6 +163,9 @@ /* Used to protect dlsym() calls */ static pthread_mutex_t dl_mutex; +// Declarations +static void unpackTime(timespec* absTime, bool isAbsolute, jlong time); + #ifdef JAVASE_EMBEDDED class MemNotifyThread: public Thread { friend class VMStructs; @@ -2434,6 +2437,57 @@ return CAST_FROM_FN_PTR(void*, UserHandler); } +class Semaphore : public StackObj { + public: + Semaphore(); + ~Semaphore(); + void signal(); + void wait(); + bool trywait(); + bool timedwait(unsigned int sec, int nsec); + private: + sem_t _semaphore; +}; + + +Semaphore::Semaphore() { + sem_init(&_semaphore, 0, 0); +} + +Semaphore::~Semaphore() { + sem_destroy(&_semaphore); +} + +void Semaphore::signal() { + sem_post(&_semaphore); +} + +void Semaphore::wait() { + sem_wait(&_semaphore); +} + +bool Semaphore::trywait() { + return sem_trywait(&_semaphore) == 0; +} + +bool Semaphore::timedwait(unsigned int sec, int nsec) { + struct timespec ts; + unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); + + while (1) { + int result = sem_timedwait(&_semaphore, &ts); + if (result == 0) { + return true; + } else if (errno == EINTR) { + continue; + } else if (errno == ETIMEDOUT) { + return false; + } else { + return false; + } + } +} + extern "C" { typedef void (*sa_handler_t)(int); typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); @@ -2473,6 +2527,7 @@ // Linux(POSIX) specific hand shaking semaphore. static sem_t sig_sem; +static Semaphore sr_semaphore; void os::signal_init_pd() { // Initialize signal structures @@ -3628,12 +3683,14 @@ pthread_sigmask(SIG_BLOCK, NULL, &suspend_set); sigdelset(&suspend_set, SR_signum); + sr_semaphore.signal(); // wait here until we are resumed while (1) { sigsuspend(&suspend_set); os::SuspendResume::State result = osthread->sr.running(); if (result == os::SuspendResume::SR_RUNNING) { + sr_semaphore.signal(); break; } } @@ -3650,7 +3707,7 @@ } else if (current == os::SuspendResume::SR_WAKEUP_REQUEST) { // ignore } else { - ShouldNotReachHere(); + // ignore } errno = old_errno; @@ -3714,8 +3771,9 @@ // but this seems the normal response to library errors static bool do_suspend(OSThread* osthread) { assert(osthread->sr.is_running(), "thread should be running"); + assert(!sr_semaphore.trywait(), "semaphore has invalid state"); + // mark as suspended and send signal - if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) { // failed to switch, state wasn't running? ShouldNotReachHere(); @@ -3723,35 +3781,22 @@ } if (sr_notify(osthread) != 0) { - // try to cancel, switch to running - - os::SuspendResume::State result = osthread->sr.cancel_suspend(); - if (result == os::SuspendResume::SR_RUNNING) { - // cancelled - return false; - } else if (result == os::SuspendResume::SR_SUSPENDED) { - // somehow managed to suspend - return true; - } else { - ShouldNotReachHere(); - return false; - } + ShouldNotReachHere(); } // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED - - for (int n = 0; !osthread->sr.is_suspended(); n++) { - for (int i = 0; i < RANDOMLY_LARGE_INTEGER2 && !osthread->sr.is_suspended(); i++) { - os::yield_all(i); - } - - // timeout, try to cancel the request - if (n >= RANDOMLY_LARGE_INTEGER) { + while (true) { + if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { + break; + } else { + // timeout os::SuspendResume::State cancelled = osthread->sr.cancel_suspend(); if (cancelled == os::SuspendResume::SR_RUNNING) { return false; } else if (cancelled == os::SuspendResume::SR_SUSPENDED) { - return true; + // make sure that we consume the signal on the semaphore as well + sr_semaphore.wait(); + break; } else { ShouldNotReachHere(); return false; @@ -3765,6 +3810,7 @@ static void do_resume(OSThread* osthread) { assert(osthread->sr.is_suspended(), "thread should be suspended"); + assert(!sr_semaphore.trywait(), "invalid semaphore state"); if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) { // failed to switch to WAKEUP_REQUEST @@ -3772,11 +3818,11 @@ return; } - while (!osthread->sr.is_running()) { + while (true) { if (sr_notify(osthread) == 0) { - for (int n = 0; n < RANDOMLY_LARGE_INTEGER && !osthread->sr.is_running(); n++) { - for (int i = 0; i < 100 && !osthread->sr.is_running(); i++) { - os::yield_all(i); + if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { + if (osthread->sr.is_running()) { + return; } } } else { @@ -5748,4 +5794,5 @@ new MemNotifyThread(fd); } } + #endif // JAVASE_EMBEDDED
--- a/src/os/linux/vm/os_linux.hpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/os/linux/vm/os_linux.hpp Thu Apr 25 08:49:05 2013 -0700 @@ -301,6 +301,6 @@ status = pthread_mutex_init (_mutex, NULL); assert_status(status == 0, status, "mutex_init"); } -} ; +}; #endif // OS_LINUX_VM_OS_LINUX_HPP
--- a/src/os/solaris/vm/osThread_solaris.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/os/solaris/vm/osThread_solaris.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -66,59 +66,6 @@ } } -static void resume_clear_context(OSThread *osthread) { - osthread->set_ucontext(NULL); -} - -static void suspend_save_context(OSThread *osthread, ucontext_t* context) { - osthread->set_ucontext(context); +void OSThread::SR_handler(Thread* thread, ucontext_t* uc) { + os::Solaris::SR_handler(thread, uc); } - -void OSThread::SR_handler(Thread* thread, ucontext_t* uc) { - // Save and restore errno to avoid confusing native code with EINTR - // after sigsuspend. - int old_errno = errno; - - OSThread* osthread = thread->osthread(); - assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread"); - - os::SuspendResume::State current = osthread->sr.state(); - if (current == os::SuspendResume::SR_SUSPEND_REQUEST) { - suspend_save_context(osthread, uc); - - // attempt to switch the state, we assume we had a SUSPEND_REQUEST - os::SuspendResume::State state = osthread->sr.suspended(); - if (state == os::SuspendResume::SR_SUSPENDED) { - sigset_t suspend_set; // signals for sigsuspend() - - // get current set of blocked signals and unblock resume signal - thr_sigsetmask(SIG_BLOCK, NULL, &suspend_set); - sigdelset(&suspend_set, os::Solaris::SIGasync()); - - // wait here until we are resumed - while (1) { - sigsuspend(&suspend_set); - - os::SuspendResume::State result = osthread->sr.running(); - if (result == os::SuspendResume::SR_RUNNING) { - break; - } - } - - } else if (state == os::SuspendResume::SR_RUNNING) { - // request was cancelled, continue - } else { - ShouldNotReachHere(); - } - - resume_clear_context(osthread); - } else if (current == os::SuspendResume::SR_RUNNING) { - // request was cancelled, continue - } else if (current == os::SuspendResume::SR_WAKEUP_REQUEST) { - // ignore - } else { - ShouldNotReachHere(); - } - - errno = old_errno; -}
--- a/src/os/solaris/vm/os_solaris.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/os/solaris/vm/os_solaris.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -247,6 +247,8 @@ static int pthread_cond_default_init(cond_t *cv, int scope, void *arg){ memset(cv, 0, sizeof(cond_t)); return 0; } } +static void unpackTime(timespec* absTime, bool isAbsolute, jlong time); + // Thread Local Storage // This is common to all Solaris platforms so it is defined here, // in this common file. @@ -2604,6 +2606,57 @@ return CAST_FROM_FN_PTR(void*, UserHandler); } +class Semaphore : public StackObj { + public: + Semaphore(); + ~Semaphore(); + void signal(); + void wait(); + bool trywait(); + bool timedwait(unsigned int sec, int nsec); + private: + sema_t _semaphore; +}; + + +Semaphore::Semaphore() { + sema_init(&_semaphore, 0, NULL, NULL); +} + +Semaphore::~Semaphore() { + sema_destroy(&_semaphore); +} + +void Semaphore::signal() { + sema_post(&_semaphore); +} + +void Semaphore::wait() { + sema_wait(&_semaphore); +} + +bool Semaphore::trywait() { + return sema_trywait(&_semaphore) == 0; +} + +bool Semaphore::timedwait(unsigned int sec, int nsec) { + struct timespec ts; + unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); + + while (1) { + int result = sema_timedwait(&_semaphore, &ts); + if (result == 0) { + return true; + } else if (errno == EINTR) { + continue; + } else if (errno == ETIME) { + return false; + } else { + return false; + } + } +} + extern "C" { typedef void (*sa_handler_t)(int); typedef void (*sa_sigaction_t)(int, siginfo_t *, void *); @@ -4188,6 +4241,68 @@ schedctl_start(schedctl_init()); } +static void resume_clear_context(OSThread *osthread) { + osthread->set_ucontext(NULL); +} + +static void suspend_save_context(OSThread *osthread, ucontext_t* context) { + osthread->set_ucontext(context); +} + +static Semaphore sr_semaphore; + +void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) { + // Save and restore errno to avoid confusing native code with EINTR + // after sigsuspend. + int old_errno = errno; + + OSThread* osthread = thread->osthread(); + assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread"); + + os::SuspendResume::State current = osthread->sr.state(); + if (current == os::SuspendResume::SR_SUSPEND_REQUEST) { + suspend_save_context(osthread, uc); + + // attempt to switch the state, we assume we had a SUSPEND_REQUEST + os::SuspendResume::State state = osthread->sr.suspended(); + if (state == os::SuspendResume::SR_SUSPENDED) { + sigset_t suspend_set; // signals for sigsuspend() + + // get current set of blocked signals and unblock resume signal + thr_sigsetmask(SIG_BLOCK, NULL, &suspend_set); + sigdelset(&suspend_set, os::Solaris::SIGasync()); + + sr_semaphore.signal(); + // wait here until we are resumed + while (1) { + sigsuspend(&suspend_set); + + os::SuspendResume::State result = osthread->sr.running(); + if (result == os::SuspendResume::SR_RUNNING) { + sr_semaphore.signal(); + break; + } + } + + } else if (state == os::SuspendResume::SR_RUNNING) { + // request was cancelled, continue + } else { + ShouldNotReachHere(); + } + + resume_clear_context(osthread); + } else if (current == os::SuspendResume::SR_RUNNING) { + // request was cancelled, continue + } else if (current == os::SuspendResume::SR_WAKEUP_REQUEST) { + // ignore + } else { + // ignore + } + + errno = old_errno; +} + + void os::interrupt(Thread* thread) { assert(Thread::current() == thread || Threads_lock->owned_by_self(), "possibility of dangling Thread pointer"); @@ -4285,8 +4400,9 @@ static bool do_suspend(OSThread* osthread) { assert(osthread->sr.is_running(), "thread should be running"); + assert(!sr_semaphore.trywait(), "semaphore has invalid state"); + // mark as suspended and send signal - if (osthread->sr.request_suspend() != os::SuspendResume::SR_SUSPEND_REQUEST) { // failed to switch, state wasn't running? ShouldNotReachHere(); @@ -4294,35 +4410,22 @@ } if (sr_notify(osthread) != 0) { - // try to cancel, switch to running - - os::SuspendResume::State result = osthread->sr.cancel_suspend(); - if (result == os::SuspendResume::SR_RUNNING) { - // cancelled - return false; - } else if (result == os::SuspendResume::SR_SUSPENDED) { - // somehow managed to suspend - return true; - } else { - ShouldNotReachHere(); - return false; - } + ShouldNotReachHere(); } // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED - - for (int n = 0; !osthread->sr.is_suspended(); n++) { - for (int i = 0; i < RANDOMLY_LARGE_INTEGER2 && !osthread->sr.is_suspended(); i++) { - os::yield_all(i); - } - - // timeout, try to cancel the request - if (n >= RANDOMLY_LARGE_INTEGER) { + while (true) { + if (sr_semaphore.timedwait(0, 2000 * NANOSECS_PER_MILLISEC)) { + break; + } else { + // timeout os::SuspendResume::State cancelled = osthread->sr.cancel_suspend(); if (cancelled == os::SuspendResume::SR_RUNNING) { return false; } else if (cancelled == os::SuspendResume::SR_SUSPENDED) { - return true; + // make sure that we consume the signal on the semaphore as well + sr_semaphore.wait(); + break; } else { ShouldNotReachHere(); return false; @@ -4336,6 +4439,7 @@ static void do_resume(OSThread* osthread) { assert(osthread->sr.is_suspended(), "thread should be suspended"); + assert(!sr_semaphore.trywait(), "invalid semaphore state"); if (osthread->sr.request_wakeup() != os::SuspendResume::SR_WAKEUP_REQUEST) { // failed to switch to WAKEUP_REQUEST @@ -4343,11 +4447,11 @@ return; } - while (!osthread->sr.is_running()) { + while (true) { if (sr_notify(osthread) == 0) { - for (int n = 0; n < RANDOMLY_LARGE_INTEGER && !osthread->sr.is_running(); n++) { - for (int i = 0; i < 100 && !osthread->sr.is_running(); i++) { - os::yield_all(i); + if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { + if (osthread->sr.is_running()) { + return; } } } else {
--- a/src/os/solaris/vm/os_solaris.hpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/os/solaris/vm/os_solaris.hpp Thu Apr 25 08:49:05 2013 -0700 @@ -127,7 +127,6 @@ static void set_SIGinterrupt(int newsig) { _SIGinterrupt = newsig; } static void set_SIGasync(int newsig) { _SIGasync = newsig; } - public: // Large Page Support--ISM. static bool largepage_range(char* addr, size_t size); @@ -158,6 +157,8 @@ static void hotspot_sigmask(Thread* thread); + // SR_handler + static void SR_handler(Thread* thread, ucontext_t* uc); protected: // Solaris-specific interface goes here static julong available_memory();
--- a/src/os_cpu/bsd_x86/vm/bsd_x86_64.ad Wed Apr 24 12:20:45 2013 -0700 +++ b/src/os_cpu/bsd_x86/vm/bsd_x86_64.ad Thu Apr 25 08:49:05 2013 -0700 @@ -55,20 +55,6 @@ // adding a syntax that specifies the sizes of fields in an order, // so that the adlc can build the emit functions automagically - enc_class Java_To_Runtime(method meth) %{ - // No relocation needed - - // movq r10, <meth> - emit_opcode(cbuf, Assembler::REX_WB); - emit_opcode(cbuf, 0xB8 | (R10_enc - 8)); - emit_d64(cbuf, (int64_t) $meth$$method); - - // call (r10) - emit_opcode(cbuf, Assembler::REX_B); - emit_opcode(cbuf, 0xFF); - emit_opcode(cbuf, 0xD0 | (R10_enc - 8)); - %} - %} @@ -76,8 +62,4 @@ source %{ -int MachCallRuntimeNode::ret_addr_offset() { - return 13; // movq r10,#addr; callq (r10) -} - %}
--- a/src/os_cpu/linux_x86/vm/linux_x86_64.ad Wed Apr 24 12:20:45 2013 -0700 +++ b/src/os_cpu/linux_x86/vm/linux_x86_64.ad Thu Apr 25 08:49:05 2013 -0700 @@ -55,20 +55,6 @@ // adding a syntax that specifies the sizes of fields in an order, // so that the adlc can build the emit functions automagically - enc_class Java_To_Runtime(method meth) %{ - // No relocation needed - - // movq r10, <meth> - emit_opcode(cbuf, Assembler::REX_WB); - emit_opcode(cbuf, 0xB8 | (R10_enc - 8)); - emit_d64(cbuf, (int64_t) $meth$$method); - - // call (r10) - emit_opcode(cbuf, Assembler::REX_B); - emit_opcode(cbuf, 0xFF); - emit_opcode(cbuf, 0xD0 | (R10_enc - 8)); - %} - %} @@ -76,8 +62,4 @@ source %{ -int MachCallRuntimeNode::ret_addr_offset() { - return 13; // movq r10,#addr; callq (r10) -} - %}
--- a/src/os_cpu/solaris_x86/vm/solaris_x86_64.ad Wed Apr 24 12:20:45 2013 -0700 +++ b/src/os_cpu/solaris_x86/vm/solaris_x86_64.ad Thu Apr 25 08:49:05 2013 -0700 @@ -54,39 +54,10 @@ // main source block for now. In future, we can generalize this by // adding a syntax that specifies the sizes of fields in an order, // so that the adlc can build the emit functions automagically - - enc_class Java_To_Runtime(method meth) %{ - // No relocation needed - - // movq r10, <meth> - emit_opcode(cbuf, Assembler::REX_WB); - emit_opcode(cbuf, 0xB8 | (R10_enc - 8)); - emit_d64(cbuf, (int64_t) $meth$$method); - - // call (r10) - emit_opcode(cbuf, Assembler::REX_B); - emit_opcode(cbuf, 0xFF); - emit_opcode(cbuf, 0xD0 | (R10_enc - 8)); - %} - - enc_class post_call_verify_mxcsr %{ - MacroAssembler _masm(&cbuf); - if (RestoreMXCSROnJNICalls) { - __ ldmxcsr(ExternalAddress(StubRoutines::amd64::mxcsr_std())); - } - else if (CheckJNICalls) { - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::amd64::verify_mxcsr_entry()))); - } - %} %} // Platform dependent source source %{ - -int MachCallRuntimeNode::ret_addr_offset() { - return 13; // movq r10,#addr; callq (r10) -} - %}
--- a/src/os_cpu/windows_x86/vm/windows_x86_64.ad Wed Apr 24 12:20:45 2013 -0700 +++ b/src/os_cpu/windows_x86/vm/windows_x86_64.ad Thu Apr 25 08:49:05 2013 -0700 @@ -53,30 +53,11 @@ // adding a syntax that specifies the sizes of fields in an order, // so that the adlc can build the emit functions automagically - enc_class Java_To_Runtime (method meth) %{ // CALL Java_To_Runtime - // No relocation needed +%} + - // movq r10, <meth> - emit_opcode(cbuf, Assembler::REX_WB); - emit_opcode(cbuf, 0xB8 | (R10_enc - 8)); - emit_d64(cbuf, (int64_t) $meth$$method); +// Platform dependent source - // call (r10) - emit_opcode(cbuf, Assembler::REX_B); - emit_opcode(cbuf, 0xFF); - emit_opcode(cbuf, 0xD0 | (R10_enc - 8)); - %} +source %{ %} - -// -// Platform dependent source -// -source %{ - -int MachCallRuntimeNode::ret_addr_offset() -{ - return 13; // movq r10,#addr; callq (r10) -} - -%}
--- a/src/share/vm/adlc/archDesc.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/adlc/archDesc.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -832,6 +832,7 @@ int length = (int)strlen(rc_name) + (int)strlen(mask) + 5; char *regMask = new char[length]; sprintf(regMask,"%s%s()", rc_name, mask); + delete[] rc_name; return regMask; } }
--- a/src/share/vm/adlc/dfa.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/adlc/dfa.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -191,12 +191,19 @@ // Macro equivalent to: _kids[0]->valid(FOO) && _kids[1]->valid(BAR) // static void child_test(FILE *fp, MatchList &mList) { - if( mList._lchild ) // If left child, check it - fprintf(fp, "STATE__VALID_CHILD(_kids[0], %s)", ArchDesc::getMachOperEnum(mList._lchild)); - if( mList._lchild && mList._rchild ) // If both, add the "&&" - fprintf(fp, " && " ); - if( mList._rchild ) // If right child, check it - fprintf(fp, "STATE__VALID_CHILD(_kids[1], %s)", ArchDesc::getMachOperEnum(mList._rchild)); + if (mList._lchild) { // If left child, check it + const char* lchild_to_upper = ArchDesc::getMachOperEnum(mList._lchild); + fprintf(fp, "STATE__VALID_CHILD(_kids[0], %s)", lchild_to_upper); + delete[] lchild_to_upper; + } + if (mList._lchild && mList._rchild) { // If both, add the "&&" + fprintf(fp, " && "); + } + if (mList._rchild) { // If right child, check it + const char* rchild_to_upper = ArchDesc::getMachOperEnum(mList._rchild); + fprintf(fp, "STATE__VALID_CHILD(_kids[1], %s)", rchild_to_upper); + delete[] rchild_to_upper; + } } //---------------------------calc_cost----------------------------------------- @@ -206,13 +213,17 @@ Expr *ArchDesc::calc_cost(FILE *fp, const char *spaces, MatchList &mList, ProductionState &status) { fprintf(fp, "%sunsigned int c = ", spaces); Expr *c = new Expr("0"); - if (mList._lchild ) { // If left child, add it in - sprintf(Expr::buffer(), "_kids[0]->_cost[%s]", ArchDesc::getMachOperEnum(mList._lchild)); + if (mList._lchild) { // If left child, add it in + const char* lchild_to_upper = ArchDesc::getMachOperEnum(mList._lchild); + sprintf(Expr::buffer(), "_kids[0]->_cost[%s]", lchild_to_upper); c->add(Expr::buffer()); + delete[] lchild_to_upper; } - if (mList._rchild) { // If right child, add it in - sprintf(Expr::buffer(), "_kids[1]->_cost[%s]", ArchDesc::getMachOperEnum(mList._rchild)); + if (mList._rchild) { // If right child, add it in + const char* rchild_to_upper = ArchDesc::getMachOperEnum(mList._rchild); + sprintf(Expr::buffer(), "_kids[1]->_cost[%s]", rchild_to_upper); c->add(Expr::buffer()); + delete[] rchild_to_upper; } // Add in cost of this rule const char *mList_cost = mList.get_cost(); @@ -232,15 +243,17 @@ fprintf(fp, "%s", spaces4); // Only generate child tests if this is not a leaf node bool has_child_constraints = mList._lchild || mList._rchild; - const char *predicate_test = mList.get_pred(); - if( has_child_constraints || predicate_test ) { + const char *predicate_test = mList.get_pred(); + if (has_child_constraints || predicate_test) { // Open the child-and-predicate-test braces fprintf(fp, "if( "); status.set_constraint(hasConstraint); child_test(fp, mList); // Only generate predicate test if one exists for this match - if( predicate_test ) { - if( has_child_constraints ) { fprintf(fp," &&\n"); } + if (predicate_test) { + if (has_child_constraints) { + fprintf(fp," &&\n"); + } fprintf(fp, "%s %s", spaces6, predicate_test); } // End of outer tests
--- a/src/share/vm/adlc/output_c.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/adlc/output_c.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -63,11 +63,10 @@ RegDef *reg_def = NULL; RegDef *next = NULL; registers->reset_RegDefs(); - for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) { + for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) { next = registers->iter_RegDefs(); const char *comma = (next != NULL) ? "," : " // no trailing comma"; - fprintf(fp," \"%s\"%s\n", - reg_def->_regname, comma ); + fprintf(fp," \"%s\"%s\n", reg_def->_regname, comma); } // Finish defining enumeration @@ -79,10 +78,10 @@ reg_def = NULL; next = NULL; registers->reset_RegDefs(); - for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) { + for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) { next = registers->iter_RegDefs(); const char *comma = (next != NULL) ? "," : " // no trailing comma"; - fprintf(fp,"\t%s%s\n", reg_def->_concrete, comma ); + fprintf(fp,"\t%s%s\n", reg_def->_concrete, comma); } // Finish defining array fprintf(fp,"\t};\n"); @@ -104,19 +103,17 @@ RegDef *reg_def = NULL; RegDef *next = NULL; registers->reset_RegDefs(); - for( reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next ) { + for (reg_def = registers->iter_RegDefs(); reg_def != NULL; reg_def = next) { next = registers->iter_RegDefs(); const char* register_encode = reg_def->register_encode(); const char *comma = (next != NULL) ? "," : " // no trailing comma"; int encval; if (!ADLParser::is_int_token(register_encode, encval)) { - fprintf(fp," %s%s // %s\n", - register_encode, comma, reg_def->_regname ); + fprintf(fp," %s%s // %s\n", register_encode, comma, reg_def->_regname); } else { // Output known constants in hex char format (backward compatibility). assert(encval < 256, "Exceeded supported width for register encoding"); - fprintf(fp," (unsigned char)'\\x%X'%s // %s\n", - encval, comma, reg_def->_regname ); + fprintf(fp," (unsigned char)'\\x%X'%s // %s\n", encval, comma, reg_def->_regname); } } // Finish defining enumeration @@ -133,9 +130,10 @@ fprintf(fp,"// Enumeration of register class names\n"); fprintf(fp, "enum machRegisterClass {\n"); registers->_rclasses.reset(); - for( const char *class_name = NULL; - (class_name = registers->_rclasses.iter()) != NULL; ) { - fprintf(fp," %s,\n", toUpper( class_name )); + for (const char *class_name = NULL; (class_name = registers->_rclasses.iter()) != NULL;) { + const char * class_name_to_upper = toUpper(class_name); + fprintf(fp," %s,\n", class_name_to_upper); + delete[] class_name_to_upper; } // Finish defining enumeration fprintf(fp, " _last_Mach_Reg_Class\n"); @@ -148,7 +146,7 @@ void ArchDesc::declare_register_masks(FILE *fp_hpp) { const char *rc_name; - if( _register ) { + if (_register) { // Build enumeration of user-defined register classes. defineRegClassEnum(fp_hpp, _register); @@ -156,24 +154,27 @@ fprintf(fp_hpp,"\n"); fprintf(fp_hpp,"// Register masks, one for each register class.\n"); _register->_rclasses.reset(); - for( rc_name = NULL; - (rc_name = _register->_rclasses.iter()) != NULL; ) { - const char *prefix = ""; - RegClass *reg_class = _register->getRegClass(rc_name); - assert( reg_class, "Using an undefined register class"); + for (rc_name = NULL; (rc_name = _register->_rclasses.iter()) != NULL;) { + const char *prefix = ""; + RegClass *reg_class = _register->getRegClass(rc_name); + assert(reg_class, "Using an undefined register class"); + + const char* rc_name_to_upper = toUpper(rc_name); if (reg_class->_user_defined == NULL) { - fprintf(fp_hpp, "extern const RegMask _%s%s_mask;\n", prefix, toUpper( rc_name ) ); - fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { return _%s%s_mask; }\n", prefix, toUpper( rc_name ), prefix, toUpper( rc_name )); + fprintf(fp_hpp, "extern const RegMask _%s%s_mask;\n", prefix, rc_name_to_upper); + fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { return _%s%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper); } else { - fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { %s }\n", prefix, toUpper( rc_name ), reg_class->_user_defined); + fprintf(fp_hpp, "inline const RegMask &%s%s_mask() { %s }\n", prefix, rc_name_to_upper, reg_class->_user_defined); } - if( reg_class->_stack_or_reg ) { + if (reg_class->_stack_or_reg) { assert(reg_class->_user_defined == NULL, "no user defined reg class here"); - fprintf(fp_hpp, "extern const RegMask _%sSTACK_OR_%s_mask;\n", prefix, toUpper( rc_name ) ); - fprintf(fp_hpp, "inline const RegMask &%sSTACK_OR_%s_mask() { return _%sSTACK_OR_%s_mask; }\n", prefix, toUpper( rc_name ), prefix, toUpper( rc_name ) ); + fprintf(fp_hpp, "extern const RegMask _%sSTACK_OR_%s_mask;\n", prefix, rc_name_to_upper); + fprintf(fp_hpp, "inline const RegMask &%sSTACK_OR_%s_mask() { return _%sSTACK_OR_%s_mask; }\n", prefix, rc_name_to_upper, prefix, rc_name_to_upper); } + delete[] rc_name_to_upper; + } } } @@ -183,34 +184,41 @@ void ArchDesc::build_register_masks(FILE *fp_cpp) { const char *rc_name; - if( _register ) { + if (_register) { // Generate a list of register masks, one for each class. fprintf(fp_cpp,"\n"); fprintf(fp_cpp,"// Register masks, one for each register class.\n"); _register->_rclasses.reset(); - for( rc_name = NULL; - (rc_name = _register->_rclasses.iter()) != NULL; ) { - const char *prefix = ""; - RegClass *reg_class = _register->getRegClass(rc_name); - assert( reg_class, "Using an undefined register class"); - - if (reg_class->_user_defined != NULL) continue; + for (rc_name = NULL; (rc_name = _register->_rclasses.iter()) != NULL;) { + const char *prefix = ""; + RegClass *reg_class = _register->getRegClass(rc_name); + assert(reg_class, "Using an undefined register class"); + + if (reg_class->_user_defined != NULL) { + continue; + } int len = RegisterForm::RegMask_Size(); - fprintf(fp_cpp, "const RegMask _%s%s_mask(", prefix, toUpper( rc_name ) ); - { int i; - for( i = 0; i < len-1; i++ ) - fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,false)); - fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,false)); + const char* rc_name_to_upper = toUpper(rc_name); + fprintf(fp_cpp, "const RegMask _%s%s_mask(", prefix, rc_name_to_upper); + + { + int i; + for(i = 0; i < len - 1; i++) { + fprintf(fp_cpp," 0x%x,", reg_class->regs_in_word(i, false)); + } + fprintf(fp_cpp," 0x%x );\n", reg_class->regs_in_word(i, false)); } - if( reg_class->_stack_or_reg ) { + if (reg_class->_stack_or_reg) { int i; - fprintf(fp_cpp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, toUpper( rc_name ) ); - for( i = 0; i < len-1; i++ ) - fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i,true)); - fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i,true)); + fprintf(fp_cpp, "const RegMask _%sSTACK_OR_%s_mask(", prefix, rc_name_to_upper); + for(i = 0; i < len - 1; i++) { + fprintf(fp_cpp," 0x%x,",reg_class->regs_in_word(i, true)); + } + fprintf(fp_cpp," 0x%x );\n",reg_class->regs_in_word(i, true)); } + delete[] rc_name_to_upper; } } } @@ -2685,7 +2693,9 @@ if (strcmp(first_reg_class, "stack_slots") == 0) { fprintf(fp," return &(Compile::current()->FIRST_STACK_mask());\n"); } else { - fprintf(fp," return &%s_mask();\n", toUpper(first_reg_class)); + const char* first_reg_class_to_upper = toUpper(first_reg_class); + fprintf(fp," return &%s_mask();\n", first_reg_class_to_upper); + delete[] first_reg_class_to_upper; } } else { // Build a switch statement to return the desired mask. @@ -2697,7 +2707,9 @@ if( !strcmp(reg_class, "stack_slots") ) { fprintf(fp, " case %d: return &(Compile::current()->FIRST_STACK_mask());\n", index); } else { - fprintf(fp, " case %d: return &%s_mask();\n", index, toUpper(reg_class)); + const char* reg_class_to_upper = toUpper(reg_class); + fprintf(fp, " case %d: return &%s_mask();\n", index, reg_class_to_upper); + delete[] reg_class_to_upper; } } fprintf(fp," }\n");
--- a/src/share/vm/adlc/output_h.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/adlc/output_h.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -2040,9 +2040,21 @@ void closing() { fprintf(_cpp, " _LAST_MACH_OPER\n"); OutputMap::closing(); } - void map(OpClassForm &opc) { fprintf(_cpp, " %s", _AD.machOperEnum(opc._ident) ); } - void map(OperandForm &oper) { fprintf(_cpp, " %s", _AD.machOperEnum(oper._ident) ); } - void map(char *name) { fprintf(_cpp, " %s", _AD.machOperEnum(name)); } + void map(OpClassForm &opc) { + const char* opc_ident_to_upper = _AD.machOperEnum(opc._ident); + fprintf(_cpp, " %s", opc_ident_to_upper); + delete[] opc_ident_to_upper; + } + void map(OperandForm &oper) { + const char* oper_ident_to_upper = _AD.machOperEnum(oper._ident); + fprintf(_cpp, " %s", oper_ident_to_upper); + delete[] oper_ident_to_upper; + } + void map(char *name) { + const char* name_to_upper = _AD.machOperEnum(name); + fprintf(_cpp, " %s", name_to_upper); + delete[] name_to_upper; + } bool do_instructions() { return false; } void map(InstructForm &inst){ assert( false, "ShouldNotCallThis()"); }
--- a/src/share/vm/classfile/systemDictionary.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/classfile/systemDictionary.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -2026,12 +2026,6 @@ } } - // Assign a classid if one has not already been assigned. The - // counter does not need to be atomically incremented since this - // is only done while holding the SystemDictionary_lock. - // All loaded classes get a unique ID. - TRACE_INIT_ID(k); - // Check for a placeholder. If there, remove it and make a // new system dictionary entry. placeholders()->find_and_remove(p_index, p_hash, name, class_loader, THREAD);
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -533,19 +533,14 @@ _sleep_factor = 0.0; _marking_task_overhead = 1.0; } else { - if (ConcGCThreads > 0) { - // notice that ConcGCThreads overwrites G1MarkingOverheadPercent + if (!FLAG_IS_DEFAULT(ConcGCThreads) && ConcGCThreads > 0) { + // Note: ConcGCThreads has precedence over G1MarkingOverheadPercent // if both are set - - _parallel_marking_threads = (uint) ConcGCThreads; - _max_parallel_marking_threads = _parallel_marking_threads; _sleep_factor = 0.0; _marking_task_overhead = 1.0; } else if (G1MarkingOverheadPercent > 0) { - // we will calculate the number of parallel marking threads - // based on a target overhead with respect to the soft real-time - // goal - + // We will calculate the number of parallel marking threads based + // on a target overhead with respect to the soft real-time goal double marking_overhead = (double) G1MarkingOverheadPercent / 100.0; double overall_cm_overhead = (double) MaxGCPauseMillis * marking_overhead / @@ -558,17 +553,22 @@ double sleep_factor = (1.0 - marking_task_overhead) / marking_task_overhead; - _parallel_marking_threads = (uint) marking_thread_num; - _max_parallel_marking_threads = _parallel_marking_threads; + FLAG_SET_ERGO(uintx, ConcGCThreads, (uint) marking_thread_num); _sleep_factor = sleep_factor; _marking_task_overhead = marking_task_overhead; } else { - _parallel_marking_threads = scale_parallel_threads((uint)ParallelGCThreads); - _max_parallel_marking_threads = _parallel_marking_threads; + // Calculate the number of parallel marking threads by scaling + // the number of parallel GC threads. + uint marking_thread_num = scale_parallel_threads((uint) ParallelGCThreads); + FLAG_SET_ERGO(uintx, ConcGCThreads, marking_thread_num); _sleep_factor = 0.0; _marking_task_overhead = 1.0; } + assert(ConcGCThreads > 0, "Should have been set"); + _parallel_marking_threads = (uint) ConcGCThreads; + _max_parallel_marking_threads = _parallel_marking_threads; + if (parallel_marking_threads() > 1) { _cleanup_task_overhead = 1.0; } else {
--- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -116,7 +116,7 @@ if (G1Log::fine()) { gclog_or_tty->date_stamp(PrintGCDateStamps); gclog_or_tty->stamp(PrintGCTimeStamps); - gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf]", + gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf secs]", scan_end - scan_start); } } @@ -149,7 +149,7 @@ if (G1Log::fine()) { gclog_or_tty->date_stamp(PrintGCDateStamps); gclog_or_tty->stamp(PrintGCTimeStamps); - gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf sec]", + gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf secs]", mark_end_sec - mark_start_sec); } @@ -231,7 +231,7 @@ if (G1Log::fine()) { gclog_or_tty->date_stamp(PrintGCDateStamps); gclog_or_tty->stamp(PrintGCTimeStamps); - gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf]", + gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf secs]", cleanup_end_sec - cleanup_start_sec); } }
--- a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -131,17 +131,23 @@ #ifdef ASSERT +template <> const int WorkerDataArray<int>::_uninitialized = -1; +template <> const double WorkerDataArray<double>::_uninitialized = -1.0; +template <> const size_t WorkerDataArray<size_t>::_uninitialized = (size_t)-1; + template <class T> void WorkerDataArray<T>::reset() { for (uint i = 0; i < _length; i++) { - _data[i] = (T)-1; + _data[i] = (T)_uninitialized; } } template <class T> void WorkerDataArray<T>::verify() { for (uint i = 0; i < _length; i++) { - assert(_data[i] >= (T)0, err_msg("Invalid data for worker %d", i)); + assert(_data[i] != _uninitialized, + err_msg("Invalid data for worker " UINT32_FORMAT ", data: %lf, uninitialized: %lf", + i, (double)_data[i], (double)_uninitialized)); } } @@ -201,20 +207,20 @@ _last_termination_attempts.verify(); _last_gc_worker_end_times_ms.verify(); - for (uint i = 0; i < _active_gc_threads; i++) { - double worker_time = _last_gc_worker_end_times_ms.get(i) - _last_gc_worker_start_times_ms.get(i); - _last_gc_worker_times_ms.set(i, worker_time); + for (uint i = 0; i < _active_gc_threads; i++) { + double worker_time = _last_gc_worker_end_times_ms.get(i) - _last_gc_worker_start_times_ms.get(i); + _last_gc_worker_times_ms.set(i, worker_time); - double worker_known_time = _last_ext_root_scan_times_ms.get(i) + - _last_satb_filtering_times_ms.get(i) + - _last_update_rs_times_ms.get(i) + - _last_scan_rs_times_ms.get(i) + - _last_obj_copy_times_ms.get(i) + - _last_termination_times_ms.get(i); + double worker_known_time = _last_ext_root_scan_times_ms.get(i) + + _last_satb_filtering_times_ms.get(i) + + _last_update_rs_times_ms.get(i) + + _last_scan_rs_times_ms.get(i) + + _last_obj_copy_times_ms.get(i) + + _last_termination_times_ms.get(i); - double worker_other_time = worker_time - worker_known_time; - _last_gc_worker_other_times_ms.set(i, worker_other_time); - } + double worker_other_time = worker_time - worker_known_time; + _last_gc_worker_other_times_ms.set(i, worker_other_time); + } _last_gc_worker_times_ms.verify(); _last_gc_worker_other_times_ms.verify();
--- a/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Thu Apr 25 08:49:05 2013 -0700 @@ -35,6 +35,8 @@ const char* _print_format; bool _print_sum; + NOT_PRODUCT(static const T _uninitialized;) + // We are caching the sum and average to only have to calculate them once. // This is not done in an MT-safe way. It is intended to allow single // threaded code to call sum() and average() multiple times in any order
--- a/src/share/vm/interpreter/linkResolver.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/interpreter/linkResolver.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -227,6 +227,7 @@ TRAPS) { vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name); if (TraceMethodHandles) { + ResourceMark rm(THREAD); tty->print_cr("lookup_polymorphic_method iid=%s %s.%s%s", vmIntrinsics::name_at(iid), klass->external_name(), name->as_C_string(), full_signature->as_C_string()); @@ -241,6 +242,7 @@ TempNewSymbol basic_signature = MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK); if (TraceMethodHandles) { + ResourceMark rm(THREAD); tty->print_cr("lookup_polymorphic_method %s %s => basic %s", name->as_C_string(), full_signature->as_C_string(), @@ -293,6 +295,8 @@ } if (result.not_null()) { #ifdef ASSERT + ResourceMark rm(THREAD); + TempNewSymbol basic_signature = MethodHandles::lookup_basic_type_signature(full_signature, CHECK); int actual_size_of_params = result->size_of_parameters(); @@ -1199,8 +1203,10 @@ Symbol* method_signature = NULL; KlassHandle current_klass; resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); - if (TraceMethodHandles) + if (TraceMethodHandles) { + ResourceMark rm(THREAD); tty->print_cr("resolve_invokehandle %s %s", method_name->as_C_string(), method_signature->as_C_string()); + } resolve_handle_call(result, resolved_klass, method_name, method_signature, current_klass, CHECK); }
--- a/src/share/vm/oops/klass.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/oops/klass.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -159,7 +159,7 @@ kl->set_next_sibling(NULL); kl->set_alloc_count(0); kl->set_alloc_size(0); - TRACE_SET_KLASS_TRACE_ID(kl, 0); + TRACE_INIT_ID(kl); kl->set_prototype_header(markOopDesc::prototype()); kl->set_biased_lock_revocation_count(0);
--- a/src/share/vm/opto/cfgnode.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/opto/cfgnode.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1306,10 +1306,11 @@ return NULL; Node *x = n2; - Node *y = n1->in(1); - if( n2 == n1->in(1) ) { + Node *y = NULL; + if( x == n1->in(1) ) { y = n1->in(2); - } else if( n2 == n1->in(1) ) { + } else if( x == n1->in(2) ) { + y = n1->in(1); } else return NULL; // Not so profitable if compare and add are constants
--- a/src/share/vm/opto/output.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/opto/output.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -449,6 +449,17 @@ int max_loop_pad = nb->code_alignment()-relocInfo::addr_unit(); if (max_loop_pad > 0) { assert(is_power_of_2(max_loop_pad+relocInfo::addr_unit()), ""); + // Adjust last_call_adr and/or last_avoid_back_to_back_adr. + // If either is the last instruction in this block, bump by + // max_loop_pad in lock-step with blk_size, so sizing + // calculations in subsequent blocks still can conservatively + // detect that it may the last instruction in this block. + if (last_call_adr == blk_starts[i]+blk_size) { + last_call_adr += max_loop_pad; + } + if (last_avoid_back_to_back_adr == blk_starts[i]+blk_size) { + last_avoid_back_to_back_adr += max_loop_pad; + } blk_size += max_loop_pad; } } @@ -1194,8 +1205,6 @@ int last_call_offset = -1; int last_avoid_back_to_back_offset = -1; #ifdef ASSERT - int block_alignment_padding = 0; - uint* jmp_target = NEW_RESOURCE_ARRAY(uint,nblocks); uint* jmp_offset = NEW_RESOURCE_ARRAY(uint,nblocks); uint* jmp_size = NEW_RESOURCE_ARRAY(uint,nblocks); @@ -1229,8 +1238,6 @@ Node *delay_slot = NULL; for (uint i=0; i < nblocks; i++) { - guarantee(blk_starts[i] >= (uint)cb->insts_size(),"should not increase size"); - Block *b = _cfg->_blocks[i]; Node *head = b->head(); @@ -1251,14 +1258,6 @@ jmp_offset[i] = 0; jmp_size[i] = 0; jmp_rule[i] = 0; - - // Maximum alignment padding for loop block was used - // during first round of branches shortening, as result - // padding for nodes (sfpt after call) was not added. - // Take this into account for block's size change check - // and allow increase block's size by the difference - // of maximum and actual alignment paddings. - int orig_blk_size = blk_starts[i+1] - blk_starts[i] + block_alignment_padding; #endif int blk_offset = current_offset; @@ -1558,8 +1557,6 @@ } } // End for all instructions in block - assert((uint)blk_offset <= blk_starts[i], "shouldn't increase distance"); - blk_starts[i] = blk_offset; // If the next block is the top of a loop, pad this block out to align // the loop top a little. Helps prevent pipe stalls at loop back branches. @@ -1573,16 +1570,13 @@ nop->emit(*cb, _regalloc); current_offset = cb->insts_size(); } -#ifdef ASSERT - int max_loop_pad = nb->code_alignment()-relocInfo::addr_unit(); - block_alignment_padding = (max_loop_pad - padding); - assert(block_alignment_padding >= 0, "sanity"); -#endif } // Verify that the distance for generated before forward // short branches is still valid. - assert(orig_blk_size >= (current_offset - blk_offset), "shouldn't increase block size"); - + guarantee((int)(blk_starts[i+1] - blk_starts[i]) >= (current_offset - blk_offset), "shouldn't increase block size"); + + // Save new block start offset + blk_starts[i] = blk_offset; } // End of for all blocks blk_starts[nblocks] = current_offset;
--- a/src/share/vm/prims/whitebox.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/prims/whitebox.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -79,45 +79,46 @@ WB_END #endif // !SERIALGC -// Keep track of the 3 allocations in NMTAllocTest so we can free them later -// on and verify that they're not visible anymore -static void* nmtMtTest1 = NULL, *nmtMtTest2 = NULL, *nmtMtTest3 = NULL; - // Alloc memory using the test memory type so that we can use that to see if // NMT picks it up correctly -WB_ENTRY(jboolean, WB_NMTAllocTest(JNIEnv* env)) - void *mem; +WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size)) + jlong addr = 0; - if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { - return false; + if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) { + addr = (jlong)(uintptr_t)os::malloc(size, mtTest); } - // Allocate 2 * 128k + 256k + 1024k and free the 1024k one to make sure we track - // everything correctly. Total should be 512k held alive. - nmtMtTest1 = os::malloc(128 * 1024, mtTest); - mem = os::malloc(1024 * 1024, mtTest); - nmtMtTest2 = os::malloc(256 * 1024, mtTest); - os::free(mem, mtTest); - nmtMtTest3 = os::malloc(128 * 1024, mtTest); - - return true; + return addr; WB_END // Free the memory allocated by NMTAllocTest -WB_ENTRY(jboolean, WB_NMTFreeTestMemory(JNIEnv* env)) +WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem)) + os::free((void*)(uintptr_t)mem, mtTest); +WB_END - if (nmtMtTest1 == NULL || nmtMtTest2 == NULL || nmtMtTest3 == NULL) { - return false; +WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size)) + jlong addr = 0; + + if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) { + addr = (jlong)(uintptr_t)os::reserve_memory(size); + MemTracker::record_virtual_memory_type((address)addr, mtTest); } - os::free(nmtMtTest1, mtTest); - nmtMtTest1 = NULL; - os::free(nmtMtTest2, mtTest); - nmtMtTest2 = NULL; - os::free(nmtMtTest3, mtTest); - nmtMtTest3 = NULL; + return addr; +WB_END + - return true; +WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) + os::commit_memory((char *)(uintptr_t)addr, size); + MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest); +WB_END + +WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) + os::uncommit_memory((char *)(uintptr_t)addr, size); +WB_END + +WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size)) + os::release_memory((char *)(uintptr_t)addr, size); WB_END // Block until the current generation of NMT data to be merged, used to reliably test the NMT feature @@ -196,9 +197,13 @@ {CC"g1NumFreeRegions", CC"()J", (void*)&WB_G1NumFreeRegions }, {CC"g1RegionSize", CC"()I", (void*)&WB_G1RegionSize }, #endif // !SERIALGC - {CC"NMTAllocTest", CC"()Z", (void*)&WB_NMTAllocTest }, - {CC"NMTFreeTestMemory", CC"()Z", (void*)&WB_NMTFreeTestMemory }, - {CC"NMTWaitForDataMerge",CC"()Z", (void*)&WB_NMTWaitForDataMerge}, + {CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc }, + {CC"NMTFree", CC"(J)V", (void*)&WB_NMTFree }, + {CC"NMTReserveMemory", CC"(J)J", (void*)&WB_NMTReserveMemory }, + {CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory }, + {CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory }, + {CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory }, + {CC"NMTWaitForDataMerge", CC"()Z", (void*)&WB_NMTWaitForDataMerge}, }; #undef CC
--- a/src/share/vm/runtime/globals.hpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/runtime/globals.hpp Thu Apr 25 08:49:05 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3616,7 +3616,7 @@ diagnostic(bool, PrintDTraceDOF, false, \ "Print the DTrace DOF passed to the system for JSDT probes") \ \ - product(uintx, StringTableSize, 1009, \ + product(uintx, StringTableSize, NOT_LP64(1009) LP64_ONLY(60013), \ "Number of buckets in the interned String table") \ \ product(bool, UseVMInterruptibleIO, false, \
--- a/src/share/vm/services/runtimeService.cpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/services/runtimeService.cpp Thu Apr 25 08:49:05 2013 -0700 @@ -115,6 +115,8 @@ // Print the time interval in which the app was executing if (PrintGCApplicationConcurrentTime) { + gclog_or_tty->date_stamp(PrintGCDateStamps); + gclog_or_tty->stamp(PrintGCTimeStamps); gclog_or_tty->print_cr("Application time: %3.7f seconds", last_application_time_sec()); } @@ -145,6 +147,8 @@ // Print the time interval for which the app was stopped // during the current safepoint operation. if (PrintGCApplicationStoppedTime) { + gclog_or_tty->date_stamp(PrintGCDateStamps); + gclog_or_tty->stamp(PrintGCTimeStamps); gclog_or_tty->print_cr("Total time for which application threads " "were stopped: %3.7f seconds", last_safepoint_time_sec());
--- a/src/share/vm/trace/trace.xml Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/trace/trace.xml Thu Apr 25 08:49:05 2013 -0700 @@ -138,21 +138,21 @@ </struct> <event id="GCHeapSummary" path="vm/gc/heap/summary" label="Heap Summary" is_instant="true"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> <value type="GCWHEN" field="when" label="When" /> <structvalue type="VirtualSpace" field="heapSpace" label="Heap Space"/> <value type="BYTES64" field="heapUsed" label="Heap Used" description="Bytes allocated by objects in the heap"/> </event> <event id="PermGenSummary" path="vm/gc/heap/perm_gen_summary" label="Perm Gen Summary" is_instant="true"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> <value type="GCWHEN" field="when" label="When" /> <structvalue type="VirtualSpace" field="permSpace" label="PermGen Space"/> <structvalue type="ObjectSpace" field="objectSpace" label="Object Space"/> </event> <event id="PSHeapSummary" path="vm/gc/heap/ps_summary" label="ParallelScavengeHeap Summary" is_instant="true"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> <value type="GCWHEN" field="when" label="When" /> <structvalue type="VirtualSpace" field="oldSpace" label="Old Space"/> @@ -166,7 +166,7 @@ <event id="GCGarbageCollection" path="vm/gc/collector/garbage_collection" label="Garbage Collection" description="Garbage collection performed by the JVM"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID" /> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID" /> <value type="GCNAME" field="name" label="Name" description="The name of the Garbage Collector" /> <value type="GCCAUSE" field="cause" label="Cause" description="The reason for triggering this Garbage Collection" /> <value type="RELATIVE_TICKS" field="sumOfPauses" label="Sum of Pauses" description="Sum of all the times in which Java execution was paused during the garbage collection" /> @@ -175,29 +175,29 @@ <event id="GCParallelOld" path="vm/gc/collector/parold_garbage_collection" label="Parallel Old Garbage Collection" description="Extra information specific to Parallel Old Garbage Collections"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID" /> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID" /> <value type="ADDRESS" field="densePrefix" label="Dense Prefix" description="The address of the dense prefix, used when compacting" /> </event> <event id="GCYoungGarbageCollection" path="vm/gc/collector/young_garbage_collection" label="Young Garbage Collection" description="Extra information specific to Young Garbage Collections"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID" /> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID" /> <value type="UINT" field="tenuringThreshold" label="Tenuring Threshold" /> </event> <event id="GCOldGarbageCollection" path="vm/gc/collector/old_garbage_collection" label="Old Garbage Collection" description="Extra information specific to Old Garbage Collections"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> </event> <event id="GCG1GarbageCollection" path="vm/gc/collector/g1_garbage_collection" label="G1 Garbage Collection" description="Extra information specific to G1 Garbage Collections"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> <value type="G1YCTYPE" field="type" label="Type" /> </event> <event id="EvacuationInfo" path="vm/gc/detailed/evacuation_info" label="Evacuation Info" is_instant="true"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> <value type="UINT" field="cSetRegions" label="Collection Set Regions"/> <value type="BYTES64" field="cSetUsedBefore" label="Collection Set Before" description="Memory usage before GC in the collection set regions"/> <value type="BYTES64" field="cSetUsedAfter" label="Collection Set After" description="Memory usage after GC in the collection set regions"/> @@ -211,11 +211,18 @@ <event id="GCReferenceStatistics" path="vm/gc/reference/statistics" label="GC Reference Processing" is_instant="true" description="Total count of processed references during GC"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> <value type="REFERENCETYPE" field="type" label="Type" /> <value type="ULONG" field="count" label="Total Count" /> </event> + <event id="ObjectCountAfterGC" path="vm/gc/detailed/object_count_after_gc" is_instant="true" label="Object Count After GC"> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID" /> + <value type="CLASS" field="class" label="Class" /> + <value type="LONG" field="count" label="Count" /> + <value type="BYTES64" field="totalSize" label="Total Size" /> + </event> + <struct id="CopyFailed"> <value type="ULONG" field="objectCount" label="Object Count"/> <value type="BYTES64" field="firstSize" label="First Failed Object Size"/> @@ -223,48 +230,41 @@ <value type="BYTES64" field="totalSize" label="Total Object Size"/> </struct> - <event id="ObjectCountAfterGC" path="vm/gc/detailed/object_count_after_gc" is_instant="true" label="Object Count After GC"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID" /> - <value type="CLASS" field="class" label="Class" /> - <value type="LONG" field="count" label="Count" /> - <value type="BYTES64" field="totalSize" label="Total Size" /> - </event> - <event id="PromotionFailed" path="vm/gc/detailed/promotion_failed" label="Promotion Failed" is_instant="true" description="Promotion of an object failed"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> <structvalue type="CopyFailed" field="data" label="data"/> <value type="OSTHREAD" field="thread" label="Running thread"/> </event> <event id="EvacuationFailed" path="vm/gc/detailed/evacuation_failed" label="Evacuation Failed" is_instant="true" description="Evacuation of an object failed"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> <structvalue type="CopyFailed" field="data" label="data"/> </event> <event id="ConcurrentModeFailure" path="vm/gc/detailed/concurrent_mode_failure" label="Concurrent Mode Failure" is_instant="true" description="Concurrent Mode failed"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> </event> <event id="GCPhasePause" path="vm/gc/phases/pause" label="GC Phase Pause"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> <value type="UTF8" field="name" label="Name" /> </event> <event id="GCPhasePauseLevel1" path="vm/gc/phases/pause_level_1" label="GC Phase Pause Level 1"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> <value type="UTF8" field="name" label="Name" /> </event> <event id="GCPhasePauseLevel2" path="vm/gc/phases/pause_level_2" label="GC Phase Pause Level 2"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> <value type="UTF8" field="name" label="Name" /> </event> <event id="GCPhasePauseLevel3" path="vm/gc/phases/pause_level_3" label="GC Phase Pause Level 3"> - <value type="ULONG" field="gcId" label="GC ID" relation="GC_ID"/> + <value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/> <value type="UTF8" field="name" label="Name" /> </event> @@ -273,7 +273,7 @@ <event id="Compilation" path="vm/compiler/compilation" label="Compilation" has_thread="true" is_requestable="false" is_constant="false"> <value type="METHOD" field="method" label="Java Method"/> - <value type="INTEGER" field="compileID" label="Compilation ID" relation="COMP_ID"/> + <value type="UINT" field="compileID" label="Compilation ID" relation="COMP_ID"/> <value type="USHORT" field="compileLevel" label="Compilation Level"/> <value type="BOOLEAN" field="succeded" label="Succeeded"/> <value type="BOOLEAN" field="isOsr" label="On Stack Replacement"/> @@ -284,14 +284,14 @@ <event id="CompilerPhase" path="vm/compiler/phase" label="Compiler Phase" has_thread="true" is_requestable="false" is_constant="false"> <value type="COMPILERPHASETYPE" field="phase" label="Compile Phase"/> - <value type="INTEGER" field="compileID" label="Compilation ID" relation="COMP_ID"/> + <value type="UINT" field="compileID" label="Compilation ID" relation="COMP_ID"/> <value type="USHORT" field="phaseLevel" label="Phase Level"/> </event> <event id="CompilerFailure" path="vm/compiler/failure" label="Compilation Failure" has_thread="true" is_requestable="false" is_constant="false" is_instant="true"> <value type="UTF8" field="failure" label="Message"/> - <value type="INTEGER" field="compileID" label="Compilation ID" relation="COMP_ID"/> + <value type="UINT" field="compileID" label="Compilation ID" relation="COMP_ID"/> </event> <!-- Code sweeper events -->
--- a/src/share/vm/trace/traceMacros.hpp Wed Apr 24 12:20:45 2013 -0700 +++ b/src/share/vm/trace/traceMacros.hpp Thu Apr 25 08:49:05 2013 -0700 @@ -33,7 +33,6 @@ #define TRACE_START() JNI_OK #define TRACE_INITIALIZE() JNI_OK -#define TRACE_SET_KLASS_TRACE_ID(x1, x2) do { } while (0) #define TRACE_DEFINE_KLASS_METHODS typedef int ___IGNORED_hs_trace_type1 #define TRACE_DEFINE_KLASS_TRACE_ID typedef int ___IGNORED_hs_trace_type2 #define TRACE_DEFINE_OFFSET typedef int ___IGNORED_hs_trace_type3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/6443505/Test6443505.java Thu Apr 25 08:49:05 2013 -0700 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 6443505 + * @summary Some cases for CmpLTMask missed; also wrong code. + * + * @run main/othervm -Xcomp -XX:CompileOnly="Test6443505.compiled" Test6443505 + */ + +public class Test6443505 { + + public static void main(String[] args) throws InterruptedException { + test(Integer.MIN_VALUE, 0); + test(0, Integer.MIN_VALUE); + test(Integer.MIN_VALUE, -1); + test(-1, Integer.MIN_VALUE); + test(Integer.MIN_VALUE, 1); + test(1, Integer.MIN_VALUE); + + test(Integer.MAX_VALUE, 0); + test(0, Integer.MAX_VALUE); + test(Integer.MAX_VALUE, -1); + test(-1, Integer.MAX_VALUE); + test(Integer.MAX_VALUE, 1); + test(1, Integer.MAX_VALUE); + + test(Integer.MIN_VALUE, Integer.MAX_VALUE); + test(Integer.MAX_VALUE, Integer.MIN_VALUE); + + test(1, -1); + test(1, 0); + test(1, 1); + test(-1, -1); + test(-1, 0); + test(-1, 1); + test(0, -1); + test(0, 0); + test(0, 1); + } + + public static void test(int a, int b) throws InterruptedException { + int C = compiled(4, a, b); + int I = interpreted(4, a, b); + if (C != I) { + System.err.println("#1 C = " + C + ", I = " + I); + System.err.println("#1 C != I, FAIL"); + System.exit(97); + } + + C = compiled(a, b, q, 4); + I = interpreted(a, b, q, 4); + if (C != I) { + System.err.println("#2 C = " + C + ", I = " + I); + System.err.println("#2 C != I, FAIL"); + System.exit(97); + } + + } + + static int q = 4; + + // If improperly compiled, uses carry/borrow bit, which is wrong. + // with -XX:+PrintOptoAssembly, look for cadd_cmpLTMask + static int compiled(int p, int x, int y) { + return (x < y) ? q + (x - y) : (x - y); + } + + // interpreted reference + static int interpreted(int p, int x, int y) { + return (x < y) ? q + (x - y) : (x - y); + } + + // Test new code with a range of cases + // with -XX:+PrintOptoAssembly, look for and_cmpLTMask + static int compiled(int x, int y, int q, int p) { + return (x < y) ? p + q : q; + } + + // interpreted reference + static int interpreted(int x, int y, int q, int p) { + return (x < y) ? p + q : q; + } + +}
--- a/test/compiler/6863420/Test.java Wed Apr 24 12:20:45 2013 -0700 +++ b/test/compiler/6863420/Test.java Thu Apr 25 08:49:05 2013 -0700 @@ -27,17 +27,35 @@ * @bug 6863420 * @summary os::javaTimeNanos() go backward on Solaris x86 * - * @run main/othervm Test + * Notice the internal timeout in timeout thread Test.TOT. + * @run main/othervm/timeout=300 Test */ public class Test { + + static final int INTERNAL_TIMEOUT=240; + static class TOT extends Thread { + public void run() { + try { + Thread.sleep(INTERNAL_TIMEOUT*1000); + } catch (InterruptedException ex) { + } + done = true; + } + } + static long value = 0; static boolean got_backward_time = false; + static volatile boolean done = false; public static void main(String args[]) { final int count = 100000; - for (int numThreads = 1; numThreads <= 32; numThreads++) { + TOT tot = new TOT(); + tot.setDaemon(true); + tot.start(); + + for (int numThreads = 1; !done && numThreads <= 32; numThreads++) { final int numRuns = 1; for (int t=1; t <= numRuns; t++) { final int curRun = t; @@ -48,7 +66,7 @@ Runnable thread = new Runnable() { public void run() { - for (long l = 0; l < 100000; l++) { + for (long l = 0; !done && l < 100000; l++) { final long start = System.nanoTime(); if (value == 12345678) { System.out.println("Wow!");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8011901/Test8011901.java Thu Apr 25 08:49:05 2013 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8011901 + * @summary instruct xaddL_no_res shouldn't allow 64 bit constants. + * @run main/othervm -XX:-BackgroundCompilation Test8011901 + * + */ + +import java.lang.reflect.*; +import sun.misc.*; + +public class Test8011901 { + + private long ctl; + + private static final sun.misc.Unsafe U; + private static final long CTL; + + static { + try { + Field unsafe = sun.misc.Unsafe.class.getDeclaredField("theUnsafe"); + unsafe.setAccessible(true); + U = (sun.misc.Unsafe) unsafe.get(null); + CTL = U.objectFieldOffset(Test8011901.class.getDeclaredField("ctl")); + } catch (Exception e) { + throw new Error(e); + } + } + + public static void main(String[] args) { + for(int c = 0; c < 20000; c++) { + new Test8011901().makeTest(); + } + System.out.println("Test Passed"); + } + + public static final long EXPECTED = 1L << 42; + + public void makeTest() { + U.getAndAddLong(this, CTL, EXPECTED); + if (ctl != EXPECTED) { + throw new RuntimeException("Test failed. Expected: " + EXPECTED + ", but got = " + ctl); + } + } +}
--- a/test/runtime/NMT/AllocTestType.java Wed Apr 24 12:20:45 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @summary Test consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd - * @key nmt jcmd - * @library /testlibrary /testlibrary/whitebox - * @build AllocTestType - * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail AllocTestType - */ - -import com.oracle.java.testlibrary.*; -import sun.hotspot.WhiteBox; - -public class AllocTestType { - - public static void main(String args[]) throws Exception { - OutputAnalyzer output; - - // Grab my own PID - String pid = Integer.toString(ProcessTools.getProcessId()); - ProcessBuilder pb = new ProcessBuilder(); - - // Use WB API to alloc with the mtTest type - if (!WhiteBox.getWhiteBox().NMTAllocTest()) { - throw new Exception("Call to WB API NMTAllocTest() failed"); - } - - // Use WB API to ensure that all data has been merged before we continue - if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { - throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); - } - - // Run 'jcmd <pid> VM.native_memory summary' - pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); - output = new OutputAnalyzer(pb.start()); - output.shouldContain("Test (reserved=512KB, committed=512KB)"); - - // Free the memory allocated by NMTAllocTest - if (!WhiteBox.getWhiteBox().NMTFreeTestMemory()) { - throw new Exception("Call to WB API NMTFreeTestMemory() failed"); - } - - // Use WB API to ensure that all data has been merged before we continue - if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { - throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); - } - output = new OutputAnalyzer(pb.start()); - output.shouldNotContain("Test (reserved="); - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/MallocTestType.java Thu Apr 25 08:49:05 2013 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Test consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @build MallocTestType + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTestType + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class MallocTestType { + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + WhiteBox wb = WhiteBox.getWhiteBox(); + + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + // Use WB API to alloc and free with the mtTest type + long memAlloc3 = wb.NMTMalloc(128 * 1024); + long memAlloc2 = wb.NMTMalloc(256 * 1024); + wb.NMTFree(memAlloc3); + long memAlloc1 = wb.NMTMalloc(512 * 1024); + wb.NMTFree(memAlloc2); + + // Use WB API to ensure that all data has been merged before we continue + if (!wb.NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + // Run 'jcmd <pid> VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=512KB, committed=512KB)"); + + // Free the memory allocated by NMTAllocTest + wb.NMTFree(memAlloc1); + + // Use WB API to ensure that all data has been merged before we continue + if (!wb.NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + } +}
--- a/test/runtime/NMT/PrintNMTStatistics.java Wed Apr 24 12:20:45 2013 -0700 +++ b/test/runtime/NMT/PrintNMTStatistics.java Thu Apr 25 08:49:05 2013 -0700 @@ -27,7 +27,9 @@ * @bug 8005936 * @summary Make sure PrintNMTStatistics works on normal JVM exit * @library /testlibrary /testlibrary/whitebox - * @run compile PrintNMTStatistics.java + * @build PrintNMTStatistics + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main PrintNMTStatistics */ import com.oracle.java.testlibrary.*; @@ -52,13 +54,15 @@ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-XX:+UnlockDiagnosticVMOptions", + "-Xbootclasspath/a:.", + "-XX:+WhiteBoxAPI", "-XX:NativeMemoryTracking=summary", - "+XX:+PrintNMTStatistics", + "-XX:+PrintNMTStatistics", "PrintNMTStatistics", "test"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldContain("Java Heap (reserved="); + output.shouldContain("Java Heap (reserved="); output.shouldNotContain("error"); output.shouldNotContain("warning"); output.shouldHaveExitValue(0);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/ThreadedMallocTestType.java Thu Apr 25 08:49:05 2013 -0700 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @build ThreadedMallocTestType + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedMallocTestType + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class ThreadedMallocTestType { + public static long memAlloc1; + public static long memAlloc2; + public static long memAlloc3; + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + final WhiteBox wb = WhiteBox.getWhiteBox(); + + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + Thread allocThread = new Thread() { + public void run() { + // Alloc memory using the WB api + memAlloc1 = wb.NMTMalloc(128 * 1024); + memAlloc2 = wb.NMTMalloc(256 * 1024); + memAlloc3 = wb.NMTMalloc(512 * 1024); + } + }; + + allocThread.start(); + allocThread.join(); + + // Use WB API to ensure that all data has been merged before we continue + if (!wb.NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + // Run 'jcmd <pid> VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=896KB, committed=896KB)"); + + Thread freeThread = new Thread() { + public void run() { + // Free the memory allocated by NMTMalloc + wb.NMTFree(memAlloc1); + wb.NMTFree(memAlloc2); + wb.NMTFree(memAlloc3); + } + }; + + freeThread.start(); + freeThread.join(); + + // Use WB API to ensure that all data has been merged before we continue + if (!wb.NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/ThreadedVirtualAllocTestType.java Thu Apr 25 08:49:05 2013 -0700 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @build ThreadedVirtualAllocTestType + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedVirtualAllocTestType + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class ThreadedVirtualAllocTestType { + public static long addr; + public static final WhiteBox wb = WhiteBox.getWhiteBox(); + public static final long commitSize = 128 * 1024; + public static final long reserveSize = 512 * 1024; + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + Thread reserveThread = new Thread() { + public void run() { + addr = wb.NMTReserveMemory(reserveSize); + } + }; + reserveThread.start(); + reserveThread.join(); + + mergeData(); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=512KB, committed=0KB)"); + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 512KB for Test"); + + Thread commitThread = new Thread() { + public void run() { + wb.NMTCommitMemory(addr, commitSize); + } + }; + commitThread.start(); + commitThread.join(); + + mergeData(); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=512KB, committed=128KB)"); + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB"); + + Thread uncommitThread = new Thread() { + public void run() { + wb.NMTUncommitMemory(addr, commitSize); + } + }; + uncommitThread.start(); + uncommitThread.join(); + + mergeData(); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=512KB, committed=0KB)"); + output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed"); + + Thread releaseThread = new Thread() { + public void run() { + wb.NMTReleaseMemory(addr, reserveSize); + } + }; + releaseThread.start(); + releaseThread.join(); + + mergeData(); + + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + output.shouldNotContain("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved"); + } + + public static void mergeData() throws Exception { + // Use WB API to ensure that all data has been merged before we continue + if (!wb.NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/VirtualAllocTestType.java Thu Apr 25 08:49:05 2013 -0700 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Test Reserve/Commit/Uncommit/Release of virtual memory and that we track it correctly + * @key nmt jcmd + * @library /testlibrary /testlibrary/whitebox + * @build VirtualAllocTestType + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail VirtualAllocTestType + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class VirtualAllocTestType { + + public static WhiteBox wb = WhiteBox.getWhiteBox(); + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + long commitSize = 128 * 1024; + long reserveSize = 256 * 1024; + long addr; + + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + addr = wb.NMTReserveMemory(reserveSize); + mergeData(); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=0KB)"); + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved 256KB for Test"); + + wb.NMTCommitMemory(addr, commitSize); + + mergeData(); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=128KB)"); + output.shouldMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed 128KB"); + + wb.NMTUncommitMemory(addr, commitSize); + + mergeData(); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=256KB, committed=0KB)"); + output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed"); + + wb.NMTReleaseMemory(addr, reserveSize); + + mergeData(); + + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved"); + } + + public static void mergeData() throws Exception { + // Use WB API to ensure that all data has been merged before we continue + if (!wb.NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + } +}
--- a/test/testlibrary/OutputAnalyzerTest.java Wed Apr 24 12:20:45 2013 -0700 +++ b/test/testlibrary/OutputAnalyzerTest.java Thu Apr 25 08:49:05 2013 -0700 @@ -36,6 +36,11 @@ String stdout = "aaaaaa"; String stderr = "bbbbbb"; + // Regexps used for testing pattern matching of the test input + String stdoutPattern = "[a]"; + String stderrPattern = "[b]"; + String nonExistingPattern = "[c]"; + OutputAnalyzer output = new OutputAnalyzer(stdout, stderr); if (!stdout.equals(output.getStdout())) { @@ -99,10 +104,73 @@ } try { - output.stderrShouldNotContain(stderr); - throw new Exception("shouldContain() failed to throw exception"); + output.stderrShouldNotContain(stderr); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + // Should match + try { + output.shouldMatch(stdoutPattern); + output.stdoutShouldMatch(stdoutPattern); + output.shouldMatch(stderrPattern); + output.stderrShouldMatch(stderrPattern); + } catch (RuntimeException e) { + throw new Exception("shouldMatch() failed", e); + } + + try { + output.shouldMatch(nonExistingPattern); + throw new Exception("shouldMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldMatch(stderrPattern); + throw new Exception( + "stdoutShouldMatch() failed to throw exception"); } catch (RuntimeException e) { - // expected + // expected + } + + try { + output.stderrShouldMatch(stdoutPattern); + throw new Exception( + "stderrShouldMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + // Should not match + try { + output.shouldNotMatch(nonExistingPattern); + output.stdoutShouldNotMatch(nonExistingPattern); + output.stderrShouldNotMatch(nonExistingPattern); + } catch (RuntimeException e) { + throw new Exception("shouldNotMatch() failed", e); + } + + try { + output.shouldNotMatch(stdoutPattern); + throw new Exception("shouldNotMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldNotMatch(stdoutPattern); + throw new Exception("shouldNotMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldNotMatch(stderrPattern); + throw new Exception("shouldNotMatch() failed to throw exception"); + } catch (RuntimeException e) { + // expected } } }
--- a/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Wed Apr 24 12:20:45 2013 -0700 +++ b/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Thu Apr 25 08:49:05 2013 -0700 @@ -24,6 +24,8 @@ package com.oracle.java.testlibrary; import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public final class OutputAnalyzer { @@ -142,15 +144,112 @@ } /** + * Verify that the stdout and stderr contents of output buffer matches + * the pattern + * + * @param pattern + * @throws RuntimeException If the pattern was not found + */ + public void shouldMatch(String pattern) { + Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (!stdoutMatcher.find() && !stderrMatcher.find()) { + throw new RuntimeException("'" + pattern + + "' missing from stdout/stderr: [" + stdout + stderr + + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer matches the + * pattern + * + * @param pattern + * @throws RuntimeException If the pattern was not found + */ + public void stdoutShouldMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + if (!matcher.find()) { + throw new RuntimeException("'" + pattern + + "' missing from stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer matches the + * pattern + * + * @param pattern + * @throws RuntimeException If the pattern was not found + */ + public void stderrShouldMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (!matcher.find()) { + throw new RuntimeException("'" + pattern + + "' missing from stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout and stderr contents of output buffer does not + * match the pattern + * + * @param pattern + * @throws RuntimeException If the pattern was found + */ + public void shouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + if (matcher.find()) { + throw new RuntimeException("'" + pattern + + "' found in stdout: [" + stdout + "]\n"); + } + matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (matcher.find()) { + throw new RuntimeException("'" + pattern + + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer does not match the + * pattern + * + * @param pattern + * @throws RuntimeException If the pattern was found + */ + public void stdoutShouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + if (matcher.find()) { + throw new RuntimeException("'" + pattern + + "' found in stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer does not match the + * pattern + * + * @param pattern + * @throws RuntimeException If the pattern was found + */ + public void stderrShouldNotMatch(String pattern) { + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (matcher.find()) { + throw new RuntimeException("'" + pattern + + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** * Verifiy the exit value of the process * * @param expectedExitValue Expected exit value from process * @throws RuntimeException If the exit value from the process did not match the expected value */ public void shouldHaveExitValue(int expectedExitValue) { - if (getExitValue() != expectedExitValue) { - throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue); - } + if (getExitValue() != expectedExitValue) { + throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue); + } } /**
--- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Wed Apr 24 12:20:45 2013 -0700 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Thu Apr 25 08:49:05 2013 -0700 @@ -71,7 +71,11 @@ public native Object[] parseCommandLine(String commandline, DiagnosticCommand[] args); // NMT - public native boolean NMTAllocTest(); - public native boolean NMTFreeTestMemory(); + public native long NMTMalloc(long size); + public native void NMTFree(long mem); + public native long NMTReserveMemory(long size); + public native void NMTCommitMemory(long addr, long size); + public native void NMTUncommitMemory(long addr, long size); + public native void NMTReleaseMemory(long addr, long size); public native boolean NMTWaitForDataMerge(); }