Fri, 04 Oct 2013 21:00:43 -0700
Merge
src/share/vm/prims/jvm.cpp | file | annotate | diff | comparison | revisions |
1.1 --- a/agent/src/os/linux/LinuxDebuggerLocal.c Sat Oct 05 03:14:53 2013 +0200 1.2 +++ b/agent/src/os/linux/LinuxDebuggerLocal.c Fri Oct 04 21:00:43 2013 -0700 1.3 @@ -29,6 +29,7 @@ 1.4 #include <sys/types.h> 1.5 #include <sys/stat.h> 1.6 #include <fcntl.h> 1.7 +#include <stdlib.h> 1.8 #include <string.h> 1.9 #include <limits.h> 1.10 1.11 @@ -80,7 +81,7 @@ 1.12 (JNIEnv *env, jclass cls) { 1.13 jclass listClass; 1.14 1.15 - if (init_libproc(getenv("LIBSAPROC_DEBUG")) != true) { 1.16 + if (init_libproc(getenv("LIBSAPROC_DEBUG") != NULL) != true) { 1.17 THROW_NEW_DEBUGGER_EXCEPTION("can't initialize libproc"); 1.18 } 1.19
2.1 --- a/agent/src/os/linux/ps_proc.c Sat Oct 05 03:14:53 2013 +0200 2.2 +++ b/agent/src/os/linux/ps_proc.c Fri Oct 04 21:00:43 2013 -0700 2.3 @@ -27,6 +27,8 @@ 2.4 #include <string.h> 2.5 #include <signal.h> 2.6 #include <errno.h> 2.7 +#include <sys/types.h> 2.8 +#include <sys/wait.h> 2.9 #include <sys/ptrace.h> 2.10 #include "libproc_impl.h" 2.11
3.1 --- a/agent/src/os/linux/salibelf.c Sat Oct 05 03:14:53 2013 +0200 3.2 +++ b/agent/src/os/linux/salibelf.c Fri Oct 04 21:00:43 2013 -0700 3.3 @@ -25,6 +25,7 @@ 3.4 #include "salibelf.h" 3.5 #include <stdlib.h> 3.6 #include <unistd.h> 3.7 +#include <string.h> 3.8 3.9 extern void print_debug(const char*,...); 3.10
4.1 --- a/agent/src/os/linux/symtab.c Sat Oct 05 03:14:53 2013 +0200 4.2 +++ b/agent/src/os/linux/symtab.c Fri Oct 04 21:00:43 2013 -0700 4.3 @@ -305,7 +305,7 @@ 4.4 4.5 unsigned char *bytes 4.6 = (unsigned char*)(note+1) + note->n_namesz; 4.7 - unsigned char *filename 4.8 + char *filename 4.9 = (build_id_to_debug_filename (note->n_descsz, bytes)); 4.10 4.11 fd = pathmap_open(filename);
5.1 --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Sat Oct 05 03:14:53 2013 +0200 5.2 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Fri Oct 04 21:00:43 2013 -0700 5.3 @@ -134,15 +134,13 @@ 5.4 private String type; 5.5 private String name; 5.6 private Address addr; 5.7 - private String kind; 5.8 - private int origin; 5.9 + private int flags; 5.10 5.11 - private Flag(String type, String name, Address addr, String kind, int origin) { 5.12 + private Flag(String type, String name, Address addr, int flags) { 5.13 this.type = type; 5.14 this.name = name; 5.15 this.addr = addr; 5.16 - this.kind = kind; 5.17 - this.origin = origin; 5.18 + this.flags = flags; 5.19 } 5.20 5.21 public String getType() { 5.22 @@ -157,12 +155,8 @@ 5.23 return addr; 5.24 } 5.25 5.26 - public String getKind() { 5.27 - return kind; 5.28 - } 5.29 - 5.30 public int getOrigin() { 5.31 - return origin; 5.32 + return flags & 0xF; // XXX can we get the mask bits from somewhere? 5.33 } 5.34 5.35 public boolean isBool() { 5.36 @@ -173,8 +167,7 @@ 5.37 if (Assert.ASSERTS_ENABLED) { 5.38 Assert.that(isBool(), "not a bool flag!"); 5.39 } 5.40 - return addr.getCIntegerAt(0, boolType.getSize(), boolType.isUnsigned()) 5.41 - != 0; 5.42 + return addr.getCIntegerAt(0, boolType.getSize(), boolType.isUnsigned()) != 0; 5.43 } 5.44 5.45 public boolean isIntx() { 5.46 @@ -843,11 +836,10 @@ 5.47 5.48 Address flagAddr = flagType.getAddressField("flags").getValue(); 5.49 5.50 - AddressField typeFld = flagType.getAddressField("type"); 5.51 - AddressField nameFld = flagType.getAddressField("name"); 5.52 - AddressField addrFld = flagType.getAddressField("addr"); 5.53 - AddressField kindFld = flagType.getAddressField("kind"); 5.54 - CIntField originFld = new CIntField(flagType.getCIntegerField("origin"), 0); 5.55 + AddressField typeFld = flagType.getAddressField("_type"); 5.56 + AddressField nameFld = flagType.getAddressField("_name"); 5.57 + AddressField addrFld = flagType.getAddressField("_addr"); 5.58 + CIntField flagsFld = new CIntField(flagType.getCIntegerField("_flags"), 0); 5.59 5.60 long flagSize = flagType.getSize(); // sizeof(Flag) 5.61 5.62 @@ -856,9 +848,8 @@ 5.63 String type = CStringUtilities.getString(typeFld.getValue(flagAddr)); 5.64 String name = CStringUtilities.getString(nameFld.getValue(flagAddr)); 5.65 Address addr = addrFld.getValue(flagAddr); 5.66 - String kind = CStringUtilities.getString(kindFld.getValue(flagAddr)); 5.67 - int origin = (int)originFld.getValue(flagAddr); 5.68 - commandLineFlags[f] = new Flag(type, name, addr, kind, origin); 5.69 + int flags = (int)flagsFld.getValue(flagAddr); 5.70 + commandLineFlags[f] = new Flag(type, name, addr, flags); 5.71 flagAddr = flagAddr.addOffsetTo(flagSize); 5.72 } 5.73
6.1 --- a/make/bsd/makefiles/gcc.make Sat Oct 05 03:14:53 2013 +0200 6.2 +++ b/make/bsd/makefiles/gcc.make Fri Oct 04 21:00:43 2013 -0700 6.3 @@ -247,7 +247,7 @@ 6.4 6.5 ifeq ($(USE_CLANG), true) 6.6 # However we need to clean the code up before we can unrestrictedly enable this option with Clang 6.7 - WARNINGS_ARE_ERRORS += -Wno-unused-value -Wno-logical-op-parentheses -Wno-parentheses-equality -Wno-parentheses 6.8 + WARNINGS_ARE_ERRORS += -Wno-logical-op-parentheses -Wno-parentheses-equality -Wno-parentheses 6.9 WARNINGS_ARE_ERRORS += -Wno-switch -Wno-tautological-compare 6.10 # Not yet supported by clang in Xcode 4.6.2 6.11 # WARNINGS_ARE_ERRORS += -Wno-tautological-constant-out-of-range-compare 6.12 @@ -262,7 +262,7 @@ 6.13 # conversions which might affect the values. Only enable it in earlier versions. 6.14 WARNING_FLAGS = -Wunused-function 6.15 ifeq ($(USE_CLANG),) 6.16 - WARNINGS_FLAGS += -Wconversion 6.17 + WARNING_FLAGS += -Wconversion 6.18 endif 6.19 endif 6.20
7.1 --- a/make/linux/makefiles/gcc.make Sat Oct 05 03:14:53 2013 +0200 7.2 +++ b/make/linux/makefiles/gcc.make Fri Oct 04 21:00:43 2013 -0700 7.3 @@ -208,7 +208,7 @@ 7.4 7.5 ifeq ($(USE_CLANG), true) 7.6 # However we need to clean the code up before we can unrestrictedly enable this option with Clang 7.7 - WARNINGS_ARE_ERRORS += -Wno-unused-value -Wno-logical-op-parentheses -Wno-parentheses-equality -Wno-parentheses 7.8 + WARNINGS_ARE_ERRORS += -Wno-logical-op-parentheses -Wno-parentheses-equality -Wno-parentheses 7.9 WARNINGS_ARE_ERRORS += -Wno-switch -Wno-tautological-constant-out-of-range-compare -Wno-tautological-compare 7.10 WARNINGS_ARE_ERRORS += -Wno-delete-non-virtual-dtor -Wno-deprecated -Wno-format -Wno-dynamic-class-memaccess 7.11 WARNINGS_ARE_ERRORS += -Wno-return-type -Wno-empty-body
8.1 --- a/src/cpu/sparc/vm/methodHandles_sparc.cpp Sat Oct 05 03:14:53 2013 +0200 8.2 +++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp Fri Oct 04 21:00:43 2013 -0700 8.3 @@ -1,5 +1,5 @@ 8.4 /* 8.5 - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. 8.6 + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. 8.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.8 * 8.9 * This code is free software; you can redistribute it and/or modify it 8.10 @@ -121,6 +121,7 @@ 8.11 8.12 void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register target, Register temp, 8.13 bool for_compiler_entry) { 8.14 + Label L_no_such_method; 8.15 assert(method == G5_method, "interpreter calling convention"); 8.16 assert_different_registers(method, target, temp); 8.17 8.18 @@ -133,6 +134,9 @@ 8.19 const Address interp_only(G2_thread, JavaThread::interp_only_mode_offset()); 8.20 __ ld(interp_only, temp); 8.21 __ cmp_and_br_short(temp, 0, Assembler::zero, Assembler::pt, run_compiled_code); 8.22 + // Null method test is replicated below in compiled case, 8.23 + // it might be able to address across the verify_thread() 8.24 + __ br_null_short(G5_method, Assembler::pn, L_no_such_method); 8.25 __ ld_ptr(G5_method, in_bytes(Method::interpreter_entry_offset()), target); 8.26 __ jmp(target, 0); 8.27 __ delayed()->nop(); 8.28 @@ -141,11 +145,19 @@ 8.29 // it doesn't matter, since this is interpreter code. 8.30 } 8.31 8.32 + // Compiled case, either static or fall-through from runtime conditional 8.33 + __ br_null_short(G5_method, Assembler::pn, L_no_such_method); 8.34 + 8.35 const ByteSize entry_offset = for_compiler_entry ? Method::from_compiled_offset() : 8.36 Method::from_interpreted_offset(); 8.37 __ ld_ptr(G5_method, in_bytes(entry_offset), target); 8.38 __ jmp(target, 0); 8.39 __ delayed()->nop(); 8.40 + 8.41 + __ bind(L_no_such_method); 8.42 + AddressLiteral ame(StubRoutines::throw_AbstractMethodError_entry()); 8.43 + __ jump_to(ame, temp); 8.44 + __ delayed()->nop(); 8.45 } 8.46 8.47 void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm,
9.1 --- a/src/cpu/sparc/vm/sparc.ad Sat Oct 05 03:14:53 2013 +0200 9.2 +++ b/src/cpu/sparc/vm/sparc.ad Fri Oct 04 21:00:43 2013 -0700 9.3 @@ -2018,6 +2018,15 @@ 9.4 return L7_REGP_mask(); 9.5 } 9.6 9.7 +const RegMask Matcher::mathExactI_result_proj_mask() { 9.8 + return G1_REGI_mask(); 9.9 +} 9.10 + 9.11 +const RegMask Matcher::mathExactI_flags_proj_mask() { 9.12 + return INT_FLAGS_mask(); 9.13 +} 9.14 + 9.15 + 9.16 %} 9.17 9.18 9.19 @@ -4245,12 +4254,16 @@ 9.20 greater_equal(0xB); 9.21 less_equal(0x2); 9.22 greater(0xA); 9.23 + overflow(0x7); 9.24 + no_overflow(0xF); 9.25 %} 9.26 %} 9.27 9.28 // Comparison Op, unsigned 9.29 operand cmpOpU() %{ 9.30 match(Bool); 9.31 + predicate(n->as_Bool()->_test._test != BoolTest::overflow && 9.32 + n->as_Bool()->_test._test != BoolTest::no_overflow); 9.33 9.34 format %{ "u" %} 9.35 interface(COND_INTER) %{ 9.36 @@ -4260,12 +4273,16 @@ 9.37 greater_equal(0xD); 9.38 less_equal(0x4); 9.39 greater(0xC); 9.40 + overflow(0x7); 9.41 + no_overflow(0xF); 9.42 %} 9.43 %} 9.44 9.45 // Comparison Op, pointer (same as unsigned) 9.46 operand cmpOpP() %{ 9.47 match(Bool); 9.48 + predicate(n->as_Bool()->_test._test != BoolTest::overflow && 9.49 + n->as_Bool()->_test._test != BoolTest::no_overflow); 9.50 9.51 format %{ "p" %} 9.52 interface(COND_INTER) %{ 9.53 @@ -4275,12 +4292,16 @@ 9.54 greater_equal(0xD); 9.55 less_equal(0x4); 9.56 greater(0xC); 9.57 + overflow(0x7); 9.58 + no_overflow(0xF); 9.59 %} 9.60 %} 9.61 9.62 // Comparison Op, branch-register encoding 9.63 operand cmpOp_reg() %{ 9.64 match(Bool); 9.65 + predicate(n->as_Bool()->_test._test != BoolTest::overflow && 9.66 + n->as_Bool()->_test._test != BoolTest::no_overflow); 9.67 9.68 format %{ "" %} 9.69 interface(COND_INTER) %{ 9.70 @@ -4290,12 +4311,16 @@ 9.71 greater_equal(0x7); 9.72 less_equal (0x2); 9.73 greater (0x6); 9.74 + overflow(0x7); // not supported 9.75 + no_overflow(0xF); // not supported 9.76 %} 9.77 %} 9.78 9.79 // Comparison Code, floating, unordered same as less 9.80 operand cmpOpF() %{ 9.81 match(Bool); 9.82 + predicate(n->as_Bool()->_test._test != BoolTest::overflow && 9.83 + n->as_Bool()->_test._test != BoolTest::no_overflow); 9.84 9.85 format %{ "fl" %} 9.86 interface(COND_INTER) %{ 9.87 @@ -4305,12 +4330,17 @@ 9.88 greater_equal(0xB); 9.89 less_equal(0xE); 9.90 greater(0x6); 9.91 + 9.92 + overflow(0x7); // not supported 9.93 + no_overflow(0xF); // not supported 9.94 %} 9.95 %} 9.96 9.97 // Used by long compare 9.98 operand cmpOp_commute() %{ 9.99 match(Bool); 9.100 + predicate(n->as_Bool()->_test._test != BoolTest::overflow && 9.101 + n->as_Bool()->_test._test != BoolTest::no_overflow); 9.102 9.103 format %{ "" %} 9.104 interface(COND_INTER) %{ 9.105 @@ -4320,6 +4350,8 @@ 9.106 greater_equal(0x2); 9.107 less_equal(0xB); 9.108 greater(0x3); 9.109 + overflow(0x7); 9.110 + no_overflow(0xF); 9.111 %} 9.112 %} 9.113
10.1 --- a/src/cpu/x86/vm/assembler_x86.cpp Sat Oct 05 03:14:53 2013 +0200 10.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp Fri Oct 04 21:00:43 2013 -0700 10.3 @@ -4769,7 +4769,7 @@ 10.4 } 10.5 10.6 void Assembler::adcq(Register dst, Register src) { 10.7 - (int) prefixq_and_encode(dst->encoding(), src->encoding()); 10.8 + (void) prefixq_and_encode(dst->encoding(), src->encoding()); 10.9 emit_arith(0x13, 0xC0, dst, src); 10.10 } 10.11 10.12 @@ -4824,7 +4824,7 @@ 10.13 } 10.14 10.15 void Assembler::andq(Register dst, Register src) { 10.16 - (int) prefixq_and_encode(dst->encoding(), src->encoding()); 10.17 + (void) prefixq_and_encode(dst->encoding(), src->encoding()); 10.18 emit_arith(0x23, 0xC0, dst, src); 10.19 } 10.20
11.1 --- a/src/cpu/x86/vm/methodHandles_x86.cpp Sat Oct 05 03:14:53 2013 +0200 11.2 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Fri Oct 04 21:00:43 2013 -0700 11.3 @@ -114,6 +114,11 @@ 11.4 void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp, 11.5 bool for_compiler_entry) { 11.6 assert(method == rbx, "interpreter calling convention"); 11.7 + 11.8 + Label L_no_such_method; 11.9 + __ testptr(rbx, rbx); 11.10 + __ jcc(Assembler::zero, L_no_such_method); 11.11 + 11.12 __ verify_method_ptr(method); 11.13 11.14 if (!for_compiler_entry && JvmtiExport::can_post_interpreter_events()) { 11.15 @@ -138,6 +143,9 @@ 11.16 const ByteSize entry_offset = for_compiler_entry ? Method::from_compiled_offset() : 11.17 Method::from_interpreted_offset(); 11.18 __ jmp(Address(method, entry_offset)); 11.19 + 11.20 + __ bind(L_no_such_method); 11.21 + __ jump(RuntimeAddress(StubRoutines::throw_AbstractMethodError_entry())); 11.22 } 11.23 11.24 void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm,
12.1 --- a/src/cpu/x86/vm/x86_32.ad Sat Oct 05 03:14:53 2013 +0200 12.2 +++ b/src/cpu/x86/vm/x86_32.ad Fri Oct 04 21:00:43 2013 -0700 12.3 @@ -1534,6 +1534,14 @@ 12.4 return EBP_REG_mask(); 12.5 } 12.6 12.7 +const RegMask Matcher::mathExactI_result_proj_mask() { 12.8 + return EAX_REG_mask(); 12.9 +} 12.10 + 12.11 +const RegMask Matcher::mathExactI_flags_proj_mask() { 12.12 + return INT_FLAGS_mask(); 12.13 +} 12.14 + 12.15 // Returns true if the high 32 bits of the value is known to be zero. 12.16 bool is_operand_hi32_zero(Node* n) { 12.17 int opc = n->Opcode(); 12.18 @@ -4922,6 +4930,8 @@ 12.19 greater_equal(0xD, "ge"); 12.20 less_equal(0xE, "le"); 12.21 greater(0xF, "g"); 12.22 + overflow(0x0, "o"); 12.23 + no_overflow(0x1, "no"); 12.24 %} 12.25 %} 12.26 12.27 @@ -4939,6 +4949,8 @@ 12.28 greater_equal(0x3, "nb"); 12.29 less_equal(0x6, "be"); 12.30 greater(0x7, "nbe"); 12.31 + overflow(0x0, "o"); 12.32 + no_overflow(0x1, "no"); 12.33 %} 12.34 %} 12.35 12.36 @@ -4957,6 +4969,8 @@ 12.37 greater_equal(0x3, "nb"); 12.38 less_equal(0x6, "be"); 12.39 greater(0x7, "nbe"); 12.40 + overflow(0x0, "o"); 12.41 + no_overflow(0x1, "no"); 12.42 %} 12.43 %} 12.44 12.45 @@ -4974,6 +4988,8 @@ 12.46 greater_equal(0x3, "nb"); 12.47 less_equal(0x6, "be"); 12.48 greater(0x7, "nbe"); 12.49 + overflow(0x0, "o"); 12.50 + no_overflow(0x1, "no"); 12.51 %} 12.52 %} 12.53 12.54 @@ -4981,6 +4997,8 @@ 12.55 operand cmpOp_fcmov() %{ 12.56 match(Bool); 12.57 12.58 + predicate(n->as_Bool()->_test._test != BoolTest::overflow && 12.59 + n->as_Bool()->_test._test != BoolTest::no_overflow); 12.60 format %{ "" %} 12.61 interface(COND_INTER) %{ 12.62 equal (0x0C8); 12.63 @@ -4989,6 +5007,8 @@ 12.64 greater_equal(0x1C0); 12.65 less_equal (0x0D0); 12.66 greater (0x1D0); 12.67 + overflow(0x0, "o"); // not really supported by the instruction 12.68 + no_overflow(0x1, "no"); // not really supported by the instruction 12.69 %} 12.70 %} 12.71 12.72 @@ -5004,6 +5024,8 @@ 12.73 greater_equal(0xE, "le"); 12.74 less_equal(0xD, "ge"); 12.75 greater(0xC, "l"); 12.76 + overflow(0x0, "o"); 12.77 + no_overflow(0x1, "no"); 12.78 %} 12.79 %} 12.80 12.81 @@ -7496,6 +7518,31 @@ 12.82 12.83 //----------Arithmetic Instructions-------------------------------------------- 12.84 //----------Addition Instructions---------------------------------------------- 12.85 + 12.86 +instruct addExactI_rReg(eAXRegI dst, rRegI src, eFlagsReg cr) 12.87 +%{ 12.88 + match(AddExactI dst src); 12.89 + effect(DEF cr); 12.90 + 12.91 + format %{ "ADD $dst, $src\t# addExact int" %} 12.92 + ins_encode %{ 12.93 + __ addl($dst$$Register, $src$$Register); 12.94 + %} 12.95 + ins_pipe(ialu_reg_reg); 12.96 +%} 12.97 + 12.98 +instruct addExactI_rReg_imm(eAXRegI dst, immI src, eFlagsReg cr) 12.99 +%{ 12.100 + match(AddExactI dst src); 12.101 + effect(DEF cr); 12.102 + 12.103 + format %{ "ADD $dst, $src\t# addExact int" %} 12.104 + ins_encode %{ 12.105 + __ addl($dst$$Register, $src$$constant); 12.106 + %} 12.107 + ins_pipe(ialu_reg_reg); 12.108 +%} 12.109 + 12.110 // Integer Addition Instructions 12.111 instruct addI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{ 12.112 match(Set dst (AddI dst src));
13.1 --- a/src/cpu/x86/vm/x86_64.ad Sat Oct 05 03:14:53 2013 +0200 13.2 +++ b/src/cpu/x86/vm/x86_64.ad Fri Oct 04 21:00:43 2013 -0700 13.3 @@ -1649,6 +1649,14 @@ 13.4 return PTR_RBP_REG_mask(); 13.5 } 13.6 13.7 +const RegMask Matcher::mathExactI_result_proj_mask() { 13.8 + return INT_RAX_REG_mask(); 13.9 +} 13.10 + 13.11 +const RegMask Matcher::mathExactI_flags_proj_mask() { 13.12 + return INT_FLAGS_mask(); 13.13 +} 13.14 + 13.15 %} 13.16 13.17 //----------ENCODING BLOCK----------------------------------------------------- 13.18 @@ -4133,6 +4141,8 @@ 13.19 greater_equal(0xD, "ge"); 13.20 less_equal(0xE, "le"); 13.21 greater(0xF, "g"); 13.22 + overflow(0x0, "o"); 13.23 + no_overflow(0x1, "no"); 13.24 %} 13.25 %} 13.26 13.27 @@ -4151,6 +4161,8 @@ 13.28 greater_equal(0x3, "nb"); 13.29 less_equal(0x6, "be"); 13.30 greater(0x7, "nbe"); 13.31 + overflow(0x0, "o"); 13.32 + no_overflow(0x1, "no"); 13.33 %} 13.34 %} 13.35 13.36 @@ -4170,6 +4182,8 @@ 13.37 greater_equal(0x3, "nb"); 13.38 less_equal(0x6, "be"); 13.39 greater(0x7, "nbe"); 13.40 + overflow(0x0, "o"); 13.41 + no_overflow(0x1, "no"); 13.42 %} 13.43 %} 13.44 13.45 @@ -4187,6 +4201,8 @@ 13.46 greater_equal(0x3, "nb"); 13.47 less_equal(0x6, "be"); 13.48 greater(0x7, "nbe"); 13.49 + overflow(0x0, "o"); 13.50 + no_overflow(0x1, "no"); 13.51 %} 13.52 %} 13.53 13.54 @@ -6922,6 +6938,30 @@ 13.55 //----------Arithmetic Instructions-------------------------------------------- 13.56 //----------Addition Instructions---------------------------------------------- 13.57 13.58 +instruct addExactI_rReg(rax_RegI dst, rRegI src, rFlagsReg cr) 13.59 +%{ 13.60 + match(AddExactI dst src); 13.61 + effect(DEF cr); 13.62 + 13.63 + format %{ "addl $dst, $src\t# addExact int" %} 13.64 + ins_encode %{ 13.65 + __ addl($dst$$Register, $src$$Register); 13.66 + %} 13.67 + ins_pipe(ialu_reg_reg); 13.68 +%} 13.69 + 13.70 +instruct addExactI_rReg_imm(rax_RegI dst, immI src, rFlagsReg cr) 13.71 +%{ 13.72 + match(AddExactI dst src); 13.73 + effect(DEF cr); 13.74 + 13.75 + format %{ "addl $dst, $src\t# addExact int" %} 13.76 + ins_encode %{ 13.77 + __ addl($dst$$Register, $src$$constant); 13.78 + %} 13.79 + ins_pipe(ialu_reg_reg); 13.80 +%} 13.81 + 13.82 instruct addI_rReg(rRegI dst, rRegI src, rFlagsReg cr) 13.83 %{ 13.84 match(Set dst (AddI dst src));
14.1 --- a/src/share/vm/adlc/adlparse.cpp Sat Oct 05 03:14:53 2013 +0200 14.2 +++ b/src/share/vm/adlc/adlparse.cpp Fri Oct 04 21:00:43 2013 -0700 14.3 @@ -3395,12 +3395,16 @@ 14.4 char *greater_equal; 14.5 char *less_equal; 14.6 char *greater; 14.7 + char *overflow; 14.8 + char *no_overflow; 14.9 const char *equal_format = "eq"; 14.10 const char *not_equal_format = "ne"; 14.11 const char *less_format = "lt"; 14.12 const char *greater_equal_format = "ge"; 14.13 const char *less_equal_format = "le"; 14.14 const char *greater_format = "gt"; 14.15 + const char *overflow_format = "o"; 14.16 + const char *no_overflow_format = "no"; 14.17 14.18 if (_curchar != '%') { 14.19 parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n"); 14.20 @@ -3437,6 +3441,12 @@ 14.21 else if ( strcmp(field,"greater") == 0 ) { 14.22 greater = interface_field_parse(&greater_format); 14.23 } 14.24 + else if ( strcmp(field,"overflow") == 0 ) { 14.25 + overflow = interface_field_parse(&overflow_format); 14.26 + } 14.27 + else if ( strcmp(field,"no_overflow") == 0 ) { 14.28 + no_overflow = interface_field_parse(&no_overflow_format); 14.29 + } 14.30 else { 14.31 parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); 14.32 return NULL; 14.33 @@ -3455,7 +3465,9 @@ 14.34 less, less_format, 14.35 greater_equal, greater_equal_format, 14.36 less_equal, less_equal_format, 14.37 - greater, greater_format); 14.38 + greater, greater_format, 14.39 + overflow, overflow_format, 14.40 + no_overflow, no_overflow_format); 14.41 return inter; 14.42 } 14.43
15.1 --- a/src/share/vm/adlc/archDesc.cpp Sat Oct 05 03:14:53 2013 +0200 15.2 +++ b/src/share/vm/adlc/archDesc.cpp Fri Oct 04 21:00:43 2013 -0700 15.3 @@ -1192,6 +1192,8 @@ 15.4 || strcmp(idealName,"CmpF") == 0 15.5 || strcmp(idealName,"FastLock") == 0 15.6 || strcmp(idealName,"FastUnlock") == 0 15.7 + || strcmp(idealName,"AddExactI") == 0 15.8 + || strcmp(idealName,"FlagsProj") == 0 15.9 || strcmp(idealName,"Bool") == 0 15.10 || strcmp(idealName,"Binary") == 0 ) { 15.11 // Removed ConI from the must_clone list. CPUs that cannot use
16.1 --- a/src/share/vm/adlc/formssel.cpp Sat Oct 05 03:14:53 2013 +0200 16.2 +++ b/src/share/vm/adlc/formssel.cpp Fri Oct 04 21:00:43 2013 -0700 16.3 @@ -2757,14 +2757,18 @@ 16.4 const char* less, const char* less_format, 16.5 const char* greater_equal, const char* greater_equal_format, 16.6 const char* less_equal, const char* less_equal_format, 16.7 - const char* greater, const char* greater_format) 16.8 + const char* greater, const char* greater_format, 16.9 + const char* overflow, const char* overflow_format, 16.10 + const char* no_overflow, const char* no_overflow_format) 16.11 : Interface("COND_INTER"), 16.12 _equal(equal), _equal_format(equal_format), 16.13 _not_equal(not_equal), _not_equal_format(not_equal_format), 16.14 _less(less), _less_format(less_format), 16.15 _greater_equal(greater_equal), _greater_equal_format(greater_equal_format), 16.16 _less_equal(less_equal), _less_equal_format(less_equal_format), 16.17 - _greater(greater), _greater_format(greater_format) { 16.18 + _greater(greater), _greater_format(greater_format), 16.19 + _overflow(overflow), _overflow_format(overflow_format), 16.20 + _no_overflow(no_overflow), _no_overflow_format(no_overflow_format) { 16.21 } 16.22 CondInterface::~CondInterface() { 16.23 // not owner of any character arrays 16.24 @@ -2777,12 +2781,14 @@ 16.25 // Write info to output files 16.26 void CondInterface::output(FILE *fp) { 16.27 Interface::output(fp); 16.28 - if ( _equal != NULL ) fprintf(fp," equal == %s\n", _equal); 16.29 - if ( _not_equal != NULL ) fprintf(fp," not_equal == %s\n", _not_equal); 16.30 - if ( _less != NULL ) fprintf(fp," less == %s\n", _less); 16.31 - if ( _greater_equal != NULL ) fprintf(fp," greater_equal == %s\n", _greater_equal); 16.32 - if ( _less_equal != NULL ) fprintf(fp," less_equal == %s\n", _less_equal); 16.33 - if ( _greater != NULL ) fprintf(fp," greater == %s\n", _greater); 16.34 + if ( _equal != NULL ) fprintf(fp," equal == %s\n", _equal); 16.35 + if ( _not_equal != NULL ) fprintf(fp," not_equal == %s\n", _not_equal); 16.36 + if ( _less != NULL ) fprintf(fp," less == %s\n", _less); 16.37 + if ( _greater_equal != NULL ) fprintf(fp," greater_equal == %s\n", _greater_equal); 16.38 + if ( _less_equal != NULL ) fprintf(fp," less_equal == %s\n", _less_equal); 16.39 + if ( _greater != NULL ) fprintf(fp," greater == %s\n", _greater); 16.40 + if ( _overflow != NULL ) fprintf(fp," overflow == %s\n", _overflow); 16.41 + if ( _no_overflow != NULL ) fprintf(fp," no_overflow == %s\n", _no_overflow); 16.42 // fprintf(fp,"\n"); 16.43 } 16.44
17.1 --- a/src/share/vm/adlc/formssel.hpp Sat Oct 05 03:14:53 2013 +0200 17.2 +++ b/src/share/vm/adlc/formssel.hpp Fri Oct 04 21:00:43 2013 -0700 17.3 @@ -798,12 +798,16 @@ 17.4 const char *_greater_equal; 17.5 const char *_less_equal; 17.6 const char *_greater; 17.7 + const char *_overflow; 17.8 + const char *_no_overflow; 17.9 const char *_equal_format; 17.10 const char *_not_equal_format; 17.11 const char *_less_format; 17.12 const char *_greater_equal_format; 17.13 const char *_less_equal_format; 17.14 const char *_greater_format; 17.15 + const char *_overflow_format; 17.16 + const char *_no_overflow_format; 17.17 17.18 // Public Methods 17.19 CondInterface(const char* equal, const char* equal_format, 17.20 @@ -811,7 +815,9 @@ 17.21 const char* less, const char* less_format, 17.22 const char* greater_equal, const char* greater_equal_format, 17.23 const char* less_equal, const char* less_equal_format, 17.24 - const char* greater, const char* greater_format); 17.25 + const char* greater, const char* greater_format, 17.26 + const char* overflow, const char* overflow_format, 17.27 + const char* no_overflow, const char* no_overflow_format); 17.28 ~CondInterface(); 17.29 17.30 void dump();
18.1 --- a/src/share/vm/adlc/output_h.cpp Sat Oct 05 03:14:53 2013 +0200 18.2 +++ b/src/share/vm/adlc/output_h.cpp Fri Oct 04 21:00:43 2013 -0700 18.3 @@ -388,6 +388,8 @@ 18.4 fprintf(fp, " else if( _c%d == BoolTest::ge ) st->print(\"%s\");\n",i,cond->_greater_equal_format); 18.5 fprintf(fp, " else if( _c%d == BoolTest::lt ) st->print(\"%s\");\n",i,cond->_less_format); 18.6 fprintf(fp, " else if( _c%d == BoolTest::gt ) st->print(\"%s\");\n",i,cond->_greater_format); 18.7 + fprintf(fp, " else if( _c%d == BoolTest::overflow ) st->print(\"%s\");\n",i,cond->_overflow_format); 18.8 + fprintf(fp, " else if( _c%d == BoolTest::no_overflow ) st->print(\"%s\");\n",i,cond->_no_overflow_format); 18.9 } 18.10 18.11 // Output code that dumps constant values, increment "i" if type is constant 18.12 @@ -1208,6 +1210,8 @@ 18.13 fprintf(fp," case BoolTest::ne : return not_equal();\n"); 18.14 fprintf(fp," case BoolTest::le : return less_equal();\n"); 18.15 fprintf(fp," case BoolTest::ge : return greater_equal();\n"); 18.16 + fprintf(fp," case BoolTest::overflow : return overflow();\n"); 18.17 + fprintf(fp," case BoolTest::no_overflow: return no_overflow();\n"); 18.18 fprintf(fp," default : ShouldNotReachHere(); return 0;\n"); 18.19 fprintf(fp," }\n"); 18.20 fprintf(fp," };\n"); 18.21 @@ -1373,6 +1377,14 @@ 18.22 if( greater != NULL ) { 18.23 define_oper_interface(fp, *oper, _globalNames, "greater", greater); 18.24 } 18.25 + const char *overflow = cInterface->_overflow; 18.26 + if( overflow != NULL ) { 18.27 + define_oper_interface(fp, *oper, _globalNames, "overflow", overflow); 18.28 + } 18.29 + const char *no_overflow = cInterface->_no_overflow; 18.30 + if( no_overflow != NULL ) { 18.31 + define_oper_interface(fp, *oper, _globalNames, "no_overflow", no_overflow); 18.32 + } 18.33 } // end Conditional Interface 18.34 // Check if it is a Constant Interface 18.35 else if (oper->_interface->is_ConstInterface() != NULL ) {
19.1 --- a/src/share/vm/c1/c1_Runtime1.cpp Sat Oct 05 03:14:53 2013 +0200 19.2 +++ b/src/share/vm/c1/c1_Runtime1.cpp Fri Oct 04 21:00:43 2013 -0700 19.3 @@ -1078,14 +1078,17 @@ 19.4 // replace instructions 19.5 // first replace the tail, then the call 19.6 #ifdef ARM 19.7 - if(load_klass_or_mirror_patch_id && !VM_Version::supports_movw()) { 19.8 + if((load_klass_or_mirror_patch_id || 19.9 + stub_id == Runtime1::load_appendix_patching_id) && 19.10 + !VM_Version::supports_movw()) { 19.11 nmethod* nm = CodeCache::find_nmethod(instr_pc); 19.12 address addr = NULL; 19.13 assert(nm != NULL, "invalid nmethod_pc"); 19.14 RelocIterator mds(nm, copy_buff, copy_buff + 1); 19.15 while (mds.next()) { 19.16 if (mds.type() == relocInfo::oop_type) { 19.17 - assert(stub_id == Runtime1::load_mirror_patching_id, "wrong stub id"); 19.18 + assert(stub_id == Runtime1::load_mirror_patching_id || 19.19 + stub_id == Runtime1::load_appendix_patching_id, "wrong stub id"); 19.20 oop_Relocation* r = mds.oop_reloc(); 19.21 addr = (address)r->oop_addr(); 19.22 break;
20.1 --- a/src/share/vm/classfile/classFileParser.cpp Sat Oct 05 03:14:53 2013 +0200 20.2 +++ b/src/share/vm/classfile/classFileParser.cpp Fri Oct 04 21:00:43 2013 -0700 20.3 @@ -1787,7 +1787,7 @@ 20.4 if (_location != _in_method) break; // only allow for methods 20.5 if (!privileged) break; // only allow in privileged code 20.6 return _method_LambdaForm_Hidden; 20.7 - case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_invoke_Stable_signature): 20.8 + case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_Stable_signature): 20.9 if (_location != _in_field) break; // only allow for fields 20.10 if (!privileged) break; // only allow in privileged code 20.11 return _field_Stable;
21.1 --- a/src/share/vm/classfile/defaultMethods.cpp Sat Oct 05 03:14:53 2013 +0200 21.2 +++ b/src/share/vm/classfile/defaultMethods.cpp Fri Oct 04 21:00:43 2013 -0700 21.3 @@ -793,7 +793,7 @@ 21.4 21.5 21.6 21.7 -#ifndef PRODUCT 21.8 +#ifdef ASSERT 21.9 // Return true is broad type is a covariant return of narrow type 21.10 static bool covariant_return_type(BasicType narrow, BasicType broad) { 21.11 if (narrow == broad) { 21.12 @@ -804,7 +804,7 @@ 21.13 } 21.14 return false; 21.15 } 21.16 -#endif // ndef PRODUCT 21.17 +#endif 21.18 21.19 static int assemble_redirect( 21.20 BytecodeConstantPool* cp, BytecodeBuffer* buffer, 21.21 @@ -1095,4 +1095,3 @@ 21.22 MetadataFactory::free_array(cld, original_ordering); 21.23 } 21.24 } 21.25 -
22.1 --- a/src/share/vm/classfile/vmSymbols.hpp Sat Oct 05 03:14:53 2013 +0200 22.2 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Oct 04 21:00:43 2013 -0700 22.3 @@ -270,7 +270,7 @@ 22.4 template(java_lang_invoke_LambdaForm, "java/lang/invoke/LambdaForm") \ 22.5 template(java_lang_invoke_ForceInline_signature, "Ljava/lang/invoke/ForceInline;") \ 22.6 template(java_lang_invoke_DontInline_signature, "Ljava/lang/invoke/DontInline;") \ 22.7 - template(sun_invoke_Stable_signature, "Lsun/invoke/Stable;") \ 22.8 + template(java_lang_invoke_Stable_signature, "Ljava/lang/invoke/Stable;") \ 22.9 template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \ 22.10 template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \ 22.11 template(java_lang_invoke_MagicLambdaImpl, "java/lang/invoke/MagicLambdaImpl") \ 22.12 @@ -631,6 +631,10 @@ 22.13 do_name(log_name,"log") do_name(log10_name,"log10") do_name(pow_name,"pow") \ 22.14 do_name(exp_name,"exp") do_name(min_name,"min") do_name(max_name,"max") \ 22.15 \ 22.16 + do_name(addExact_name,"addExact") \ 22.17 + do_name(subtractExact_name,"subtractExact") \ 22.18 + do_name(multiplyExact_name,"multiplyExact") \ 22.19 + \ 22.20 do_intrinsic(_dabs, java_lang_Math, abs_name, double_double_signature, F_S) \ 22.21 do_intrinsic(_dsin, java_lang_Math, sin_name, double_double_signature, F_S) \ 22.22 do_intrinsic(_dcos, java_lang_Math, cos_name, double_double_signature, F_S) \ 22.23 @@ -643,6 +647,7 @@ 22.24 do_intrinsic(_dexp, java_lang_Math, exp_name, double_double_signature, F_S) \ 22.25 do_intrinsic(_min, java_lang_Math, min_name, int2_int_signature, F_S) \ 22.26 do_intrinsic(_max, java_lang_Math, max_name, int2_int_signature, F_S) \ 22.27 + do_intrinsic(_addExact, java_lang_Math, addExact_name, int2_int_signature, F_S) \ 22.28 \ 22.29 do_intrinsic(_floatToRawIntBits, java_lang_Float, floatToRawIntBits_name, float_int_signature, F_S) \ 22.30 do_name( floatToRawIntBits_name, "floatToRawIntBits") \
23.1 --- a/src/share/vm/code/codeCache.cpp Sat Oct 05 03:14:53 2013 +0200 23.2 +++ b/src/share/vm/code/codeCache.cpp Fri Oct 04 21:00:43 2013 -0700 23.3 @@ -124,7 +124,6 @@ 23.4 int CodeCache::_number_of_nmethods_with_dependencies = 0; 23.5 bool CodeCache::_needs_cache_clean = false; 23.6 nmethod* CodeCache::_scavenge_root_nmethods = NULL; 23.7 -nmethod* CodeCache::_saved_nmethods = NULL; 23.8 23.9 int CodeCache::_codemem_full_count = 0; 23.10 23.11 @@ -464,96 +463,11 @@ 23.12 } 23.13 #endif //PRODUCT 23.14 23.15 -/** 23.16 - * Remove and return nmethod from the saved code list in order to reanimate it. 23.17 - */ 23.18 -nmethod* CodeCache::reanimate_saved_code(Method* m) { 23.19 - MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 23.20 - nmethod* saved = _saved_nmethods; 23.21 - nmethod* prev = NULL; 23.22 - while (saved != NULL) { 23.23 - if (saved->is_in_use() && saved->method() == m) { 23.24 - if (prev != NULL) { 23.25 - prev->set_saved_nmethod_link(saved->saved_nmethod_link()); 23.26 - } else { 23.27 - _saved_nmethods = saved->saved_nmethod_link(); 23.28 - } 23.29 - assert(saved->is_speculatively_disconnected(), "shouldn't call for other nmethods"); 23.30 - saved->set_speculatively_disconnected(false); 23.31 - saved->set_saved_nmethod_link(NULL); 23.32 - if (PrintMethodFlushing) { 23.33 - saved->print_on(tty, " ### nmethod is reconnected"); 23.34 - } 23.35 - if (LogCompilation && (xtty != NULL)) { 23.36 - ttyLocker ttyl; 23.37 - xtty->begin_elem("nmethod_reconnected compile_id='%3d'", saved->compile_id()); 23.38 - xtty->method(m); 23.39 - xtty->stamp(); 23.40 - xtty->end_elem(); 23.41 - } 23.42 - return saved; 23.43 - } 23.44 - prev = saved; 23.45 - saved = saved->saved_nmethod_link(); 23.46 - } 23.47 - return NULL; 23.48 -} 23.49 - 23.50 -/** 23.51 - * Remove nmethod from the saved code list in order to discard it permanently 23.52 - */ 23.53 -void CodeCache::remove_saved_code(nmethod* nm) { 23.54 - // For conc swpr this will be called with CodeCache_lock taken by caller 23.55 - assert_locked_or_safepoint(CodeCache_lock); 23.56 - assert(nm->is_speculatively_disconnected(), "shouldn't call for other nmethods"); 23.57 - nmethod* saved = _saved_nmethods; 23.58 - nmethod* prev = NULL; 23.59 - while (saved != NULL) { 23.60 - if (saved == nm) { 23.61 - if (prev != NULL) { 23.62 - prev->set_saved_nmethod_link(saved->saved_nmethod_link()); 23.63 - } else { 23.64 - _saved_nmethods = saved->saved_nmethod_link(); 23.65 - } 23.66 - if (LogCompilation && (xtty != NULL)) { 23.67 - ttyLocker ttyl; 23.68 - xtty->begin_elem("nmethod_removed compile_id='%3d'", nm->compile_id()); 23.69 - xtty->stamp(); 23.70 - xtty->end_elem(); 23.71 - } 23.72 - return; 23.73 - } 23.74 - prev = saved; 23.75 - saved = saved->saved_nmethod_link(); 23.76 - } 23.77 - ShouldNotReachHere(); 23.78 -} 23.79 - 23.80 -void CodeCache::speculatively_disconnect(nmethod* nm) { 23.81 - assert_locked_or_safepoint(CodeCache_lock); 23.82 - assert(nm->is_in_use() && !nm->is_speculatively_disconnected(), "should only disconnect live nmethods"); 23.83 - nm->set_saved_nmethod_link(_saved_nmethods); 23.84 - _saved_nmethods = nm; 23.85 - if (PrintMethodFlushing) { 23.86 - nm->print_on(tty, " ### nmethod is speculatively disconnected"); 23.87 - } 23.88 - if (LogCompilation && (xtty != NULL)) { 23.89 - ttyLocker ttyl; 23.90 - xtty->begin_elem("nmethod_disconnected compile_id='%3d'", nm->compile_id()); 23.91 - xtty->method(nm->method()); 23.92 - xtty->stamp(); 23.93 - xtty->end_elem(); 23.94 - } 23.95 - nm->method()->clear_code(); 23.96 - nm->set_speculatively_disconnected(true); 23.97 -} 23.98 - 23.99 23.100 void CodeCache::gc_prologue() { 23.101 assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_epilogue must be called"); 23.102 } 23.103 23.104 - 23.105 void CodeCache::gc_epilogue() { 23.106 assert_locked_or_safepoint(CodeCache_lock); 23.107 FOR_ALL_ALIVE_BLOBS(cb) {
24.1 --- a/src/share/vm/code/codeCache.hpp Sat Oct 05 03:14:53 2013 +0200 24.2 +++ b/src/share/vm/code/codeCache.hpp Fri Oct 04 21:00:43 2013 -0700 24.3 @@ -57,7 +57,6 @@ 24.4 static int _number_of_nmethods_with_dependencies; 24.5 static bool _needs_cache_clean; 24.6 static nmethod* _scavenge_root_nmethods; // linked via nm->scavenge_root_link() 24.7 - static nmethod* _saved_nmethods; // Linked list of speculatively disconnected nmethods. 24.8 24.9 static void verify_if_often() PRODUCT_RETURN; 24.10 24.11 @@ -167,17 +166,12 @@ 24.12 static size_t capacity() { return _heap->capacity(); } 24.13 static size_t max_capacity() { return _heap->max_capacity(); } 24.14 static size_t unallocated_capacity() { return _heap->unallocated_capacity(); } 24.15 - static bool needs_flushing() { return unallocated_capacity() < CodeCacheFlushingMinimumFreeSpace; } 24.16 static double reverse_free_ratio(); 24.17 24.18 static bool needs_cache_clean() { return _needs_cache_clean; } 24.19 static void set_needs_cache_clean(bool v) { _needs_cache_clean = v; } 24.20 static void clear_inline_caches(); // clear all inline caches 24.21 24.22 - static nmethod* reanimate_saved_code(Method* m); 24.23 - static void remove_saved_code(nmethod* nm); 24.24 - static void speculatively_disconnect(nmethod* nm); 24.25 - 24.26 // Deoptimization 24.27 static int mark_for_deoptimization(DepChange& changes); 24.28 #ifdef HOTSWAP
25.1 --- a/src/share/vm/code/nmethod.cpp Sat Oct 05 03:14:53 2013 +0200 25.2 +++ b/src/share/vm/code/nmethod.cpp Fri Oct 04 21:00:43 2013 -0700 25.3 @@ -462,7 +462,6 @@ 25.4 _state = alive; 25.5 _marked_for_reclamation = 0; 25.6 _has_flushed_dependencies = 0; 25.7 - _speculatively_disconnected = 0; 25.8 _has_unsafe_access = 0; 25.9 _has_method_handle_invokes = 0; 25.10 _lazy_critical_native = 0; 25.11 @@ -481,7 +480,6 @@ 25.12 _osr_link = NULL; 25.13 _scavenge_root_link = NULL; 25.14 _scavenge_root_state = 0; 25.15 - _saved_nmethod_link = NULL; 25.16 _compiler = NULL; 25.17 25.18 #ifdef HAVE_DTRACE_H 25.19 @@ -686,6 +684,7 @@ 25.20 _osr_entry_point = NULL; 25.21 _exception_cache = NULL; 25.22 _pc_desc_cache.reset_to(NULL); 25.23 + _hotness_counter = NMethodSweeper::hotness_counter_reset_val(); 25.24 25.25 code_buffer->copy_values_to(this); 25.26 if (ScavengeRootsInCode && detect_scavenge_root_oops()) { 25.27 @@ -770,6 +769,7 @@ 25.28 _osr_entry_point = NULL; 25.29 _exception_cache = NULL; 25.30 _pc_desc_cache.reset_to(NULL); 25.31 + _hotness_counter = NMethodSweeper::hotness_counter_reset_val(); 25.32 25.33 code_buffer->copy_values_to(this); 25.34 debug_only(verify_scavenge_root_oops()); 25.35 @@ -842,6 +842,7 @@ 25.36 _comp_level = comp_level; 25.37 _compiler = compiler; 25.38 _orig_pc_offset = orig_pc_offset; 25.39 + _hotness_counter = NMethodSweeper::hotness_counter_reset_val(); 25.40 25.41 // Section offsets 25.42 _consts_offset = content_offset() + code_buffer->total_offset_of(code_buffer->consts()); 25.43 @@ -1176,7 +1177,7 @@ 25.44 25.45 // This is a private interface with the sweeper. 25.46 void nmethod::mark_as_seen_on_stack() { 25.47 - assert(is_not_entrant(), "must be a non-entrant method"); 25.48 + assert(is_alive(), "Must be an alive method"); 25.49 // Set the traversal mark to ensure that the sweeper does 2 25.50 // cleaning passes before moving to zombie. 25.51 set_stack_traversal_mark(NMethodSweeper::traversal_count()); 25.52 @@ -1261,7 +1262,7 @@ 25.53 25.54 set_osr_link(NULL); 25.55 //set_scavenge_root_link(NULL); // done by prune_scavenge_root_nmethods 25.56 - NMethodSweeper::notify(this); 25.57 + NMethodSweeper::notify(); 25.58 } 25.59 25.60 void nmethod::invalidate_osr_method() { 25.61 @@ -1351,6 +1352,15 @@ 25.62 nmethod_needs_unregister = true; 25.63 } 25.64 25.65 + // Must happen before state change. Otherwise we have a race condition in 25.66 + // nmethod::can_not_entrant_be_converted(). I.e., a method can immediately 25.67 + // transition its state from 'not_entrant' to 'zombie' without having to wait 25.68 + // for stack scanning. 25.69 + if (state == not_entrant) { 25.70 + mark_as_seen_on_stack(); 25.71 + OrderAccess::storestore(); 25.72 + } 25.73 + 25.74 // Change state 25.75 _state = state; 25.76 25.77 @@ -1369,11 +1379,6 @@ 25.78 HandleMark hm; 25.79 method()->clear_code(); 25.80 } 25.81 - 25.82 - if (state == not_entrant) { 25.83 - mark_as_seen_on_stack(); 25.84 - } 25.85 - 25.86 } // leave critical region under Patching_lock 25.87 25.88 // When the nmethod becomes zombie it is no longer alive so the 25.89 @@ -1416,7 +1421,7 @@ 25.90 } 25.91 25.92 // Make sweeper aware that there is a zombie method that needs to be removed 25.93 - NMethodSweeper::notify(this); 25.94 + NMethodSweeper::notify(); 25.95 25.96 return true; 25.97 } 25.98 @@ -1451,10 +1456,6 @@ 25.99 CodeCache::drop_scavenge_root_nmethod(this); 25.100 } 25.101 25.102 - if (is_speculatively_disconnected()) { 25.103 - CodeCache::remove_saved_code(this); 25.104 - } 25.105 - 25.106 #ifdef SHARK 25.107 ((SharkCompiler *) compiler())->free_compiled_method(insts_begin()); 25.108 #endif // SHARK
26.1 --- a/src/share/vm/code/nmethod.hpp Sat Oct 05 03:14:53 2013 +0200 26.2 +++ b/src/share/vm/code/nmethod.hpp Fri Oct 04 21:00:43 2013 -0700 26.3 @@ -119,7 +119,6 @@ 26.4 // To support simple linked-list chaining of nmethods: 26.5 nmethod* _osr_link; // from InstanceKlass::osr_nmethods_head 26.6 nmethod* _scavenge_root_link; // from CodeCache::scavenge_root_nmethods 26.7 - nmethod* _saved_nmethod_link; // from CodeCache::speculatively_disconnect 26.8 26.9 static nmethod* volatile _oops_do_mark_nmethods; 26.10 nmethod* volatile _oops_do_mark_link; 26.11 @@ -165,7 +164,6 @@ 26.12 26.13 // protected by CodeCache_lock 26.14 bool _has_flushed_dependencies; // Used for maintenance of dependencies (CodeCache_lock) 26.15 - bool _speculatively_disconnected; // Marked for potential unload 26.16 26.17 bool _marked_for_reclamation; // Used by NMethodSweeper (set only by sweeper) 26.18 bool _marked_for_deoptimization; // Used for stack deoptimization 26.19 @@ -180,7 +178,7 @@ 26.20 unsigned int _has_wide_vectors:1; // Preserve wide vectors at safepoints 26.21 26.22 // Protected by Patching_lock 26.23 - unsigned char _state; // {alive, not_entrant, zombie, unloaded} 26.24 + volatile unsigned char _state; // {alive, not_entrant, zombie, unloaded} 26.25 26.26 #ifdef ASSERT 26.27 bool _oops_are_stale; // indicates that it's no longer safe to access oops section 26.28 @@ -202,11 +200,18 @@ 26.29 26.30 // not_entrant method removal. Each mark_sweep pass will update 26.31 // this mark to current sweep invocation count if it is seen on the 26.32 - // stack. An not_entrant method can be removed when there is no 26.33 + // stack. An not_entrant method can be removed when there are no 26.34 // more activations, i.e., when the _stack_traversal_mark is less than 26.35 // current sweep traversal index. 26.36 long _stack_traversal_mark; 26.37 26.38 + // The _hotness_counter indicates the hotness of a method. The higher 26.39 + // the value the hotter the method. The hotness counter of a nmethod is 26.40 + // set to [(ReservedCodeCacheSize / (1024 * 1024)) * 2] each time the method 26.41 + // is active while stack scanning (mark_active_nmethods()). The hotness 26.42 + // counter is decreased (by 1) while sweeping. 26.43 + int _hotness_counter; 26.44 + 26.45 ExceptionCache *_exception_cache; 26.46 PcDescCache _pc_desc_cache; 26.47 26.48 @@ -382,6 +387,10 @@ 26.49 26.50 int total_size () const; 26.51 26.52 + void dec_hotness_counter() { _hotness_counter--; } 26.53 + void set_hotness_counter(int val) { _hotness_counter = val; } 26.54 + int hotness_counter() const { return _hotness_counter; } 26.55 + 26.56 // Containment 26.57 bool consts_contains (address addr) const { return consts_begin () <= addr && addr < consts_end (); } 26.58 bool insts_contains (address addr) const { return insts_begin () <= addr && addr < insts_end (); } 26.59 @@ -408,8 +417,8 @@ 26.60 // alive. It is used when an uncommon trap happens. Returns true 26.61 // if this thread changed the state of the nmethod or false if 26.62 // another thread performed the transition. 26.63 - bool make_not_entrant() { return make_not_entrant_or_zombie(not_entrant); } 26.64 - bool make_zombie() { return make_not_entrant_or_zombie(zombie); } 26.65 + bool make_not_entrant() { return make_not_entrant_or_zombie(not_entrant); } 26.66 + bool make_zombie() { return make_not_entrant_or_zombie(zombie); } 26.67 26.68 // used by jvmti to track if the unload event has been reported 26.69 bool unload_reported() { return _unload_reported; } 26.70 @@ -437,9 +446,6 @@ 26.71 bool has_method_handle_invokes() const { return _has_method_handle_invokes; } 26.72 void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; } 26.73 26.74 - bool is_speculatively_disconnected() const { return _speculatively_disconnected; } 26.75 - void set_speculatively_disconnected(bool z) { _speculatively_disconnected = z; } 26.76 - 26.77 bool is_lazy_critical_native() const { return _lazy_critical_native; } 26.78 void set_lazy_critical_native(bool z) { _lazy_critical_native = z; } 26.79 26.80 @@ -499,9 +505,6 @@ 26.81 nmethod* scavenge_root_link() const { return _scavenge_root_link; } 26.82 void set_scavenge_root_link(nmethod *n) { _scavenge_root_link = n; } 26.83 26.84 - nmethod* saved_nmethod_link() const { return _saved_nmethod_link; } 26.85 - void set_saved_nmethod_link(nmethod *n) { _saved_nmethod_link = n; } 26.86 - 26.87 public: 26.88 26.89 // Sweeper support
27.1 --- a/src/share/vm/compiler/compileBroker.cpp Sat Oct 05 03:14:53 2013 +0200 27.2 +++ b/src/share/vm/compiler/compileBroker.cpp Fri Oct 04 21:00:43 2013 -0700 27.3 @@ -634,19 +634,36 @@ 27.4 NMethodSweeper::possibly_sweep(); 27.5 27.6 MutexLocker locker(lock()); 27.7 - // Wait for an available CompileTask. 27.8 + // If _first is NULL we have no more compile jobs. There are two reasons for 27.9 + // having no compile jobs: First, we compiled everything we wanted. Second, 27.10 + // we ran out of code cache so compilation has been disabled. In the latter 27.11 + // case we perform code cache sweeps to free memory such that we can re-enable 27.12 + // compilation. 27.13 while (_first == NULL) { 27.14 - // There is no work to be done right now. Wait. 27.15 - if (UseCodeCacheFlushing && (!CompileBroker::should_compile_new_jobs() || CodeCache::needs_flushing())) { 27.16 - // During the emergency sweeping periods, wake up and sweep occasionally 27.17 - bool timedout = lock()->wait(!Mutex::_no_safepoint_check_flag, NmethodSweepCheckInterval*1000); 27.18 - if (timedout) { 27.19 + if (UseCodeCacheFlushing && !CompileBroker::should_compile_new_jobs()) { 27.20 + // Wait a certain amount of time to possibly do another sweep. 27.21 + // We must wait until stack scanning has happened so that we can 27.22 + // transition a method's state from 'not_entrant' to 'zombie'. 27.23 + long wait_time = NmethodSweepCheckInterval * 1000; 27.24 + if (FLAG_IS_DEFAULT(NmethodSweepCheckInterval)) { 27.25 + // Only one thread at a time can do sweeping. Scale the 27.26 + // wait time according to the number of compiler threads. 27.27 + // As a result, the next sweep is likely to happen every 100ms 27.28 + // with an arbitrary number of threads that do sweeping. 27.29 + wait_time = 100 * CICompilerCount; 27.30 + } 27.31 + bool timeout = lock()->wait(!Mutex::_no_safepoint_check_flag, wait_time); 27.32 + if (timeout) { 27.33 MutexUnlocker ul(lock()); 27.34 - // When otherwise not busy, run nmethod sweeping 27.35 NMethodSweeper::possibly_sweep(); 27.36 } 27.37 } else { 27.38 - // During normal operation no need to wake up on timer 27.39 + // If there are no compilation tasks and we can compile new jobs 27.40 + // (i.e., there is enough free space in the code cache) there is 27.41 + // no need to invoke the sweeper. As a result, the hotness of methods 27.42 + // remains unchanged. This behavior is desired, since we want to keep 27.43 + // the stable state, i.e., we do not want to evict methods from the 27.44 + // code cache if it is unnecessary. 27.45 lock()->wait(); 27.46 } 27.47 } 27.48 @@ -1227,16 +1244,9 @@ 27.49 return method_code; 27.50 } 27.51 } 27.52 - if (method->is_not_compilable(comp_level)) return NULL; 27.53 - 27.54 - if (UseCodeCacheFlushing) { 27.55 - nmethod* saved = CodeCache::reanimate_saved_code(method()); 27.56 - if (saved != NULL) { 27.57 - method->set_code(method, saved); 27.58 - return saved; 27.59 - } 27.60 + if (method->is_not_compilable(comp_level)) { 27.61 + return NULL; 27.62 } 27.63 - 27.64 } else { 27.65 // osr compilation 27.66 #ifndef TIERED 27.67 @@ -1585,9 +1595,6 @@ 27.68 if (CodeCache::unallocated_capacity() < CodeCacheMinimumFreeSpace) { 27.69 // the code cache is really full 27.70 handle_full_code_cache(); 27.71 - } else if (UseCodeCacheFlushing && CodeCache::needs_flushing()) { 27.72 - // Attempt to start cleaning the code cache while there is still a little headroom 27.73 - NMethodSweeper::handle_full_code_cache(false); 27.74 } 27.75 27.76 CompileTask* task = queue->get(); 27.77 @@ -1943,7 +1950,11 @@ 27.78 } 27.79 #endif 27.80 if (UseCodeCacheFlushing) { 27.81 - NMethodSweeper::handle_full_code_cache(true); 27.82 + // Since code cache is full, immediately stop new compiles 27.83 + if (CompileBroker::set_should_compile_new_jobs(CompileBroker::stop_compilation)) { 27.84 + NMethodSweeper::log_sweep("disable_compiler"); 27.85 + NMethodSweeper::possibly_sweep(); 27.86 + } 27.87 } else { 27.88 UseCompiler = false; 27.89 AlwaysCompileLoopMethods = false;
28.1 --- a/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Sat Oct 05 03:14:53 2013 +0200 28.2 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp Fri Oct 04 21:00:43 2013 -0700 28.3 @@ -81,7 +81,7 @@ 28.4 size_t* marked_bytes_array, 28.5 BitMap* task_card_bm) { 28.6 G1CollectedHeap* g1h = _g1h; 28.7 - CardTableModRefBS* ct_bs = (CardTableModRefBS*) (g1h->barrier_set()); 28.8 + CardTableModRefBS* ct_bs = g1h->g1_barrier_set(); 28.9 28.10 HeapWord* start = mr.start(); 28.11 HeapWord* end = mr.end();
29.1 --- a/src/share/vm/gc_implementation/g1/g1CardCounts.cpp Sat Oct 05 03:14:53 2013 +0200 29.2 +++ b/src/share/vm/gc_implementation/g1/g1CardCounts.cpp Fri Oct 04 21:00:43 2013 -0700 29.3 @@ -65,9 +65,7 @@ 29.4 // threshold limit is no more than this. 29.5 guarantee(G1ConcRSHotCardLimit <= max_jubyte, "sanity"); 29.6 29.7 - ModRefBarrierSet* bs = _g1h->mr_bs(); 29.8 - guarantee(bs->is_a(BarrierSet::CardTableModRef), "Precondition"); 29.9 - _ct_bs = (CardTableModRefBS*)bs; 29.10 + _ct_bs = _g1h->g1_barrier_set(); 29.11 _ct_bot = _ct_bs->byte_for_const(_g1h->reserved_region().start()); 29.12 29.13 // Allocate/Reserve the counts table
30.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Sat Oct 05 03:14:53 2013 +0200 30.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Oct 04 21:00:43 2013 -0700 30.3 @@ -125,10 +125,8 @@ 30.4 int _histo[256]; 30.5 public: 30.6 ClearLoggedCardTableEntryClosure() : 30.7 - _calls(0) 30.8 + _calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set()) 30.9 { 30.10 - _g1h = G1CollectedHeap::heap(); 30.11 - _ctbs = (CardTableModRefBS*)_g1h->barrier_set(); 30.12 for (int i = 0; i < 256; i++) _histo[i] = 0; 30.13 } 30.14 bool do_card_ptr(jbyte* card_ptr, int worker_i) { 30.15 @@ -158,11 +156,8 @@ 30.16 CardTableModRefBS* _ctbs; 30.17 public: 30.18 RedirtyLoggedCardTableEntryClosure() : 30.19 - _calls(0) 30.20 - { 30.21 - _g1h = G1CollectedHeap::heap(); 30.22 - _ctbs = (CardTableModRefBS*)_g1h->barrier_set(); 30.23 - } 30.24 + _calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set()) {} 30.25 + 30.26 bool do_card_ptr(jbyte* card_ptr, int worker_i) { 30.27 if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) { 30.28 _calls++; 30.29 @@ -478,7 +473,7 @@ 30.30 30.31 void G1CollectedHeap::check_ct_logs_at_safepoint() { 30.32 DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); 30.33 - CardTableModRefBS* ct_bs = (CardTableModRefBS*)barrier_set(); 30.34 + CardTableModRefBS* ct_bs = g1_barrier_set(); 30.35 30.36 // Count the dirty cards at the start. 30.37 CountNonCleanMemRegionClosure count1(this); 30.38 @@ -1205,7 +1200,7 @@ 30.39 }; 30.40 30.41 void G1CollectedHeap::clear_rsets_post_compaction() { 30.42 - PostMCRemSetClearClosure rs_clear(this, mr_bs()); 30.43 + PostMCRemSetClearClosure rs_clear(this, g1_barrier_set()); 30.44 heap_region_iterate(&rs_clear); 30.45 } 30.46 30.47 @@ -1777,7 +1772,6 @@ 30.48 } 30.49 30.50 bool G1CollectedHeap::expand(size_t expand_bytes) { 30.51 - size_t old_mem_size = _g1_storage.committed_size(); 30.52 size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes); 30.53 aligned_expand_bytes = align_size_up(aligned_expand_bytes, 30.54 HeapRegion::GrainBytes); 30.55 @@ -1787,6 +1781,13 @@ 30.56 ergo_format_byte("attempted expansion amount"), 30.57 expand_bytes, aligned_expand_bytes); 30.58 30.59 + if (_g1_storage.uncommitted_size() == 0) { 30.60 + ergo_verbose0(ErgoHeapSizing, 30.61 + "did not expand the heap", 30.62 + ergo_format_reason("heap already fully expanded")); 30.63 + return false; 30.64 + } 30.65 + 30.66 // First commit the memory. 30.67 HeapWord* old_end = (HeapWord*) _g1_storage.high(); 30.68 bool successful = _g1_storage.expand_by(aligned_expand_bytes); 30.69 @@ -1845,7 +1846,6 @@ 30.70 } 30.71 30.72 void G1CollectedHeap::shrink_helper(size_t shrink_bytes) { 30.73 - size_t old_mem_size = _g1_storage.committed_size(); 30.74 size_t aligned_shrink_bytes = 30.75 ReservedSpace::page_align_size_down(shrink_bytes); 30.76 aligned_shrink_bytes = align_size_down(aligned_shrink_bytes, 30.77 @@ -2045,20 +2045,13 @@ 30.78 // Create the gen rem set (and barrier set) for the entire reserved region. 30.79 _rem_set = collector_policy()->create_rem_set(_reserved, 2); 30.80 set_barrier_set(rem_set()->bs()); 30.81 - if (barrier_set()->is_a(BarrierSet::ModRef)) { 30.82 - _mr_bs = (ModRefBarrierSet*)_barrier_set; 30.83 - } else { 30.84 - vm_exit_during_initialization("G1 requires a mod ref bs."); 30.85 + if (!barrier_set()->is_a(BarrierSet::G1SATBCTLogging)) { 30.86 + vm_exit_during_initialization("G1 requires a G1SATBLoggingCardTableModRefBS"); 30.87 return JNI_ENOMEM; 30.88 } 30.89 30.90 // Also create a G1 rem set. 30.91 - if (mr_bs()->is_a(BarrierSet::CardTableModRef)) { 30.92 - _g1_rem_set = new G1RemSet(this, (CardTableModRefBS*)mr_bs()); 30.93 - } else { 30.94 - vm_exit_during_initialization("G1 requires a cardtable mod ref bs."); 30.95 - return JNI_ENOMEM; 30.96 - } 30.97 + _g1_rem_set = new G1RemSet(this, g1_barrier_set()); 30.98 30.99 // Carve out the G1 part of the heap. 30.100 30.101 @@ -3681,6 +3674,11 @@ 30.102 assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); 30.103 // Fill TLAB's and such 30.104 ensure_parsability(true); 30.105 + 30.106 + if (G1SummarizeRSetStats && (G1SummarizeRSetStatsPeriod > 0) && 30.107 + (total_collections() % G1SummarizeRSetStatsPeriod == 0)) { 30.108 + g1_rem_set()->print_periodic_summary_info("Before GC RS summary"); 30.109 + } 30.110 } 30.111 30.112 void G1CollectedHeap::gc_epilogue(bool full /* Ignored */) { 30.113 @@ -3689,7 +3687,7 @@ 30.114 (G1SummarizeRSetStatsPeriod > 0) && 30.115 // we are at the end of the GC. Total collections has already been increased. 30.116 ((total_collections() - 1) % G1SummarizeRSetStatsPeriod == 0)) { 30.117 - g1_rem_set()->print_periodic_summary_info(); 30.118 + g1_rem_set()->print_periodic_summary_info("After GC RS summary"); 30.119 } 30.120 30.121 // FIXME: what is this about? 30.122 @@ -4550,7 +4548,7 @@ 30.123 : _g1h(g1h), 30.124 _refs(g1h->task_queue(queue_num)), 30.125 _dcq(&g1h->dirty_card_queue_set()), 30.126 - _ct_bs((CardTableModRefBS*)_g1h->barrier_set()), 30.127 + _ct_bs(g1h->g1_barrier_set()), 30.128 _g1_rem(g1h->g1_rem_set()), 30.129 _hash_seed(17), _queue_num(queue_num), 30.130 _term_attempts(0), 30.131 @@ -5979,11 +5977,11 @@ 30.132 } 30.133 30.134 class G1ParCleanupCTTask : public AbstractGangTask { 30.135 - CardTableModRefBS* _ct_bs; 30.136 + G1SATBCardTableModRefBS* _ct_bs; 30.137 G1CollectedHeap* _g1h; 30.138 HeapRegion* volatile _su_head; 30.139 public: 30.140 - G1ParCleanupCTTask(CardTableModRefBS* ct_bs, 30.141 + G1ParCleanupCTTask(G1SATBCardTableModRefBS* ct_bs, 30.142 G1CollectedHeap* g1h) : 30.143 AbstractGangTask("G1 Par Cleanup CT Task"), 30.144 _ct_bs(ct_bs), _g1h(g1h) { } 30.145 @@ -6006,9 +6004,9 @@ 30.146 #ifndef PRODUCT 30.147 class G1VerifyCardTableCleanup: public HeapRegionClosure { 30.148 G1CollectedHeap* _g1h; 30.149 - CardTableModRefBS* _ct_bs; 30.150 + G1SATBCardTableModRefBS* _ct_bs; 30.151 public: 30.152 - G1VerifyCardTableCleanup(G1CollectedHeap* g1h, CardTableModRefBS* ct_bs) 30.153 + G1VerifyCardTableCleanup(G1CollectedHeap* g1h, G1SATBCardTableModRefBS* ct_bs) 30.154 : _g1h(g1h), _ct_bs(ct_bs) { } 30.155 virtual bool doHeapRegion(HeapRegion* r) { 30.156 if (r->is_survivor()) { 30.157 @@ -6022,7 +6020,7 @@ 30.158 30.159 void G1CollectedHeap::verify_not_dirty_region(HeapRegion* hr) { 30.160 // All of the region should be clean. 30.161 - CardTableModRefBS* ct_bs = (CardTableModRefBS*)barrier_set(); 30.162 + G1SATBCardTableModRefBS* ct_bs = g1_barrier_set(); 30.163 MemRegion mr(hr->bottom(), hr->end()); 30.164 ct_bs->verify_not_dirty_region(mr); 30.165 } 30.166 @@ -6035,13 +6033,13 @@ 30.167 // not dirty that area (one less thing to have to do while holding 30.168 // a lock). So we can only verify that [bottom(),pre_dummy_top()] 30.169 // is dirty. 30.170 - CardTableModRefBS* ct_bs = (CardTableModRefBS*) barrier_set(); 30.171 + G1SATBCardTableModRefBS* ct_bs = g1_barrier_set(); 30.172 MemRegion mr(hr->bottom(), hr->pre_dummy_top()); 30.173 ct_bs->verify_dirty_region(mr); 30.174 } 30.175 30.176 void G1CollectedHeap::verify_dirty_young_list(HeapRegion* head) { 30.177 - CardTableModRefBS* ct_bs = (CardTableModRefBS*) barrier_set(); 30.178 + G1SATBCardTableModRefBS* ct_bs = g1_barrier_set(); 30.179 for (HeapRegion* hr = head; hr != NULL; hr = hr->get_next_young_region()) { 30.180 verify_dirty_region(hr); 30.181 } 30.182 @@ -6053,7 +6051,7 @@ 30.183 #endif 30.184 30.185 void G1CollectedHeap::cleanUpCardTable() { 30.186 - CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set()); 30.187 + G1SATBCardTableModRefBS* ct_bs = g1_barrier_set(); 30.188 double start = os::elapsedTime(); 30.189 30.190 {
31.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Sat Oct 05 03:14:53 2013 +0200 31.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Oct 04 21:00:43 2013 -0700 31.3 @@ -31,6 +31,7 @@ 31.4 #include "gc_implementation/g1/g1HRPrinter.hpp" 31.5 #include "gc_implementation/g1/g1MonitoringSupport.hpp" 31.6 #include "gc_implementation/g1/g1RemSet.hpp" 31.7 +#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" 31.8 #include "gc_implementation/g1/g1YCTypes.hpp" 31.9 #include "gc_implementation/g1/heapRegionSeq.hpp" 31.10 #include "gc_implementation/g1/heapRegionSets.hpp" 31.11 @@ -791,8 +792,6 @@ 31.12 31.13 // The g1 remembered set of the heap. 31.14 G1RemSet* _g1_rem_set; 31.15 - // And it's mod ref barrier set, used to track updates for the above. 31.16 - ModRefBarrierSet* _mr_bs; 31.17 31.18 // A set of cards that cover the objects for which the Rsets should be updated 31.19 // concurrently after the collection. 31.20 @@ -1127,7 +1126,6 @@ 31.21 31.22 // The rem set and barrier set. 31.23 G1RemSet* g1_rem_set() const { return _g1_rem_set; } 31.24 - ModRefBarrierSet* mr_bs() const { return _mr_bs; } 31.25 31.26 unsigned get_gc_time_stamp() { 31.27 return _gc_time_stamp; 31.28 @@ -1346,6 +1344,10 @@ 31.29 31.30 virtual bool is_in_closed_subset(const void* p) const; 31.31 31.32 + G1SATBCardTableModRefBS* g1_barrier_set() { 31.33 + return (G1SATBCardTableModRefBS*) barrier_set(); 31.34 + } 31.35 + 31.36 // This resets the card table to all zeros. It is used after 31.37 // a collection pause which used the card table to claim cards. 31.38 void cleanUpCardTable(); 31.39 @@ -1875,7 +1877,7 @@ 31.40 G1CollectedHeap* _g1h; 31.41 RefToScanQueue* _refs; 31.42 DirtyCardQueue _dcq; 31.43 - CardTableModRefBS* _ct_bs; 31.44 + G1SATBCardTableModRefBS* _ct_bs; 31.45 G1RemSet* _g1_rem; 31.46 31.47 G1ParGCAllocBufferContainer _surviving_alloc_buffer; 31.48 @@ -1914,7 +1916,7 @@ 31.49 void add_to_undo_waste(size_t waste) { _undo_waste += waste; } 31.50 31.51 DirtyCardQueue& dirty_card_queue() { return _dcq; } 31.52 - CardTableModRefBS* ctbs() { return _ct_bs; } 31.53 + G1SATBCardTableModRefBS* ctbs() { return _ct_bs; } 31.54 31.55 template <class T> void immediate_rs_update(HeapRegion* from, T* p, int tid) { 31.56 if (!from->is_survivor()) {
32.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Sat Oct 05 03:14:53 2013 +0200 32.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Fri Oct 04 21:00:43 2013 -0700 32.3 @@ -134,7 +134,7 @@ 32.4 assert(containing_hr->is_in(end - 1), "it should also contain end - 1"); 32.5 32.6 MemRegion mr(start, end); 32.7 - ((CardTableModRefBS*)_g1h->barrier_set())->dirty(mr); 32.8 + g1_barrier_set()->dirty(mr); 32.9 } 32.10 32.11 inline RefToScanQueue* G1CollectedHeap::task_queue(int i) const {
33.1 --- a/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp Sat Oct 05 03:14:53 2013 +0200 33.2 +++ b/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp Fri Oct 04 21:00:43 2013 -0700 33.3 @@ -41,11 +41,11 @@ 33.4 private: 33.5 G1CollectedHeap* _g1; 33.6 DirtyCardQueue *_dcq; 33.7 - CardTableModRefBS* _ct_bs; 33.8 + G1SATBCardTableModRefBS* _ct_bs; 33.9 33.10 public: 33.11 UpdateRSetDeferred(G1CollectedHeap* g1, DirtyCardQueue* dcq) : 33.12 - _g1(g1), _ct_bs((CardTableModRefBS*)_g1->barrier_set()), _dcq(dcq) {} 33.13 + _g1(g1), _ct_bs(_g1->g1_barrier_set()), _dcq(dcq) {} 33.14 33.15 virtual void do_oop(narrowOop* p) { do_oop_work(p); } 33.16 virtual void do_oop( oop* p) { do_oop_work(p); }
34.1 --- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Sat Oct 05 03:14:53 2013 +0200 34.2 +++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Fri Oct 04 21:00:43 2013 -0700 34.3 @@ -220,7 +220,7 @@ 34.4 public: 34.5 G1PrepareCompactClosure(CompactibleSpace* cs) 34.6 : _g1h(G1CollectedHeap::heap()), 34.7 - _mrbs(G1CollectedHeap::heap()->mr_bs()), 34.8 + _mrbs(_g1h->g1_barrier_set()), 34.9 _cp(NULL, cs, cs->initialize_threshold()), 34.10 _humongous_proxy_set("G1MarkSweep Humongous Proxy Set") { } 34.11
35.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp Sat Oct 05 03:14:53 2013 +0200 35.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp Fri Oct 04 21:00:43 2013 -0700 35.3 @@ -83,7 +83,9 @@ 35.4 for (uint i = 0; i < n_workers(); i++) { 35.5 _cset_rs_update_cl[i] = NULL; 35.6 } 35.7 - _prev_period_summary.initialize(this, n_workers()); 35.8 + if (G1SummarizeRSetStats) { 35.9 + _prev_period_summary.initialize(this); 35.10 + } 35.11 } 35.12 35.13 G1RemSet::~G1RemSet() { 35.14 @@ -109,7 +111,7 @@ 35.15 CodeBlobToOopClosure* _code_root_cl; 35.16 35.17 G1BlockOffsetSharedArray* _bot_shared; 35.18 - CardTableModRefBS *_ct_bs; 35.19 + G1SATBCardTableModRefBS *_ct_bs; 35.20 35.21 double _strong_code_root_scan_time_sec; 35.22 int _worker_i; 35.23 @@ -130,7 +132,7 @@ 35.24 { 35.25 _g1h = G1CollectedHeap::heap(); 35.26 _bot_shared = _g1h->bot_shared(); 35.27 - _ct_bs = (CardTableModRefBS*) (_g1h->barrier_set()); 35.28 + _ct_bs = _g1h->g1_barrier_set(); 35.29 _block_size = MAX2<int>(G1RSetScanBlockSize, 1); 35.30 } 35.31 35.32 @@ -505,12 +507,7 @@ 35.33 ScrubRSClosure(BitMap* region_bm, BitMap* card_bm) : 35.34 _g1h(G1CollectedHeap::heap()), 35.35 _region_bm(region_bm), _card_bm(card_bm), 35.36 - _ctbs(NULL) 35.37 - { 35.38 - ModRefBarrierSet* bs = _g1h->mr_bs(); 35.39 - guarantee(bs->is_a(BarrierSet::CardTableModRef), "Precondition"); 35.40 - _ctbs = (CardTableModRefBS*)bs; 35.41 - } 35.42 + _ctbs(_g1h->g1_barrier_set()) {} 35.43 35.44 bool doHeapRegion(HeapRegion* r) { 35.45 if (!r->continuesHumongous()) { 35.46 @@ -731,19 +728,19 @@ 35.47 return has_refs_into_cset; 35.48 } 35.49 35.50 -void G1RemSet::print_periodic_summary_info() { 35.51 +void G1RemSet::print_periodic_summary_info(const char* header) { 35.52 G1RemSetSummary current; 35.53 - current.initialize(this, n_workers()); 35.54 + current.initialize(this); 35.55 35.56 _prev_period_summary.subtract_from(¤t); 35.57 - print_summary_info(&_prev_period_summary); 35.58 + print_summary_info(&_prev_period_summary, header); 35.59 35.60 _prev_period_summary.set(¤t); 35.61 } 35.62 35.63 void G1RemSet::print_summary_info() { 35.64 G1RemSetSummary current; 35.65 - current.initialize(this, n_workers()); 35.66 + current.initialize(this); 35.67 35.68 print_summary_info(¤t, " Cumulative RS summary"); 35.69 }
36.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.hpp Sat Oct 05 03:14:53 2013 +0200 36.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.hpp Fri Oct 04 21:00:43 2013 -0700 36.3 @@ -145,7 +145,7 @@ 36.4 virtual void print_summary_info(); 36.5 36.6 // Print accumulated summary info from the last time called. 36.7 - virtual void print_periodic_summary_info(); 36.8 + virtual void print_periodic_summary_info(const char* header); 36.9 36.10 // Prepare remembered set for verification. 36.11 virtual void prepare_for_verify();
37.1 --- a/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp Sat Oct 05 03:14:53 2013 +0200 37.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp Fri Oct 04 21:00:43 2013 -0700 37.3 @@ -77,12 +77,12 @@ 37.4 return _rs_threads_vtimes[thread]; 37.5 } 37.6 37.7 -void G1RemSetSummary::initialize(G1RemSet* remset, uint num_workers) { 37.8 +void G1RemSetSummary::initialize(G1RemSet* remset) { 37.9 assert(_rs_threads_vtimes == NULL, "just checking"); 37.10 assert(remset != NULL, "just checking"); 37.11 37.12 _remset = remset; 37.13 - _num_vtimes = num_workers; 37.14 + _num_vtimes = ConcurrentG1Refine::thread_num(); 37.15 _rs_threads_vtimes = NEW_C_HEAP_ARRAY(double, _num_vtimes, mtGC); 37.16 memset(_rs_threads_vtimes, 0, sizeof(double) * _num_vtimes); 37.17 37.18 @@ -125,25 +125,115 @@ 37.19 _sampling_thread_vtime = other->sampling_thread_vtime() - _sampling_thread_vtime; 37.20 } 37.21 37.22 +static double percent_of(size_t numerator, size_t denominator) { 37.23 + if (denominator != 0) { 37.24 + return (double)numerator / denominator * 100.0f; 37.25 + } else { 37.26 + return 0.0f; 37.27 + } 37.28 +} 37.29 + 37.30 +static size_t round_to_K(size_t value) { 37.31 + return value / K; 37.32 +} 37.33 + 37.34 +class RegionTypeCounter VALUE_OBJ_CLASS_SPEC { 37.35 +private: 37.36 + const char* _name; 37.37 + 37.38 + size_t _rs_mem_size; 37.39 + size_t _cards_occupied; 37.40 + size_t _amount; 37.41 + 37.42 + size_t _code_root_mem_size; 37.43 + size_t _code_root_elems; 37.44 + 37.45 + double rs_mem_size_percent_of(size_t total) { 37.46 + return percent_of(_rs_mem_size, total); 37.47 + } 37.48 + 37.49 + double cards_occupied_percent_of(size_t total) { 37.50 + return percent_of(_cards_occupied, total); 37.51 + } 37.52 + 37.53 + double code_root_mem_size_percent_of(size_t total) { 37.54 + return percent_of(_code_root_mem_size, total); 37.55 + } 37.56 + 37.57 + double code_root_elems_percent_of(size_t total) { 37.58 + return percent_of(_code_root_elems, total); 37.59 + } 37.60 + 37.61 + size_t amount() const { return _amount; } 37.62 + 37.63 +public: 37.64 + 37.65 + RegionTypeCounter(const char* name) : _name(name), _rs_mem_size(0), _cards_occupied(0), 37.66 + _amount(0), _code_root_mem_size(0), _code_root_elems(0) { } 37.67 + 37.68 + void add(size_t rs_mem_size, size_t cards_occupied, size_t code_root_mem_size, 37.69 + size_t code_root_elems) { 37.70 + _rs_mem_size += rs_mem_size; 37.71 + _cards_occupied += cards_occupied; 37.72 + _code_root_mem_size += code_root_mem_size; 37.73 + _code_root_elems += code_root_elems; 37.74 + _amount++; 37.75 + } 37.76 + 37.77 + size_t rs_mem_size() const { return _rs_mem_size; } 37.78 + size_t cards_occupied() const { return _cards_occupied; } 37.79 + 37.80 + size_t code_root_mem_size() const { return _code_root_mem_size; } 37.81 + size_t code_root_elems() const { return _code_root_elems; } 37.82 + 37.83 + void print_rs_mem_info_on(outputStream * out, size_t total) { 37.84 + out->print_cr(" %8dK (%5.1f%%) by %zd %s regions", round_to_K(rs_mem_size()), rs_mem_size_percent_of(total), amount(), _name); 37.85 + } 37.86 + 37.87 + void print_cards_occupied_info_on(outputStream * out, size_t total) { 37.88 + out->print_cr(" %8d (%5.1f%%) entries by %zd %s regions", cards_occupied(), cards_occupied_percent_of(total), amount(), _name); 37.89 + } 37.90 + 37.91 + void print_code_root_mem_info_on(outputStream * out, size_t total) { 37.92 + out->print_cr(" %8dK (%5.1f%%) by %zd %s regions", round_to_K(code_root_mem_size()), code_root_mem_size_percent_of(total), amount(), _name); 37.93 + } 37.94 + 37.95 + void print_code_root_elems_info_on(outputStream * out, size_t total) { 37.96 + out->print_cr(" %8d (%5.1f%%) elements by %zd %s regions", code_root_elems(), code_root_elems_percent_of(total), amount(), _name); 37.97 + } 37.98 +}; 37.99 + 37.100 + 37.101 class HRRSStatsIter: public HeapRegionClosure { 37.102 - size_t _occupied; 37.103 +private: 37.104 + RegionTypeCounter _young; 37.105 + RegionTypeCounter _humonguous; 37.106 + RegionTypeCounter _free; 37.107 + RegionTypeCounter _old; 37.108 + RegionTypeCounter _all; 37.109 37.110 - size_t _total_rs_mem_sz; 37.111 size_t _max_rs_mem_sz; 37.112 HeapRegion* _max_rs_mem_sz_region; 37.113 37.114 - size_t _total_code_root_mem_sz; 37.115 + size_t total_rs_mem_sz() const { return _all.rs_mem_size(); } 37.116 + size_t total_cards_occupied() const { return _all.cards_occupied(); } 37.117 + 37.118 + size_t max_rs_mem_sz() const { return _max_rs_mem_sz; } 37.119 + HeapRegion* max_rs_mem_sz_region() const { return _max_rs_mem_sz_region; } 37.120 + 37.121 size_t _max_code_root_mem_sz; 37.122 HeapRegion* _max_code_root_mem_sz_region; 37.123 + 37.124 + size_t total_code_root_mem_sz() const { return _all.code_root_mem_size(); } 37.125 + size_t total_code_root_elems() const { return _all.code_root_elems(); } 37.126 + 37.127 + size_t max_code_root_mem_sz() const { return _max_code_root_mem_sz; } 37.128 + HeapRegion* max_code_root_mem_sz_region() const { return _max_code_root_mem_sz_region; } 37.129 + 37.130 public: 37.131 - HRRSStatsIter() : 37.132 - _occupied(0), 37.133 - _total_rs_mem_sz(0), 37.134 - _max_rs_mem_sz(0), 37.135 - _max_rs_mem_sz_region(NULL), 37.136 - _total_code_root_mem_sz(0), 37.137 - _max_code_root_mem_sz(0), 37.138 - _max_code_root_mem_sz_region(NULL) 37.139 + HRRSStatsIter() : _all("All"), _young("Young"), _humonguous("Humonguous"), 37.140 + _free("Free"), _old("Old"), _max_code_root_mem_sz_region(NULL), _max_rs_mem_sz_region(NULL), 37.141 + _max_rs_mem_sz(0), _max_code_root_mem_sz(0) 37.142 {} 37.143 37.144 bool doHeapRegion(HeapRegion* r) { 37.145 @@ -156,46 +246,95 @@ 37.146 _max_rs_mem_sz = rs_mem_sz; 37.147 _max_rs_mem_sz_region = r; 37.148 } 37.149 - _total_rs_mem_sz += rs_mem_sz; 37.150 - 37.151 + size_t occupied_cards = hrrs->occupied(); 37.152 size_t code_root_mem_sz = hrrs->strong_code_roots_mem_size(); 37.153 - if (code_root_mem_sz > _max_code_root_mem_sz) { 37.154 - _max_code_root_mem_sz = code_root_mem_sz; 37.155 + if (code_root_mem_sz > max_code_root_mem_sz()) { 37.156 _max_code_root_mem_sz_region = r; 37.157 } 37.158 - _total_code_root_mem_sz += code_root_mem_sz; 37.159 + size_t code_root_elems = hrrs->strong_code_roots_list_length(); 37.160 37.161 - size_t occ = hrrs->occupied(); 37.162 - _occupied += occ; 37.163 + RegionTypeCounter* current = NULL; 37.164 + if (r->is_young()) { 37.165 + current = &_young; 37.166 + } else if (r->isHumongous()) { 37.167 + current = &_humonguous; 37.168 + } else if (r->is_empty()) { 37.169 + current = &_free; 37.170 + } else { 37.171 + current = &_old; 37.172 + } 37.173 + current->add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems); 37.174 + _all.add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems); 37.175 + 37.176 return false; 37.177 } 37.178 - size_t total_rs_mem_sz() { return _total_rs_mem_sz; } 37.179 - size_t max_rs_mem_sz() { return _max_rs_mem_sz; } 37.180 - HeapRegion* max_rs_mem_sz_region() { return _max_rs_mem_sz_region; } 37.181 - size_t total_code_root_mem_sz() { return _total_code_root_mem_sz; } 37.182 - size_t max_code_root_mem_sz() { return _max_code_root_mem_sz; } 37.183 - HeapRegion* max_code_root_mem_sz_region() { return _max_code_root_mem_sz_region; } 37.184 - size_t occupied() { return _occupied; } 37.185 + 37.186 + void print_summary_on(outputStream* out) { 37.187 + RegionTypeCounter* counters[] = { &_young, &_humonguous, &_free, &_old, NULL }; 37.188 + 37.189 + out->print_cr("\n Current rem set statistics"); 37.190 + out->print_cr(" Total per region rem sets sizes = "SIZE_FORMAT"K." 37.191 + " Max = "SIZE_FORMAT"K.", 37.192 + round_to_K(total_rs_mem_sz()), round_to_K(max_rs_mem_sz())); 37.193 + for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { 37.194 + (*current)->print_rs_mem_info_on(out, total_rs_mem_sz()); 37.195 + } 37.196 + 37.197 + out->print_cr(" Static structures = "SIZE_FORMAT"K," 37.198 + " free_lists = "SIZE_FORMAT"K.", 37.199 + round_to_K(HeapRegionRemSet::static_mem_size()), 37.200 + round_to_K(HeapRegionRemSet::fl_mem_size())); 37.201 + 37.202 + out->print_cr(" "SIZE_FORMAT" occupied cards represented.", 37.203 + total_cards_occupied()); 37.204 + for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { 37.205 + (*current)->print_cards_occupied_info_on(out, total_cards_occupied()); 37.206 + } 37.207 + 37.208 + // Largest sized rem set region statistics 37.209 + HeapRegionRemSet* rem_set = max_rs_mem_sz_region()->rem_set(); 37.210 + out->print_cr(" Region with largest rem set = "HR_FORMAT", " 37.211 + "size = "SIZE_FORMAT "K, occupied = "SIZE_FORMAT"K.", 37.212 + HR_FORMAT_PARAMS(max_rs_mem_sz_region()), 37.213 + round_to_K(rem_set->mem_size()), 37.214 + round_to_K(rem_set->occupied())); 37.215 + 37.216 + // Strong code root statistics 37.217 + HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region()->rem_set(); 37.218 + out->print_cr(" Total heap region code root sets sizes = "SIZE_FORMAT"K." 37.219 + " Max = "SIZE_FORMAT"K.", 37.220 + round_to_K(total_code_root_mem_sz()), 37.221 + round_to_K(max_code_root_rem_set->strong_code_roots_mem_size())); 37.222 + for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { 37.223 + (*current)->print_code_root_mem_info_on(out, total_code_root_mem_sz()); 37.224 + } 37.225 + 37.226 + out->print_cr(" "SIZE_FORMAT" code roots represented.", 37.227 + total_code_root_elems()); 37.228 + for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { 37.229 + (*current)->print_code_root_elems_info_on(out, total_code_root_elems()); 37.230 + } 37.231 + 37.232 + out->print_cr(" Region with largest amount of code roots = "HR_FORMAT", " 37.233 + "size = "SIZE_FORMAT "K, num_elems = "SIZE_FORMAT".", 37.234 + HR_FORMAT_PARAMS(max_code_root_mem_sz_region()), 37.235 + round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()), 37.236 + round_to_K(max_code_root_rem_set->strong_code_roots_list_length())); 37.237 + } 37.238 }; 37.239 37.240 -double calc_percentage(size_t numerator, size_t denominator) { 37.241 - if (denominator != 0) { 37.242 - return (double)numerator / denominator * 100.0; 37.243 - } else { 37.244 - return 0.0f; 37.245 - } 37.246 -} 37.247 - 37.248 void G1RemSetSummary::print_on(outputStream* out) { 37.249 - out->print_cr("\n Concurrent RS processed "SIZE_FORMAT" cards", 37.250 + out->print_cr("\n Recent concurrent refinement statistics"); 37.251 + out->print_cr(" Processed "SIZE_FORMAT" cards", 37.252 num_concurrent_refined_cards()); 37.253 out->print_cr(" Of %d completed buffers:", num_processed_buf_total()); 37.254 out->print_cr(" %8d (%5.1f%%) by concurrent RS threads.", 37.255 num_processed_buf_total(), 37.256 - calc_percentage(num_processed_buf_rs_threads(), num_processed_buf_total())); 37.257 + percent_of(num_processed_buf_rs_threads(), num_processed_buf_total())); 37.258 out->print_cr(" %8d (%5.1f%%) by mutator threads.", 37.259 num_processed_buf_mutator(), 37.260 - calc_percentage(num_processed_buf_mutator(), num_processed_buf_total())); 37.261 + percent_of(num_processed_buf_mutator(), num_processed_buf_total())); 37.262 + out->print_cr(" Did %d coarsenings.", num_coarsenings()); 37.263 out->print_cr(" Concurrent RS threads times (s)"); 37.264 out->print(" "); 37.265 for (uint i = 0; i < _num_vtimes; i++) { 37.266 @@ -207,33 +346,5 @@ 37.267 37.268 HRRSStatsIter blk; 37.269 G1CollectedHeap::heap()->heap_region_iterate(&blk); 37.270 - // RemSet stats 37.271 - out->print_cr(" Total heap region rem set sizes = "SIZE_FORMAT"K." 37.272 - " Max = "SIZE_FORMAT"K.", 37.273 - blk.total_rs_mem_sz()/K, blk.max_rs_mem_sz()/K); 37.274 - out->print_cr(" Static structures = "SIZE_FORMAT"K," 37.275 - " free_lists = "SIZE_FORMAT"K.", 37.276 - HeapRegionRemSet::static_mem_size() / K, 37.277 - HeapRegionRemSet::fl_mem_size() / K); 37.278 - out->print_cr(" "SIZE_FORMAT" occupied cards represented.", 37.279 - blk.occupied()); 37.280 - HeapRegion* max_rs_mem_sz_region = blk.max_rs_mem_sz_region(); 37.281 - HeapRegionRemSet* max_rs_rem_set = max_rs_mem_sz_region->rem_set(); 37.282 - out->print_cr(" Max size region = "HR_FORMAT", " 37.283 - "size = "SIZE_FORMAT "K, occupied = "SIZE_FORMAT"K.", 37.284 - HR_FORMAT_PARAMS(max_rs_mem_sz_region), 37.285 - (max_rs_rem_set->mem_size() + K - 1)/K, 37.286 - (max_rs_rem_set->occupied() + K - 1)/K); 37.287 - out->print_cr(" Did %d coarsenings.", num_coarsenings()); 37.288 - // Strong code root stats 37.289 - out->print_cr(" Total heap region code-root set sizes = "SIZE_FORMAT"K." 37.290 - " Max = "SIZE_FORMAT"K.", 37.291 - blk.total_code_root_mem_sz()/K, blk.max_code_root_mem_sz()/K); 37.292 - HeapRegion* max_code_root_mem_sz_region = blk.max_code_root_mem_sz_region(); 37.293 - HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region->rem_set(); 37.294 - out->print_cr(" Max size region = "HR_FORMAT", " 37.295 - "size = "SIZE_FORMAT "K, num_elems = "SIZE_FORMAT".", 37.296 - HR_FORMAT_PARAMS(max_code_root_mem_sz_region), 37.297 - (max_code_root_rem_set->strong_code_roots_mem_size() + K - 1)/K, 37.298 - (max_code_root_rem_set->strong_code_roots_list_length())); 37.299 + blk.print_summary_on(out); 37.300 }
38.1 --- a/src/share/vm/gc_implementation/g1/g1RemSetSummary.hpp Sat Oct 05 03:14:53 2013 +0200 38.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSetSummary.hpp Fri Oct 04 21:00:43 2013 -0700 38.3 @@ -84,7 +84,7 @@ 38.4 void subtract_from(G1RemSetSummary* other); 38.5 38.6 // initialize and get the first sampling 38.7 - void initialize(G1RemSet* remset, uint num_workers); 38.8 + void initialize(G1RemSet* remset); 38.9 38.10 void print_on(outputStream* out); 38.11
39.1 --- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Sat Oct 05 03:14:53 2013 +0200 39.2 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Fri Oct 04 21:00:43 2013 -0700 39.3 @@ -64,6 +64,27 @@ 39.4 } 39.5 } 39.6 39.7 +bool G1SATBCardTableModRefBS::mark_card_deferred(size_t card_index) { 39.8 + jbyte val = _byte_map[card_index]; 39.9 + // It's already processed 39.10 + if ((val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val()) { 39.11 + return false; 39.12 + } 39.13 + // Cached bit can be installed either on a clean card or on a claimed card. 39.14 + jbyte new_val = val; 39.15 + if (val == clean_card_val()) { 39.16 + new_val = (jbyte)deferred_card_val(); 39.17 + } else { 39.18 + if (val & claimed_card_val()) { 39.19 + new_val = val | (jbyte)deferred_card_val(); 39.20 + } 39.21 + } 39.22 + if (new_val != val) { 39.23 + Atomic::cmpxchg(new_val, &_byte_map[card_index], val); 39.24 + } 39.25 + return true; 39.26 +} 39.27 + 39.28 G1SATBCardTableLoggingModRefBS:: 39.29 G1SATBCardTableLoggingModRefBS(MemRegion whole_heap, 39.30 int max_covered_regions) :
40.1 --- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Sat Oct 05 03:14:53 2013 +0200 40.2 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Fri Oct 04 21:00:43 2013 -0700 40.3 @@ -89,6 +89,42 @@ 40.4 write_ref_array_pre_work(dst, count); 40.5 } 40.6 } 40.7 + 40.8 +/* 40.9 + Claimed and deferred bits are used together in G1 during the evacuation 40.10 + pause. These bits can have the following state transitions: 40.11 + 1. The claimed bit can be put over any other card state. Except that 40.12 + the "dirty -> dirty and claimed" transition is checked for in 40.13 + G1 code and is not used. 40.14 + 2. Deferred bit can be set only if the previous state of the card 40.15 + was either clean or claimed. mark_card_deferred() is wait-free. 40.16 + We do not care if the operation is be successful because if 40.17 + it does not it will only result in duplicate entry in the update 40.18 + buffer because of the "cache-miss". So it's not worth spinning. 40.19 + */ 40.20 + 40.21 + bool is_card_claimed(size_t card_index) { 40.22 + jbyte val = _byte_map[card_index]; 40.23 + return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val(); 40.24 + } 40.25 + 40.26 + void set_card_claimed(size_t card_index) { 40.27 + jbyte val = _byte_map[card_index]; 40.28 + if (val == clean_card_val()) { 40.29 + val = (jbyte)claimed_card_val(); 40.30 + } else { 40.31 + val |= (jbyte)claimed_card_val(); 40.32 + } 40.33 + _byte_map[card_index] = val; 40.34 + } 40.35 + 40.36 + bool mark_card_deferred(size_t card_index); 40.37 + 40.38 + bool is_card_deferred(size_t card_index) { 40.39 + jbyte val = _byte_map[card_index]; 40.40 + return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val(); 40.41 + } 40.42 + 40.43 }; 40.44 40.45 // Adds card-table logging to the post-barrier.
41.1 --- a/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp Sat Oct 05 03:14:53 2013 +0200 41.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp Fri Oct 04 21:00:43 2013 -0700 41.3 @@ -40,10 +40,8 @@ 41.4 41.5 void initialize_flags() { 41.6 // Do basic sizing work 41.7 - this->TwoGenerationCollectorPolicy::initialize_flags(); 41.8 + TwoGenerationCollectorPolicy::initialize_flags(); 41.9 41.10 - // If the user hasn't explicitly set the number of worker 41.11 - // threads, set the count. 41.12 assert(UseSerialGC || 41.13 !FLAG_IS_DEFAULT(ParallelGCThreads) || 41.14 (ParallelGCThreads > 0),
42.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Sat Oct 05 03:14:53 2013 +0200 42.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp Fri Oct 04 21:00:43 2013 -0700 42.3 @@ -23,7 +23,6 @@ 42.4 */ 42.5 42.6 #include "precompiled.hpp" 42.7 -#include "gc_implementation/parallelScavenge/generationSizer.hpp" 42.8 #include "gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp" 42.9 #include "gc_implementation/parallelScavenge/psGCAdaptivePolicyCounters.hpp" 42.10 #include "gc_implementation/parallelScavenge/psScavenge.hpp"
43.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Sat Oct 05 03:14:53 2013 +0200 43.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp Fri Oct 04 21:00:43 2013 -0700 43.3 @@ -53,7 +53,6 @@ 43.4 43.5 // Forward decls 43.6 class elapsedTimer; 43.7 -class GenerationSizer; 43.8 43.9 class PSAdaptiveSizePolicy : public AdaptiveSizePolicy { 43.10 friend class PSGCAdaptivePolicyCounters;
44.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Sat Oct 05 03:14:53 2013 +0200 44.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Oct 04 21:00:43 2013 -0700 44.3 @@ -26,7 +26,6 @@ 44.4 #include "classfile/symbolTable.hpp" 44.5 #include "classfile/systemDictionary.hpp" 44.6 #include "code/codeCache.hpp" 44.7 -#include "gc_implementation/parallelScavenge/generationSizer.hpp" 44.8 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" 44.9 #include "gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp" 44.10 #include "gc_implementation/parallelScavenge/psMarkSweep.hpp"
45.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Sat Oct 05 03:14:53 2013 +0200 45.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Oct 04 21:00:43 2013 -0700 45.3 @@ -27,7 +27,6 @@ 45.4 #include "classfile/systemDictionary.hpp" 45.5 #include "code/codeCache.hpp" 45.6 #include "gc_implementation/parallelScavenge/gcTaskManager.hpp" 45.7 -#include "gc_implementation/parallelScavenge/generationSizer.hpp" 45.8 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.inline.hpp" 45.9 #include "gc_implementation/parallelScavenge/pcTasks.hpp" 45.10 #include "gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp"
46.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Sat Oct 05 03:14:53 2013 +0200 46.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Fri Oct 04 21:00:43 2013 -0700 46.3 @@ -27,7 +27,6 @@ 46.4 #include "code/codeCache.hpp" 46.5 #include "gc_implementation/parallelScavenge/cardTableExtension.hpp" 46.6 #include "gc_implementation/parallelScavenge/gcTaskManager.hpp" 46.7 -#include "gc_implementation/parallelScavenge/generationSizer.hpp" 46.8 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" 46.9 #include "gc_implementation/parallelScavenge/psAdaptiveSizePolicy.hpp" 46.10 #include "gc_implementation/parallelScavenge/psMarkSweep.hpp"
47.1 --- a/src/share/vm/memory/cardTableModRefBS.cpp Sat Oct 05 03:14:53 2013 +0200 47.2 +++ b/src/share/vm/memory/cardTableModRefBS.cpp Fri Oct 04 21:00:43 2013 -0700 47.3 @@ -423,60 +423,6 @@ 47.4 inline_write_ref_field(field, newVal); 47.5 } 47.6 47.7 -/* 47.8 - Claimed and deferred bits are used together in G1 during the evacuation 47.9 - pause. These bits can have the following state transitions: 47.10 - 1. The claimed bit can be put over any other card state. Except that 47.11 - the "dirty -> dirty and claimed" transition is checked for in 47.12 - G1 code and is not used. 47.13 - 2. Deferred bit can be set only if the previous state of the card 47.14 - was either clean or claimed. mark_card_deferred() is wait-free. 47.15 - We do not care if the operation is be successful because if 47.16 - it does not it will only result in duplicate entry in the update 47.17 - buffer because of the "cache-miss". So it's not worth spinning. 47.18 - */ 47.19 - 47.20 - 47.21 -bool CardTableModRefBS::claim_card(size_t card_index) { 47.22 - jbyte val = _byte_map[card_index]; 47.23 - assert(val != dirty_card_val(), "Shouldn't claim a dirty card"); 47.24 - while (val == clean_card_val() || 47.25 - (val & (clean_card_mask_val() | claimed_card_val())) != claimed_card_val()) { 47.26 - jbyte new_val = val; 47.27 - if (val == clean_card_val()) { 47.28 - new_val = (jbyte)claimed_card_val(); 47.29 - } else { 47.30 - new_val = val | (jbyte)claimed_card_val(); 47.31 - } 47.32 - jbyte res = Atomic::cmpxchg(new_val, &_byte_map[card_index], val); 47.33 - if (res == val) { 47.34 - return true; 47.35 - } 47.36 - val = res; 47.37 - } 47.38 - return false; 47.39 -} 47.40 - 47.41 -bool CardTableModRefBS::mark_card_deferred(size_t card_index) { 47.42 - jbyte val = _byte_map[card_index]; 47.43 - // It's already processed 47.44 - if ((val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val()) { 47.45 - return false; 47.46 - } 47.47 - // Cached bit can be installed either on a clean card or on a claimed card. 47.48 - jbyte new_val = val; 47.49 - if (val == clean_card_val()) { 47.50 - new_val = (jbyte)deferred_card_val(); 47.51 - } else { 47.52 - if (val & claimed_card_val()) { 47.53 - new_val = val | (jbyte)deferred_card_val(); 47.54 - } 47.55 - } 47.56 - if (new_val != val) { 47.57 - Atomic::cmpxchg(new_val, &_byte_map[card_index], val); 47.58 - } 47.59 - return true; 47.60 -} 47.61 47.62 void CardTableModRefBS::non_clean_card_iterate_possibly_parallel(Space* sp, 47.63 MemRegion mr,
48.1 --- a/src/share/vm/memory/cardTableModRefBS.hpp Sat Oct 05 03:14:53 2013 +0200 48.2 +++ b/src/share/vm/memory/cardTableModRefBS.hpp Fri Oct 04 21:00:43 2013 -0700 48.3 @@ -339,34 +339,10 @@ 48.4 _byte_map[card_index] = dirty_card_val(); 48.5 } 48.6 48.7 - bool is_card_claimed(size_t card_index) { 48.8 - jbyte val = _byte_map[card_index]; 48.9 - return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val(); 48.10 - } 48.11 - 48.12 - void set_card_claimed(size_t card_index) { 48.13 - jbyte val = _byte_map[card_index]; 48.14 - if (val == clean_card_val()) { 48.15 - val = (jbyte)claimed_card_val(); 48.16 - } else { 48.17 - val |= (jbyte)claimed_card_val(); 48.18 - } 48.19 - _byte_map[card_index] = val; 48.20 - } 48.21 - 48.22 - bool claim_card(size_t card_index); 48.23 - 48.24 bool is_card_clean(size_t card_index) { 48.25 return _byte_map[card_index] == clean_card_val(); 48.26 } 48.27 48.28 - bool is_card_deferred(size_t card_index) { 48.29 - jbyte val = _byte_map[card_index]; 48.30 - return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val(); 48.31 - } 48.32 - 48.33 - bool mark_card_deferred(size_t card_index); 48.34 - 48.35 // Card marking array base (adjusted for heap low boundary) 48.36 // This would be the 0th element of _byte_map, if the heap started at 0x0. 48.37 // But since the heap starts at some higher address, this points to somewhere
49.1 --- a/src/share/vm/memory/collectorPolicy.cpp Sat Oct 05 03:14:53 2013 +0200 49.2 +++ b/src/share/vm/memory/collectorPolicy.cpp Fri Oct 04 21:00:43 2013 -0700 49.3 @@ -64,19 +64,21 @@ 49.4 vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified"); 49.5 } 49.6 49.7 - if (!is_size_aligned(MaxMetaspaceSize, max_alignment())) { 49.8 - FLAG_SET_ERGO(uintx, MaxMetaspaceSize, 49.9 - restricted_align_down(MaxMetaspaceSize, max_alignment())); 49.10 + // Do not use FLAG_SET_ERGO to update MaxMetaspaceSize, since this will 49.11 + // override if MaxMetaspaceSize was set on the command line or not. 49.12 + // This information is needed later to conform to the specification of the 49.13 + // java.lang.management.MemoryUsage API. 49.14 + // 49.15 + // Ideally, we would be able to set the default value of MaxMetaspaceSize in 49.16 + // globals.hpp to the aligned value, but this is not possible, since the 49.17 + // alignment depends on other flags being parsed. 49.18 + MaxMetaspaceSize = restricted_align_down(MaxMetaspaceSize, max_alignment()); 49.19 + 49.20 + if (MetaspaceSize > MaxMetaspaceSize) { 49.21 + MetaspaceSize = MaxMetaspaceSize; 49.22 } 49.23 49.24 - if (MetaspaceSize > MaxMetaspaceSize) { 49.25 - FLAG_SET_ERGO(uintx, MetaspaceSize, MaxMetaspaceSize); 49.26 - } 49.27 - 49.28 - if (!is_size_aligned(MetaspaceSize, min_alignment())) { 49.29 - FLAG_SET_ERGO(uintx, MetaspaceSize, 49.30 - restricted_align_down(MetaspaceSize, min_alignment())); 49.31 - } 49.32 + MetaspaceSize = restricted_align_down(MetaspaceSize, min_alignment()); 49.33 49.34 assert(MetaspaceSize <= MaxMetaspaceSize, "Must be"); 49.35 49.36 @@ -135,15 +137,8 @@ 49.37 49.38 GenRemSet* CollectorPolicy::create_rem_set(MemRegion whole_heap, 49.39 int max_covered_regions) { 49.40 - switch (rem_set_name()) { 49.41 - case GenRemSet::CardTable: { 49.42 - CardTableRS* res = new CardTableRS(whole_heap, max_covered_regions); 49.43 - return res; 49.44 - } 49.45 - default: 49.46 - guarantee(false, "unrecognized GenRemSet::Name"); 49.47 - return NULL; 49.48 - } 49.49 + assert(rem_set_name() == GenRemSet::CardTable, "unrecognized GenRemSet::Name"); 49.50 + return new CardTableRS(whole_heap, max_covered_regions); 49.51 } 49.52 49.53 void CollectorPolicy::cleared_all_soft_refs() {
50.1 --- a/src/share/vm/memory/genRemSet.cpp Sat Oct 05 03:14:53 2013 +0200 50.2 +++ b/src/share/vm/memory/genRemSet.cpp Fri Oct 04 21:00:43 2013 -0700 50.3 @@ -32,13 +32,8 @@ 50.4 // enumeration.) 50.5 50.6 uintx GenRemSet::max_alignment_constraint(Name nm) { 50.7 - switch (nm) { 50.8 - case GenRemSet::CardTable: 50.9 - return CardTableRS::ct_max_alignment_constraint(); 50.10 - default: 50.11 - guarantee(false, "Unrecognized GenRemSet type."); 50.12 - return (0); // Make Windows compiler happy 50.13 - } 50.14 + assert(nm == GenRemSet::CardTable, "Unrecognized GenRemSet type."); 50.15 + return CardTableRS::ct_max_alignment_constraint(); 50.16 } 50.17 50.18 class HasAccumulatedModifiedOopsClosure : public KlassClosure {
51.1 --- a/src/share/vm/memory/metaspace.cpp Sat Oct 05 03:14:53 2013 +0200 51.2 +++ b/src/share/vm/memory/metaspace.cpp Fri Oct 04 21:00:43 2013 -0700 51.3 @@ -3104,7 +3104,7 @@ 51.4 MetaWord* Metaspace::allocate(size_t word_size, MetadataType mdtype) { 51.5 // DumpSharedSpaces doesn't use class metadata area (yet) 51.6 // Also, don't use class_vsm() unless UseCompressedClassPointers is true. 51.7 - if (mdtype == ClassType && using_class_space()) { 51.8 + if (is_class_space_allocation(mdtype)) { 51.9 return class_vsm()->allocate(word_size); 51.10 } else { 51.11 return vsm()->allocate(word_size); 51.12 @@ -3252,8 +3252,8 @@ 51.13 MetaspaceAux::dump(gclog_or_tty); 51.14 } 51.15 // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support 51.16 - const char* space_string = (mdtype == ClassType) ? "Compressed class space" : 51.17 - "Metadata space"; 51.18 + const char* space_string = is_class_space_allocation(mdtype) ? "Compressed class space" : 51.19 + "Metadata space"; 51.20 report_java_out_of_memory(space_string); 51.21 51.22 if (JvmtiExport::should_post_resource_exhausted()) { 51.23 @@ -3261,7 +3261,7 @@ 51.24 JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR, 51.25 space_string); 51.26 } 51.27 - if (mdtype == ClassType) { 51.28 + if (is_class_space_allocation(mdtype)) { 51.29 THROW_OOP_0(Universe::out_of_memory_error_class_metaspace()); 51.30 } else { 51.31 THROW_OOP_0(Universe::out_of_memory_error_metaspace());
52.1 --- a/src/share/vm/memory/metaspace.hpp Sat Oct 05 03:14:53 2013 +0200 52.2 +++ b/src/share/vm/memory/metaspace.hpp Fri Oct 04 21:00:43 2013 -0700 52.3 @@ -235,6 +235,9 @@ 52.4 return NOT_LP64(false) LP64_ONLY(UseCompressedClassPointers && !DumpSharedSpaces); 52.5 } 52.6 52.7 + static bool is_class_space_allocation(MetadataType mdType) { 52.8 + return mdType == ClassType && using_class_space(); 52.9 + } 52.10 }; 52.11 52.12 class MetaspaceAux : AllStatic {
53.1 --- a/src/share/vm/oops/method.cpp Sat Oct 05 03:14:53 2013 +0200 53.2 +++ b/src/share/vm/oops/method.cpp Fri Oct 04 21:00:43 2013 -0700 53.3 @@ -901,16 +901,6 @@ 53.4 // This function must not hit a safepoint! 53.5 address Method::verified_code_entry() { 53.6 debug_only(No_Safepoint_Verifier nsv;) 53.7 - nmethod *code = (nmethod *)OrderAccess::load_ptr_acquire(&_code); 53.8 - if (code == NULL && UseCodeCacheFlushing) { 53.9 - nmethod *saved_code = CodeCache::reanimate_saved_code(this); 53.10 - if (saved_code != NULL) { 53.11 - methodHandle method(this); 53.12 - assert( ! saved_code->is_osr_method(), "should not get here for osr" ); 53.13 - set_code( method, saved_code ); 53.14 - } 53.15 - } 53.16 - 53.17 assert(_from_compiled_entry != NULL, "must be set"); 53.18 return _from_compiled_entry; 53.19 }
54.1 --- a/src/share/vm/opto/c2_globals.hpp Sat Oct 05 03:14:53 2013 +0200 54.2 +++ b/src/share/vm/opto/c2_globals.hpp Fri Oct 04 21:00:43 2013 -0700 54.3 @@ -636,7 +636,9 @@ 54.4 \ 54.5 diagnostic(bool, OptimizeExpensiveOps, true, \ 54.6 "Find best control for expensive operations") \ 54.7 - 54.8 + \ 54.9 + product(bool, UseMathExactIntrinsics, true, \ 54.10 + "Enables intrinsification of various java.lang.Math funcitons") 54.11 54.12 C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG) 54.13
55.1 --- a/src/share/vm/opto/callGenerator.hpp Sat Oct 05 03:14:53 2013 +0200 55.2 +++ b/src/share/vm/opto/callGenerator.hpp Fri Oct 04 21:00:43 2013 -0700 55.3 @@ -65,6 +65,8 @@ 55.4 virtual bool is_predicted() const { return false; } 55.5 // is_trap: Does not return to the caller. (E.g., uncommon trap.) 55.6 virtual bool is_trap() const { return false; } 55.7 + // does_virtual_dispatch: Should try inlining as normal method first. 55.8 + virtual bool does_virtual_dispatch() const { return false; } 55.9 55.10 // is_late_inline: supports conversion of call into an inline 55.11 virtual bool is_late_inline() const { return false; }
56.1 --- a/src/share/vm/opto/classes.cpp Sat Oct 05 03:14:53 2013 +0200 56.2 +++ b/src/share/vm/opto/classes.cpp Fri Oct 04 21:00:43 2013 -0700 56.3 @@ -32,6 +32,7 @@ 56.4 #include "opto/loopnode.hpp" 56.5 #include "opto/machnode.hpp" 56.6 #include "opto/memnode.hpp" 56.7 +#include "opto/mathexactnode.hpp" 56.8 #include "opto/mulnode.hpp" 56.9 #include "opto/multnode.hpp" 56.10 #include "opto/node.hpp"
57.1 --- a/src/share/vm/opto/classes.hpp Sat Oct 05 03:14:53 2013 +0200 57.2 +++ b/src/share/vm/opto/classes.hpp Fri Oct 04 21:00:43 2013 -0700 57.3 @@ -29,6 +29,7 @@ 57.4 macro(AbsF) 57.5 macro(AbsI) 57.6 macro(AddD) 57.7 +macro(AddExactI) 57.8 macro(AddF) 57.9 macro(AddI) 57.10 macro(AddL) 57.11 @@ -133,6 +134,7 @@ 57.12 macro(ExpD) 57.13 macro(FastLock) 57.14 macro(FastUnlock) 57.15 +macro(FlagsProj) 57.16 macro(Goto) 57.17 macro(Halt) 57.18 macro(If) 57.19 @@ -167,6 +169,7 @@ 57.20 macro(LoopLimit) 57.21 macro(Mach) 57.22 macro(MachProj) 57.23 +macro(MathExact) 57.24 macro(MaxI) 57.25 macro(MemBarAcquire) 57.26 macro(MemBarAcquireLock)
58.1 --- a/src/share/vm/opto/doCall.cpp Sat Oct 05 03:14:53 2013 +0200 58.2 +++ b/src/share/vm/opto/doCall.cpp Fri Oct 04 21:00:43 2013 -0700 58.3 @@ -110,6 +110,7 @@ 58.4 // then we return it as the inlined version of the call. 58.5 // We do this before the strict f.p. check below because the 58.6 // intrinsics handle strict f.p. correctly. 58.7 + CallGenerator* cg_intrinsic = NULL; 58.8 if (allow_inline && allow_intrinsics) { 58.9 CallGenerator* cg = find_intrinsic(callee, call_does_dispatch); 58.10 if (cg != NULL) { 58.11 @@ -121,7 +122,16 @@ 58.12 cg = CallGenerator::for_predicted_intrinsic(cg, inline_cg); 58.13 } 58.14 } 58.15 - return cg; 58.16 + 58.17 + // If intrinsic does the virtual dispatch, we try to use the type profile 58.18 + // first, and hopefully inline it as the regular virtual call below. 58.19 + // We will retry the intrinsic if nothing had claimed it afterwards. 58.20 + if (cg->does_virtual_dispatch()) { 58.21 + cg_intrinsic = cg; 58.22 + cg = NULL; 58.23 + } else { 58.24 + return cg; 58.25 + } 58.26 } 58.27 } 58.28 58.29 @@ -266,6 +276,13 @@ 58.30 } 58.31 } 58.32 58.33 + // Nothing claimed the intrinsic, we go with straight-forward inlining 58.34 + // for already discovered intrinsic. 58.35 + if (allow_inline && allow_intrinsics && cg_intrinsic != NULL) { 58.36 + assert(cg_intrinsic->does_virtual_dispatch(), "sanity"); 58.37 + return cg_intrinsic; 58.38 + } 58.39 + 58.40 // There was no special inlining tactic, or it bailed out. 58.41 // Use a more generic tactic, like a simple call. 58.42 if (call_does_dispatch) {
59.1 --- a/src/share/vm/opto/graphKit.cpp Sat Oct 05 03:14:53 2013 +0200 59.2 +++ b/src/share/vm/opto/graphKit.cpp Fri Oct 04 21:00:43 2013 -0700 59.3 @@ -3849,9 +3849,9 @@ 59.4 const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), 59.5 false, NULL, 0); 59.6 const TypePtr* value_field_type = string_type->add_offset(value_offset); 59.7 - int value_field_idx = C->get_alias_index(value_field_type); 59.8 - store_to_memory(ctrl, basic_plus_adr(str, value_offset), 59.9 - value, T_OBJECT, value_field_idx); 59.10 + 59.11 + store_oop_to_object(ctrl, str, basic_plus_adr(str, value_offset), value_field_type, 59.12 + value, TypeAryPtr::CHARS, T_OBJECT); 59.13 } 59.14 59.15 void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) {
60.1 --- a/src/share/vm/opto/ifnode.cpp Sat Oct 05 03:14:53 2013 +0200 60.2 +++ b/src/share/vm/opto/ifnode.cpp Fri Oct 04 21:00:43 2013 -0700 60.3 @@ -76,6 +76,7 @@ 60.4 if( !i1->is_Bool() ) return NULL; 60.5 BoolNode *b = i1->as_Bool(); 60.6 Node *cmp = b->in(1); 60.7 + if( cmp->is_FlagsProj() ) return NULL; 60.8 if( !cmp->is_Cmp() ) return NULL; 60.9 i1 = cmp->in(1); 60.10 if( i1 == NULL || !i1->is_Phi() ) return NULL;
61.1 --- a/src/share/vm/opto/lcm.cpp Sat Oct 05 03:14:53 2013 +0200 61.2 +++ b/src/share/vm/opto/lcm.cpp Fri Oct 04 21:00:43 2013 -0700 61.3 @@ -472,6 +472,13 @@ 61.4 break; 61.5 } 61.6 61.7 + // For nodes that produce a FlagsProj, make the node adjacent to the 61.8 + // use of the FlagsProj 61.9 + if (use->is_FlagsProj() && get_block_for_node(use) == block) { 61.10 + found_machif = true; 61.11 + break; 61.12 + } 61.13 + 61.14 // More than this instruction pending for successor to be ready, 61.15 // don't choose this if other opportunities are ready 61.16 if (ready_cnt.at(use->_idx) > 1)
62.1 --- a/src/share/vm/opto/library_call.cpp Sat Oct 05 03:14:53 2013 +0200 62.2 +++ b/src/share/vm/opto/library_call.cpp Fri Oct 04 21:00:43 2013 -0700 62.3 @@ -32,6 +32,7 @@ 62.4 #include "opto/callGenerator.hpp" 62.5 #include "opto/cfgnode.hpp" 62.6 #include "opto/idealKit.hpp" 62.7 +#include "opto/mathexactnode.hpp" 62.8 #include "opto/mulnode.hpp" 62.9 #include "opto/parse.hpp" 62.10 #include "opto/runtime.hpp" 62.11 @@ -46,19 +47,22 @@ 62.12 private: 62.13 bool _is_virtual; 62.14 bool _is_predicted; 62.15 + bool _does_virtual_dispatch; 62.16 vmIntrinsics::ID _intrinsic_id; 62.17 62.18 public: 62.19 - LibraryIntrinsic(ciMethod* m, bool is_virtual, bool is_predicted, vmIntrinsics::ID id) 62.20 + LibraryIntrinsic(ciMethod* m, bool is_virtual, bool is_predicted, bool does_virtual_dispatch, vmIntrinsics::ID id) 62.21 : InlineCallGenerator(m), 62.22 _is_virtual(is_virtual), 62.23 _is_predicted(is_predicted), 62.24 + _does_virtual_dispatch(does_virtual_dispatch), 62.25 _intrinsic_id(id) 62.26 { 62.27 } 62.28 virtual bool is_intrinsic() const { return true; } 62.29 virtual bool is_virtual() const { return _is_virtual; } 62.30 virtual bool is_predicted() const { return _is_predicted; } 62.31 + virtual bool does_virtual_dispatch() const { return _does_virtual_dispatch; } 62.32 virtual JVMState* generate(JVMState* jvms); 62.33 virtual Node* generate_predicate(JVMState* jvms); 62.34 vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; } 62.35 @@ -199,6 +203,8 @@ 62.36 bool inline_math_native(vmIntrinsics::ID id); 62.37 bool inline_trig(vmIntrinsics::ID id); 62.38 bool inline_math(vmIntrinsics::ID id); 62.39 + bool inline_math_mathExact(Node* math); 62.40 + bool inline_math_addExact(); 62.41 bool inline_exp(); 62.42 bool inline_pow(); 62.43 void finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName); 62.44 @@ -352,6 +358,7 @@ 62.45 } 62.46 62.47 bool is_predicted = false; 62.48 + bool does_virtual_dispatch = false; 62.49 62.50 switch (id) { 62.51 case vmIntrinsics::_compareTo: 62.52 @@ -378,8 +385,10 @@ 62.53 break; 62.54 case vmIntrinsics::_hashCode: 62.55 if (!InlineObjectHash) return NULL; 62.56 + does_virtual_dispatch = true; 62.57 break; 62.58 case vmIntrinsics::_clone: 62.59 + does_virtual_dispatch = true; 62.60 case vmIntrinsics::_copyOf: 62.61 case vmIntrinsics::_copyOfRange: 62.62 if (!InlineObjectCopy) return NULL; 62.63 @@ -498,6 +507,15 @@ 62.64 if (!UseCRC32Intrinsics) return NULL; 62.65 break; 62.66 62.67 + case vmIntrinsics::_addExact: 62.68 + if (!Matcher::match_rule_supported(Op_AddExactI)) { 62.69 + return NULL; 62.70 + } 62.71 + if (!UseMathExactIntrinsics) { 62.72 + return NULL; 62.73 + } 62.74 + break; 62.75 + 62.76 default: 62.77 assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility"); 62.78 assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?"); 62.79 @@ -529,7 +547,7 @@ 62.80 if (!InlineUnsafeOps) return NULL; 62.81 } 62.82 62.83 - return new LibraryIntrinsic(m, is_virtual, is_predicted, (vmIntrinsics::ID) id); 62.84 + return new LibraryIntrinsic(m, is_virtual, is_predicted, does_virtual_dispatch, (vmIntrinsics::ID) id); 62.85 } 62.86 62.87 //----------------------register_library_intrinsics----------------------- 62.88 @@ -668,6 +686,8 @@ 62.89 case vmIntrinsics::_min: 62.90 case vmIntrinsics::_max: return inline_min_max(intrinsic_id()); 62.91 62.92 + case vmIntrinsics::_addExact: return inline_math_addExact(); 62.93 + 62.94 case vmIntrinsics::_arraycopy: return inline_arraycopy(); 62.95 62.96 case vmIntrinsics::_compareTo: return inline_string_compareTo(); 62.97 @@ -1911,6 +1931,45 @@ 62.98 return true; 62.99 } 62.100 62.101 +bool LibraryCallKit::inline_math_mathExact(Node* math) { 62.102 + Node* result = _gvn.transform( new(C) ProjNode(math, MathExactNode::result_proj_node)); 62.103 + Node* flags = _gvn.transform( new(C) FlagsProjNode(math, MathExactNode::flags_proj_node)); 62.104 + 62.105 + Node* bol = _gvn.transform( new (C) BoolNode(flags, BoolTest::overflow) ); 62.106 + IfNode* check = create_and_map_if(control(), bol, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN); 62.107 + Node* fast_path = _gvn.transform( new (C) IfFalseNode(check)); 62.108 + Node* slow_path = _gvn.transform( new (C) IfTrueNode(check) ); 62.109 + 62.110 + { 62.111 + PreserveJVMState pjvms(this); 62.112 + PreserveReexecuteState preexecs(this); 62.113 + jvms()->set_should_reexecute(true); 62.114 + 62.115 + set_control(slow_path); 62.116 + set_i_o(i_o()); 62.117 + 62.118 + uncommon_trap(Deoptimization::Reason_intrinsic, 62.119 + Deoptimization::Action_none); 62.120 + } 62.121 + 62.122 + set_control(fast_path); 62.123 + set_result(result); 62.124 + return true; 62.125 +} 62.126 + 62.127 +bool LibraryCallKit::inline_math_addExact() { 62.128 + Node* arg1 = argument(0); 62.129 + Node* arg2 = argument(1); 62.130 + 62.131 + Node* add = _gvn.transform( new(C) AddExactINode(NULL, arg1, arg2) ); 62.132 + if (add->Opcode() == Op_AddExactI) { 62.133 + return inline_math_mathExact(add); 62.134 + } else { 62.135 + set_result(add); 62.136 + } 62.137 + return true; 62.138 +} 62.139 + 62.140 Node* 62.141 LibraryCallKit::generate_min_max(vmIntrinsics::ID id, Node* x0, Node* y0) { 62.142 // These are the candidate return value:
63.1 --- a/src/share/vm/opto/loopTransform.cpp Sat Oct 05 03:14:53 2013 +0200 63.2 +++ b/src/share/vm/opto/loopTransform.cpp Fri Oct 04 21:00:43 2013 -0700 63.3 @@ -776,6 +776,9 @@ 63.4 continue; // not RC 63.5 63.6 Node *cmp = bol->in(1); 63.7 + if (cmp->is_FlagsProj()) { 63.8 + continue; 63.9 + } 63.10 63.11 Node *rc_exp = cmp->in(1); 63.12 Node *limit = cmp->in(2);
64.1 --- a/src/share/vm/opto/loopopts.cpp Sat Oct 05 03:14:53 2013 +0200 64.2 +++ b/src/share/vm/opto/loopopts.cpp Fri Oct 04 21:00:43 2013 -0700 64.3 @@ -2355,7 +2355,8 @@ 64.4 opc == Op_Catch || 64.5 opc == Op_CatchProj || 64.6 opc == Op_Jump || 64.7 - opc == Op_JumpProj) { 64.8 + opc == Op_JumpProj || 64.9 + opc == Op_FlagsProj) { 64.10 #if !defined(PRODUCT) 64.11 if (TracePartialPeeling) { 64.12 tty->print_cr("\nExit control too complex: lp: %d", head->_idx);
65.1 --- a/src/share/vm/opto/matcher.cpp Sat Oct 05 03:14:53 2013 +0200 65.2 +++ b/src/share/vm/opto/matcher.cpp Fri Oct 04 21:00:43 2013 -0700 65.3 @@ -1964,6 +1964,7 @@ 65.4 case Op_Catch: 65.5 case Op_CatchProj: 65.6 case Op_CProj: 65.7 + case Op_FlagsProj: 65.8 case Op_JumpProj: 65.9 case Op_JProj: 65.10 case Op_NeverBranch:
66.1 --- a/src/share/vm/opto/matcher.hpp Sat Oct 05 03:14:53 2013 +0200 66.2 +++ b/src/share/vm/opto/matcher.hpp Fri Oct 04 21:00:43 2013 -0700 66.3 @@ -337,6 +337,9 @@ 66.4 // Register for MODL projection of divmodL 66.5 static RegMask modL_proj_mask(); 66.6 66.7 + static const RegMask mathExactI_result_proj_mask(); 66.8 + static const RegMask mathExactI_flags_proj_mask(); 66.9 + 66.10 // Use hardware DIV instruction when it is faster than 66.11 // a code which use multiply for division by constant. 66.12 static bool use_asm_for_ldiv_by_con( jlong divisor );
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 67.2 +++ b/src/share/vm/opto/mathexactnode.cpp Fri Oct 04 21:00:43 2013 -0700 67.3 @@ -0,0 +1,143 @@ 67.4 +/* 67.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 67.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 67.7 + * 67.8 + * This code is free software; you can redistribute it and/or modify it 67.9 + * under the terms of the GNU General Public License version 2 only, as 67.10 + * published by the Free Software Foundation. 67.11 + * 67.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 67.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 67.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 67.15 + * version 2 for more details (a copy is included in the LICENSE file that 67.16 + * accompanied this code). 67.17 + * 67.18 + * You should have received a copy of the GNU General Public License version 67.19 + * 2 along with this work; if not, write to the Free Software Foundation, 67.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 67.21 + * 67.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 67.23 + * or visit www.oracle.com if you need additional information or have any 67.24 + * questions. 67.25 + * 67.26 + */ 67.27 + 67.28 +#include "precompiled.hpp" 67.29 +#include "memory/allocation.inline.hpp" 67.30 +#include "opto/addnode.hpp" 67.31 +#include "opto/machnode.hpp" 67.32 +#include "opto/mathexactnode.hpp" 67.33 +#include "opto/matcher.hpp" 67.34 +#include "opto/subnode.hpp" 67.35 + 67.36 +MathExactNode::MathExactNode(Node* ctrl, Node* n1, Node* n2) : MultiNode(3) { 67.37 + init_req(0, ctrl); 67.38 + init_req(1, n1); 67.39 + init_req(2, n2); 67.40 +} 67.41 + 67.42 +Node* AddExactINode::match(const ProjNode* proj, const Matcher* m) { 67.43 + uint ideal_reg = proj->ideal_reg(); 67.44 + RegMask rm; 67.45 + if (proj->_con == result_proj_node) { 67.46 + rm = m->mathExactI_result_proj_mask(); 67.47 + } else { 67.48 + assert(proj->_con == flags_proj_node, "must be result or flags"); 67.49 + assert(ideal_reg == Op_RegFlags, "sanity"); 67.50 + rm = m->mathExactI_flags_proj_mask(); 67.51 + } 67.52 + return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg); 67.53 +} 67.54 + 67.55 +// If the MathExactNode won't overflow we have to replace the 67.56 +// FlagsProjNode and ProjNode that is generated by the MathExactNode 67.57 +Node* MathExactNode::no_overflow(PhaseGVN *phase, Node* new_result) { 67.58 + PhaseIterGVN *igvn = phase->is_IterGVN(); 67.59 + if (igvn) { 67.60 + ProjNode* result = result_node(); 67.61 + ProjNode* flags = flags_node(); 67.62 + 67.63 + if (result != NULL) { 67.64 + igvn->replace_node(result, new_result); 67.65 + } 67.66 + 67.67 + if (flags != NULL) { 67.68 + BoolNode* bolnode = (BoolNode *) flags->unique_out(); 67.69 + switch (bolnode->_test._test) { 67.70 + case BoolTest::overflow: 67.71 + // if the check is for overflow - never taken 67.72 + igvn->replace_node(bolnode, phase->intcon(0)); 67.73 + break; 67.74 + case BoolTest::no_overflow: 67.75 + // if the check is for no overflow - always taken 67.76 + igvn->replace_node(bolnode, phase->intcon(1)); 67.77 + break; 67.78 + default: 67.79 + fatal("Unexpected value of BoolTest"); 67.80 + break; 67.81 + } 67.82 + flags->del_req(0); 67.83 + } 67.84 + } 67.85 + return new_result; 67.86 +} 67.87 + 67.88 +Node *AddExactINode::Ideal(PhaseGVN *phase, bool can_reshape) { 67.89 + Node *arg1 = in(1); 67.90 + Node *arg2 = in(2); 67.91 + 67.92 + const Type* type1 = phase->type(arg1); 67.93 + const Type* type2 = phase->type(arg2); 67.94 + 67.95 + if (type1 != Type::TOP && type1->singleton() && 67.96 + type2 != Type::TOP && type2->singleton()) { 67.97 + jint val1 = arg1->get_int(); 67.98 + jint val2 = arg2->get_int(); 67.99 + jint result = val1 + val2; 67.100 + // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result 67.101 + if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) { 67.102 + Node* con_result = ConINode::make(phase->C, result); 67.103 + return no_overflow(phase, con_result); 67.104 + } 67.105 + return NULL; 67.106 + } 67.107 + 67.108 + if (type1 == TypeInt::ZERO) { // (Add 0 x) == x 67.109 + Node* add_result = new (phase->C) AddINode(arg1, arg2); 67.110 + return no_overflow(phase, add_result); 67.111 + } 67.112 + 67.113 + if (type2 == TypeInt::ZERO) { // (Add x 0) == x 67.114 + Node* add_result = new (phase->C) AddINode(arg1, arg2); 67.115 + return no_overflow(phase, add_result); 67.116 + } 67.117 + 67.118 + if (type2->singleton()) { 67.119 + return NULL; // no change - keep constant on the right 67.120 + } 67.121 + 67.122 + if (type1->singleton()) { 67.123 + // Make it x + Constant - move constant to the right 67.124 + swap_edges(1, 2); 67.125 + return this; 67.126 + } 67.127 + 67.128 + if (arg2->is_Load()) { 67.129 + return NULL; // no change - keep load on the right 67.130 + } 67.131 + 67.132 + if (arg1->is_Load()) { 67.133 + // Make it x + Load - move load to the right 67.134 + swap_edges(1, 2); 67.135 + return this; 67.136 + } 67.137 + 67.138 + if (arg1->_idx > arg2->_idx) { 67.139 + // Sort the edges 67.140 + swap_edges(1, 2); 67.141 + return this; 67.142 + } 67.143 + 67.144 + return NULL; 67.145 +} 67.146 +
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 68.2 +++ b/src/share/vm/opto/mathexactnode.hpp Fri Oct 04 21:00:43 2013 -0700 68.3 @@ -0,0 +1,81 @@ 68.4 +/* 68.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 68.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 68.7 + * 68.8 + * This code is free software; you can redistribute it and/or modify it 68.9 + * under the terms of the GNU General Public License version 2 only, as 68.10 + * published by the Free Software Foundation. 68.11 + * 68.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 68.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 68.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 68.15 + * version 2 for more details (a copy is included in the LICENSE file that 68.16 + * accompanied this code). 68.17 + * 68.18 + * You should have received a copy of the GNU General Public License version 68.19 + * 2 along with this work; if not, write to the Free Software Foundation, 68.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 68.21 + * 68.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 68.23 + * or visit www.oracle.com if you need additional information or have any 68.24 + * questions. 68.25 + * 68.26 + */ 68.27 + 68.28 +#ifndef SHARE_VM_OPTO_MATHEXACTNODE_HPP 68.29 +#define SHARE_VM_OPTO_MATHEXACTNODE_HPP 68.30 + 68.31 +#include "opto/multnode.hpp" 68.32 +#include "opto/node.hpp" 68.33 +#include "opto/type.hpp" 68.34 + 68.35 +class Node; 68.36 + 68.37 +class PhaseGVN; 68.38 +class PhaseTransform; 68.39 + 68.40 +class MathExactNode : public MultiNode { 68.41 +public: 68.42 + MathExactNode(Node* ctrl, Node* in1, Node* in2); 68.43 + enum { 68.44 + result_proj_node = 0, 68.45 + flags_proj_node = 1 68.46 + }; 68.47 + virtual int Opcode() const; 68.48 + virtual Node* Identity(PhaseTransform* phase) { return this; } 68.49 + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape) { return NULL; } 68.50 + virtual const Type* Value(PhaseTransform* phase) const { return bottom_type(); } 68.51 + virtual uint hash() const { return Node::hash(); } 68.52 + virtual bool is_CFG() const { return false; } 68.53 + virtual uint ideal_reg() const { return NotAMachineReg; } 68.54 + 68.55 + ProjNode* result_node() { return proj_out(result_proj_node); } 68.56 + ProjNode* flags_node() { return proj_out(flags_proj_node); } 68.57 +protected: 68.58 + Node* no_overflow(PhaseGVN *phase, Node* new_result); 68.59 +}; 68.60 + 68.61 +class AddExactINode : public MathExactNode { 68.62 +public: 68.63 + AddExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactNode(ctrl, in1, in2) {} 68.64 + virtual int Opcode() const; 68.65 + virtual const Type* bottom_type() const { return TypeTuple::INT_CC_PAIR; } 68.66 + virtual Node* match(const ProjNode* proj, const Matcher* m); 68.67 + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 68.68 +}; 68.69 + 68.70 +class FlagsProjNode : public ProjNode { 68.71 +public: 68.72 + FlagsProjNode(Node* src, uint con) : ProjNode(src, con) { 68.73 + init_class_id(Class_FlagsProj); 68.74 + } 68.75 + 68.76 + virtual int Opcode() const; 68.77 + virtual bool is_CFG() const { return false; } 68.78 + virtual const Type* bottom_type() const { return TypeInt::CC; } 68.79 + virtual uint ideal_reg() const { return Op_RegFlags; } 68.80 +}; 68.81 + 68.82 + 68.83 +#endif 68.84 +
69.1 --- a/src/share/vm/opto/multnode.cpp Sat Oct 05 03:14:53 2013 +0200 69.2 +++ b/src/share/vm/opto/multnode.cpp Fri Oct 04 21:00:43 2013 -0700 69.3 @@ -25,6 +25,7 @@ 69.4 #include "precompiled.hpp" 69.5 #include "opto/callnode.hpp" 69.6 #include "opto/matcher.hpp" 69.7 +#include "opto/mathexactnode.hpp" 69.8 #include "opto/multnode.hpp" 69.9 #include "opto/opcodes.hpp" 69.10 #include "opto/phaseX.hpp" 69.11 @@ -46,15 +47,21 @@ 69.12 assert(Opcode() != Op_If || outcnt() == 2, "bad if #1"); 69.13 for( DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++ ) { 69.14 Node *p = fast_out(i); 69.15 - if( !p->is_Proj() ) { 69.16 + if (p->is_Proj()) { 69.17 + ProjNode *proj = p->as_Proj(); 69.18 + if (proj->_con == which_proj) { 69.19 + assert(Opcode() != Op_If || proj->Opcode() == (which_proj?Op_IfTrue:Op_IfFalse), "bad if #2"); 69.20 + return proj; 69.21 + } 69.22 + } else if (p->is_FlagsProj()) { 69.23 + FlagsProjNode *proj = p->as_FlagsProj(); 69.24 + if (proj->_con == which_proj) { 69.25 + return proj; 69.26 + } 69.27 + } else { 69.28 assert(p == this && this->is_Start(), "else must be proj"); 69.29 continue; 69.30 } 69.31 - ProjNode *proj = p->as_Proj(); 69.32 - if( proj->_con == which_proj ) { 69.33 - assert(Opcode() != Op_If || proj->Opcode() == (which_proj?Op_IfTrue:Op_IfFalse), "bad if #2"); 69.34 - return proj; 69.35 - } 69.36 } 69.37 return NULL; 69.38 }
70.1 --- a/src/share/vm/opto/node.hpp Sat Oct 05 03:14:53 2013 +0200 70.2 +++ b/src/share/vm/opto/node.hpp Fri Oct 04 21:00:43 2013 -0700 70.3 @@ -69,6 +69,7 @@ 70.4 class EncodePKlassNode; 70.5 class FastLockNode; 70.6 class FastUnlockNode; 70.7 +class FlagsProjNode; 70.8 class IfNode; 70.9 class IfFalseNode; 70.10 class IfTrueNode; 70.11 @@ -623,6 +624,7 @@ 70.12 DEFINE_CLASS_ID(Cmp, Sub, 0) 70.13 DEFINE_CLASS_ID(FastLock, Cmp, 0) 70.14 DEFINE_CLASS_ID(FastUnlock, Cmp, 1) 70.15 + DEFINE_CLASS_ID(FlagsProj, Cmp, 2) 70.16 70.17 DEFINE_CLASS_ID(MergeMem, Node, 7) 70.18 DEFINE_CLASS_ID(Bool, Node, 8) 70.19 @@ -726,6 +728,7 @@ 70.20 DEFINE_CLASS_QUERY(EncodePKlass) 70.21 DEFINE_CLASS_QUERY(FastLock) 70.22 DEFINE_CLASS_QUERY(FastUnlock) 70.23 + DEFINE_CLASS_QUERY(FlagsProj) 70.24 DEFINE_CLASS_QUERY(If) 70.25 DEFINE_CLASS_QUERY(IfFalse) 70.26 DEFINE_CLASS_QUERY(IfTrue)
71.1 --- a/src/share/vm/opto/subnode.cpp Sat Oct 05 03:14:53 2013 +0200 71.2 +++ b/src/share/vm/opto/subnode.cpp Fri Oct 04 21:00:43 2013 -0700 71.3 @@ -1064,7 +1064,7 @@ 71.4 // Print special per-node info 71.5 #ifndef PRODUCT 71.6 void BoolTest::dump_on(outputStream *st) const { 71.7 - const char *msg[] = {"eq","gt","??","lt","ne","le","??","ge"}; 71.8 + const char *msg[] = {"eq","gt","of","lt","ne","le","nof","ge"}; 71.9 st->print(msg[_test]); 71.10 } 71.11 #endif 71.12 @@ -1126,7 +1126,7 @@ 71.13 Node *cmp = in(1); 71.14 if( !cmp->is_Sub() ) return NULL; 71.15 int cop = cmp->Opcode(); 71.16 - if( cop == Op_FastLock || cop == Op_FastUnlock ) return NULL; 71.17 + if( cop == Op_FastLock || cop == Op_FastUnlock || cop == Op_FlagsProj) return NULL; 71.18 Node *cmp1 = cmp->in(1); 71.19 Node *cmp2 = cmp->in(2); 71.20 if( !cmp1 ) return NULL;
72.1 --- a/src/share/vm/opto/subnode.hpp Sat Oct 05 03:14:53 2013 +0200 72.2 +++ b/src/share/vm/opto/subnode.hpp Fri Oct 04 21:00:43 2013 -0700 72.3 @@ -263,16 +263,16 @@ 72.4 // We pick the values as 3 bits; the low order 2 bits we compare against the 72.5 // condition codes, the high bit flips the sense of the result. 72.6 struct BoolTest VALUE_OBJ_CLASS_SPEC { 72.7 - enum mask { eq = 0, ne = 4, le = 5, ge = 7, lt = 3, gt = 1, illegal = 8 }; 72.8 + enum mask { eq = 0, ne = 4, le = 5, ge = 7, lt = 3, gt = 1, overflow = 2, no_overflow = 6, illegal = 8 }; 72.9 mask _test; 72.10 BoolTest( mask btm ) : _test(btm) {} 72.11 const Type *cc2logical( const Type *CC ) const; 72.12 // Commute the test. I use a small table lookup. The table is created as 72.13 // a simple char array where each element is the ASCII version of a 'mask' 72.14 // enum from above. 72.15 - mask commute( ) const { return mask("038147858"[_test]-'0'); } 72.16 + mask commute( ) const { return mask("032147658"[_test]-'0'); } 72.17 mask negate( ) const { return mask(_test^4); } 72.18 - bool is_canonical( ) const { return (_test == BoolTest::ne || _test == BoolTest::lt || _test == BoolTest::le); } 72.19 + bool is_canonical( ) const { return (_test == BoolTest::ne || _test == BoolTest::lt || _test == BoolTest::le || _test == BoolTest::overflow); } 72.20 #ifndef PRODUCT 72.21 void dump_on(outputStream *st) const; 72.22 #endif
73.1 --- a/src/share/vm/opto/type.cpp Sat Oct 05 03:14:53 2013 +0200 73.2 +++ b/src/share/vm/opto/type.cpp Fri Oct 04 21:00:43 2013 -0700 73.3 @@ -430,6 +430,11 @@ 73.4 longpair[1] = TypeLong::LONG; 73.5 TypeTuple::LONG_PAIR = TypeTuple::make(2, longpair); 73.6 73.7 + const Type **intccpair = TypeTuple::fields(2); 73.8 + intccpair[0] = TypeInt::INT; 73.9 + intccpair[1] = TypeInt::CC; 73.10 + TypeTuple::INT_CC_PAIR = TypeTuple::make(2, intccpair); 73.11 + 73.12 _const_basic_type[T_NARROWOOP] = TypeNarrowOop::BOTTOM; 73.13 _const_basic_type[T_NARROWKLASS] = Type::BOTTOM; 73.14 _const_basic_type[T_BOOLEAN] = TypeInt::BOOL; 73.15 @@ -1646,6 +1651,7 @@ 73.16 const TypeTuple *TypeTuple::START_I2C; 73.17 const TypeTuple *TypeTuple::INT_PAIR; 73.18 const TypeTuple *TypeTuple::LONG_PAIR; 73.19 +const TypeTuple *TypeTuple::INT_CC_PAIR; 73.20 73.21 73.22 //------------------------------make-------------------------------------------
74.1 --- a/src/share/vm/opto/type.hpp Sat Oct 05 03:14:53 2013 +0200 74.2 +++ b/src/share/vm/opto/type.hpp Fri Oct 04 21:00:43 2013 -0700 74.3 @@ -584,6 +584,7 @@ 74.4 static const TypeTuple *START_I2C; 74.5 static const TypeTuple *INT_PAIR; 74.6 static const TypeTuple *LONG_PAIR; 74.7 + static const TypeTuple *INT_CC_PAIR; 74.8 #ifndef PRODUCT 74.9 virtual void dump2( Dict &d, uint, outputStream *st ) const; // Specialized per-Type dumping 74.10 #endif
75.1 --- a/src/share/vm/prims/jvm.cpp Sat Oct 05 03:14:53 2013 +0200 75.2 +++ b/src/share/vm/prims/jvm.cpp Fri Oct 04 21:00:43 2013 -0700 75.3 @@ -3984,13 +3984,13 @@ 75.4 75.5 JVM_LEAF(jboolean, JVM_AccessVMBooleanFlag(const char* name, jboolean* value, jboolean is_get)) 75.6 JVMWrapper("JVM_AccessBoolVMFlag"); 75.7 - return is_get ? CommandLineFlags::boolAt((char*) name, (bool*) value) : CommandLineFlags::boolAtPut((char*) name, (bool*) value, INTERNAL); 75.8 + return is_get ? CommandLineFlags::boolAt((char*) name, (bool*) value) : CommandLineFlags::boolAtPut((char*) name, (bool*) value, Flag::INTERNAL); 75.9 JVM_END 75.10 75.11 JVM_LEAF(jboolean, JVM_AccessVMIntFlag(const char* name, jint* value, jboolean is_get)) 75.12 JVMWrapper("JVM_AccessVMIntFlag"); 75.13 intx v; 75.14 - jboolean result = is_get ? CommandLineFlags::intxAt((char*) name, &v) : CommandLineFlags::intxAtPut((char*) name, &v, INTERNAL); 75.15 + jboolean result = is_get ? CommandLineFlags::intxAt((char*) name, &v) : CommandLineFlags::intxAtPut((char*) name, &v, Flag::INTERNAL); 75.16 *value = (jint)v; 75.17 return result; 75.18 JVM_END
76.1 --- a/src/share/vm/runtime/arguments.cpp Sat Oct 05 03:14:53 2013 +0200 76.2 +++ b/src/share/vm/runtime/arguments.cpp Fri Oct 04 21:00:43 2013 -0700 76.3 @@ -625,11 +625,11 @@ 76.4 } 76.5 } 76.6 76.7 -static bool set_bool_flag(char* name, bool value, FlagValueOrigin origin) { 76.8 +static bool set_bool_flag(char* name, bool value, Flag::Flags origin) { 76.9 return CommandLineFlags::boolAtPut(name, &value, origin); 76.10 } 76.11 76.12 -static bool set_fp_numeric_flag(char* name, char* value, FlagValueOrigin origin) { 76.13 +static bool set_fp_numeric_flag(char* name, char* value, Flag::Flags origin) { 76.14 double v; 76.15 if (sscanf(value, "%lf", &v) != 1) { 76.16 return false; 76.17 @@ -641,7 +641,7 @@ 76.18 return false; 76.19 } 76.20 76.21 -static bool set_numeric_flag(char* name, char* value, FlagValueOrigin origin) { 76.22 +static bool set_numeric_flag(char* name, char* value, Flag::Flags origin) { 76.23 julong v; 76.24 intx intx_v; 76.25 bool is_neg = false; 76.26 @@ -674,14 +674,14 @@ 76.27 return false; 76.28 } 76.29 76.30 -static bool set_string_flag(char* name, const char* value, FlagValueOrigin origin) { 76.31 +static bool set_string_flag(char* name, const char* value, Flag::Flags origin) { 76.32 if (!CommandLineFlags::ccstrAtPut(name, &value, origin)) return false; 76.33 // Contract: CommandLineFlags always returns a pointer that needs freeing. 76.34 FREE_C_HEAP_ARRAY(char, value, mtInternal); 76.35 return true; 76.36 } 76.37 76.38 -static bool append_to_string_flag(char* name, const char* new_value, FlagValueOrigin origin) { 76.39 +static bool append_to_string_flag(char* name, const char* new_value, Flag::Flags origin) { 76.40 const char* old_value = ""; 76.41 if (!CommandLineFlags::ccstrAt(name, &old_value)) return false; 76.42 size_t old_len = old_value != NULL ? strlen(old_value) : 0; 76.43 @@ -709,7 +709,7 @@ 76.44 return true; 76.45 } 76.46 76.47 -bool Arguments::parse_argument(const char* arg, FlagValueOrigin origin) { 76.48 +bool Arguments::parse_argument(const char* arg, Flag::Flags origin) { 76.49 76.50 // range of acceptable characters spelled out for portability reasons 76.51 #define NAME_RANGE "[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]" 76.52 @@ -850,7 +850,7 @@ 76.53 } 76.54 76.55 bool Arguments::process_argument(const char* arg, 76.56 - jboolean ignore_unrecognized, FlagValueOrigin origin) { 76.57 + jboolean ignore_unrecognized, Flag::Flags origin) { 76.58 76.59 JDK_Version since = JDK_Version(); 76.60 76.61 @@ -904,7 +904,7 @@ 76.62 jio_fprintf(defaultStream::error_stream(), 76.63 "Did you mean '%s%s%s'?\n", 76.64 (fuzzy_matched->is_bool()) ? "(+/-)" : "", 76.65 - fuzzy_matched->name, 76.66 + fuzzy_matched->_name, 76.67 (fuzzy_matched->is_bool()) ? "" : "=<value>"); 76.68 } 76.69 } 76.70 @@ -952,7 +952,7 @@ 76.71 // this allows a way to include spaces in string-valued options 76.72 token[pos] = '\0'; 76.73 logOption(token); 76.74 - result &= process_argument(token, ignore_unrecognized, CONFIG_FILE); 76.75 + result &= process_argument(token, ignore_unrecognized, Flag::CONFIG_FILE); 76.76 build_jvm_flags(token); 76.77 pos = 0; 76.78 in_white_space = true; 76.79 @@ -970,7 +970,7 @@ 76.80 } 76.81 if (pos > 0) { 76.82 token[pos] = '\0'; 76.83 - result &= process_argument(token, ignore_unrecognized, CONFIG_FILE); 76.84 + result &= process_argument(token, ignore_unrecognized, Flag::CONFIG_FILE); 76.85 build_jvm_flags(token); 76.86 } 76.87 fclose(stream); 76.88 @@ -1132,6 +1132,9 @@ 76.89 Tier3InvokeNotifyFreqLog = 0; 76.90 Tier4InvocationThreshold = 0; 76.91 } 76.92 + if (FLAG_IS_DEFAULT(NmethodSweepFraction)) { 76.93 + FLAG_SET_DEFAULT(NmethodSweepFraction, 1 + ReservedCodeCacheSize / (16 * M)); 76.94 + } 76.95 } 76.96 76.97 #if INCLUDE_ALL_GCS 76.98 @@ -2337,6 +2340,10 @@ 76.99 (2*G)/M); 76.100 status = false; 76.101 } 76.102 + 76.103 + status &= verify_interval(NmethodSweepFraction, 1, ReservedCodeCacheSize/K, "NmethodSweepFraction"); 76.104 + status &= verify_interval(NmethodSweepActivity, 0, 2000, "NmethodSweepActivity"); 76.105 + 76.106 return status; 76.107 } 76.108 76.109 @@ -2438,7 +2445,7 @@ 76.110 } 76.111 76.112 // Parse JavaVMInitArgs structure passed in 76.113 - result = parse_each_vm_init_arg(args, &scp, &scp_assembly_required, COMMAND_LINE); 76.114 + result = parse_each_vm_init_arg(args, &scp, &scp_assembly_required, Flag::COMMAND_LINE); 76.115 if (result != JNI_OK) { 76.116 return result; 76.117 } 76.118 @@ -2510,7 +2517,7 @@ 76.119 jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, 76.120 SysClassPath* scp_p, 76.121 bool* scp_assembly_required_p, 76.122 - FlagValueOrigin origin) { 76.123 + Flag::Flags origin) { 76.124 // Remaining part of option string 76.125 const char* tail; 76.126 76.127 @@ -3333,7 +3340,7 @@ 76.128 } 76.129 } 76.130 76.131 - return(parse_each_vm_init_arg(&vm_args, scp_p, scp_assembly_required_p, ENVIRON_VAR)); 76.132 + return(parse_each_vm_init_arg(&vm_args, scp_p, scp_assembly_required_p, Flag::ENVIRON_VAR)); 76.133 } 76.134 return JNI_OK; 76.135 }
77.1 --- a/src/share/vm/runtime/arguments.hpp Sat Oct 05 03:14:53 2013 +0200 77.2 +++ b/src/share/vm/runtime/arguments.hpp Fri Oct 04 21:00:43 2013 -0700 77.3 @@ -360,15 +360,15 @@ 77.4 77.5 // Argument parsing 77.6 static void do_pd_flag_adjustments(); 77.7 - static bool parse_argument(const char* arg, FlagValueOrigin origin); 77.8 - static bool process_argument(const char* arg, jboolean ignore_unrecognized, FlagValueOrigin origin); 77.9 + static bool parse_argument(const char* arg, Flag::Flags origin); 77.10 + static bool process_argument(const char* arg, jboolean ignore_unrecognized, Flag::Flags origin); 77.11 static void process_java_launcher_argument(const char*, void*); 77.12 static void process_java_compiler_argument(char* arg); 77.13 static jint parse_options_environment_variable(const char* name, SysClassPath* scp_p, bool* scp_assembly_required_p); 77.14 static jint parse_java_tool_options_environment_variable(SysClassPath* scp_p, bool* scp_assembly_required_p); 77.15 static jint parse_java_options_environment_variable(SysClassPath* scp_p, bool* scp_assembly_required_p); 77.16 static jint parse_vm_init_args(const JavaVMInitArgs* args); 77.17 - static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, SysClassPath* scp_p, bool* scp_assembly_required_p, FlagValueOrigin origin); 77.18 + static jint parse_each_vm_init_arg(const JavaVMInitArgs* args, SysClassPath* scp_p, bool* scp_assembly_required_p, Flag::Flags origin); 77.19 static jint finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_required); 77.20 static bool is_bad_option(const JavaVMOption* option, jboolean ignore, 77.21 const char* option_type);
78.1 --- a/src/share/vm/runtime/globals.cpp Sat Oct 05 03:14:53 2013 +0200 78.2 +++ b/src/share/vm/runtime/globals.cpp Fri Oct 04 21:00:43 2013 -0700 78.3 @@ -62,26 +62,174 @@ 78.4 MATERIALIZE_FLAGS_EXT 78.5 78.6 78.7 +void Flag::check_writable() { 78.8 + if (is_constant_in_binary()) { 78.9 + fatal(err_msg("flag is constant: %s", _name)); 78.10 + } 78.11 +} 78.12 + 78.13 +bool Flag::is_bool() const { 78.14 + return strcmp(_type, "bool") == 0; 78.15 +} 78.16 + 78.17 +bool Flag::get_bool() const { 78.18 + return *((bool*) _addr); 78.19 +} 78.20 + 78.21 +void Flag::set_bool(bool value) { 78.22 + check_writable(); 78.23 + *((bool*) _addr) = value; 78.24 +} 78.25 + 78.26 +bool Flag::is_intx() const { 78.27 + return strcmp(_type, "intx") == 0; 78.28 +} 78.29 + 78.30 +intx Flag::get_intx() const { 78.31 + return *((intx*) _addr); 78.32 +} 78.33 + 78.34 +void Flag::set_intx(intx value) { 78.35 + check_writable(); 78.36 + *((intx*) _addr) = value; 78.37 +} 78.38 + 78.39 +bool Flag::is_uintx() const { 78.40 + return strcmp(_type, "uintx") == 0; 78.41 +} 78.42 + 78.43 +uintx Flag::get_uintx() const { 78.44 + return *((uintx*) _addr); 78.45 +} 78.46 + 78.47 +void Flag::set_uintx(uintx value) { 78.48 + check_writable(); 78.49 + *((uintx*) _addr) = value; 78.50 +} 78.51 + 78.52 +bool Flag::is_uint64_t() const { 78.53 + return strcmp(_type, "uint64_t") == 0; 78.54 +} 78.55 + 78.56 +uint64_t Flag::get_uint64_t() const { 78.57 + return *((uint64_t*) _addr); 78.58 +} 78.59 + 78.60 +void Flag::set_uint64_t(uint64_t value) { 78.61 + check_writable(); 78.62 + *((uint64_t*) _addr) = value; 78.63 +} 78.64 + 78.65 +bool Flag::is_double() const { 78.66 + return strcmp(_type, "double") == 0; 78.67 +} 78.68 + 78.69 +double Flag::get_double() const { 78.70 + return *((double*) _addr); 78.71 +} 78.72 + 78.73 +void Flag::set_double(double value) { 78.74 + check_writable(); 78.75 + *((double*) _addr) = value; 78.76 +} 78.77 + 78.78 +bool Flag::is_ccstr() const { 78.79 + return strcmp(_type, "ccstr") == 0 || strcmp(_type, "ccstrlist") == 0; 78.80 +} 78.81 + 78.82 +bool Flag::ccstr_accumulates() const { 78.83 + return strcmp(_type, "ccstrlist") == 0; 78.84 +} 78.85 + 78.86 +ccstr Flag::get_ccstr() const { 78.87 + return *((ccstr*) _addr); 78.88 +} 78.89 + 78.90 +void Flag::set_ccstr(ccstr value) { 78.91 + check_writable(); 78.92 + *((ccstr*) _addr) = value; 78.93 +} 78.94 + 78.95 + 78.96 +Flag::Flags Flag::get_origin() { 78.97 + return Flags(_flags & VALUE_ORIGIN_MASK); 78.98 +} 78.99 + 78.100 +void Flag::set_origin(Flags origin) { 78.101 + assert((origin & VALUE_ORIGIN_MASK) == origin, "sanity"); 78.102 + _flags = Flags((_flags & ~VALUE_ORIGIN_MASK) | origin); 78.103 +} 78.104 + 78.105 +bool Flag::is_default() { 78.106 + return (get_origin() == DEFAULT); 78.107 +} 78.108 + 78.109 +bool Flag::is_ergonomic() { 78.110 + return (get_origin() == ERGONOMIC); 78.111 +} 78.112 + 78.113 +bool Flag::is_command_line() { 78.114 + return (get_origin() == COMMAND_LINE); 78.115 +} 78.116 + 78.117 +bool Flag::is_product() const { 78.118 + return (_flags & KIND_PRODUCT) != 0; 78.119 +} 78.120 + 78.121 +bool Flag::is_manageable() const { 78.122 + return (_flags & KIND_MANAGEABLE) != 0; 78.123 +} 78.124 + 78.125 +bool Flag::is_diagnostic() const { 78.126 + return (_flags & KIND_DIAGNOSTIC) != 0; 78.127 +} 78.128 + 78.129 +bool Flag::is_experimental() const { 78.130 + return (_flags & KIND_EXPERIMENTAL) != 0; 78.131 +} 78.132 + 78.133 +bool Flag::is_notproduct() const { 78.134 + return (_flags & KIND_NOT_PRODUCT) != 0; 78.135 +} 78.136 + 78.137 +bool Flag::is_develop() const { 78.138 + return (_flags & KIND_DEVELOP) != 0; 78.139 +} 78.140 + 78.141 +bool Flag::is_read_write() const { 78.142 + return (_flags & KIND_READ_WRITE) != 0; 78.143 +} 78.144 + 78.145 +bool Flag::is_commercial() const { 78.146 + return (_flags & KIND_COMMERCIAL) != 0; 78.147 +} 78.148 + 78.149 +/** 78.150 + * Returns if this flag is a constant in the binary. Right now this is 78.151 + * true for notproduct and develop flags in product builds. 78.152 + */ 78.153 +bool Flag::is_constant_in_binary() const { 78.154 +#ifdef PRODUCT 78.155 + return is_notproduct() || is_develop(); 78.156 +#else 78.157 + return false; 78.158 +#endif 78.159 +} 78.160 + 78.161 bool Flag::is_unlocker() const { 78.162 - return strcmp(name, "UnlockDiagnosticVMOptions") == 0 || 78.163 - strcmp(name, "UnlockExperimentalVMOptions") == 0 || 78.164 + return strcmp(_name, "UnlockDiagnosticVMOptions") == 0 || 78.165 + strcmp(_name, "UnlockExperimentalVMOptions") == 0 || 78.166 is_unlocker_ext(); 78.167 } 78.168 78.169 bool Flag::is_unlocked() const { 78.170 - if (strcmp(kind, "{diagnostic}") == 0 || 78.171 - strcmp(kind, "{C2 diagnostic}") == 0 || 78.172 - strcmp(kind, "{ARCH diagnostic}") == 0 || 78.173 - strcmp(kind, "{Shark diagnostic}") == 0) { 78.174 + if (is_diagnostic()) { 78.175 return UnlockDiagnosticVMOptions; 78.176 - } else if (strcmp(kind, "{experimental}") == 0 || 78.177 - strcmp(kind, "{C2 experimental}") == 0 || 78.178 - strcmp(kind, "{ARCH experimental}") == 0 || 78.179 - strcmp(kind, "{Shark experimental}") == 0) { 78.180 + } 78.181 + if (is_experimental()) { 78.182 return UnlockExperimentalVMOptions; 78.183 - } else { 78.184 - return is_unlocked_ext(); 78.185 } 78.186 + return is_unlocked_ext(); 78.187 } 78.188 78.189 // Get custom message for this locked flag, or return NULL if 78.190 @@ -91,16 +239,14 @@ 78.191 } 78.192 78.193 bool Flag::is_writeable() const { 78.194 - return strcmp(kind, "{manageable}") == 0 || 78.195 - strcmp(kind, "{product rw}") == 0 || 78.196 - is_writeable_ext(); 78.197 + return is_manageable() || (is_product() && is_read_write()) || is_writeable_ext(); 78.198 } 78.199 78.200 // All flags except "manageable" are assumed to be internal flags. 78.201 // Long term, we need to define a mechanism to specify which flags 78.202 // are external/stable and change this function accordingly. 78.203 bool Flag::is_external() const { 78.204 - return strcmp(kind, "{manageable}") == 0 || is_external_ext(); 78.205 + return is_manageable() || is_external_ext(); 78.206 } 78.207 78.208 78.209 @@ -108,53 +254,113 @@ 78.210 #define FORMAT_BUFFER_LEN 16 78.211 78.212 void Flag::print_on(outputStream* st, bool withComments) { 78.213 - st->print("%9s %-40s %c= ", type, name, (origin != DEFAULT ? ':' : ' ')); 78.214 - if (is_bool()) st->print("%-16s", get_bool() ? "true" : "false"); 78.215 - if (is_intx()) st->print("%-16ld", get_intx()); 78.216 - if (is_uintx()) st->print("%-16lu", get_uintx()); 78.217 - if (is_uint64_t()) st->print("%-16lu", get_uint64_t()); 78.218 - if (is_double()) st->print("%-16f", get_double()); 78.219 + // Don't print notproduct and develop flags in a product build. 78.220 + if (is_constant_in_binary()) { 78.221 + return; 78.222 + } 78.223 78.224 + st->print("%9s %-40s %c= ", _type, _name, (!is_default() ? ':' : ' ')); 78.225 + 78.226 + if (is_bool()) { 78.227 + st->print("%-16s", get_bool() ? "true" : "false"); 78.228 + } 78.229 + if (is_intx()) { 78.230 + st->print("%-16ld", get_intx()); 78.231 + } 78.232 + if (is_uintx()) { 78.233 + st->print("%-16lu", get_uintx()); 78.234 + } 78.235 + if (is_uint64_t()) { 78.236 + st->print("%-16lu", get_uint64_t()); 78.237 + } 78.238 + if (is_double()) { 78.239 + st->print("%-16f", get_double()); 78.240 + } 78.241 if (is_ccstr()) { 78.242 - const char* cp = get_ccstr(); 78.243 - if (cp != NULL) { 78.244 - const char* eol; 78.245 - while ((eol = strchr(cp, '\n')) != NULL) { 78.246 - char format_buffer[FORMAT_BUFFER_LEN]; 78.247 - size_t llen = pointer_delta(eol, cp, sizeof(char)); 78.248 - jio_snprintf(format_buffer, FORMAT_BUFFER_LEN, 78.249 - "%%." SIZE_FORMAT "s", llen); 78.250 - st->print(format_buffer, cp); 78.251 - st->cr(); 78.252 - cp = eol+1; 78.253 - st->print("%5s %-35s += ", "", name); 78.254 - } 78.255 - st->print("%-16s", cp); 78.256 - } 78.257 - else st->print("%-16s", ""); 78.258 + const char* cp = get_ccstr(); 78.259 + if (cp != NULL) { 78.260 + const char* eol; 78.261 + while ((eol = strchr(cp, '\n')) != NULL) { 78.262 + char format_buffer[FORMAT_BUFFER_LEN]; 78.263 + size_t llen = pointer_delta(eol, cp, sizeof(char)); 78.264 + jio_snprintf(format_buffer, FORMAT_BUFFER_LEN, 78.265 + "%%." SIZE_FORMAT "s", llen); 78.266 + st->print(format_buffer, cp); 78.267 + st->cr(); 78.268 + cp = eol+1; 78.269 + st->print("%5s %-35s += ", "", _name); 78.270 + } 78.271 + st->print("%-16s", cp); 78.272 + } 78.273 + else st->print("%-16s", ""); 78.274 } 78.275 - st->print("%-20s", kind); 78.276 + 78.277 + st->print("%-20"); 78.278 + print_kind(st); 78.279 + 78.280 if (withComments) { 78.281 #ifndef PRODUCT 78.282 - st->print("%s", doc ); 78.283 + st->print("%s", _doc); 78.284 #endif 78.285 } 78.286 st->cr(); 78.287 } 78.288 78.289 +void Flag::print_kind(outputStream* st) { 78.290 + struct Data { 78.291 + int flag; 78.292 + const char* name; 78.293 + }; 78.294 + 78.295 + Data data[] = { 78.296 + { KIND_C1, "C1" }, 78.297 + { KIND_C2, "C2" }, 78.298 + { KIND_ARCH, "ARCH" }, 78.299 + { KIND_SHARK, "SHARK" }, 78.300 + { KIND_PLATFORM_DEPENDENT, "pd" }, 78.301 + { KIND_PRODUCT, "product" }, 78.302 + { KIND_MANAGEABLE, "manageable" }, 78.303 + { KIND_DIAGNOSTIC, "diagnostic" }, 78.304 + { KIND_NOT_PRODUCT, "notproduct" }, 78.305 + { KIND_DEVELOP, "develop" }, 78.306 + { KIND_LP64_PRODUCT, "lp64_product" }, 78.307 + { KIND_READ_WRITE, "rw" }, 78.308 + { -1, "" } 78.309 + }; 78.310 + 78.311 + if ((_flags & KIND_MASK) != 0) { 78.312 + st->print("{"); 78.313 + bool is_first = true; 78.314 + 78.315 + for (int i = 0; data[i].flag != -1; i++) { 78.316 + Data d = data[i]; 78.317 + if ((_flags & d.flag) != 0) { 78.318 + if (is_first) { 78.319 + is_first = false; 78.320 + } else { 78.321 + st->print(" "); 78.322 + } 78.323 + st->print(d.name); 78.324 + } 78.325 + } 78.326 + 78.327 + st->print("}"); 78.328 + } 78.329 +} 78.330 + 78.331 void Flag::print_as_flag(outputStream* st) { 78.332 if (is_bool()) { 78.333 - st->print("-XX:%s%s", get_bool() ? "+" : "-", name); 78.334 + st->print("-XX:%s%s", get_bool() ? "+" : "-", _name); 78.335 } else if (is_intx()) { 78.336 - st->print("-XX:%s=" INTX_FORMAT, name, get_intx()); 78.337 + st->print("-XX:%s=" INTX_FORMAT, _name, get_intx()); 78.338 } else if (is_uintx()) { 78.339 - st->print("-XX:%s=" UINTX_FORMAT, name, get_uintx()); 78.340 + st->print("-XX:%s=" UINTX_FORMAT, _name, get_uintx()); 78.341 } else if (is_uint64_t()) { 78.342 - st->print("-XX:%s=" UINT64_FORMAT, name, get_uint64_t()); 78.343 + st->print("-XX:%s=" UINT64_FORMAT, _name, get_uint64_t()); 78.344 } else if (is_double()) { 78.345 - st->print("-XX:%s=%f", name, get_double()); 78.346 + st->print("-XX:%s=%f", _name, get_double()); 78.347 } else if (is_ccstr()) { 78.348 - st->print("-XX:%s=", name); 78.349 + st->print("-XX:%s=", _name); 78.350 const char* cp = get_ccstr(); 78.351 if (cp != NULL) { 78.352 // Need to turn embedded '\n's back into separate arguments 78.353 @@ -167,7 +373,7 @@ 78.354 st->print("%c", *cp); 78.355 break; 78.356 case '\n': 78.357 - st->print(" -XX:%s=", name); 78.358 + st->print(" -XX:%s=", _name); 78.359 break; 78.360 } 78.361 } 78.362 @@ -180,79 +386,51 @@ 78.363 // 4991491 do not "optimize out" the was_set false values: omitting them 78.364 // tickles a Microsoft compiler bug causing flagTable to be malformed 78.365 78.366 -#define RUNTIME_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{product}", DEFAULT }, 78.367 -#define RUNTIME_PD_PRODUCT_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{pd product}", DEFAULT }, 78.368 -#define RUNTIME_DIAGNOSTIC_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{diagnostic}", DEFAULT }, 78.369 -#define RUNTIME_EXPERIMENTAL_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{experimental}", DEFAULT }, 78.370 -#define RUNTIME_MANAGEABLE_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{manageable}", DEFAULT }, 78.371 -#define RUNTIME_PRODUCT_RW_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{product rw}", DEFAULT }, 78.372 +#define NAME(name) NOT_PRODUCT(&name) PRODUCT_ONLY(&CONST_##name) 78.373 78.374 -#ifdef PRODUCT 78.375 - #define RUNTIME_DEVELOP_FLAG_STRUCT(type, name, value, doc) /* flag is constant */ 78.376 - #define RUNTIME_PD_DEVELOP_FLAG_STRUCT(type, name, doc) /* flag is constant */ 78.377 - #define RUNTIME_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) 78.378 -#else 78.379 - #define RUNTIME_DEVELOP_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "", DEFAULT }, 78.380 - #define RUNTIME_PD_DEVELOP_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, doc, "{pd}", DEFAULT }, 78.381 - #define RUNTIME_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "{notproduct}", DEFAULT }, 78.382 -#endif 78.383 +#define RUNTIME_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_PRODUCT) }, 78.384 +#define RUNTIME_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_PRODUCT | Flag::KIND_PLATFORM_DEPENDENT) }, 78.385 +#define RUNTIME_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_DIAGNOSTIC) }, 78.386 +#define RUNTIME_EXPERIMENTAL_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_EXPERIMENTAL) }, 78.387 +#define RUNTIME_MANAGEABLE_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_MANAGEABLE) }, 78.388 +#define RUNTIME_PRODUCT_RW_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_PRODUCT | Flag::KIND_READ_WRITE) }, 78.389 +#define RUNTIME_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_DEVELOP) }, 78.390 +#define RUNTIME_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) }, 78.391 +#define RUNTIME_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_NOT_PRODUCT) }, 78.392 78.393 #ifdef _LP64 78.394 - #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{lp64_product}", DEFAULT }, 78.395 +#define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_LP64_PRODUCT) }, 78.396 #else 78.397 - #define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) /* flag is constant */ 78.398 +#define RUNTIME_LP64_PRODUCT_FLAG_STRUCT(type, name, value, doc) /* flag is constant */ 78.399 #endif // _LP64 78.400 78.401 -#define C1_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{C1 product}", DEFAULT }, 78.402 -#define C1_PD_PRODUCT_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{C1 pd product}", DEFAULT }, 78.403 -#define C1_DIAGNOSTIC_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{C1 diagnostic}", DEFAULT }, 78.404 -#ifdef PRODUCT 78.405 - #define C1_DEVELOP_FLAG_STRUCT(type, name, value, doc) /* flag is constant */ 78.406 - #define C1_PD_DEVELOP_FLAG_STRUCT(type, name, doc) /* flag is constant */ 78.407 - #define C1_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) 78.408 -#else 78.409 - #define C1_DEVELOP_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "{C1}", DEFAULT }, 78.410 - #define C1_PD_DEVELOP_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, doc, "{C1 pd}", DEFAULT }, 78.411 - #define C1_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "{C1 notproduct}", DEFAULT }, 78.412 -#endif 78.413 +#define C1_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_PRODUCT) }, 78.414 +#define C1_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_PRODUCT | Flag::KIND_PLATFORM_DEPENDENT) }, 78.415 +#define C1_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_DIAGNOSTIC) }, 78.416 +#define C1_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_DEVELOP) }, 78.417 +#define C1_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) }, 78.418 +#define C1_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C1 | Flag::KIND_NOT_PRODUCT) }, 78.419 78.420 -#define C2_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{C2 product}", DEFAULT }, 78.421 -#define C2_PD_PRODUCT_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{C2 pd product}", DEFAULT }, 78.422 -#define C2_DIAGNOSTIC_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{C2 diagnostic}", DEFAULT }, 78.423 -#define C2_EXPERIMENTAL_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{C2 experimental}", DEFAULT }, 78.424 -#ifdef PRODUCT 78.425 - #define C2_DEVELOP_FLAG_STRUCT(type, name, value, doc) /* flag is constant */ 78.426 - #define C2_PD_DEVELOP_FLAG_STRUCT(type, name, doc) /* flag is constant */ 78.427 - #define C2_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) 78.428 -#else 78.429 - #define C2_DEVELOP_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "{C2}", DEFAULT }, 78.430 - #define C2_PD_DEVELOP_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, doc, "{C2 pd}", DEFAULT }, 78.431 - #define C2_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "{C2 notproduct}", DEFAULT }, 78.432 -#endif 78.433 +#define C2_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_PRODUCT) }, 78.434 +#define C2_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_PRODUCT | Flag::KIND_PLATFORM_DEPENDENT) }, 78.435 +#define C2_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_DIAGNOSTIC) }, 78.436 +#define C2_EXPERIMENTAL_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_EXPERIMENTAL) }, 78.437 +#define C2_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_DEVELOP) }, 78.438 +#define C2_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) }, 78.439 +#define C2_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_C2 | Flag::KIND_NOT_PRODUCT) }, 78.440 78.441 -#define ARCH_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{ARCH product}", DEFAULT }, 78.442 -#define ARCH_DIAGNOSTIC_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{ARCH diagnostic}", DEFAULT }, 78.443 -#define ARCH_EXPERIMENTAL_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{ARCH experimental}", DEFAULT }, 78.444 -#ifdef PRODUCT 78.445 - #define ARCH_DEVELOP_FLAG_STRUCT(type, name, value, doc) /* flag is constant */ 78.446 - #define ARCH_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) 78.447 -#else 78.448 - #define ARCH_DEVELOP_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "{ARCH}", DEFAULT }, 78.449 - #define ARCH_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "{ARCH notproduct}", DEFAULT }, 78.450 -#endif 78.451 +#define ARCH_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_PRODUCT) }, 78.452 +#define ARCH_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_DIAGNOSTIC) }, 78.453 +#define ARCH_EXPERIMENTAL_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_EXPERIMENTAL) }, 78.454 +#define ARCH_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_DEVELOP) }, 78.455 +#define ARCH_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_NOT_PRODUCT) }, 78.456 78.457 -#define SHARK_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{Shark product}", DEFAULT }, 78.458 -#define SHARK_PD_PRODUCT_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{Shark pd product}", DEFAULT }, 78.459 -#define SHARK_DIAGNOSTIC_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{Shark diagnostic}", DEFAULT }, 78.460 -#ifdef PRODUCT 78.461 - #define SHARK_DEVELOP_FLAG_STRUCT(type, name, value, doc) /* flag is constant */ 78.462 - #define SHARK_PD_DEVELOP_FLAG_STRUCT(type, name, doc) /* flag is constant */ 78.463 - #define SHARK_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) 78.464 -#else 78.465 - #define SHARK_DEVELOP_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "{Shark}", DEFAULT }, 78.466 - #define SHARK_PD_DEVELOP_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, doc, "{Shark pd}", DEFAULT }, 78.467 - #define SHARK_NOTPRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, doc, "{Shark notproduct}", DEFAULT }, 78.468 -#endif 78.469 +#define SHARK_PRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_PRODUCT) }, 78.470 +#define SHARK_PD_PRODUCT_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_PRODUCT | Flag::KIND_PLATFORM_DEPENDENT) }, 78.471 +#define SHARK_DIAGNOSTIC_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_DIAGNOSTIC) }, 78.472 +#define SHARK_DEVELOP_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_DEVELOP) }, 78.473 +#define SHARK_PD_DEVELOP_FLAG_STRUCT( type, name, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_DEVELOP | Flag::KIND_PLATFORM_DEPENDENT) }, 78.474 +#define SHARK_NOTPRODUCT_FLAG_STRUCT( type, name, value, doc) { #type, XSTR(name), NAME(name), NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_SHARK | Flag::KIND_NOT_PRODUCT) }, 78.475 78.476 static Flag flagTable[] = { 78.477 RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT, RUNTIME_LP64_PRODUCT_FLAG_STRUCT) 78.478 @@ -285,9 +463,14 @@ 78.479 78.480 // Search the flag table for a named flag 78.481 Flag* Flag::find_flag(const char* name, size_t length, bool allow_locked) { 78.482 - for (Flag* current = &flagTable[0]; current->name != NULL; current++) { 78.483 - if (str_equal(current->name, name, length)) { 78.484 - // Found a matching entry. Report locked flags only if allowed. 78.485 + for (Flag* current = &flagTable[0]; current->_name != NULL; current++) { 78.486 + if (str_equal(current->_name, name, length)) { 78.487 + // Found a matching entry. 78.488 + // Don't report notproduct and develop flags in product builds. 78.489 + if (current->is_constant_in_binary()) { 78.490 + return NULL; 78.491 + } 78.492 + // Report locked flags only if allowed. 78.493 if (!(current->is_unlocked() || current->is_unlocker())) { 78.494 if (!allow_locked) { 78.495 // disable use of locked flags, e.g. diagnostic, experimental, 78.496 @@ -327,8 +510,8 @@ 78.497 float score; 78.498 float max_score = -1; 78.499 78.500 - for (Flag* current = &flagTable[0]; current->name != NULL; current++) { 78.501 - score = str_similar(current->name, name, length); 78.502 + for (Flag* current = &flagTable[0]; current->_name != NULL; current++) { 78.503 + score = str_similar(current->_name, name, length); 78.504 if (score > max_score) { 78.505 max_score = score; 78.506 match = current; 78.507 @@ -357,25 +540,25 @@ 78.508 bool CommandLineFlagsEx::is_default(CommandLineFlag flag) { 78.509 assert((size_t)flag < Flag::numFlags, "bad command line flag index"); 78.510 Flag* f = &Flag::flags[flag]; 78.511 - return (f->origin == DEFAULT); 78.512 + return f->is_default(); 78.513 } 78.514 78.515 bool CommandLineFlagsEx::is_ergo(CommandLineFlag flag) { 78.516 assert((size_t)flag < Flag::numFlags, "bad command line flag index"); 78.517 Flag* f = &Flag::flags[flag]; 78.518 - return (f->origin == ERGONOMIC); 78.519 + return f->is_ergonomic(); 78.520 } 78.521 78.522 bool CommandLineFlagsEx::is_cmdline(CommandLineFlag flag) { 78.523 assert((size_t)flag < Flag::numFlags, "bad command line flag index"); 78.524 Flag* f = &Flag::flags[flag]; 78.525 - return (f->origin == COMMAND_LINE); 78.526 + return f->is_command_line(); 78.527 } 78.528 78.529 bool CommandLineFlags::wasSetOnCmdline(const char* name, bool* value) { 78.530 Flag* result = Flag::find_flag((char*)name, strlen(name)); 78.531 if (result == NULL) return false; 78.532 - *value = (result->origin == COMMAND_LINE); 78.533 + *value = result->is_command_line(); 78.534 return true; 78.535 } 78.536 78.537 @@ -387,22 +570,22 @@ 78.538 return true; 78.539 } 78.540 78.541 -bool CommandLineFlags::boolAtPut(char* name, size_t len, bool* value, FlagValueOrigin origin) { 78.542 +bool CommandLineFlags::boolAtPut(char* name, size_t len, bool* value, Flag::Flags origin) { 78.543 Flag* result = Flag::find_flag(name, len); 78.544 if (result == NULL) return false; 78.545 if (!result->is_bool()) return false; 78.546 bool old_value = result->get_bool(); 78.547 result->set_bool(*value); 78.548 *value = old_value; 78.549 - result->origin = origin; 78.550 + result->set_origin(origin); 78.551 return true; 78.552 } 78.553 78.554 -void CommandLineFlagsEx::boolAtPut(CommandLineFlagWithType flag, bool value, FlagValueOrigin origin) { 78.555 +void CommandLineFlagsEx::boolAtPut(CommandLineFlagWithType flag, bool value, Flag::Flags origin) { 78.556 Flag* faddr = address_of_flag(flag); 78.557 guarantee(faddr != NULL && faddr->is_bool(), "wrong flag type"); 78.558 faddr->set_bool(value); 78.559 - faddr->origin = origin; 78.560 + faddr->set_origin(origin); 78.561 } 78.562 78.563 bool CommandLineFlags::intxAt(char* name, size_t len, intx* value) { 78.564 @@ -413,22 +596,22 @@ 78.565 return true; 78.566 } 78.567 78.568 -bool CommandLineFlags::intxAtPut(char* name, size_t len, intx* value, FlagValueOrigin origin) { 78.569 +bool CommandLineFlags::intxAtPut(char* name, size_t len, intx* value, Flag::Flags origin) { 78.570 Flag* result = Flag::find_flag(name, len); 78.571 if (result == NULL) return false; 78.572 if (!result->is_intx()) return false; 78.573 intx old_value = result->get_intx(); 78.574 result->set_intx(*value); 78.575 *value = old_value; 78.576 - result->origin = origin; 78.577 + result->set_origin(origin); 78.578 return true; 78.579 } 78.580 78.581 -void CommandLineFlagsEx::intxAtPut(CommandLineFlagWithType flag, intx value, FlagValueOrigin origin) { 78.582 +void CommandLineFlagsEx::intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin) { 78.583 Flag* faddr = address_of_flag(flag); 78.584 guarantee(faddr != NULL && faddr->is_intx(), "wrong flag type"); 78.585 faddr->set_intx(value); 78.586 - faddr->origin = origin; 78.587 + faddr->set_origin(origin); 78.588 } 78.589 78.590 bool CommandLineFlags::uintxAt(char* name, size_t len, uintx* value) { 78.591 @@ -439,22 +622,22 @@ 78.592 return true; 78.593 } 78.594 78.595 -bool CommandLineFlags::uintxAtPut(char* name, size_t len, uintx* value, FlagValueOrigin origin) { 78.596 +bool CommandLineFlags::uintxAtPut(char* name, size_t len, uintx* value, Flag::Flags origin) { 78.597 Flag* result = Flag::find_flag(name, len); 78.598 if (result == NULL) return false; 78.599 if (!result->is_uintx()) return false; 78.600 uintx old_value = result->get_uintx(); 78.601 result->set_uintx(*value); 78.602 *value = old_value; 78.603 - result->origin = origin; 78.604 + result->set_origin(origin); 78.605 return true; 78.606 } 78.607 78.608 -void CommandLineFlagsEx::uintxAtPut(CommandLineFlagWithType flag, uintx value, FlagValueOrigin origin) { 78.609 +void CommandLineFlagsEx::uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin) { 78.610 Flag* faddr = address_of_flag(flag); 78.611 guarantee(faddr != NULL && faddr->is_uintx(), "wrong flag type"); 78.612 faddr->set_uintx(value); 78.613 - faddr->origin = origin; 78.614 + faddr->set_origin(origin); 78.615 } 78.616 78.617 bool CommandLineFlags::uint64_tAt(char* name, size_t len, uint64_t* value) { 78.618 @@ -465,22 +648,22 @@ 78.619 return true; 78.620 } 78.621 78.622 -bool CommandLineFlags::uint64_tAtPut(char* name, size_t len, uint64_t* value, FlagValueOrigin origin) { 78.623 +bool CommandLineFlags::uint64_tAtPut(char* name, size_t len, uint64_t* value, Flag::Flags origin) { 78.624 Flag* result = Flag::find_flag(name, len); 78.625 if (result == NULL) return false; 78.626 if (!result->is_uint64_t()) return false; 78.627 uint64_t old_value = result->get_uint64_t(); 78.628 result->set_uint64_t(*value); 78.629 *value = old_value; 78.630 - result->origin = origin; 78.631 + result->set_origin(origin); 78.632 return true; 78.633 } 78.634 78.635 -void CommandLineFlagsEx::uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, FlagValueOrigin origin) { 78.636 +void CommandLineFlagsEx::uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin) { 78.637 Flag* faddr = address_of_flag(flag); 78.638 guarantee(faddr != NULL && faddr->is_uint64_t(), "wrong flag type"); 78.639 faddr->set_uint64_t(value); 78.640 - faddr->origin = origin; 78.641 + faddr->set_origin(origin); 78.642 } 78.643 78.644 bool CommandLineFlags::doubleAt(char* name, size_t len, double* value) { 78.645 @@ -491,22 +674,22 @@ 78.646 return true; 78.647 } 78.648 78.649 -bool CommandLineFlags::doubleAtPut(char* name, size_t len, double* value, FlagValueOrigin origin) { 78.650 +bool CommandLineFlags::doubleAtPut(char* name, size_t len, double* value, Flag::Flags origin) { 78.651 Flag* result = Flag::find_flag(name, len); 78.652 if (result == NULL) return false; 78.653 if (!result->is_double()) return false; 78.654 double old_value = result->get_double(); 78.655 result->set_double(*value); 78.656 *value = old_value; 78.657 - result->origin = origin; 78.658 + result->set_origin(origin); 78.659 return true; 78.660 } 78.661 78.662 -void CommandLineFlagsEx::doubleAtPut(CommandLineFlagWithType flag, double value, FlagValueOrigin origin) { 78.663 +void CommandLineFlagsEx::doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin) { 78.664 Flag* faddr = address_of_flag(flag); 78.665 guarantee(faddr != NULL && faddr->is_double(), "wrong flag type"); 78.666 faddr->set_double(value); 78.667 - faddr->origin = origin; 78.668 + faddr->set_origin(origin); 78.669 } 78.670 78.671 bool CommandLineFlags::ccstrAt(char* name, size_t len, ccstr* value) { 78.672 @@ -519,7 +702,7 @@ 78.673 78.674 // Contract: Flag will make private copy of the incoming value. 78.675 // Outgoing value is always malloc-ed, and caller MUST call free. 78.676 -bool CommandLineFlags::ccstrAtPut(char* name, size_t len, ccstr* value, FlagValueOrigin origin) { 78.677 +bool CommandLineFlags::ccstrAtPut(char* name, size_t len, ccstr* value, Flag::Flags origin) { 78.678 Flag* result = Flag::find_flag(name, len); 78.679 if (result == NULL) return false; 78.680 if (!result->is_ccstr()) return false; 78.681 @@ -530,35 +713,35 @@ 78.682 strcpy(new_value, *value); 78.683 } 78.684 result->set_ccstr(new_value); 78.685 - if (result->origin == DEFAULT && old_value != NULL) { 78.686 + if (result->is_default() && old_value != NULL) { 78.687 // Prior value is NOT heap allocated, but was a literal constant. 78.688 char* old_value_to_free = NEW_C_HEAP_ARRAY(char, strlen(old_value)+1, mtInternal); 78.689 strcpy(old_value_to_free, old_value); 78.690 old_value = old_value_to_free; 78.691 } 78.692 *value = old_value; 78.693 - result->origin = origin; 78.694 + result->set_origin(origin); 78.695 return true; 78.696 } 78.697 78.698 // Contract: Flag will make private copy of the incoming value. 78.699 -void CommandLineFlagsEx::ccstrAtPut(CommandLineFlagWithType flag, ccstr value, FlagValueOrigin origin) { 78.700 +void CommandLineFlagsEx::ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin) { 78.701 Flag* faddr = address_of_flag(flag); 78.702 guarantee(faddr != NULL && faddr->is_ccstr(), "wrong flag type"); 78.703 ccstr old_value = faddr->get_ccstr(); 78.704 char* new_value = NEW_C_HEAP_ARRAY(char, strlen(value)+1, mtInternal); 78.705 strcpy(new_value, value); 78.706 faddr->set_ccstr(new_value); 78.707 - if (faddr->origin != DEFAULT && old_value != NULL) { 78.708 + if (!faddr->is_default() && old_value != NULL) { 78.709 // Prior value is heap allocated so free it. 78.710 FREE_C_HEAP_ARRAY(char, old_value, mtInternal); 78.711 } 78.712 - faddr->origin = origin; 78.713 + faddr->set_origin(origin); 78.714 } 78.715 78.716 extern "C" { 78.717 static int compare_flags(const void* void_a, const void* void_b) { 78.718 - return strcmp((*((Flag**) void_a))->name, (*((Flag**) void_b))->name); 78.719 + return strcmp((*((Flag**) void_a))->_name, (*((Flag**) void_b))->_name); 78.720 } 78.721 } 78.722 78.723 @@ -567,20 +750,19 @@ 78.724 // note: this method is called before the thread structure is in place 78.725 // which means resource allocation cannot be used. 78.726 78.727 - // Compute size 78.728 - int length= 0; 78.729 - while (flagTable[length].name != NULL) length++; 78.730 + // The last entry is the null entry. 78.731 + const size_t length = Flag::numFlags - 1; 78.732 78.733 // Sort 78.734 Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal); 78.735 - for (int index = 0; index < length; index++) { 78.736 - array[index] = &flagTable[index]; 78.737 + for (size_t i = 0; i < length; i++) { 78.738 + array[i] = &flagTable[i]; 78.739 } 78.740 qsort(array, length, sizeof(Flag*), compare_flags); 78.741 78.742 // Print 78.743 - for (int i = 0; i < length; i++) { 78.744 - if (array[i]->origin /* naked field! */) { 78.745 + for (size_t i = 0; i < length; i++) { 78.746 + if (array[i]->get_origin() /* naked field! */) { 78.747 array[i]->print_as_flag(out); 78.748 out->print(" "); 78.749 } 78.750 @@ -603,20 +785,19 @@ 78.751 // note: this method is called before the thread structure is in place 78.752 // which means resource allocation cannot be used. 78.753 78.754 - // Compute size 78.755 - int length= 0; 78.756 - while (flagTable[length].name != NULL) length++; 78.757 + // The last entry is the null entry. 78.758 + const size_t length = Flag::numFlags - 1; 78.759 78.760 // Sort 78.761 Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal); 78.762 - for (int index = 0; index < length; index++) { 78.763 - array[index] = &flagTable[index]; 78.764 + for (size_t i = 0; i < length; i++) { 78.765 + array[i] = &flagTable[i]; 78.766 } 78.767 qsort(array, length, sizeof(Flag*), compare_flags); 78.768 78.769 // Print 78.770 out->print_cr("[Global flags]"); 78.771 - for (int i = 0; i < length; i++) { 78.772 + for (size_t i = 0; i < length; i++) { 78.773 if (array[i]->is_unlocked()) { 78.774 array[i]->print_on(out, withComments); 78.775 }
79.1 --- a/src/share/vm/runtime/globals.hpp Sat Oct 05 03:14:53 2013 +0200 79.2 +++ b/src/share/vm/runtime/globals.hpp Fri Oct 04 21:00:43 2013 -0700 79.3 @@ -194,29 +194,49 @@ 79.4 typedef const char* ccstr; 79.5 typedef const char* ccstrlist; // represents string arguments which accumulate 79.6 79.7 -enum FlagValueOrigin { 79.8 - DEFAULT = 0, 79.9 - COMMAND_LINE = 1, 79.10 - ENVIRON_VAR = 2, 79.11 - CONFIG_FILE = 3, 79.12 - MANAGEMENT = 4, 79.13 - ERGONOMIC = 5, 79.14 - ATTACH_ON_DEMAND = 6, 79.15 - INTERNAL = 99 79.16 -}; 79.17 +struct Flag { 79.18 + enum Flags { 79.19 + // value origin 79.20 + DEFAULT = 0, 79.21 + COMMAND_LINE = 1, 79.22 + ENVIRON_VAR = 2, 79.23 + CONFIG_FILE = 3, 79.24 + MANAGEMENT = 4, 79.25 + ERGONOMIC = 5, 79.26 + ATTACH_ON_DEMAND = 6, 79.27 + INTERNAL = 7, 79.28 79.29 -struct Flag { 79.30 - const char *type; 79.31 - const char *name; 79.32 - void* addr; 79.33 + LAST_VALUE_ORIGIN = INTERNAL, 79.34 + VALUE_ORIGIN_BITS = 4, 79.35 + VALUE_ORIGIN_MASK = right_n_bits(VALUE_ORIGIN_BITS), 79.36 79.37 - NOT_PRODUCT(const char *doc;) 79.38 + // flag kind 79.39 + KIND_PRODUCT = 1 << 4, 79.40 + KIND_MANAGEABLE = 1 << 5, 79.41 + KIND_DIAGNOSTIC = 1 << 6, 79.42 + KIND_EXPERIMENTAL = 1 << 7, 79.43 + KIND_NOT_PRODUCT = 1 << 8, 79.44 + KIND_DEVELOP = 1 << 9, 79.45 + KIND_PLATFORM_DEPENDENT = 1 << 10, 79.46 + KIND_READ_WRITE = 1 << 11, 79.47 + KIND_C1 = 1 << 12, 79.48 + KIND_C2 = 1 << 13, 79.49 + KIND_ARCH = 1 << 14, 79.50 + KIND_SHARK = 1 << 15, 79.51 + KIND_LP64_PRODUCT = 1 << 16, 79.52 + KIND_COMMERCIAL = 1 << 17, 79.53 79.54 - const char *kind; 79.55 - FlagValueOrigin origin; 79.56 + KIND_MASK = ~VALUE_ORIGIN_MASK 79.57 + }; 79.58 + 79.59 + const char* _type; 79.60 + const char* _name; 79.61 + void* _addr; 79.62 + NOT_PRODUCT(const char* _doc;) 79.63 + Flags _flags; 79.64 79.65 // points to all Flags static array 79.66 - static Flag *flags; 79.67 + static Flag* flags; 79.68 79.69 // number of flags 79.70 static size_t numFlags; 79.71 @@ -224,30 +244,50 @@ 79.72 static Flag* find_flag(const char* name, size_t length, bool allow_locked = false); 79.73 static Flag* fuzzy_match(const char* name, size_t length, bool allow_locked = false); 79.74 79.75 - bool is_bool() const { return strcmp(type, "bool") == 0; } 79.76 - bool get_bool() const { return *((bool*) addr); } 79.77 - void set_bool(bool value) { *((bool*) addr) = value; } 79.78 + void check_writable(); 79.79 79.80 - bool is_intx() const { return strcmp(type, "intx") == 0; } 79.81 - intx get_intx() const { return *((intx*) addr); } 79.82 - void set_intx(intx value) { *((intx*) addr) = value; } 79.83 + bool is_bool() const; 79.84 + bool get_bool() const; 79.85 + void set_bool(bool value); 79.86 79.87 - bool is_uintx() const { return strcmp(type, "uintx") == 0; } 79.88 - uintx get_uintx() const { return *((uintx*) addr); } 79.89 - void set_uintx(uintx value) { *((uintx*) addr) = value; } 79.90 + bool is_intx() const; 79.91 + intx get_intx() const; 79.92 + void set_intx(intx value); 79.93 79.94 - bool is_uint64_t() const { return strcmp(type, "uint64_t") == 0; } 79.95 - uint64_t get_uint64_t() const { return *((uint64_t*) addr); } 79.96 - void set_uint64_t(uint64_t value) { *((uint64_t*) addr) = value; } 79.97 + bool is_uintx() const; 79.98 + uintx get_uintx() const; 79.99 + void set_uintx(uintx value); 79.100 79.101 - bool is_double() const { return strcmp(type, "double") == 0; } 79.102 - double get_double() const { return *((double*) addr); } 79.103 - void set_double(double value) { *((double*) addr) = value; } 79.104 + bool is_uint64_t() const; 79.105 + uint64_t get_uint64_t() const; 79.106 + void set_uint64_t(uint64_t value); 79.107 79.108 - bool is_ccstr() const { return strcmp(type, "ccstr") == 0 || strcmp(type, "ccstrlist") == 0; } 79.109 - bool ccstr_accumulates() const { return strcmp(type, "ccstrlist") == 0; } 79.110 - ccstr get_ccstr() const { return *((ccstr*) addr); } 79.111 - void set_ccstr(ccstr value) { *((ccstr*) addr) = value; } 79.112 + bool is_double() const; 79.113 + double get_double() const; 79.114 + void set_double(double value); 79.115 + 79.116 + bool is_ccstr() const; 79.117 + bool ccstr_accumulates() const; 79.118 + ccstr get_ccstr() const; 79.119 + void set_ccstr(ccstr value); 79.120 + 79.121 + Flags get_origin(); 79.122 + void set_origin(Flags origin); 79.123 + 79.124 + bool is_default(); 79.125 + bool is_ergonomic(); 79.126 + bool is_command_line(); 79.127 + 79.128 + bool is_product() const; 79.129 + bool is_manageable() const; 79.130 + bool is_diagnostic() const; 79.131 + bool is_experimental() const; 79.132 + bool is_notproduct() const; 79.133 + bool is_develop() const; 79.134 + bool is_read_write() const; 79.135 + bool is_commercial() const; 79.136 + 79.137 + bool is_constant_in_binary() const; 79.138 79.139 bool is_unlocker() const; 79.140 bool is_unlocked() const; 79.141 @@ -263,6 +303,7 @@ 79.142 void get_locked_message_ext(char*, int) const; 79.143 79.144 void print_on(outputStream* st, bool withComments = false ); 79.145 + void print_kind(outputStream* st); 79.146 void print_as_flag(outputStream* st); 79.147 }; 79.148 79.149 @@ -310,33 +351,33 @@ 79.150 public: 79.151 static bool boolAt(char* name, size_t len, bool* value); 79.152 static bool boolAt(char* name, bool* value) { return boolAt(name, strlen(name), value); } 79.153 - static bool boolAtPut(char* name, size_t len, bool* value, FlagValueOrigin origin); 79.154 - static bool boolAtPut(char* name, bool* value, FlagValueOrigin origin) { return boolAtPut(name, strlen(name), value, origin); } 79.155 + static bool boolAtPut(char* name, size_t len, bool* value, Flag::Flags origin); 79.156 + static bool boolAtPut(char* name, bool* value, Flag::Flags origin) { return boolAtPut(name, strlen(name), value, origin); } 79.157 79.158 static bool intxAt(char* name, size_t len, intx* value); 79.159 static bool intxAt(char* name, intx* value) { return intxAt(name, strlen(name), value); } 79.160 - static bool intxAtPut(char* name, size_t len, intx* value, FlagValueOrigin origin); 79.161 - static bool intxAtPut(char* name, intx* value, FlagValueOrigin origin) { return intxAtPut(name, strlen(name), value, origin); } 79.162 + static bool intxAtPut(char* name, size_t len, intx* value, Flag::Flags origin); 79.163 + static bool intxAtPut(char* name, intx* value, Flag::Flags origin) { return intxAtPut(name, strlen(name), value, origin); } 79.164 79.165 static bool uintxAt(char* name, size_t len, uintx* value); 79.166 static bool uintxAt(char* name, uintx* value) { return uintxAt(name, strlen(name), value); } 79.167 - static bool uintxAtPut(char* name, size_t len, uintx* value, FlagValueOrigin origin); 79.168 - static bool uintxAtPut(char* name, uintx* value, FlagValueOrigin origin) { return uintxAtPut(name, strlen(name), value, origin); } 79.169 + static bool uintxAtPut(char* name, size_t len, uintx* value, Flag::Flags origin); 79.170 + static bool uintxAtPut(char* name, uintx* value, Flag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); } 79.171 79.172 static bool uint64_tAt(char* name, size_t len, uint64_t* value); 79.173 static bool uint64_tAt(char* name, uint64_t* value) { return uint64_tAt(name, strlen(name), value); } 79.174 - static bool uint64_tAtPut(char* name, size_t len, uint64_t* value, FlagValueOrigin origin); 79.175 - static bool uint64_tAtPut(char* name, uint64_t* value, FlagValueOrigin origin) { return uint64_tAtPut(name, strlen(name), value, origin); } 79.176 + static bool uint64_tAtPut(char* name, size_t len, uint64_t* value, Flag::Flags origin); 79.177 + static bool uint64_tAtPut(char* name, uint64_t* value, Flag::Flags origin) { return uint64_tAtPut(name, strlen(name), value, origin); } 79.178 79.179 static bool doubleAt(char* name, size_t len, double* value); 79.180 static bool doubleAt(char* name, double* value) { return doubleAt(name, strlen(name), value); } 79.181 - static bool doubleAtPut(char* name, size_t len, double* value, FlagValueOrigin origin); 79.182 - static bool doubleAtPut(char* name, double* value, FlagValueOrigin origin) { return doubleAtPut(name, strlen(name), value, origin); } 79.183 + static bool doubleAtPut(char* name, size_t len, double* value, Flag::Flags origin); 79.184 + static bool doubleAtPut(char* name, double* value, Flag::Flags origin) { return doubleAtPut(name, strlen(name), value, origin); } 79.185 79.186 static bool ccstrAt(char* name, size_t len, ccstr* value); 79.187 static bool ccstrAt(char* name, ccstr* value) { return ccstrAt(name, strlen(name), value); } 79.188 - static bool ccstrAtPut(char* name, size_t len, ccstr* value, FlagValueOrigin origin); 79.189 - static bool ccstrAtPut(char* name, ccstr* value, FlagValueOrigin origin) { return ccstrAtPut(name, strlen(name), value, origin); } 79.190 + static bool ccstrAtPut(char* name, size_t len, ccstr* value, Flag::Flags origin); 79.191 + static bool ccstrAtPut(char* name, ccstr* value, Flag::Flags origin) { return ccstrAtPut(name, strlen(name), value, origin); } 79.192 79.193 // Returns false if name is not a command line flag. 79.194 static bool wasSetOnCmdline(const char* name, bool* value); 79.195 @@ -2830,6 +2871,10 @@ 79.196 product(intx, NmethodSweepCheckInterval, 5, \ 79.197 "Compilers wake up every n seconds to possibly sweep nmethods") \ 79.198 \ 79.199 + product(intx, NmethodSweepActivity, 10, \ 79.200 + "Removes cold nmethods from code cache if > 0. Higher values " \ 79.201 + "result in more aggressive sweeping") \ 79.202 + \ 79.203 notproduct(bool, LogSweeper, false, \ 79.204 "Keep a ring buffer of sweeper activity") \ 79.205 \ 79.206 @@ -3201,15 +3246,6 @@ 79.207 product(bool, UseCodeCacheFlushing, true, \ 79.208 "Attempt to clean the code cache before shutting off compiler") \ 79.209 \ 79.210 - product(intx, MinCodeCacheFlushingInterval, 30, \ 79.211 - "Min number of seconds between code cache cleaning sessions") \ 79.212 - \ 79.213 - product(uintx, CodeCacheFlushingMinimumFreeSpace, 1500*K, \ 79.214 - "When less than X space left, start code cache cleaning") \ 79.215 - \ 79.216 - product(uintx, CodeCacheFlushingFraction, 2, \ 79.217 - "Fraction of the code cache that is flushed when full") \ 79.218 - \ 79.219 /* interpreter debugging */ \ 79.220 develop(intx, BinarySwitchThreshold, 5, \ 79.221 "Minimal number of lookupswitch entries for rewriting to binary " \ 79.222 @@ -3730,20 +3766,20 @@ 79.223 */ 79.224 79.225 // Interface macros 79.226 -#define DECLARE_PRODUCT_FLAG(type, name, value, doc) extern "C" type name; 79.227 -#define DECLARE_PD_PRODUCT_FLAG(type, name, doc) extern "C" type name; 79.228 -#define DECLARE_DIAGNOSTIC_FLAG(type, name, value, doc) extern "C" type name; 79.229 +#define DECLARE_PRODUCT_FLAG(type, name, value, doc) extern "C" type name; 79.230 +#define DECLARE_PD_PRODUCT_FLAG(type, name, doc) extern "C" type name; 79.231 +#define DECLARE_DIAGNOSTIC_FLAG(type, name, value, doc) extern "C" type name; 79.232 #define DECLARE_EXPERIMENTAL_FLAG(type, name, value, doc) extern "C" type name; 79.233 -#define DECLARE_MANAGEABLE_FLAG(type, name, value, doc) extern "C" type name; 79.234 -#define DECLARE_PRODUCT_RW_FLAG(type, name, value, doc) extern "C" type name; 79.235 +#define DECLARE_MANAGEABLE_FLAG(type, name, value, doc) extern "C" type name; 79.236 +#define DECLARE_PRODUCT_RW_FLAG(type, name, value, doc) extern "C" type name; 79.237 #ifdef PRODUCT 79.238 -#define DECLARE_DEVELOPER_FLAG(type, name, value, doc) const type name = value; 79.239 -#define DECLARE_PD_DEVELOPER_FLAG(type, name, doc) const type name = pd_##name; 79.240 -#define DECLARE_NOTPRODUCT_FLAG(type, name, value, doc) 79.241 +#define DECLARE_DEVELOPER_FLAG(type, name, value, doc) extern "C" type CONST_##name; const type name = value; 79.242 +#define DECLARE_PD_DEVELOPER_FLAG(type, name, doc) extern "C" type CONST_##name; const type name = pd_##name; 79.243 +#define DECLARE_NOTPRODUCT_FLAG(type, name, value, doc) extern "C" type CONST_##name; 79.244 #else 79.245 -#define DECLARE_DEVELOPER_FLAG(type, name, value, doc) extern "C" type name; 79.246 -#define DECLARE_PD_DEVELOPER_FLAG(type, name, doc) extern "C" type name; 79.247 -#define DECLARE_NOTPRODUCT_FLAG(type, name, value, doc) extern "C" type name; 79.248 +#define DECLARE_DEVELOPER_FLAG(type, name, value, doc) extern "C" type name; 79.249 +#define DECLARE_PD_DEVELOPER_FLAG(type, name, doc) extern "C" type name; 79.250 +#define DECLARE_NOTPRODUCT_FLAG(type, name, value, doc) extern "C" type name; 79.251 #endif 79.252 // Special LP64 flags, product only needed for now. 79.253 #ifdef _LP64 79.254 @@ -3753,23 +3789,23 @@ 79.255 #endif // _LP64 79.256 79.257 // Implementation macros 79.258 -#define MATERIALIZE_PRODUCT_FLAG(type, name, value, doc) type name = value; 79.259 -#define MATERIALIZE_PD_PRODUCT_FLAG(type, name, doc) type name = pd_##name; 79.260 -#define MATERIALIZE_DIAGNOSTIC_FLAG(type, name, value, doc) type name = value; 79.261 +#define MATERIALIZE_PRODUCT_FLAG(type, name, value, doc) type name = value; 79.262 +#define MATERIALIZE_PD_PRODUCT_FLAG(type, name, doc) type name = pd_##name; 79.263 +#define MATERIALIZE_DIAGNOSTIC_FLAG(type, name, value, doc) type name = value; 79.264 #define MATERIALIZE_EXPERIMENTAL_FLAG(type, name, value, doc) type name = value; 79.265 -#define MATERIALIZE_MANAGEABLE_FLAG(type, name, value, doc) type name = value; 79.266 -#define MATERIALIZE_PRODUCT_RW_FLAG(type, name, value, doc) type name = value; 79.267 +#define MATERIALIZE_MANAGEABLE_FLAG(type, name, value, doc) type name = value; 79.268 +#define MATERIALIZE_PRODUCT_RW_FLAG(type, name, value, doc) type name = value; 79.269 #ifdef PRODUCT 79.270 -#define MATERIALIZE_DEVELOPER_FLAG(type, name, value, doc) /* flag name is constant */ 79.271 -#define MATERIALIZE_PD_DEVELOPER_FLAG(type, name, doc) /* flag name is constant */ 79.272 -#define MATERIALIZE_NOTPRODUCT_FLAG(type, name, value, doc) 79.273 +#define MATERIALIZE_DEVELOPER_FLAG(type, name, value, doc) type CONST_##name = value; 79.274 +#define MATERIALIZE_PD_DEVELOPER_FLAG(type, name, doc) type CONST_##name = pd_##name; 79.275 +#define MATERIALIZE_NOTPRODUCT_FLAG(type, name, value, doc) type CONST_##name = value; 79.276 #else 79.277 -#define MATERIALIZE_DEVELOPER_FLAG(type, name, value, doc) type name = value; 79.278 -#define MATERIALIZE_PD_DEVELOPER_FLAG(type, name, doc) type name = pd_##name; 79.279 -#define MATERIALIZE_NOTPRODUCT_FLAG(type, name, value, doc) type name = value; 79.280 +#define MATERIALIZE_DEVELOPER_FLAG(type, name, value, doc) type name = value; 79.281 +#define MATERIALIZE_PD_DEVELOPER_FLAG(type, name, doc) type name = pd_##name; 79.282 +#define MATERIALIZE_NOTPRODUCT_FLAG(type, name, value, doc) type name = value; 79.283 #endif 79.284 #ifdef _LP64 79.285 -#define MATERIALIZE_LP64_PRODUCT_FLAG(type, name, value, doc) type name = value; 79.286 +#define MATERIALIZE_LP64_PRODUCT_FLAG(type, name, value, doc) type name = value; 79.287 #else 79.288 #define MATERIALIZE_LP64_PRODUCT_FLAG(type, name, value, doc) /* flag is constant */ 79.289 #endif // _LP64
80.1 --- a/src/share/vm/runtime/globals_extension.hpp Sat Oct 05 03:14:53 2013 +0200 80.2 +++ b/src/share/vm/runtime/globals_extension.hpp Fri Oct 04 21:00:43 2013 -0700 80.3 @@ -34,64 +34,42 @@ 80.4 // Parens left off in the following for the enum decl below. 80.5 #define FLAG_MEMBER(flag) Flag_##flag 80.6 80.7 -#define RUNTIME_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.8 -#define RUNTIME_PD_PRODUCT_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), 80.9 -#define RUNTIME_DIAGNOSTIC_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.10 +#define RUNTIME_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.11 +#define RUNTIME_PD_PRODUCT_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), 80.12 +#define RUNTIME_DIAGNOSTIC_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.13 #define RUNTIME_EXPERIMENTAL_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.14 -#define RUNTIME_MANAGEABLE_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.15 -#define RUNTIME_PRODUCT_RW_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.16 -#ifdef PRODUCT 80.17 - #define RUNTIME_DEVELOP_FLAG_MEMBER(type, name, value, doc) /* flag is constant */ 80.18 - #define RUNTIME_PD_DEVELOP_FLAG_MEMBER(type, name, doc) /* flag is constant */ 80.19 - #define RUNTIME_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) 80.20 +#define RUNTIME_MANAGEABLE_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.21 +#define RUNTIME_PRODUCT_RW_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.22 +#define RUNTIME_DEVELOP_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.23 +#define RUNTIME_PD_DEVELOP_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), 80.24 +#define RUNTIME_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.25 + 80.26 +#ifdef _LP64 80.27 +#define RUNTIME_LP64_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.28 #else 80.29 - #define RUNTIME_DEVELOP_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.30 - #define RUNTIME_PD_DEVELOP_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), 80.31 - #define RUNTIME_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.32 -#endif 80.33 -#ifdef _LP64 80.34 -#define RUNTIME_LP64_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.35 -#else 80.36 -#define RUNTIME_LP64_PRODUCT_FLAG_MEMBER(type, name, value, doc) /* flag is constant */ 80.37 +#define RUNTIME_LP64_PRODUCT_FLAG_MEMBER(type, name, value, doc) /* flag is constant */ 80.38 #endif // _LP64 80.39 80.40 -#define C1_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.41 -#define C1_PD_PRODUCT_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), 80.42 -#define C1_DIAGNOSTIC_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.43 -#ifdef PRODUCT 80.44 - #define C1_DEVELOP_FLAG_MEMBER(type, name, value, doc) /* flag is constant */ 80.45 - #define C1_PD_DEVELOP_FLAG_MEMBER(type, name, doc) /* flag is constant */ 80.46 - #define C1_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) 80.47 -#else 80.48 - #define C1_DEVELOP_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.49 - #define C1_PD_DEVELOP_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), 80.50 - #define C1_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.51 -#endif 80.52 +#define C1_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.53 +#define C1_PD_PRODUCT_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), 80.54 +#define C1_DIAGNOSTIC_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.55 +#define C1_DEVELOP_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.56 +#define C1_PD_DEVELOP_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), 80.57 +#define C1_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.58 80.59 -#define C2_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.60 -#define C2_PD_PRODUCT_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), 80.61 -#define C2_DIAGNOSTIC_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.62 -#define C2_EXPERIMENTAL_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.63 -#ifdef PRODUCT 80.64 - #define C2_DEVELOP_FLAG_MEMBER(type, name, value, doc) /* flag is constant */ 80.65 - #define C2_PD_DEVELOP_FLAG_MEMBER(type, name, doc) /* flag is constant */ 80.66 - #define C2_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) 80.67 -#else 80.68 - #define C2_DEVELOP_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.69 - #define C2_PD_DEVELOP_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), 80.70 - #define C2_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.71 -#endif 80.72 +#define C2_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.73 +#define C2_PD_PRODUCT_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), 80.74 +#define C2_DIAGNOSTIC_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.75 +#define C2_EXPERIMENTAL_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.76 +#define C2_DEVELOP_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.77 +#define C2_PD_DEVELOP_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), 80.78 +#define C2_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.79 80.80 #define ARCH_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.81 #define ARCH_DIAGNOSTIC_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.82 #define ARCH_EXPERIMENTAL_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.83 -#ifdef PRODUCT 80.84 - #define ARCH_DEVELOP_FLAG_MEMBER(type, name, value, doc) /* flag is constant */ 80.85 - #define ARCH_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) 80.86 -#else 80.87 - #define ARCH_DEVELOP_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.88 - #define ARCH_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.89 -#endif 80.90 +#define ARCH_DEVELOP_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.91 +#define ARCH_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), 80.92 80.93 typedef enum { 80.94 RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER, RUNTIME_LP64_PRODUCT_FLAG_MEMBER) 80.95 @@ -114,64 +92,42 @@ 80.96 80.97 #define FLAG_MEMBER_WITH_TYPE(flag,type) Flag_##flag##_##type 80.98 80.99 -#define RUNTIME_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.100 -#define RUNTIME_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.101 -#define RUNTIME_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.102 +#define RUNTIME_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.103 +#define RUNTIME_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.104 +#define RUNTIME_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.105 #define RUNTIME_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.106 -#define RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.107 -#define RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.108 -#ifdef PRODUCT 80.109 - #define RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) /* flag is constant */ 80.110 - #define RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc) /* flag is constant */ 80.111 - #define RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) 80.112 +#define RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.113 +#define RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.114 +#define RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.115 +#define RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.116 +#define RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.117 + 80.118 +#define C1_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.119 +#define C1_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.120 +#define C1_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.121 +#define C1_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.122 +#define C1_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.123 +#define C1_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.124 + 80.125 +#ifdef _LP64 80.126 +#define RUNTIME_LP64_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.127 #else 80.128 - #define RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.129 - #define RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.130 - #define RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.131 -#endif 80.132 - 80.133 -#define C1_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.134 -#define C1_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.135 -#define C1_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.136 -#ifdef PRODUCT 80.137 - #define C1_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) /* flag is constant */ 80.138 - #define C1_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc) /* flag is constant */ 80.139 - #define C1_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) 80.140 -#else 80.141 - #define C1_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.142 - #define C1_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.143 - #define C1_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.144 -#endif 80.145 -#ifdef _LP64 80.146 -#define RUNTIME_LP64_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.147 -#else 80.148 -#define RUNTIME_LP64_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) /* flag is constant */ 80.149 +#define RUNTIME_LP64_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) /* flag is constant */ 80.150 #endif // _LP64 80.151 80.152 -#define C2_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.153 -#define C2_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.154 -#define C2_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.155 +#define C2_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.156 +#define C2_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.157 +#define C2_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.158 #define C2_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.159 -#ifdef PRODUCT 80.160 - #define C2_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) /* flag is constant */ 80.161 - #define C2_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc) /* flag is constant */ 80.162 - #define C2_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) 80.163 -#else 80.164 - #define C2_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.165 - #define C2_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.166 - #define C2_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.167 -#endif 80.168 +#define C2_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.169 +#define C2_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.170 +#define C2_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.171 80.172 #define ARCH_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.173 #define ARCH_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.174 -#define ARCH_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.175 -#ifdef PRODUCT 80.176 - #define ARCH_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) /* flag is constant */ 80.177 - #define ARCH_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) 80.178 -#else 80.179 - #define ARCH_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.180 - #define ARCH_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.181 -#endif 80.182 +#define ARCH_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.183 +#define ARCH_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.184 +#define ARCH_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), 80.185 80.186 typedef enum { 80.187 RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE, 80.188 @@ -233,19 +189,19 @@ 80.189 80.190 #define FLAG_SET_DEFAULT(name, value) ((name) = (value)) 80.191 80.192 -#define FLAG_SET_CMDLINE(type, name, value) (CommandLineFlagsEx::type##AtPut(FLAG_MEMBER_WITH_TYPE(name,type), (type)(value), COMMAND_LINE)) 80.193 -#define FLAG_SET_ERGO(type, name, value) (CommandLineFlagsEx::type##AtPut(FLAG_MEMBER_WITH_TYPE(name,type), (type)(value), ERGONOMIC)) 80.194 +#define FLAG_SET_CMDLINE(type, name, value) (CommandLineFlagsEx::type##AtPut(FLAG_MEMBER_WITH_TYPE(name,type), (type)(value), Flag::COMMAND_LINE)) 80.195 +#define FLAG_SET_ERGO(type, name, value) (CommandLineFlagsEx::type##AtPut(FLAG_MEMBER_WITH_TYPE(name,type), (type)(value), Flag::ERGONOMIC)) 80.196 80.197 // Can't put the following in CommandLineFlags because 80.198 // of a circular dependency on the enum definition. 80.199 class CommandLineFlagsEx : CommandLineFlags { 80.200 public: 80.201 - static void boolAtPut(CommandLineFlagWithType flag, bool value, FlagValueOrigin origin); 80.202 - static void intxAtPut(CommandLineFlagWithType flag, intx value, FlagValueOrigin origin); 80.203 - static void uintxAtPut(CommandLineFlagWithType flag, uintx value, FlagValueOrigin origin); 80.204 - static void uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, FlagValueOrigin origin); 80.205 - static void doubleAtPut(CommandLineFlagWithType flag, double value, FlagValueOrigin origin); 80.206 - static void ccstrAtPut(CommandLineFlagWithType flag, ccstr value, FlagValueOrigin origin); 80.207 + static void boolAtPut(CommandLineFlagWithType flag, bool value, Flag::Flags origin); 80.208 + static void intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin); 80.209 + static void uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin); 80.210 + static void uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin); 80.211 + static void doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin); 80.212 + static void ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin); 80.213 80.214 static bool is_default(CommandLineFlag flag); 80.215 static bool is_ergo(CommandLineFlag flag);
81.1 --- a/src/share/vm/runtime/safepoint.cpp Sat Oct 05 03:14:53 2013 +0200 81.2 +++ b/src/share/vm/runtime/safepoint.cpp Fri Oct 04 21:00:43 2013 -0700 81.3 @@ -519,8 +519,8 @@ 81.4 } 81.5 81.6 { 81.7 - TraceTime t4("sweeping nmethods", TraceSafepointCleanupTime); 81.8 - NMethodSweeper::scan_stacks(); 81.9 + TraceTime t4("mark nmethods", TraceSafepointCleanupTime); 81.10 + NMethodSweeper::mark_active_nmethods(); 81.11 } 81.12 81.13 if (SymbolTable::needs_rehashing()) {
82.1 --- a/src/share/vm/runtime/sweeper.cpp Sat Oct 05 03:14:53 2013 +0200 82.2 +++ b/src/share/vm/runtime/sweeper.cpp Fri Oct 04 21:00:43 2013 -0700 82.3 @@ -127,64 +127,79 @@ 82.4 #define SWEEP(nm) 82.5 #endif 82.6 82.7 +nmethod* NMethodSweeper::_current = NULL; // Current nmethod 82.8 +long NMethodSweeper::_traversals = 0; // Nof. stack traversals performed 82.9 +int NMethodSweeper::_seen = 0; // Nof. nmethods we have currently processed in current pass of CodeCache 82.10 +int NMethodSweeper::_flushed_count = 0; // Nof. nmethods flushed in current sweep 82.11 +int NMethodSweeper::_zombified_count = 0; // Nof. nmethods made zombie in current sweep 82.12 +int NMethodSweeper::_marked_count = 0; // Nof. nmethods marked for reclaim in current sweep 82.13 82.14 -long NMethodSweeper::_traversals = 0; // No. of stack traversals performed 82.15 -nmethod* NMethodSweeper::_current = NULL; // Current nmethod 82.16 -int NMethodSweeper::_seen = 0 ; // No. of nmethods we have currently processed in current pass of CodeCache 82.17 -int NMethodSweeper::_flushed_count = 0; // Nof. nmethods flushed in current sweep 82.18 -int NMethodSweeper::_zombified_count = 0; // Nof. nmethods made zombie in current sweep 82.19 -int NMethodSweeper::_marked_count = 0; // Nof. nmethods marked for reclaim in current sweep 82.20 - 82.21 -volatile int NMethodSweeper::_invocations = 0; // No. of invocations left until we are completed with this pass 82.22 +volatile int NMethodSweeper::_invocations = 0; // Nof. invocations left until we are completed with this pass 82.23 volatile int NMethodSweeper::_sweep_started = 0; // Whether a sweep is in progress. 82.24 82.25 -jint NMethodSweeper::_locked_seen = 0; 82.26 +jint NMethodSweeper::_locked_seen = 0; 82.27 jint NMethodSweeper::_not_entrant_seen_on_stack = 0; 82.28 -bool NMethodSweeper::_resweep = false; 82.29 -jint NMethodSweeper::_flush_token = 0; 82.30 -jlong NMethodSweeper::_last_full_flush_time = 0; 82.31 -int NMethodSweeper::_highest_marked = 0; 82.32 -int NMethodSweeper::_dead_compile_ids = 0; 82.33 -long NMethodSweeper::_last_flush_traversal_id = 0; 82.34 +bool NMethodSweeper::_request_mark_phase = false; 82.35 82.36 -int NMethodSweeper::_number_of_flushes = 0; // Total of full traversals caused by full cache 82.37 int NMethodSweeper::_total_nof_methods_reclaimed = 0; 82.38 -jlong NMethodSweeper::_total_time_sweeping = 0; 82.39 -jlong NMethodSweeper::_total_time_this_sweep = 0; 82.40 -jlong NMethodSweeper::_peak_sweep_time = 0; 82.41 -jlong NMethodSweeper::_peak_sweep_fraction_time = 0; 82.42 -jlong NMethodSweeper::_total_disconnect_time = 0; 82.43 -jlong NMethodSweeper::_peak_disconnect_time = 0; 82.44 +jlong NMethodSweeper::_total_time_sweeping = 0; 82.45 +jlong NMethodSweeper::_total_time_this_sweep = 0; 82.46 +jlong NMethodSweeper::_peak_sweep_time = 0; 82.47 +jlong NMethodSweeper::_peak_sweep_fraction_time = 0; 82.48 +int NMethodSweeper::_hotness_counter_reset_val = 0; 82.49 + 82.50 82.51 class MarkActivationClosure: public CodeBlobClosure { 82.52 public: 82.53 virtual void do_code_blob(CodeBlob* cb) { 82.54 - // If we see an activation belonging to a non_entrant nmethod, we mark it. 82.55 - if (cb->is_nmethod() && ((nmethod*)cb)->is_not_entrant()) { 82.56 - ((nmethod*)cb)->mark_as_seen_on_stack(); 82.57 + if (cb->is_nmethod()) { 82.58 + nmethod* nm = (nmethod*)cb; 82.59 + nm->set_hotness_counter(NMethodSweeper::hotness_counter_reset_val()); 82.60 + // If we see an activation belonging to a non_entrant nmethod, we mark it. 82.61 + if (nm->is_not_entrant()) { 82.62 + nm->mark_as_seen_on_stack(); 82.63 + } 82.64 } 82.65 } 82.66 }; 82.67 static MarkActivationClosure mark_activation_closure; 82.68 82.69 +class SetHotnessClosure: public CodeBlobClosure { 82.70 +public: 82.71 + virtual void do_code_blob(CodeBlob* cb) { 82.72 + if (cb->is_nmethod()) { 82.73 + nmethod* nm = (nmethod*)cb; 82.74 + nm->set_hotness_counter(NMethodSweeper::hotness_counter_reset_val()); 82.75 + } 82.76 + } 82.77 +}; 82.78 +static SetHotnessClosure set_hotness_closure; 82.79 + 82.80 + 82.81 +int NMethodSweeper::hotness_counter_reset_val() { 82.82 + if (_hotness_counter_reset_val == 0) { 82.83 + _hotness_counter_reset_val = (ReservedCodeCacheSize < M) ? 1 : (ReservedCodeCacheSize / M) * 2; 82.84 + } 82.85 + return _hotness_counter_reset_val; 82.86 +} 82.87 bool NMethodSweeper::sweep_in_progress() { 82.88 return (_current != NULL); 82.89 } 82.90 82.91 -void NMethodSweeper::scan_stacks() { 82.92 +// Scans the stacks of all Java threads and marks activations of not-entrant methods. 82.93 +// No need to synchronize access, since 'mark_active_nmethods' is always executed at a 82.94 +// safepoint. 82.95 +void NMethodSweeper::mark_active_nmethods() { 82.96 assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint"); 82.97 - if (!MethodFlushing) return; 82.98 - 82.99 - // No need to synchronize access, since this is always executed at a 82.100 - // safepoint. 82.101 - 82.102 - // Make sure CompiledIC_lock in unlocked, since we might update some 82.103 - // inline caches. If it is, we just bail-out and try later. 82.104 - if (CompiledIC_lock->is_locked() || Patching_lock->is_locked()) return; 82.105 + // If we do not want to reclaim not-entrant or zombie methods there is no need 82.106 + // to scan stacks 82.107 + if (!MethodFlushing) { 82.108 + return; 82.109 + } 82.110 82.111 // Check for restart 82.112 assert(CodeCache::find_blob_unsafe(_current) == _current, "Sweeper nmethod cached state invalid"); 82.113 - if (!sweep_in_progress() && _resweep) { 82.114 + if (!sweep_in_progress() && need_marking_phase()) { 82.115 _seen = 0; 82.116 _invocations = NmethodSweepFraction; 82.117 _current = CodeCache::first_nmethod(); 82.118 @@ -197,30 +212,22 @@ 82.119 Threads::nmethods_do(&mark_activation_closure); 82.120 82.121 // reset the flags since we started a scan from the beginning. 82.122 - _resweep = false; 82.123 + reset_nmethod_marking(); 82.124 _locked_seen = 0; 82.125 _not_entrant_seen_on_stack = 0; 82.126 + } else { 82.127 + // Only set hotness counter 82.128 + Threads::nmethods_do(&set_hotness_closure); 82.129 } 82.130 82.131 - if (UseCodeCacheFlushing) { 82.132 - // only allow new flushes after the interval is complete. 82.133 - jlong now = os::javaTimeMillis(); 82.134 - jlong max_interval = (jlong)MinCodeCacheFlushingInterval * (jlong)1000; 82.135 - jlong curr_interval = now - _last_full_flush_time; 82.136 - if (curr_interval > max_interval) { 82.137 - _flush_token = 0; 82.138 - } 82.139 - 82.140 - if (!CodeCache::needs_flushing() && !CompileBroker::should_compile_new_jobs()) { 82.141 - CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation); 82.142 - log_sweep("restart_compiler"); 82.143 - } 82.144 - } 82.145 + OrderAccess::storestore(); 82.146 } 82.147 82.148 void NMethodSweeper::possibly_sweep() { 82.149 assert(JavaThread::current()->thread_state() == _thread_in_vm, "must run in vm mode"); 82.150 - if (!MethodFlushing || !sweep_in_progress()) return; 82.151 + if (!MethodFlushing || !sweep_in_progress()) { 82.152 + return; 82.153 + } 82.154 82.155 if (_invocations > 0) { 82.156 // Only one thread at a time will sweep 82.157 @@ -258,8 +265,7 @@ 82.158 if (!CompileBroker::should_compile_new_jobs()) { 82.159 // If we have turned off compilations we might as well do full sweeps 82.160 // in order to reach the clean state faster. Otherwise the sleeping compiler 82.161 - // threads will slow down sweeping. After a few iterations the cache 82.162 - // will be clean and sweeping stops (_resweep will not be set) 82.163 + // threads will slow down sweeping. 82.164 _invocations = 1; 82.165 } 82.166 82.167 @@ -271,9 +277,11 @@ 82.168 int todo = (CodeCache::nof_nmethods() - _seen) / _invocations; 82.169 int swept_count = 0; 82.170 82.171 + 82.172 assert(!SafepointSynchronize::is_at_safepoint(), "should not be in safepoint when we get here"); 82.173 assert(!CodeCache_lock->owned_by_self(), "just checking"); 82.174 82.175 + int freed_memory = 0; 82.176 { 82.177 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 82.178 82.179 @@ -299,7 +307,7 @@ 82.180 // Now ready to process nmethod and give up CodeCache_lock 82.181 { 82.182 MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 82.183 - process_nmethod(_current); 82.184 + freed_memory += process_nmethod(_current); 82.185 } 82.186 _seen++; 82.187 _current = next; 82.188 @@ -308,11 +316,11 @@ 82.189 82.190 assert(_invocations > 1 || _current == NULL, "must have scanned the whole cache"); 82.191 82.192 - if (!sweep_in_progress() && !_resweep && (_locked_seen || _not_entrant_seen_on_stack)) { 82.193 + if (!sweep_in_progress() && !need_marking_phase() && (_locked_seen || _not_entrant_seen_on_stack)) { 82.194 // we've completed a scan without making progress but there were 82.195 // nmethods we were unable to process either because they were 82.196 - // locked or were still on stack. We don't have to aggresively 82.197 - // clean them up so just stop scanning. We could scan once more 82.198 + // locked or were still on stack. We don't have to aggressively 82.199 + // clean them up so just stop scanning. We could scan once more 82.200 // but that complicates the control logic and it's unlikely to 82.201 // matter much. 82.202 if (PrintMethodFlushing) { 82.203 @@ -351,9 +359,16 @@ 82.204 log_sweep("finished"); 82.205 } 82.206 82.207 - // Sweeper is the only case where memory is released, 82.208 - // check here if it is time to restart the compiler. 82.209 - if (UseCodeCacheFlushing && !CompileBroker::should_compile_new_jobs() && !CodeCache::needs_flushing()) { 82.210 + // Sweeper is the only case where memory is released, check here if it 82.211 + // is time to restart the compiler. Only checking if there is a certain 82.212 + // amount of free memory in the code cache might lead to re-enabling 82.213 + // compilation although no memory has been released. For example, there are 82.214 + // cases when compilation was disabled although there is 4MB (or more) free 82.215 + // memory in the code cache. The reason is code cache fragmentation. Therefore, 82.216 + // it only makes sense to re-enable compilation if we have actually freed memory. 82.217 + // Note that typically several kB are released for sweeping 16MB of the code 82.218 + // cache. As a result, 'freed_memory' > 0 to restart the compiler. 82.219 + if (UseCodeCacheFlushing && (!CompileBroker::should_compile_new_jobs() && (freed_memory > 0))) { 82.220 CompileBroker::set_should_compile_new_jobs(CompileBroker::run_compilation); 82.221 log_sweep("restart_compiler"); 82.222 } 82.223 @@ -367,8 +382,8 @@ 82.224 _thread = CompilerThread::current(); 82.225 if (!nm->is_zombie() && !nm->is_unloaded()) { 82.226 // Only expose live nmethods for scanning 82.227 - _thread->set_scanned_nmethod(nm); 82.228 - } 82.229 + _thread->set_scanned_nmethod(nm); 82.230 + } 82.231 } 82.232 ~NMethodMarker() { 82.233 _thread->set_scanned_nmethod(NULL); 82.234 @@ -392,20 +407,20 @@ 82.235 nm->flush(); 82.236 } 82.237 82.238 -void NMethodSweeper::process_nmethod(nmethod *nm) { 82.239 +int NMethodSweeper::process_nmethod(nmethod *nm) { 82.240 assert(!CodeCache_lock->owned_by_self(), "just checking"); 82.241 82.242 + int freed_memory = 0; 82.243 // Make sure this nmethod doesn't get unloaded during the scan, 82.244 - // since the locks acquired below might safepoint. 82.245 + // since safepoints may happen during acquired below locks. 82.246 NMethodMarker nmm(nm); 82.247 - 82.248 SWEEP(nm); 82.249 82.250 // Skip methods that are currently referenced by the VM 82.251 if (nm->is_locked_by_vm()) { 82.252 // But still remember to clean-up inline caches for alive nmethods 82.253 if (nm->is_alive()) { 82.254 - // Clean-up all inline caches that points to zombie/non-reentrant methods 82.255 + // Clean inline caches that point to zombie/non-entrant methods 82.256 MutexLocker cl(CompiledIC_lock); 82.257 nm->cleanup_inline_caches(); 82.258 SWEEP(nm); 82.259 @@ -413,18 +428,19 @@ 82.260 _locked_seen++; 82.261 SWEEP(nm); 82.262 } 82.263 - return; 82.264 + return freed_memory; 82.265 } 82.266 82.267 if (nm->is_zombie()) { 82.268 - // If it is first time, we see nmethod then we mark it. Otherwise, 82.269 - // we reclame it. When we have seen a zombie method twice, we know that 82.270 + // If it is the first time we see nmethod then we mark it. Otherwise, 82.271 + // we reclaim it. When we have seen a zombie method twice, we know that 82.272 // there are no inline caches that refer to it. 82.273 if (nm->is_marked_for_reclamation()) { 82.274 assert(!nm->is_locked_by_vm(), "must not flush locked nmethods"); 82.275 if (PrintMethodFlushing && Verbose) { 82.276 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (marked for reclamation) being flushed", nm->compile_id(), nm); 82.277 } 82.278 + freed_memory = nm->total_size(); 82.279 release_nmethod(nm); 82.280 _flushed_count++; 82.281 } else { 82.282 @@ -432,19 +448,19 @@ 82.283 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (zombie) being marked for reclamation", nm->compile_id(), nm); 82.284 } 82.285 nm->mark_for_reclamation(); 82.286 - _resweep = true; 82.287 + request_nmethod_marking(); 82.288 _marked_count++; 82.289 SWEEP(nm); 82.290 } 82.291 } else if (nm->is_not_entrant()) { 82.292 - // If there is no current activations of this method on the 82.293 + // If there are no current activations of this method on the 82.294 // stack we can safely convert it to a zombie method 82.295 if (nm->can_not_entrant_be_converted()) { 82.296 if (PrintMethodFlushing && Verbose) { 82.297 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm); 82.298 } 82.299 nm->make_zombie(); 82.300 - _resweep = true; 82.301 + request_nmethod_marking(); 82.302 _zombified_count++; 82.303 SWEEP(nm); 82.304 } else { 82.305 @@ -459,159 +475,57 @@ 82.306 } 82.307 } else if (nm->is_unloaded()) { 82.308 // Unloaded code, just make it a zombie 82.309 - if (PrintMethodFlushing && Verbose) 82.310 + if (PrintMethodFlushing && Verbose) { 82.311 tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (unloaded) being made zombie", nm->compile_id(), nm); 82.312 - 82.313 + } 82.314 if (nm->is_osr_method()) { 82.315 SWEEP(nm); 82.316 // No inline caches will ever point to osr methods, so we can just remove it 82.317 + freed_memory = nm->total_size(); 82.318 release_nmethod(nm); 82.319 _flushed_count++; 82.320 } else { 82.321 nm->make_zombie(); 82.322 - _resweep = true; 82.323 + request_nmethod_marking(); 82.324 _zombified_count++; 82.325 SWEEP(nm); 82.326 } 82.327 } else { 82.328 - assert(nm->is_alive(), "should be alive"); 82.329 - 82.330 if (UseCodeCacheFlushing) { 82.331 - if (nm->is_speculatively_disconnected() && !nm->is_locked_by_vm() && !nm->is_osr_method() && 82.332 - (_traversals > _last_flush_traversal_id + 2) && (nm->compile_id() < _highest_marked)) { 82.333 - // This method has not been called since the forced cleanup happened 82.334 - nm->make_not_entrant(); 82.335 + if (!nm->is_locked_by_vm() && !nm->is_osr_method() && !nm->is_native_method()) { 82.336 + // Do not make native methods and OSR-methods not-entrant 82.337 + nm->dec_hotness_counter(); 82.338 + // Get the initial value of the hotness counter. This value depends on the 82.339 + // ReservedCodeCacheSize 82.340 + int reset_val = hotness_counter_reset_val(); 82.341 + int time_since_reset = reset_val - nm->hotness_counter(); 82.342 + double threshold = -reset_val + (CodeCache::reverse_free_ratio() * NmethodSweepActivity); 82.343 + // The less free space in the code cache we have - the bigger reverse_free_ratio() is. 82.344 + // I.e., 'threshold' increases with lower available space in the code cache and a higher 82.345 + // NmethodSweepActivity. If the current hotness counter - which decreases from its initial 82.346 + // value until it is reset by stack walking - is smaller than the computed threshold, the 82.347 + // corresponding nmethod is considered for removal. 82.348 + if ((NmethodSweepActivity > 0) && (nm->hotness_counter() < threshold) && (time_since_reset > 10)) { 82.349 + // A method is marked as not-entrant if the method is 82.350 + // 1) 'old enough': nm->hotness_counter() < threshold 82.351 + // 2) The method was in_use for a minimum amount of time: (time_since_reset > 10) 82.352 + // The second condition is necessary if we are dealing with very small code cache 82.353 + // sizes (e.g., <10m) and the code cache size is too small to hold all hot methods. 82.354 + // The second condition ensures that methods are not immediately made not-entrant 82.355 + // after compilation. 82.356 + nm->make_not_entrant(); 82.357 + request_nmethod_marking(); 82.358 + } 82.359 } 82.360 } 82.361 - 82.362 - // Clean-up all inline caches that points to zombie/non-reentrant methods 82.363 + // Clean-up all inline caches that point to zombie/non-reentrant methods 82.364 MutexLocker cl(CompiledIC_lock); 82.365 nm->cleanup_inline_caches(); 82.366 SWEEP(nm); 82.367 } 82.368 + return freed_memory; 82.369 } 82.370 82.371 -// Code cache unloading: when compilers notice the code cache is getting full, 82.372 -// they will call a vm op that comes here. This code attempts to speculatively 82.373 -// unload the oldest half of the nmethods (based on the compile job id) by 82.374 -// saving the old code in a list in the CodeCache. Then 82.375 -// execution resumes. If a method so marked is not called by the second sweeper 82.376 -// stack traversal after the current one, the nmethod will be marked non-entrant and 82.377 -// got rid of by normal sweeping. If the method is called, the Method*'s 82.378 -// _code field is restored and the Method*/nmethod 82.379 -// go back to their normal state. 82.380 -void NMethodSweeper::handle_full_code_cache(bool is_full) { 82.381 - 82.382 - if (is_full) { 82.383 - // Since code cache is full, immediately stop new compiles 82.384 - if (CompileBroker::set_should_compile_new_jobs(CompileBroker::stop_compilation)) { 82.385 - log_sweep("disable_compiler"); 82.386 - } 82.387 - } 82.388 - 82.389 - // Make sure only one thread can flush 82.390 - // The token is reset after CodeCacheMinimumFlushInterval in scan stacks, 82.391 - // no need to check the timeout here. 82.392 - jint old = Atomic::cmpxchg( 1, &_flush_token, 0 ); 82.393 - if (old != 0) { 82.394 - return; 82.395 - } 82.396 - 82.397 - VM_HandleFullCodeCache op(is_full); 82.398 - VMThread::execute(&op); 82.399 - 82.400 - // resweep again as soon as possible 82.401 - _resweep = true; 82.402 -} 82.403 - 82.404 -void NMethodSweeper::speculative_disconnect_nmethods(bool is_full) { 82.405 - // If there was a race in detecting full code cache, only run 82.406 - // one vm op for it or keep the compiler shut off 82.407 - 82.408 - jlong disconnect_start_counter = os::elapsed_counter(); 82.409 - 82.410 - // Traverse the code cache trying to dump the oldest nmethods 82.411 - int curr_max_comp_id = CompileBroker::get_compilation_id(); 82.412 - int flush_target = ((curr_max_comp_id - _dead_compile_ids) / CodeCacheFlushingFraction) + _dead_compile_ids; 82.413 - 82.414 - log_sweep("start_cleaning"); 82.415 - 82.416 - nmethod* nm = CodeCache::alive_nmethod(CodeCache::first()); 82.417 - jint disconnected = 0; 82.418 - jint made_not_entrant = 0; 82.419 - jint nmethod_count = 0; 82.420 - 82.421 - while ((nm != NULL)){ 82.422 - int curr_comp_id = nm->compile_id(); 82.423 - 82.424 - // OSR methods cannot be flushed like this. Also, don't flush native methods 82.425 - // since they are part of the JDK in most cases 82.426 - if (!nm->is_osr_method() && !nm->is_locked_by_vm() && !nm->is_native_method()) { 82.427 - 82.428 - // only count methods that can be speculatively disconnected 82.429 - nmethod_count++; 82.430 - 82.431 - if (nm->is_in_use() && (curr_comp_id < flush_target)) { 82.432 - if ((nm->method()->code() == nm)) { 82.433 - // This method has not been previously considered for 82.434 - // unloading or it was restored already 82.435 - CodeCache::speculatively_disconnect(nm); 82.436 - disconnected++; 82.437 - } else if (nm->is_speculatively_disconnected()) { 82.438 - // This method was previously considered for preemptive unloading and was not called since then 82.439 - CompilationPolicy::policy()->delay_compilation(nm->method()); 82.440 - nm->make_not_entrant(); 82.441 - made_not_entrant++; 82.442 - } 82.443 - 82.444 - if (curr_comp_id > _highest_marked) { 82.445 - _highest_marked = curr_comp_id; 82.446 - } 82.447 - } 82.448 - } 82.449 - nm = CodeCache::alive_nmethod(CodeCache::next(nm)); 82.450 - } 82.451 - 82.452 - // remember how many compile_ids wheren't seen last flush. 82.453 - _dead_compile_ids = curr_max_comp_id - nmethod_count; 82.454 - 82.455 - log_sweep("stop_cleaning", 82.456 - "disconnected='" UINT32_FORMAT "' made_not_entrant='" UINT32_FORMAT "'", 82.457 - disconnected, made_not_entrant); 82.458 - 82.459 - // Shut off compiler. Sweeper will start over with a new stack scan and 82.460 - // traversal cycle and turn it back on if it clears enough space. 82.461 - if (is_full) { 82.462 - _last_full_flush_time = os::javaTimeMillis(); 82.463 - } 82.464 - 82.465 - jlong disconnect_end_counter = os::elapsed_counter(); 82.466 - jlong disconnect_time = disconnect_end_counter - disconnect_start_counter; 82.467 - _total_disconnect_time += disconnect_time; 82.468 - _peak_disconnect_time = MAX2(disconnect_time, _peak_disconnect_time); 82.469 - 82.470 - EventCleanCodeCache event(UNTIMED); 82.471 - if (event.should_commit()) { 82.472 - event.set_starttime(disconnect_start_counter); 82.473 - event.set_endtime(disconnect_end_counter); 82.474 - event.set_disconnectedCount(disconnected); 82.475 - event.set_madeNonEntrantCount(made_not_entrant); 82.476 - event.commit(); 82.477 - } 82.478 - _number_of_flushes++; 82.479 - 82.480 - // After two more traversals the sweeper will get rid of unrestored nmethods 82.481 - _last_flush_traversal_id = _traversals; 82.482 - _resweep = true; 82.483 -#ifdef ASSERT 82.484 - 82.485 - if(PrintMethodFlushing && Verbose) { 82.486 - tty->print_cr("### sweeper: unload time: " INT64_FORMAT, (jlong)disconnect_time); 82.487 - } 82.488 -#endif 82.489 -} 82.490 - 82.491 - 82.492 // Print out some state information about the current sweep and the 82.493 // state of the code cache if it's requested. 82.494 void NMethodSweeper::log_sweep(const char* msg, const char* format, ...) {
83.1 --- a/src/share/vm/runtime/sweeper.hpp Sat Oct 05 03:14:53 2013 +0200 83.2 +++ b/src/share/vm/runtime/sweeper.hpp Fri Oct 04 21:00:43 2013 -0700 83.3 @@ -27,8 +27,30 @@ 83.4 83.5 // An NmethodSweeper is an incremental cleaner for: 83.6 // - cleanup inline caches 83.7 -// - reclamation of unreferences zombie nmethods 83.8 -// 83.9 +// - reclamation of nmethods 83.10 +// Removing nmethods from the code cache includes two operations 83.11 +// 1) mark active nmethods 83.12 +// Is done in 'mark_active_nmethods()'. This function is called at a 83.13 +// safepoint and marks all nmethods that are active on a thread's stack. 83.14 +// 2) sweep nmethods 83.15 +// Is done in sweep_code_cache(). This function is the only place in the 83.16 +// sweeper where memory is reclaimed. Note that sweep_code_cache() is not 83.17 +// called at a safepoint. However, sweep_code_cache() stops executing if 83.18 +// another thread requests a safepoint. Consequently, 'mark_active_nmethods()' 83.19 +// and sweep_code_cache() cannot execute at the same time. 83.20 +// To reclaim memory, nmethods are first marked as 'not-entrant'. Methods can 83.21 +// be made not-entrant by (i) the sweeper, (ii) deoptimization, (iii) dependency 83.22 +// invalidation, and (iv) being replaced be a different method version (tiered 83.23 +// compilation). Not-entrant nmethod cannot be called by Java threads, but they 83.24 +// can still be active on the stack. To ensure that active nmethod are not reclaimed, 83.25 +// we have to wait until the next marking phase has completed. If a not-entrant 83.26 +// nmethod was NOT marked as active, it can be converted to 'zombie' state. To safely 83.27 +// remove the nmethod, all inline caches (IC) that point to the the nmethod must be 83.28 +// cleared. After that, the nmethod can be evicted from the code cache. Each nmethod's 83.29 +// state change happens during separate sweeps. It may take at least 3 sweeps before an 83.30 +// nmethod's space is freed. Sweeping is currently done by compiler threads between 83.31 +// compilations or at least each 5 sec (NmethodSweepCheckInterval) when the code cache 83.32 +// is full. 83.33 83.34 class NMethodSweeper : public AllStatic { 83.35 static long _traversals; // Stack scan count, also sweep ID. 83.36 @@ -41,46 +63,38 @@ 83.37 static volatile int _invocations; // No. of invocations left until we are completed with this pass 83.38 static volatile int _sweep_started; // Flag to control conc sweeper 83.39 83.40 - //The following are reset in scan_stacks and synchronized by the safepoint 83.41 - static bool _resweep; // Indicates that a change has happend and we want another sweep, 83.42 - // always checked and reset at a safepoint so memory will be in sync. 83.43 - static int _locked_seen; // Number of locked nmethods encountered during the scan 83.44 + //The following are reset in mark_active_nmethods and synchronized by the safepoint 83.45 + static bool _request_mark_phase; // Indicates that a change has happend and we need another mark pahse, 83.46 + // always checked and reset at a safepoint so memory will be in sync. 83.47 + static int _locked_seen; // Number of locked nmethods encountered during the scan 83.48 static int _not_entrant_seen_on_stack; // Number of not entrant nmethod were are still on stack 83.49 - static jint _flush_token; // token that guards method flushing, making sure it is executed only once. 83.50 - 83.51 - // These are set during a flush, a VM-operation 83.52 - static long _last_flush_traversal_id; // trav number at last flush unloading 83.53 - static jlong _last_full_flush_time; // timestamp of last emergency unloading 83.54 - 83.55 - // These are synchronized by the _sweep_started token 83.56 - static int _highest_marked; // highest compile id dumped at last emergency unloading 83.57 - static int _dead_compile_ids; // number of compile ids that where not in the cache last flush 83.58 83.59 // Stat counters 83.60 - static int _number_of_flushes; // Total of full traversals caused by full cache 83.61 static int _total_nof_methods_reclaimed; // Accumulated nof methods flushed 83.62 static jlong _total_time_sweeping; // Accumulated time sweeping 83.63 static jlong _total_time_this_sweep; // Total time this sweep 83.64 static jlong _peak_sweep_time; // Peak time for a full sweep 83.65 static jlong _peak_sweep_fraction_time; // Peak time sweeping one fraction 83.66 - static jlong _total_disconnect_time; // Total time cleaning code mem 83.67 - static jlong _peak_disconnect_time; // Peak time cleaning code mem 83.68 83.69 - static void process_nmethod(nmethod *nm); 83.70 + static int process_nmethod(nmethod *nm); 83.71 static void release_nmethod(nmethod* nm); 83.72 83.73 - static void log_sweep(const char* msg, const char* format = NULL, ...); 83.74 static bool sweep_in_progress(); 83.75 + static void sweep_code_cache(); 83.76 + static void request_nmethod_marking() { _request_mark_phase = true; } 83.77 + static void reset_nmethod_marking() { _request_mark_phase = false; } 83.78 + static bool need_marking_phase() { return _request_mark_phase; } 83.79 + 83.80 + static int _hotness_counter_reset_val; 83.81 83.82 public: 83.83 static long traversal_count() { return _traversals; } 83.84 - static int number_of_flushes() { return _number_of_flushes; } 83.85 static int total_nof_methods_reclaimed() { return _total_nof_methods_reclaimed; } 83.86 static jlong total_time_sweeping() { return _total_time_sweeping; } 83.87 static jlong peak_sweep_time() { return _peak_sweep_time; } 83.88 static jlong peak_sweep_fraction_time() { return _peak_sweep_fraction_time; } 83.89 - static jlong total_disconnect_time() { return _total_disconnect_time; } 83.90 - static jlong peak_disconnect_time() { return _peak_disconnect_time; } 83.91 + static void log_sweep(const char* msg, const char* format = NULL, ...); 83.92 + 83.93 83.94 #ifdef ASSERT 83.95 static bool is_sweeping(nmethod* which) { return _current == which; } 83.96 @@ -90,19 +104,18 @@ 83.97 static void report_events(); 83.98 #endif 83.99 83.100 - static void scan_stacks(); // Invoked at the end of each safepoint 83.101 - static void sweep_code_cache(); // Concurrent part of sweep job 83.102 - static void possibly_sweep(); // Compiler threads call this to sweep 83.103 + static void mark_active_nmethods(); // Invoked at the end of each safepoint 83.104 + static void possibly_sweep(); // Compiler threads call this to sweep 83.105 83.106 - static void notify(nmethod* nm) { 83.107 + static int sort_nmethods_by_hotness(nmethod** nm1, nmethod** nm2); 83.108 + static int hotness_counter_reset_val(); 83.109 + 83.110 + static void notify() { 83.111 // Request a new sweep of the code cache from the beginning. No 83.112 // need to synchronize the setting of this flag since it only 83.113 // changes to false at safepoint so we can never overwrite it with false. 83.114 - _resweep = true; 83.115 + request_nmethod_marking(); 83.116 } 83.117 - 83.118 - static void handle_full_code_cache(bool is_full); // Called by compilers who fail to allocate 83.119 - static void speculative_disconnect_nmethods(bool was_full); // Called by vm op to deal with alloc failure 83.120 }; 83.121 83.122 #endif // SHARE_VM_RUNTIME_SWEEPER_HPP
84.1 --- a/src/share/vm/runtime/vmStructs.cpp Sat Oct 05 03:14:53 2013 +0200 84.2 +++ b/src/share/vm/runtime/vmStructs.cpp Fri Oct 04 21:00:43 2013 -0700 84.3 @@ -176,6 +176,7 @@ 84.4 #include "opto/loopnode.hpp" 84.5 #include "opto/machnode.hpp" 84.6 #include "opto/matcher.hpp" 84.7 +#include "opto/mathexactnode.hpp" 84.8 #include "opto/mulnode.hpp" 84.9 #include "opto/phaseX.hpp" 84.10 #include "opto/parse.hpp" 84.11 @@ -841,7 +842,7 @@ 84.12 nonstatic_field(nmethod, _osr_link, nmethod*) \ 84.13 nonstatic_field(nmethod, _scavenge_root_link, nmethod*) \ 84.14 nonstatic_field(nmethod, _scavenge_root_state, jbyte) \ 84.15 - nonstatic_field(nmethod, _state, unsigned char) \ 84.16 + nonstatic_field(nmethod, _state, volatile unsigned char) \ 84.17 nonstatic_field(nmethod, _exception_offset, int) \ 84.18 nonstatic_field(nmethod, _deoptimize_offset, int) \ 84.19 nonstatic_field(nmethod, _deoptimize_mh_offset, int) \ 84.20 @@ -1185,11 +1186,10 @@ 84.21 /* -XX flags */ \ 84.22 /*********************/ \ 84.23 \ 84.24 - nonstatic_field(Flag, type, const char*) \ 84.25 - nonstatic_field(Flag, name, const char*) \ 84.26 - unchecked_nonstatic_field(Flag, addr, sizeof(void*)) /* NOTE: no type */ \ 84.27 - nonstatic_field(Flag, kind, const char*) \ 84.28 - nonstatic_field(Flag, origin, FlagValueOrigin) \ 84.29 + nonstatic_field(Flag, _type, const char*) \ 84.30 + nonstatic_field(Flag, _name, const char*) \ 84.31 + unchecked_nonstatic_field(Flag, _addr, sizeof(void*)) /* NOTE: no type */ \ 84.32 + nonstatic_field(Flag, _flags, Flag::Flags) \ 84.33 static_field(Flag, flags, Flag*) \ 84.34 static_field(Flag, numFlags, size_t) \ 84.35 \ 84.36 @@ -1360,6 +1360,7 @@ 84.37 declare_integer_type(long) \ 84.38 declare_integer_type(char) \ 84.39 declare_unsigned_integer_type(unsigned char) \ 84.40 + declare_unsigned_integer_type(volatile unsigned char) \ 84.41 declare_unsigned_integer_type(u_char) \ 84.42 declare_unsigned_integer_type(unsigned int) \ 84.43 declare_unsigned_integer_type(uint) \ 84.44 @@ -1382,6 +1383,7 @@ 84.45 declare_toplevel_type(char**) \ 84.46 declare_toplevel_type(u_char*) \ 84.47 declare_toplevel_type(unsigned char*) \ 84.48 + declare_toplevel_type(volatile unsigned char*) \ 84.49 \ 84.50 /*******************************************************************/ \ 84.51 /* Types which it will be handy to have available over in the SA */ \ 84.52 @@ -1928,6 +1930,9 @@ 84.53 declare_c2_type(CmpF3Node, CmpFNode) \ 84.54 declare_c2_type(CmpDNode, CmpNode) \ 84.55 declare_c2_type(CmpD3Node, CmpDNode) \ 84.56 + declare_c2_type(MathExactNode, MultiNode) \ 84.57 + declare_c2_type(AddExactINode, MathExactNode) \ 84.58 + declare_c2_type(FlagsProjNode, ProjNode) \ 84.59 declare_c2_type(BoolNode, Node) \ 84.60 declare_c2_type(AbsNode, Node) \ 84.61 declare_c2_type(AbsINode, AbsNode) \ 84.62 @@ -2074,7 +2079,7 @@ 84.63 declare_integer_type(JavaThreadState) \ 84.64 declare_integer_type(Location::Type) \ 84.65 declare_integer_type(Location::Where) \ 84.66 - declare_integer_type(FlagValueOrigin) \ 84.67 + declare_integer_type(Flag::Flags) \ 84.68 COMPILER2_PRESENT(declare_integer_type(OptoReg::Name)) \ 84.69 \ 84.70 declare_toplevel_type(CHeapObj<mtInternal>) \ 84.71 @@ -2082,7 +2087,7 @@ 84.72 declare_type(Array<u1>, MetaspaceObj) \ 84.73 declare_type(Array<u2>, MetaspaceObj) \ 84.74 declare_type(Array<Klass*>, MetaspaceObj) \ 84.75 - declare_type(Array<Method*>, MetaspaceObj) \ 84.76 + declare_type(Array<Method*>, MetaspaceObj) \ 84.77 \ 84.78 declare_integer_type(AccessFlags) /* FIXME: wrong type (not integer) */\ 84.79 declare_toplevel_type(address) /* FIXME: should this be an integer type? */\
85.1 --- a/src/share/vm/runtime/vm_operations.cpp Sat Oct 05 03:14:53 2013 +0200 85.2 +++ b/src/share/vm/runtime/vm_operations.cpp Fri Oct 04 21:00:43 2013 -0700 85.3 @@ -173,10 +173,6 @@ 85.4 SymbolTable::unlink(); 85.5 } 85.6 85.7 -void VM_HandleFullCodeCache::doit() { 85.8 - NMethodSweeper::speculative_disconnect_nmethods(_is_full); 85.9 -} 85.10 - 85.11 void VM_Verify::doit() { 85.12 Universe::heap()->prepare_for_verify(); 85.13 Universe::verify(_silent);
86.1 --- a/src/share/vm/runtime/vm_operations.hpp Sat Oct 05 03:14:53 2013 +0200 86.2 +++ b/src/share/vm/runtime/vm_operations.hpp Fri Oct 04 21:00:43 2013 -0700 86.3 @@ -51,7 +51,6 @@ 86.4 template(DeoptimizeAll) \ 86.5 template(ZombieAll) \ 86.6 template(UnlinkSymbols) \ 86.7 - template(HandleFullCodeCache) \ 86.8 template(Verify) \ 86.9 template(PrintJNI) \ 86.10 template(HeapDumper) \ 86.11 @@ -261,16 +260,6 @@ 86.12 bool allow_nested_vm_operations() const { return true; } 86.13 }; 86.14 86.15 -class VM_HandleFullCodeCache: public VM_Operation { 86.16 - private: 86.17 - bool _is_full; 86.18 - public: 86.19 - VM_HandleFullCodeCache(bool is_full) { _is_full = is_full; } 86.20 - VMOp_Type type() const { return VMOp_HandleFullCodeCache; } 86.21 - void doit(); 86.22 - bool allow_nested_vm_operations() const { return true; } 86.23 -}; 86.24 - 86.25 #ifndef PRODUCT 86.26 class VM_DeoptimizeAll: public VM_Operation { 86.27 private:
87.1 --- a/src/share/vm/services/attachListener.cpp Sat Oct 05 03:14:53 2013 +0200 87.2 +++ b/src/share/vm/services/attachListener.cpp Fri Oct 04 21:00:43 2013 -0700 87.3 @@ -245,7 +245,7 @@ 87.4 } 87.5 value = (tmp != 0); 87.6 } 87.7 - bool res = CommandLineFlags::boolAtPut((char*)name, &value, ATTACH_ON_DEMAND); 87.8 + bool res = CommandLineFlags::boolAtPut((char*)name, &value, Flag::ATTACH_ON_DEMAND); 87.9 if (! res) { 87.10 out->print_cr("setting flag %s failed", name); 87.11 } 87.12 @@ -263,7 +263,7 @@ 87.13 return JNI_ERR; 87.14 } 87.15 } 87.16 - bool res = CommandLineFlags::intxAtPut((char*)name, &value, ATTACH_ON_DEMAND); 87.17 + bool res = CommandLineFlags::intxAtPut((char*)name, &value, Flag::ATTACH_ON_DEMAND); 87.18 if (! res) { 87.19 out->print_cr("setting flag %s failed", name); 87.20 } 87.21 @@ -282,7 +282,7 @@ 87.22 return JNI_ERR; 87.23 } 87.24 } 87.25 - bool res = CommandLineFlags::uintxAtPut((char*)name, &value, ATTACH_ON_DEMAND); 87.26 + bool res = CommandLineFlags::uintxAtPut((char*)name, &value, Flag::ATTACH_ON_DEMAND); 87.27 if (! res) { 87.28 out->print_cr("setting flag %s failed", name); 87.29 } 87.30 @@ -301,7 +301,7 @@ 87.31 return JNI_ERR; 87.32 } 87.33 } 87.34 - bool res = CommandLineFlags::uint64_tAtPut((char*)name, &value, ATTACH_ON_DEMAND); 87.35 + bool res = CommandLineFlags::uint64_tAtPut((char*)name, &value, Flag::ATTACH_ON_DEMAND); 87.36 if (! res) { 87.37 out->print_cr("setting flag %s failed", name); 87.38 } 87.39 @@ -316,7 +316,7 @@ 87.40 out->print_cr("flag value must be a string"); 87.41 return JNI_ERR; 87.42 } 87.43 - bool res = CommandLineFlags::ccstrAtPut((char*)name, &value, ATTACH_ON_DEMAND); 87.44 + bool res = CommandLineFlags::ccstrAtPut((char*)name, &value, Flag::ATTACH_ON_DEMAND); 87.45 if (res) { 87.46 FREE_C_HEAP_ARRAY(char, value, mtInternal); 87.47 } else {
88.1 --- a/src/share/vm/services/classLoadingService.cpp Sat Oct 05 03:14:53 2013 +0200 88.2 +++ b/src/share/vm/services/classLoadingService.cpp Fri Oct 04 21:00:43 2013 -0700 88.3 @@ -202,7 +202,7 @@ 88.4 MutexLocker m(Management_lock); 88.5 88.6 // verbose will be set to the previous value 88.7 - bool succeed = CommandLineFlags::boolAtPut((char*)"TraceClassLoading", &verbose, MANAGEMENT); 88.8 + bool succeed = CommandLineFlags::boolAtPut((char*)"TraceClassLoading", &verbose, Flag::MANAGEMENT); 88.9 assert(succeed, "Setting TraceClassLoading flag fails"); 88.10 reset_trace_class_unloading(); 88.11 88.12 @@ -213,7 +213,7 @@ 88.13 void ClassLoadingService::reset_trace_class_unloading() { 88.14 assert(Management_lock->owned_by_self(), "Must own the Management_lock"); 88.15 bool value = MemoryService::get_verbose() || ClassLoadingService::get_verbose(); 88.16 - bool succeed = CommandLineFlags::boolAtPut((char*)"TraceClassUnloading", &value, MANAGEMENT); 88.17 + bool succeed = CommandLineFlags::boolAtPut((char*)"TraceClassUnloading", &value, Flag::MANAGEMENT); 88.18 assert(succeed, "Setting TraceClassUnLoading flag fails"); 88.19 } 88.20
89.1 --- a/src/share/vm/services/dtraceAttacher.cpp Sat Oct 05 03:14:53 2013 +0200 89.2 +++ b/src/share/vm/services/dtraceAttacher.cpp Fri Oct 04 21:00:43 2013 -0700 89.3 @@ -51,7 +51,7 @@ 89.4 89.5 static void set_bool_flag(const char* flag, bool value) { 89.6 CommandLineFlags::boolAtPut((char*)flag, strlen(flag), &value, 89.7 - ATTACH_ON_DEMAND); 89.8 + Flag::ATTACH_ON_DEMAND); 89.9 } 89.10 89.11 // Enable only the "fine grained" flags. Do *not* touch
90.1 --- a/src/share/vm/services/management.cpp Sat Oct 05 03:14:53 2013 +0200 90.2 +++ b/src/share/vm/services/management.cpp Fri Oct 04 21:00:43 2013 -0700 90.3 @@ -1643,9 +1643,13 @@ 90.4 int num_entries = 0; 90.5 for (int i = 0; i < nFlags; i++) { 90.6 Flag* flag = &Flag::flags[i]; 90.7 + // Exclude notproduct and develop flags in product builds. 90.8 + if (flag->is_constant_in_binary()) { 90.9 + continue; 90.10 + } 90.11 // Exclude the locked (experimental, diagnostic) flags 90.12 if (flag->is_unlocked() || flag->is_unlocker()) { 90.13 - Handle s = java_lang_String::create_from_str(flag->name, CHECK_0); 90.14 + Handle s = java_lang_String::create_from_str(flag->_name, CHECK_0); 90.15 flags_ah->obj_at_put(num_entries, s()); 90.16 num_entries++; 90.17 } 90.18 @@ -1669,7 +1673,7 @@ 90.19 bool add_global_entry(JNIEnv* env, Handle name, jmmVMGlobal *global, Flag *flag, TRAPS) { 90.20 Handle flag_name; 90.21 if (name() == NULL) { 90.22 - flag_name = java_lang_String::create_from_str(flag->name, CHECK_false); 90.23 + flag_name = java_lang_String::create_from_str(flag->_name, CHECK_false); 90.24 } else { 90.25 flag_name = name; 90.26 } 90.27 @@ -1698,23 +1702,23 @@ 90.28 90.29 global->writeable = flag->is_writeable(); 90.30 global->external = flag->is_external(); 90.31 - switch (flag->origin) { 90.32 - case DEFAULT: 90.33 + switch (flag->get_origin()) { 90.34 + case Flag::DEFAULT: 90.35 global->origin = JMM_VMGLOBAL_ORIGIN_DEFAULT; 90.36 break; 90.37 - case COMMAND_LINE: 90.38 + case Flag::COMMAND_LINE: 90.39 global->origin = JMM_VMGLOBAL_ORIGIN_COMMAND_LINE; 90.40 break; 90.41 - case ENVIRON_VAR: 90.42 + case Flag::ENVIRON_VAR: 90.43 global->origin = JMM_VMGLOBAL_ORIGIN_ENVIRON_VAR; 90.44 break; 90.45 - case CONFIG_FILE: 90.46 + case Flag::CONFIG_FILE: 90.47 global->origin = JMM_VMGLOBAL_ORIGIN_CONFIG_FILE; 90.48 break; 90.49 - case MANAGEMENT: 90.50 + case Flag::MANAGEMENT: 90.51 global->origin = JMM_VMGLOBAL_ORIGIN_MANAGEMENT; 90.52 break; 90.53 - case ERGONOMIC: 90.54 + case Flag::ERGONOMIC: 90.55 global->origin = JMM_VMGLOBAL_ORIGIN_ERGONOMIC; 90.56 break; 90.57 default: 90.58 @@ -1781,6 +1785,10 @@ 90.59 int num_entries = 0; 90.60 for (int i = 0; i < nFlags && num_entries < count; i++) { 90.61 Flag* flag = &Flag::flags[i]; 90.62 + // Exclude notproduct and develop flags in product builds. 90.63 + if (flag->is_constant_in_binary()) { 90.64 + continue; 90.65 + } 90.66 // Exclude the locked (diagnostic, experimental) flags 90.67 if ((flag->is_unlocked() || flag->is_unlocker()) && 90.68 add_global_entry(env, null_h, &globals[num_entries], flag, THREAD)) { 90.69 @@ -1813,23 +1821,23 @@ 90.70 bool succeed; 90.71 if (flag->is_bool()) { 90.72 bool bvalue = (new_value.z == JNI_TRUE ? true : false); 90.73 - succeed = CommandLineFlags::boolAtPut(name, &bvalue, MANAGEMENT); 90.74 + succeed = CommandLineFlags::boolAtPut(name, &bvalue, Flag::MANAGEMENT); 90.75 } else if (flag->is_intx()) { 90.76 intx ivalue = (intx)new_value.j; 90.77 - succeed = CommandLineFlags::intxAtPut(name, &ivalue, MANAGEMENT); 90.78 + succeed = CommandLineFlags::intxAtPut(name, &ivalue, Flag::MANAGEMENT); 90.79 } else if (flag->is_uintx()) { 90.80 uintx uvalue = (uintx)new_value.j; 90.81 - succeed = CommandLineFlags::uintxAtPut(name, &uvalue, MANAGEMENT); 90.82 + succeed = CommandLineFlags::uintxAtPut(name, &uvalue, Flag::MANAGEMENT); 90.83 } else if (flag->is_uint64_t()) { 90.84 uint64_t uvalue = (uint64_t)new_value.j; 90.85 - succeed = CommandLineFlags::uint64_tAtPut(name, &uvalue, MANAGEMENT); 90.86 + succeed = CommandLineFlags::uint64_tAtPut(name, &uvalue, Flag::MANAGEMENT); 90.87 } else if (flag->is_ccstr()) { 90.88 oop str = JNIHandles::resolve_external_guard(new_value.l); 90.89 if (str == NULL) { 90.90 THROW(vmSymbols::java_lang_NullPointerException()); 90.91 } 90.92 ccstr svalue = java_lang_String::as_utf8_string(str); 90.93 - succeed = CommandLineFlags::ccstrAtPut(name, &svalue, MANAGEMENT); 90.94 + succeed = CommandLineFlags::ccstrAtPut(name, &svalue, Flag::MANAGEMENT); 90.95 } 90.96 assert(succeed, "Setting flag should succeed"); 90.97 JVM_END
91.1 --- a/src/share/vm/services/memoryService.cpp Sat Oct 05 03:14:53 2013 +0200 91.2 +++ b/src/share/vm/services/memoryService.cpp Fri Oct 04 21:00:43 2013 -0700 91.3 @@ -515,7 +515,7 @@ 91.4 bool MemoryService::set_verbose(bool verbose) { 91.5 MutexLocker m(Management_lock); 91.6 // verbose will be set to the previous value 91.7 - bool succeed = CommandLineFlags::boolAtPut((char*)"PrintGC", &verbose, MANAGEMENT); 91.8 + bool succeed = CommandLineFlags::boolAtPut((char*)"PrintGC", &verbose, Flag::MANAGEMENT); 91.9 assert(succeed, "Setting PrintGC flag fails"); 91.10 ClassLoadingService::reset_trace_class_unloading(); 91.11 91.12 @@ -618,4 +618,3 @@ 91.13 MemoryService::gc_end(_fullGC, _recordPostGCUsage, _recordAccumulatedGCTime, 91.14 _recordGCEndTime, _countCollection, _cause); 91.15 } 91.16 -
92.1 --- a/src/share/vm/trace/trace.xml Sat Oct 05 03:14:53 2013 +0200 92.2 +++ b/src/share/vm/trace/trace.xml Fri Oct 04 21:00:43 2013 -0700 92.3 @@ -313,13 +313,6 @@ 92.4 <value type="UINT" field="zombifiedCount" label="Methods Zombified"/> 92.5 </event> 92.6 92.7 - <event id="CleanCodeCache" path="vm/code_sweeper/clean" label="Clean Code Cache" 92.8 - description="Clean code cache from oldest methods" 92.9 - has_thread="true" is_requestable="false" is_constant="false"> 92.10 - <value type="UINT" field="disconnectedCount" label="Methods Disconnected"/> 92.11 - <value type="UINT" field="madeNonEntrantCount" label="Methods Made Non-Entrant"/> 92.12 - </event> 92.13 - 92.14 <!-- Code cache events --> 92.15 92.16 <event id="CodeCacheFull" path="vm/code_cache/full" label="Code Cache Full"
93.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 93.2 +++ b/test/compiler/intrinsics/mathexact/CondTest.java Fri Oct 04 21:00:43 2013 -0700 93.3 @@ -0,0 +1,59 @@ 93.4 +/* 93.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 93.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 93.7 + * 93.8 + * This code is free software; you can redistribute it and/or modify it 93.9 + * under the terms of the GNU General Public License version 2 only, as 93.10 + * published by the Free Software Foundation. 93.11 + * 93.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 93.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 93.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 93.15 + * version 2 for more details (a copy is included in the LICENSE file that 93.16 + * accompanied this code). 93.17 + * 93.18 + * You should have received a copy of the GNU General Public License version 93.19 + * 2 along with this work; if not, write to the Free Software Foundation, 93.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 93.21 + * 93.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 93.23 + * or visit www.oracle.com if you need additional information or have any 93.24 + * questions. 93.25 + */ 93.26 + 93.27 +/* 93.28 + * @test 93.29 + * @bug 8024924 93.30 + * @summary Test non constant addExact 93.31 + * @compile CondTest.java Verify.java 93.32 + * @run main CondTest 93.33 + * 93.34 + */ 93.35 + 93.36 +import java.lang.ArithmeticException; 93.37 + 93.38 +public class CondTest { 93.39 + public static int result = 0; 93.40 + 93.41 + public static void main(String[] args) { 93.42 + for (int i = 0; i < 50000; ++i) { 93.43 + runTest(); 93.44 + } 93.45 + } 93.46 + 93.47 + public static void runTest() { 93.48 + int i = 7; 93.49 + while (java.lang.Math.addExact(i, result) < 89361) { 93.50 + if ((java.lang.Math.addExact(i, i) & 1) == 1) { 93.51 + i += 3; 93.52 + } else if ((i & 5) == 4) { 93.53 + i += 7; 93.54 + } else if ((i & 0xf) == 6) { 93.55 + i += 2; 93.56 + } else { 93.57 + i += 1; 93.58 + } 93.59 + result += 2; 93.60 + } 93.61 + } 93.62 +}
94.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 94.2 +++ b/test/compiler/intrinsics/mathexact/ConstantTest.java Fri Oct 04 21:00:43 2013 -0700 94.3 @@ -0,0 +1,47 @@ 94.4 +/* 94.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 94.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 94.7 + * 94.8 + * This code is free software; you can redistribute it and/or modify it 94.9 + * under the terms of the GNU General Public License version 2 only, as 94.10 + * published by the Free Software Foundation. 94.11 + * 94.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 94.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 94.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 94.15 + * version 2 for more details (a copy is included in the LICENSE file that 94.16 + * accompanied this code). 94.17 + * 94.18 + * You should have received a copy of the GNU General Public License version 94.19 + * 2 along with this work; if not, write to the Free Software Foundation, 94.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 94.21 + * 94.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 94.23 + * or visit www.oracle.com if you need additional information or have any 94.24 + * questions. 94.25 + */ 94.26 + 94.27 +/* 94.28 + * @test 94.29 + * @bug 8024924 94.30 + * @summary Test constant addExact 94.31 + * @compile ConstantTest.java Verify.java 94.32 + * @run main ConstantTest 94.33 + * 94.34 + */ 94.35 + 94.36 +import java.lang.ArithmeticException; 94.37 + 94.38 +public class ConstantTest { 94.39 + public static void main(String[] args) { 94.40 + for (int i = 0; i < 50000; ++i) { 94.41 + Verify.verify(5, 7); 94.42 + Verify.verify(Integer.MAX_VALUE, 1); 94.43 + Verify.verify(Integer.MIN_VALUE, -1); 94.44 + Verify.verify(Integer.MAX_VALUE, -1); 94.45 + Verify.verify(Integer.MIN_VALUE, 1); 94.46 + Verify.verify(Integer.MAX_VALUE / 2, Integer.MAX_VALUE / 2); 94.47 + Verify.verify(Integer.MAX_VALUE / 2, (Integer.MAX_VALUE / 2) + 3); 94.48 + } 94.49 + } 94.50 +}
95.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 95.2 +++ b/test/compiler/intrinsics/mathexact/LoadTest.java Fri Oct 04 21:00:43 2013 -0700 95.3 @@ -0,0 +1,55 @@ 95.4 +/* 95.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 95.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 95.7 + * 95.8 + * This code is free software; you can redistribute it and/or modify it 95.9 + * under the terms of the GNU General Public License version 2 only, as 95.10 + * published by the Free Software Foundation. 95.11 + * 95.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 95.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 95.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 95.15 + * version 2 for more details (a copy is included in the LICENSE file that 95.16 + * accompanied this code). 95.17 + * 95.18 + * You should have received a copy of the GNU General Public License version 95.19 + * 2 along with this work; if not, write to the Free Software Foundation, 95.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 95.21 + * 95.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 95.23 + * or visit www.oracle.com if you need additional information or have any 95.24 + * questions. 95.25 + */ 95.26 + 95.27 +/* 95.28 + * @test 95.29 + * @bug 8024924 95.30 + * @summary Test non constant addExact 95.31 + * @compile LoadTest.java Verify.java 95.32 + * @run main LoadTest 95.33 + * 95.34 + */ 95.35 + 95.36 +import java.lang.ArithmeticException; 95.37 + 95.38 +public class LoadTest { 95.39 + public static java.util.Random rnd = new java.util.Random(); 95.40 + public static int[] values = new int[256]; 95.41 + 95.42 + public static void main(String[] args) { 95.43 + for (int i = 0; i < values.length; ++i) { 95.44 + values[i] = rnd.nextInt(); 95.45 + } 95.46 + 95.47 + for (int i = 0; i < 50000; ++i) { 95.48 + Verify.verify(values[i & 255], values[i & 255] - i); 95.49 + Verify.verify(values[i & 255] + i, values[i & 255] - i); 95.50 + Verify.verify(values[i & 255], values[i & 255]); 95.51 + if ((i & 1) == 1 && i > 5) { 95.52 + Verify.verify(values[i & 255] + i, values[i & 255] - i); 95.53 + } else { 95.54 + Verify.verify(values[i & 255] - i, values[i & 255] + i); 95.55 + } 95.56 + } 95.57 + } 95.58 +}
96.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 96.2 +++ b/test/compiler/intrinsics/mathexact/LoopDependentTest.java Fri Oct 04 21:00:43 2013 -0700 96.3 @@ -0,0 +1,48 @@ 96.4 +/* 96.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 96.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 96.7 + * 96.8 + * This code is free software; you can redistribute it and/or modify it 96.9 + * under the terms of the GNU General Public License version 2 only, as 96.10 + * published by the Free Software Foundation. 96.11 + * 96.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 96.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 96.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 96.15 + * version 2 for more details (a copy is included in the LICENSE file that 96.16 + * accompanied this code). 96.17 + * 96.18 + * You should have received a copy of the GNU General Public License version 96.19 + * 2 along with this work; if not, write to the Free Software Foundation, 96.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 96.21 + * 96.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 96.23 + * or visit www.oracle.com if you need additional information or have any 96.24 + * questions. 96.25 + */ 96.26 + 96.27 +/* 96.28 + * @test 96.29 + * @bug 8024924 96.30 + * @summary Test non constant addExact 96.31 + * @compile LoopDependentTest.java Verify.java 96.32 + * @run main LoopDependentTest 96.33 + * 96.34 + */ 96.35 + 96.36 +import java.lang.ArithmeticException; 96.37 + 96.38 +public class LoopDependentTest { 96.39 + public static java.util.Random rnd = new java.util.Random(); 96.40 + 96.41 + public static void main(String[] args) { 96.42 + int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt(); 96.43 + for (int i = 0; i < 50000; ++i) { 96.44 + Verify.verify(rnd1 + i, rnd2 + i); 96.45 + Verify.verify(rnd1 + i, rnd2 + (i & 0xff)); 96.46 + Verify.verify(rnd1 - i, rnd2 - (i & 0xff)); 96.47 + Verify.verify(rnd1 + i + 1, rnd2 + i + 2); 96.48 + Verify.verify(rnd1 + i * 2, rnd2 + i); 96.49 + } 96.50 + } 96.51 +}
97.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 97.2 +++ b/test/compiler/intrinsics/mathexact/NonConstantTest.java Fri Oct 04 21:00:43 2013 -0700 97.3 @@ -0,0 +1,48 @@ 97.4 +/* 97.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 97.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 97.7 + * 97.8 + * This code is free software; you can redistribute it and/or modify it 97.9 + * under the terms of the GNU General Public License version 2 only, as 97.10 + * published by the Free Software Foundation. 97.11 + * 97.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 97.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 97.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 97.15 + * version 2 for more details (a copy is included in the LICENSE file that 97.16 + * accompanied this code). 97.17 + * 97.18 + * You should have received a copy of the GNU General Public License version 97.19 + * 2 along with this work; if not, write to the Free Software Foundation, 97.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 97.21 + * 97.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 97.23 + * or visit www.oracle.com if you need additional information or have any 97.24 + * questions. 97.25 + */ 97.26 + 97.27 +/* 97.28 + * @test 97.29 + * @bug 8024924 97.30 + * @summary Test non constant addExact 97.31 + * @compile NonConstantTest.java Verify.java 97.32 + * @run main NonConstantTest 97.33 + * 97.34 + */ 97.35 + 97.36 +import java.lang.ArithmeticException; 97.37 + 97.38 +public class NonConstantTest { 97.39 + public static java.util.Random rnd = new java.util.Random(); 97.40 + 97.41 + public static void main(String[] args) { 97.42 + for (int i = 0; i < 50000; ++i) { 97.43 + int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt(); 97.44 + Verify.verify(rnd1, rnd2); 97.45 + Verify.verify(rnd1, rnd2 + 1); 97.46 + Verify.verify(rnd1 + 1, rnd2); 97.47 + Verify.verify(rnd1 - 1, rnd2); 97.48 + Verify.verify(rnd1, rnd2 - 1); 97.49 + } 97.50 + } 97.51 +}
98.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 98.2 +++ b/test/compiler/intrinsics/mathexact/Verify.java Fri Oct 04 21:00:43 2013 -0700 98.3 @@ -0,0 +1,68 @@ 98.4 +/* 98.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 98.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 98.7 + * 98.8 + * This code is free software; you can redistribute it and/or modify it 98.9 + * under the terms of the GNU General Public License version 2 only, as 98.10 + * published by the Free Software Foundation. 98.11 + * 98.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 98.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 98.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 98.15 + * version 2 for more details (a copy is included in the LICENSE file that 98.16 + * accompanied this code). 98.17 + * 98.18 + * You should have received a copy of the GNU General Public License version 98.19 + * 2 along with this work; if not, write to the Free Software Foundation, 98.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 98.21 + * 98.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 98.23 + * or visit www.oracle.com if you need additional information or have any 98.24 + * questions. 98.25 + */ 98.26 + 98.27 +public class Verify { 98.28 + public static String throwWord(boolean threw) { 98.29 + return (threw ? "threw" : "didn't throw"); 98.30 + } 98.31 + 98.32 + public static void verify(int a, int b) { 98.33 + boolean exception1 = false, exception2 = false; 98.34 + int result1 = 0, result2 = 0; 98.35 + try { 98.36 + result1 = testIntrinsic(a, b); 98.37 + } catch (ArithmeticException e) { 98.38 + exception1 = true; 98.39 + } 98.40 + try { 98.41 + result2 = testNonIntrinsic(a, b); 98.42 + } catch (ArithmeticException e) { 98.43 + exception2 = true; 98.44 + } 98.45 + 98.46 + if (exception1 != exception2) { 98.47 + throw new RuntimeException("Intrinsic version " + throwWord(exception1) + " exception, NonIntrinsic version " + throwWord(exception2) + " for: " + a + " + " + b); 98.48 + } 98.49 + if (result1 != result2) { 98.50 + throw new RuntimeException("Intrinsic version returned: " + a + " while NonIntrinsic version returned: " + b); 98.51 + } 98.52 + } 98.53 + 98.54 + public static int testIntrinsic(int a, int b) { 98.55 + return java.lang.Math.addExact(a, b); 98.56 + } 98.57 + 98.58 + public static int testNonIntrinsic(int a, int b) { 98.59 + return safeAddExact(a, b); 98.60 + } 98.61 + 98.62 + // Copied java.lang.Math.addExact to avoid intrinsification 98.63 + public static int safeAddExact(int x, int y) { 98.64 + int r = x + y; 98.65 + // HD 2-12 Overflow iff both arguments have the opposite sign of the result 98.66 + if (((x ^ r) & (y ^ r)) < 0) { 98.67 + throw new ArithmeticException("integer overflow"); 98.68 + } 98.69 + return r; 98.70 + } 98.71 +}
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 99.2 +++ b/test/compiler/jsr292/methodHandleExceptions/ByteClassLoader.java Fri Oct 04 21:00:43 2013 -0700 99.3 @@ -0,0 +1,44 @@ 99.4 +/* 99.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 99.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 99.7 + * 99.8 + * This code is free software; you can redistribute it and/or modify it 99.9 + * under the terms of the GNU General Public License version 2 only, as 99.10 + * published by the Free Software Foundation. 99.11 + * 99.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 99.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 99.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 99.15 + * version 2 for more details (a copy is included in the LICENSE file that 99.16 + * accompanied this code). 99.17 + * 99.18 + * You should have received a copy of the GNU General Public License version 99.19 + * 2 along with this work; if not, write to the Free Software Foundation, 99.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 99.21 + * 99.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 99.23 + * or visit www.oracle.com if you need additional information or have any 99.24 + * questions. 99.25 + * 99.26 + */ 99.27 + 99.28 +/** 99.29 + * A minimal classloader for loading bytecodes that could not result from 99.30 + * properly compiled Java. 99.31 + * 99.32 + * @author dr2chase 99.33 + */ 99.34 +public class ByteClassLoader extends ClassLoader { 99.35 + /** 99.36 + * (pre)load class name using classData for the definition. 99.37 + * 99.38 + * @param name 99.39 + * @param classData 99.40 + * @return 99.41 + */ 99.42 + public Class<?> loadBytes(String name, byte[] classData) { 99.43 + Class<?> clazz = defineClass(name, classData, 0, classData.length); 99.44 + resolveClass(clazz); 99.45 + return clazz; 99.46 + } 99.47 +}
100.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 100.2 +++ b/test/compiler/jsr292/methodHandleExceptions/C.java Fri Oct 04 21:00:43 2013 -0700 100.3 @@ -0,0 +1,33 @@ 100.4 +/* 100.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 100.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 100.7 + * 100.8 + * This code is free software; you can redistribute it and/or modify it 100.9 + * under the terms of the GNU General Public License version 2 only, as 100.10 + * published by the Free Software Foundation. 100.11 + * 100.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 100.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 100.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 100.15 + * version 2 for more details (a copy is included in the LICENSE file that 100.16 + * accompanied this code). 100.17 + * 100.18 + * You should have received a copy of the GNU General Public License version 100.19 + * 2 along with this work; if not, write to the Free Software Foundation, 100.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 100.21 + * 100.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 100.23 + * or visit www.oracle.com if you need additional information or have any 100.24 + * questions. 100.25 + * 100.26 + */ 100.27 + 100.28 +/** 100.29 + * Test class -- implements I, which provides default for m, but this class 100.30 + * declares it abstract which (should) hide the interface default, and throw 100.31 + * an abstract method error if it is called (calling it requires bytecode hacking 100.32 + * or inconsistent compilation). 100.33 + */ 100.34 +public abstract class C implements I { 100.35 + public abstract int m(); 100.36 +}
101.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 101.2 +++ b/test/compiler/jsr292/methodHandleExceptions/I.java Fri Oct 04 21:00:43 2013 -0700 101.3 @@ -0,0 +1,27 @@ 101.4 +/* 101.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 101.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 101.7 + * 101.8 + * This code is free software; you can redistribute it and/or modify it 101.9 + * under the terms of the GNU General Public License version 2 only, as 101.10 + * published by the Free Software Foundation. 101.11 + * 101.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 101.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 101.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 101.15 + * version 2 for more details (a copy is included in the LICENSE file that 101.16 + * accompanied this code). 101.17 + * 101.18 + * You should have received a copy of the GNU General Public License version 101.19 + * 2 along with this work; if not, write to the Free Software Foundation, 101.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 101.21 + * 101.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 101.23 + * or visit www.oracle.com if you need additional information or have any 101.24 + * questions. 101.25 + * 101.26 + */ 101.27 + 101.28 +public interface I { 101.29 + default public int m() { return 1; } 101.30 +}
102.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 102.2 +++ b/test/compiler/jsr292/methodHandleExceptions/TestAMEnotNPE.java Fri Oct 04 21:00:43 2013 -0700 102.3 @@ -0,0 +1,143 @@ 102.4 +/* 102.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 102.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 102.7 + * 102.8 + * This code is free software; you can redistribute it and/or modify it 102.9 + * under the terms of the GNU General Public License version 2 only, as 102.10 + * published by the Free Software Foundation. 102.11 + * 102.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 102.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 102.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 102.15 + * version 2 for more details (a copy is included in the LICENSE file that 102.16 + * accompanied this code). 102.17 + * 102.18 + * You should have received a copy of the GNU General Public License version 102.19 + * 2 along with this work; if not, write to the Free Software Foundation, 102.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 102.21 + * 102.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 102.23 + * or visit www.oracle.com if you need additional information or have any 102.24 + * questions. 102.25 + * 102.26 + */ 102.27 + 102.28 +import java.lang.reflect.InvocationTargetException; 102.29 +import jdk.internal.org.objectweb.asm.ClassWriter; 102.30 +import jdk.internal.org.objectweb.asm.Handle; 102.31 +import jdk.internal.org.objectweb.asm.MethodVisitor; 102.32 +import jdk.internal.org.objectweb.asm.Opcodes; 102.33 + 102.34 +/** 102.35 + * @test 102.36 + * @bug 8025260 102.37 + * @summary Ensure that AbstractMethodError is thrown, not NullPointerException, through MethodHandles::jump_from_method_handle code path 102.38 + * 102.39 + * @compile -XDignore.symbol.file ByteClassLoader.java I.java C.java TestAMEnotNPE.java 102.40 + * @run main/othervm TestAMEnotNPE 102.41 + */ 102.42 + 102.43 +public class TestAMEnotNPE implements Opcodes { 102.44 + 102.45 + /** 102.46 + * The bytes for D, a NOT abstract class extending abstract class C 102.47 + * without supplying an implementation for abstract method m. 102.48 + * There is a default method in the interface I, but it should lose to 102.49 + * the abstract class. 102.50 + 102.51 + class D extends C { 102.52 + D() { super(); } 102.53 + // does not define m 102.54 + } 102.55 + 102.56 + * @return 102.57 + * @throws Exception 102.58 + */ 102.59 + public static byte[] bytesForD() throws Exception { 102.60 + 102.61 + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS); 102.62 + MethodVisitor mv; 102.63 + 102.64 + cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "D", null, "C", null); 102.65 + 102.66 + { 102.67 + mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 102.68 + mv.visitCode(); 102.69 + mv.visitVarInsn(ALOAD, 0); 102.70 + mv.visitMethodInsn(INVOKESPECIAL, "C", "<init>", "()V"); 102.71 + mv.visitInsn(RETURN); 102.72 + mv.visitMaxs(0, 0); 102.73 + mv.visitEnd(); 102.74 + } 102.75 + cw.visitEnd(); 102.76 + 102.77 + return cw.toByteArray(); 102.78 + } 102.79 + 102.80 + 102.81 + /** 102.82 + * The bytecodes for an invokeExact of a particular methodHandle, I.m, invoked on a D 102.83 + 102.84 + class T { 102.85 + T() { super(); } // boring constructor 102.86 + int test() { 102.87 + MethodHandle mh = `I.m():int`; 102.88 + D d = new D(); 102.89 + return mh.invokeExact(d); // Should explode here, AbstractMethodError 102.90 + } 102.91 + } 102.92 + 102.93 + * @return 102.94 + * @throws Exception 102.95 + */ 102.96 + public static byte[] bytesForT() throws Exception { 102.97 + 102.98 + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS); 102.99 + MethodVisitor mv; 102.100 + 102.101 + cw.visit(V1_8, ACC_PUBLIC + ACC_SUPER, "T", null, "java/lang/Object", null); 102.102 + { 102.103 + mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 102.104 + mv.visitCode(); 102.105 + mv.visitVarInsn(ALOAD, 0); 102.106 + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); 102.107 + mv.visitInsn(RETURN); 102.108 + mv.visitMaxs(0,0); 102.109 + mv.visitEnd(); 102.110 + } 102.111 + { 102.112 + mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "test", "()I", null, null); 102.113 + mv.visitCode(); 102.114 + mv.visitLdcInsn(new Handle(Opcodes.H_INVOKEINTERFACE, "I", "m", "()I")); 102.115 + mv.visitTypeInsn(NEW, "D"); 102.116 + mv.visitInsn(DUP); 102.117 + mv.visitMethodInsn(INVOKESPECIAL, "D", "<init>", "()V"); 102.118 + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invokeExact", "(LI;)I"); 102.119 + mv.visitInsn(IRETURN); 102.120 + mv.visitMaxs(0,0); 102.121 + mv.visitEnd(); 102.122 + } 102.123 + cw.visitEnd(); 102.124 + return cw.toByteArray(); 102.125 + } 102.126 + 102.127 + public static void main(String args[] ) throws Throwable { 102.128 + ByteClassLoader bcl = new ByteClassLoader(); 102.129 + Class<?> d = bcl.loadBytes("D", bytesForD()); 102.130 + Class<?> t = bcl.loadBytes("T", bytesForT()); 102.131 + try { 102.132 + Object result = t.getMethod("test").invoke(null); 102.133 + System.out.println("Expected AbstractMethodError wrapped in InvocationTargetException, saw no exception"); 102.134 + throw new Error("Missing expected exception"); 102.135 + } catch (InvocationTargetException e) { 102.136 + Throwable th = e.getCause(); 102.137 + if (th instanceof AbstractMethodError) { 102.138 + th.printStackTrace(System.out); 102.139 + System.out.println("PASS, saw expected exception (AbstractMethodError, wrapped in InvocationTargetException)."); 102.140 + } else { 102.141 + System.out.println("Expected AbstractMethodError wrapped in InvocationTargetException, saw " + th); 102.142 + throw th; 102.143 + } 102.144 + } 102.145 + } 102.146 +}
103.1 --- a/test/compiler/whitebox/CompilerWhiteBoxTest.java Sat Oct 05 03:14:53 2013 +0200 103.2 +++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java Fri Oct 04 21:00:43 2013 -0700 103.3 @@ -74,6 +74,9 @@ 103.4 protected static final int THRESHOLD; 103.5 /** count of invocation to triger OSR compilation */ 103.6 protected static final long BACKEDGE_THRESHOLD; 103.7 + /** Value of {@code java.vm.info} (interpreted|mixed|comp mode) */ 103.8 + protected static final String MODE 103.9 + = System.getProperty("java.vm.info"); 103.10 103.11 static { 103.12 if (TIERED_COMPILATION) { 103.13 @@ -202,7 +205,7 @@ 103.14 if (WHITE_BOX.getMethodCompilationLevel(method, true) != 0) { 103.15 throw new RuntimeException(method + " osr_comp_level must be == 0"); 103.16 } 103.17 - } 103.18 + } 103.19 103.20 /** 103.21 * Checks, that {@linkplain #method} is compiled.
104.1 --- a/test/compiler/whitebox/DeoptimizeAllTest.java Sat Oct 05 03:14:53 2013 +0200 104.2 +++ b/test/compiler/whitebox/DeoptimizeAllTest.java Fri Oct 04 21:00:43 2013 -0700 104.3 @@ -53,6 +53,12 @@ 104.4 */ 104.5 @Override 104.6 protected void test() throws Exception { 104.7 + if (testCase.isOsr && CompilerWhiteBoxTest.MODE.startsWith( 104.8 + "compiled ")) { 104.9 + System.err.printf("Warning: %s is not applicable in %s%n", 104.10 + testCase.name(), CompilerWhiteBoxTest.MODE); 104.11 + return; 104.12 + } 104.13 compile(); 104.14 checkCompiled(); 104.15 WHITE_BOX.deoptimizeAll();
105.1 --- a/test/compiler/whitebox/DeoptimizeMethodTest.java Sat Oct 05 03:14:53 2013 +0200 105.2 +++ b/test/compiler/whitebox/DeoptimizeMethodTest.java Fri Oct 04 21:00:43 2013 -0700 105.3 @@ -53,6 +53,12 @@ 105.4 */ 105.5 @Override 105.6 protected void test() throws Exception { 105.7 + if (testCase.isOsr && CompilerWhiteBoxTest.MODE.startsWith( 105.8 + "compiled ")) { 105.9 + System.err.printf("Warning: %s is not applicable in %s%n", 105.10 + testCase.name(), CompilerWhiteBoxTest.MODE); 105.11 + return; 105.12 + } 105.13 compile(); 105.14 checkCompiled(); 105.15 deoptimize();
106.1 --- a/test/compiler/whitebox/EnqueueMethodForCompilationTest.java Sat Oct 05 03:14:53 2013 +0200 106.2 +++ b/test/compiler/whitebox/EnqueueMethodForCompilationTest.java Fri Oct 04 21:00:43 2013 -0700 106.3 @@ -70,12 +70,10 @@ 106.4 106.5 int compLevel = getCompLevel(); 106.6 int bci = WHITE_BOX.getMethodEntryBci(method); 106.7 - System.out.println("bci = " + bci); 106.8 - printInfo(); 106.9 deoptimize(); 106.10 - printInfo(); 106.11 checkNotCompiled(); 106.12 - printInfo(); 106.13 + WHITE_BOX.clearMethodState(method); 106.14 + 106.15 WHITE_BOX.enqueueMethodForCompilation(method, compLevel, bci); 106.16 checkCompiled(); 106.17 deoptimize();
107.1 --- a/test/compiler/whitebox/IsMethodCompilableTest.java Sat Oct 05 03:14:53 2013 +0200 107.2 +++ b/test/compiler/whitebox/IsMethodCompilableTest.java Fri Oct 04 21:00:43 2013 -0700 107.3 @@ -68,6 +68,12 @@ 107.4 */ 107.5 @Override 107.6 protected void test() throws Exception { 107.7 + if (testCase.isOsr && CompilerWhiteBoxTest.MODE.startsWith( 107.8 + "compiled ")) { 107.9 + System.err.printf("Warning: %s is not applicable in %s%n", 107.10 + testCase.name(), CompilerWhiteBoxTest.MODE); 107.11 + return; 107.12 + } 107.13 if (!isCompilable()) { 107.14 throw new RuntimeException(method + " must be compilable"); 107.15 }
108.1 --- a/test/compiler/whitebox/MakeMethodNotCompilableTest.java Sat Oct 05 03:14:53 2013 +0200 108.2 +++ b/test/compiler/whitebox/MakeMethodNotCompilableTest.java Fri Oct 04 21:00:43 2013 -0700 108.3 @@ -62,6 +62,12 @@ 108.4 */ 108.5 @Override 108.6 protected void test() throws Exception { 108.7 + if (testCase.isOsr && CompilerWhiteBoxTest.MODE.startsWith( 108.8 + "compiled ")) { 108.9 + System.err.printf("Warning: %s is not applicable in %s%n", 108.10 + testCase.name(), CompilerWhiteBoxTest.MODE); 108.11 + return; 108.12 + } 108.13 checkNotCompiled(); 108.14 if (!isCompilable()) { 108.15 throw new RuntimeException(method + " must be compilable");
109.1 --- a/test/gc/g1/TestSummarizeRSetStats.java Sat Oct 05 03:14:53 2013 +0200 109.2 +++ b/test/gc/g1/TestSummarizeRSetStats.java Fri Oct 04 21:00:43 2013 -0700 109.3 @@ -25,140 +25,61 @@ 109.4 * @test TestSummarizeRSetStats.java 109.5 * @bug 8013895 109.6 * @library /testlibrary 109.7 - * @build TestSummarizeRSetStats 109.8 + * @build TestSummarizeRSetStatsTools TestSummarizeRSetStats 109.9 * @summary Verify output of -XX:+G1SummarizeRSetStats 109.10 * @run main TestSummarizeRSetStats 109.11 * 109.12 * Test the output of G1SummarizeRSetStats in conjunction with G1SummarizeRSetStatsPeriod. 109.13 */ 109.14 109.15 -import com.oracle.java.testlibrary.*; 109.16 -import java.lang.Thread; 109.17 -import java.util.ArrayList; 109.18 -import java.util.Arrays; 109.19 - 109.20 -class RunSystemGCs { 109.21 - // 4M size, both are directly allocated into the old gen 109.22 - static Object[] largeObject1 = new Object[1024 * 1024]; 109.23 - static Object[] largeObject2 = new Object[1024 * 1024]; 109.24 - 109.25 - static int[] temp; 109.26 - 109.27 - public static void main(String[] args) { 109.28 - // create some cross-references between these objects 109.29 - for (int i = 0; i < largeObject1.length; i++) { 109.30 - largeObject1[i] = largeObject2; 109.31 - } 109.32 - 109.33 - for (int i = 0; i < largeObject2.length; i++) { 109.34 - largeObject2[i] = largeObject1; 109.35 - } 109.36 - 109.37 - int numGCs = Integer.parseInt(args[0]); 109.38 - 109.39 - if (numGCs > 0) { 109.40 - // try to force a minor collection: the young gen is 4M, the 109.41 - // amount of data allocated below is roughly that (4*1024*1024 + 109.42 - // some header data) 109.43 - for (int i = 0; i < 1024 ; i++) { 109.44 - temp = new int[1024]; 109.45 - } 109.46 - } 109.47 - 109.48 - for (int i = 0; i < numGCs - 1; i++) { 109.49 - System.gc(); 109.50 - } 109.51 - } 109.52 -} 109.53 - 109.54 public class TestSummarizeRSetStats { 109.55 109.56 - public static String runTest(String[] additionalArgs, int numGCs) throws Exception { 109.57 - ArrayList<String> finalargs = new ArrayList<String>(); 109.58 - String[] defaultArgs = new String[] { 109.59 - "-XX:+UseG1GC", 109.60 - "-Xmn4m", 109.61 - "-Xmx20m", 109.62 - "-XX:InitiatingHeapOccupancyPercent=100", // we don't want the additional GCs due to initial marking 109.63 - "-XX:+PrintGC", 109.64 - "-XX:+UnlockDiagnosticVMOptions", 109.65 - "-XX:G1HeapRegionSize=1M", 109.66 - }; 109.67 - 109.68 - finalargs.addAll(Arrays.asList(defaultArgs)); 109.69 - 109.70 - if (additionalArgs != null) { 109.71 - finalargs.addAll(Arrays.asList(additionalArgs)); 109.72 - } 109.73 - 109.74 - finalargs.add(RunSystemGCs.class.getName()); 109.75 - finalargs.add(String.valueOf(numGCs)); 109.76 - 109.77 - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 109.78 - finalargs.toArray(new String[0])); 109.79 - OutputAnalyzer output = new OutputAnalyzer(pb.start()); 109.80 - 109.81 - output.shouldHaveExitValue(0); 109.82 - 109.83 - String result = output.getStdout(); 109.84 - return result; 109.85 - } 109.86 - 109.87 - private static void expectStatistics(String result, int expectedCumulative, int expectedPeriodic) throws Exception { 109.88 - int actualTotal = result.split("Concurrent RS processed").length - 1; 109.89 - int actualCumulative = result.split("Cumulative RS summary").length - 1; 109.90 - 109.91 - if (expectedCumulative != actualCumulative) { 109.92 - throw new Exception("Incorrect amount of RSet summaries at the end. Expected " + expectedCumulative + ", got " + actualCumulative); 109.93 - } 109.94 - 109.95 - if (expectedPeriodic != (actualTotal - actualCumulative)) { 109.96 - throw new Exception("Incorrect amount of per-period RSet summaries at the end. Expected " + expectedPeriodic + ", got " + (actualTotal - actualCumulative)); 109.97 - } 109.98 - } 109.99 - 109.100 public static void main(String[] args) throws Exception { 109.101 String result; 109.102 109.103 - // no RSet statistics output 109.104 - result = runTest(null, 0); 109.105 - expectStatistics(result, 0, 0); 109.106 + if (!TestSummarizeRSetStatsTools.testingG1GC()) { 109.107 + return; 109.108 + } 109.109 109.110 - // no RSet statistics output 109.111 - result = runTest(null, 2); 109.112 - expectStatistics(result, 0, 0); 109.113 + // no remembered set summary output 109.114 + result = TestSummarizeRSetStatsTools.runTest(null, 0); 109.115 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 0, 0); 109.116 109.117 - // no RSet statistics output 109.118 - result = runTest(new String[] { "-XX:G1SummarizeRSetStatsPeriod=1" }, 3); 109.119 - expectStatistics(result, 0, 0); 109.120 + // no remembered set summary output 109.121 + result = TestSummarizeRSetStatsTools.runTest(null, 2); 109.122 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 0, 0); 109.123 109.124 - // single RSet statistics output at the end 109.125 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 0); 109.126 - expectStatistics(result, 1, 0); 109.127 + // no remembered set summary output 109.128 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:G1SummarizeRSetStatsPeriod=1" }, 3); 109.129 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 0, 0); 109.130 109.131 - // single RSet statistics output at the end 109.132 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 2); 109.133 - expectStatistics(result, 1, 0); 109.134 + // single remembered set summary output at the end 109.135 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 0); 109.136 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 0); 109.137 109.138 - // single RSet statistics output 109.139 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 0); 109.140 - expectStatistics(result, 1, 0); 109.141 + // single remembered set summary output at the end 109.142 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 2); 109.143 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 0); 109.144 109.145 - // two times RSet statistics output 109.146 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 1); 109.147 - expectStatistics(result, 1, 1); 109.148 + // single remembered set summary output 109.149 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 0); 109.150 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 0); 109.151 109.152 - // four times RSet statistics output 109.153 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 3); 109.154 - expectStatistics(result, 1, 3); 109.155 + // two times remembered set summary output 109.156 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 1); 109.157 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 2); 109.158 109.159 - // three times RSet statistics output 109.160 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=2" }, 3); 109.161 - expectStatistics(result, 1, 2); 109.162 + // four times remembered set summary output 109.163 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 3); 109.164 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 6); 109.165 109.166 - // single RSet statistics output 109.167 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=100" }, 3); 109.168 - expectStatistics(result, 1, 1); 109.169 + // three times remembered set summary output 109.170 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=2" }, 3); 109.171 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 4); 109.172 + 109.173 + // single remembered set summary output 109.174 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=100" }, 3); 109.175 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 2); 109.176 } 109.177 } 109.178
110.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 110.2 +++ b/test/gc/g1/TestSummarizeRSetStatsPerRegion.java Fri Oct 04 21:00:43 2013 -0700 110.3 @@ -0,0 +1,55 @@ 110.4 +/* 110.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 110.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 110.7 + * 110.8 + * This code is free software; you can redistribute it and/or modify it 110.9 + * under the terms of the GNU General Public License version 2 only, as 110.10 + * published by the Free Software Foundation. 110.11 + * 110.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 110.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 110.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 110.15 + * version 2 for more details (a copy is included in the LICENSE file that 110.16 + * accompanied this code). 110.17 + * 110.18 + * You should have received a copy of the GNU General Public License version 110.19 + * 2 along with this work; if not, write to the Free Software Foundation, 110.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 110.21 + * 110.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 110.23 + * or visit www.oracle.com if you need additional information or have any 110.24 + * questions. 110.25 + */ 110.26 + 110.27 +/* 110.28 + * @test TestSummarizeRSetStatsPerRegion.java 110.29 + * @bug 8014078 110.30 + * @library /testlibrary 110.31 + * @build TestSummarizeRSetStatsTools TestSummarizeRSetStatsPerRegion 110.32 + * @summary Verify output of -XX:+G1SummarizeRSetStats in regards to per-region type output 110.33 + * @run main TestSummarizeRSetStatsPerRegion 110.34 + */ 110.35 + 110.36 +import com.oracle.java.testlibrary.*; 110.37 +import java.lang.Thread; 110.38 +import java.util.ArrayList; 110.39 +import java.util.Arrays; 110.40 + 110.41 +public class TestSummarizeRSetStatsPerRegion { 110.42 + 110.43 + public static void main(String[] args) throws Exception { 110.44 + String result; 110.45 + 110.46 + if (!TestSummarizeRSetStatsTools.testingG1GC()) { 110.47 + return; 110.48 + } 110.49 + 110.50 + // single remembered set summary output at the end 110.51 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 0); 110.52 + TestSummarizeRSetStatsTools.expectPerRegionRSetSummaries(result, 1, 0); 110.53 + 110.54 + // two times remembered set summary output 110.55 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 1); 110.56 + TestSummarizeRSetStatsTools.expectPerRegionRSetSummaries(result, 1, 2); 110.57 + } 110.58 +}
111.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 111.2 +++ b/test/gc/g1/TestSummarizeRSetStatsThreads.java Fri Oct 04 21:00:43 2013 -0700 111.3 @@ -0,0 +1,83 @@ 111.4 +/* 111.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 111.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 111.7 + * 111.8 + * This code is free software; you can redistribute it and/or modify it 111.9 + * under the terms of the GNU General Public License version 2 only, as 111.10 + * published by the Free Software Foundation. 111.11 + * 111.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 111.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 111.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 111.15 + * version 2 for more details (a copy is included in the LICENSE file that 111.16 + * accompanied this code). 111.17 + * 111.18 + * You should have received a copy of the GNU General Public License version 111.19 + * 2 along with this work; if not, write to the Free Software Foundation, 111.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 111.21 + * 111.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 111.23 + * or visit www.oracle.com if you need additional information or have any 111.24 + * questions. 111.25 + */ 111.26 + 111.27 +/* 111.28 + * @test TestSummarizeRSetStatsThreads 111.29 + * @bug 8025441 111.30 + * @summary Ensure that various values of worker threads/concurrent 111.31 + * refinement threads do not crash the VM. 111.32 + * @key gc 111.33 + * @library /testlibrary 111.34 + */ 111.35 + 111.36 +import java.util.regex.Matcher; 111.37 +import java.util.regex.Pattern; 111.38 + 111.39 +import com.oracle.java.testlibrary.ProcessTools; 111.40 +import com.oracle.java.testlibrary.OutputAnalyzer; 111.41 + 111.42 +public class TestSummarizeRSetStatsThreads { 111.43 + 111.44 + private static void runTest(int refinementThreads, int workerThreads) throws Exception { 111.45 + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", 111.46 + "-XX:+UnlockDiagnosticVMOptions", 111.47 + "-XX:+G1SummarizeRSetStats", 111.48 + "-XX:G1ConcRefinementThreads=" + refinementThreads, 111.49 + "-XX:ParallelGCThreads=" + workerThreads, 111.50 + "-version"); 111.51 + 111.52 + OutputAnalyzer output = new OutputAnalyzer(pb.start()); 111.53 + 111.54 + // check output to contain the string "Concurrent RS threads times (s)" followed by 111.55 + // the correct number of values in the next line. 111.56 + 111.57 + // a zero in refinement thread numbers indicates that the value in ParallelGCThreads should be used. 111.58 + // Additionally use at least one thread. 111.59 + int expectedNumRefinementThreads = refinementThreads == 0 ? workerThreads : refinementThreads; 111.60 + expectedNumRefinementThreads = Math.max(1, expectedNumRefinementThreads); 111.61 + // create the pattern made up of n copies of a floating point number pattern 111.62 + String numberPattern = String.format("%0" + expectedNumRefinementThreads + "d", 0) 111.63 + .replace("0", "\\s+\\d+\\.\\d+"); 111.64 + String pattern = "Concurrent RS threads times \\(s\\)$" + numberPattern + "$"; 111.65 + Matcher m = Pattern.compile(pattern, Pattern.MULTILINE).matcher(output.getStdout()); 111.66 + 111.67 + if (!m.find()) { 111.68 + throw new Exception("Could not find correct output for concurrent RS threads times in stdout," + 111.69 + " should match the pattern \"" + pattern + "\", but stdout is \n" + output.getStdout()); 111.70 + } 111.71 + output.shouldHaveExitValue(0); 111.72 + } 111.73 + 111.74 + public static void main(String[] args) throws Exception { 111.75 + if (!TestSummarizeRSetStatsTools.testingG1GC()) { 111.76 + return; 111.77 + } 111.78 + // different valid combinations of number of refinement and gc worker threads 111.79 + runTest(0, 0); 111.80 + runTest(0, 5); 111.81 + runTest(5, 0); 111.82 + runTest(10, 10); 111.83 + runTest(1, 2); 111.84 + runTest(4, 3); 111.85 + } 111.86 +}
112.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 112.2 +++ b/test/gc/g1/TestSummarizeRSetStatsTools.java Fri Oct 04 21:00:43 2013 -0700 112.3 @@ -0,0 +1,154 @@ 112.4 +/* 112.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 112.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 112.7 + * 112.8 + * This code is free software; you can redistribute it and/or modify it 112.9 + * under the terms of the GNU General Public License version 2 only, as 112.10 + * published by the Free Software Foundation. 112.11 + * 112.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 112.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 112.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 112.15 + * version 2 for more details (a copy is included in the LICENSE file that 112.16 + * accompanied this code). 112.17 + * 112.18 + * You should have received a copy of the GNU General Public License version 112.19 + * 2 along with this work; if not, write to the Free Software Foundation, 112.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 112.21 + * 112.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 112.23 + * or visit www.oracle.com if you need additional information or have any 112.24 + * questions. 112.25 + */ 112.26 + 112.27 +/* 112.28 + * Common helpers for TestSummarizeRSetStats* tests 112.29 + */ 112.30 + 112.31 +import sun.management.ManagementFactoryHelper; 112.32 +import com.sun.management.HotSpotDiagnosticMXBean; 112.33 +import com.sun.management.VMOption; 112.34 + 112.35 +import com.oracle.java.testlibrary.*; 112.36 +import java.util.regex.Matcher; 112.37 +import java.util.regex.Pattern; 112.38 +import java.lang.Thread; 112.39 +import java.util.ArrayList; 112.40 +import java.util.Arrays; 112.41 + 112.42 +class VerifySummaryOutput { 112.43 + // 4M size, both are directly allocated into the old gen 112.44 + static Object[] largeObject1 = new Object[1024 * 1024]; 112.45 + static Object[] largeObject2 = new Object[1024 * 1024]; 112.46 + 112.47 + static int[] temp; 112.48 + 112.49 + public static void main(String[] args) { 112.50 + // create some cross-references between these objects 112.51 + for (int i = 0; i < largeObject1.length; i++) { 112.52 + largeObject1[i] = largeObject2; 112.53 + } 112.54 + 112.55 + for (int i = 0; i < largeObject2.length; i++) { 112.56 + largeObject2[i] = largeObject1; 112.57 + } 112.58 + 112.59 + int numGCs = Integer.parseInt(args[0]); 112.60 + 112.61 + if (numGCs > 0) { 112.62 + // try to force a minor collection: the young gen is 4M, the 112.63 + // amount of data allocated below is roughly that (4*1024*1024 + 112.64 + // some header data) 112.65 + for (int i = 0; i < 1024 ; i++) { 112.66 + temp = new int[1024]; 112.67 + } 112.68 + } 112.69 + 112.70 + for (int i = 0; i < numGCs - 1; i++) { 112.71 + System.gc(); 112.72 + } 112.73 + } 112.74 +} 112.75 + 112.76 +public class TestSummarizeRSetStatsTools { 112.77 + 112.78 + // the VM is currently run using G1GC, i.e. trying to test G1 functionality. 112.79 + public static boolean testingG1GC() { 112.80 + HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean(); 112.81 + 112.82 + VMOption option = diagnostic.getVMOption("UseG1GC"); 112.83 + if (option.getValue().equals("false")) { 112.84 + System.out.println("Skipping this test. It is only a G1 test."); 112.85 + return false; 112.86 + } 112.87 + return true; 112.88 + } 112.89 + 112.90 + public static String runTest(String[] additionalArgs, int numGCs) throws Exception { 112.91 + ArrayList<String> finalargs = new ArrayList<String>(); 112.92 + String[] defaultArgs = new String[] { 112.93 + "-XX:+UseG1GC", 112.94 + "-XX:+UseCompressedOops", 112.95 + "-Xmn4m", 112.96 + "-Xmx20m", 112.97 + "-XX:InitiatingHeapOccupancyPercent=100", // we don't want the additional GCs due to initial marking 112.98 + "-XX:+PrintGC", 112.99 + "-XX:+UnlockDiagnosticVMOptions", 112.100 + "-XX:G1HeapRegionSize=1M", 112.101 + }; 112.102 + 112.103 + finalargs.addAll(Arrays.asList(defaultArgs)); 112.104 + 112.105 + if (additionalArgs != null) { 112.106 + finalargs.addAll(Arrays.asList(additionalArgs)); 112.107 + } 112.108 + 112.109 + finalargs.add(VerifySummaryOutput.class.getName()); 112.110 + finalargs.add(String.valueOf(numGCs)); 112.111 + 112.112 + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 112.113 + finalargs.toArray(new String[0])); 112.114 + OutputAnalyzer output = new OutputAnalyzer(pb.start()); 112.115 + 112.116 + output.shouldHaveExitValue(0); 112.117 + 112.118 + String result = output.getStdout(); 112.119 + return result; 112.120 + } 112.121 + 112.122 + private static void checkCounts(int expected, int actual, String which) throws Exception { 112.123 + if (expected != actual) { 112.124 + throw new Exception("RSet summaries mention " + which + " regions an incorrect number of times. Expected " + expected + ", got " + actual); 112.125 + } 112.126 + } 112.127 + 112.128 + public static void expectPerRegionRSetSummaries(String result, int expectedCumulative, int expectedPeriodic) throws Exception { 112.129 + expectRSetSummaries(result, expectedCumulative, expectedPeriodic); 112.130 + int actualYoung = result.split("Young regions").length - 1; 112.131 + int actualHumonguous = result.split("Humonguous regions").length - 1; 112.132 + int actualFree = result.split("Free regions").length - 1; 112.133 + int actualOther = result.split("Old regions").length - 1; 112.134 + 112.135 + // the strings we check for above are printed four times per summary 112.136 + int expectedPerRegionTypeInfo = (expectedCumulative + expectedPeriodic) * 4; 112.137 + 112.138 + checkCounts(expectedPerRegionTypeInfo, actualYoung, "Young"); 112.139 + checkCounts(expectedPerRegionTypeInfo, actualHumonguous, "Humonguous"); 112.140 + checkCounts(expectedPerRegionTypeInfo, actualFree, "Free"); 112.141 + checkCounts(expectedPerRegionTypeInfo, actualOther, "Old"); 112.142 + } 112.143 + 112.144 + public static void expectRSetSummaries(String result, int expectedCumulative, int expectedPeriodic) throws Exception { 112.145 + int actualTotal = result.split("concurrent refinement").length - 1; 112.146 + int actualCumulative = result.split("Cumulative RS summary").length - 1; 112.147 + 112.148 + if (expectedCumulative != actualCumulative) { 112.149 + throw new Exception("Incorrect amount of RSet summaries at the end. Expected " + expectedCumulative + ", got " + actualCumulative); 112.150 + } 112.151 + 112.152 + if (expectedPeriodic != (actualTotal - actualCumulative)) { 112.153 + throw new Exception("Incorrect amount of per-period RSet summaries at the end. Expected " + expectedPeriodic + ", got " + (actualTotal - actualCumulative)); 112.154 + } 112.155 + } 112.156 +} 112.157 +
113.1 --- a/test/gc/metaspace/G1AddMetaspaceDependency.java Sat Oct 05 03:14:53 2013 +0200 113.2 +++ b/test/gc/metaspace/G1AddMetaspaceDependency.java Fri Oct 04 21:00:43 2013 -0700 113.3 @@ -107,7 +107,6 @@ 113.4 Loader f_loader = new Loader(b_name, b_bytes, a_name, a_loader); 113.5 Loader g_loader = new Loader(b_name, b_bytes, a_name, a_loader); 113.6 113.7 - byte[] b = new byte[20 * 2 << 20]; 113.8 Class<?> c; 113.9 c = b_loader.loadClass(b_name); 113.10 c = c_loader.loadClass(b_name);
114.1 --- a/test/gc/metaspace/TestPerfCountersAndMemoryPools.java Sat Oct 05 03:14:53 2013 +0200 114.2 +++ b/test/gc/metaspace/TestPerfCountersAndMemoryPools.java Fri Oct 04 21:00:43 2013 -0700 114.3 @@ -29,10 +29,11 @@ 114.4 114.5 /* @test TestPerfCountersAndMemoryPools 114.6 * @bug 8023476 114.7 + * @library /testlibrary 114.8 * @summary Tests that a MemoryPoolMXBeans and PerfCounters for metaspace 114.9 * report the same data. 114.10 - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedKlassPointers -XX:+UseSerialGC -XX:+UsePerfData TestPerfCountersAndMemoryPools 114.11 - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedKlassPointers -XX:+UseSerialGC -XX:+UsePerfData TestPerfCountersAndMemoryPools 114.12 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedKlassPointers -XX:+UseSerialGC -XX:+UsePerfData -Xint TestPerfCountersAndMemoryPools 114.13 + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedKlassPointers -XX:+UseSerialGC -XX:+UsePerfData -Xint TestPerfCountersAndMemoryPools 114.14 */ 114.15 public class TestPerfCountersAndMemoryPools { 114.16 public static void main(String[] args) throws Exception { 114.17 @@ -43,11 +44,11 @@ 114.18 } 114.19 } 114.20 114.21 - private static MemoryUsage getMemoryUsage(String memoryPoolName) { 114.22 + private static MemoryPoolMXBean getMemoryPool(String memoryPoolName) { 114.23 List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans(); 114.24 for (MemoryPoolMXBean pool : pools) { 114.25 if (pool.getName().equals(memoryPoolName)) { 114.26 - return pool.getUsage(); 114.27 + return pool; 114.28 } 114.29 } 114.30 114.31 @@ -57,19 +58,18 @@ 114.32 114.33 private static void checkMemoryUsage(String memoryPoolName, String perfNS) 114.34 throws Exception { 114.35 - // Need to do a gc before each comparison to update the perf counters 114.36 + MemoryPoolMXBean pool = getMemoryPool(memoryPoolName); 114.37 114.38 + // Must do a GC to update performance counters 114.39 System.gc(); 114.40 - MemoryUsage mu = getMemoryUsage(memoryPoolName); 114.41 - assertEQ(getMinCapacity(perfNS), mu.getInit()); 114.42 + assertEQ(getMinCapacity(perfNS), pool.getUsage().getInit()); 114.43 114.44 + // Must do a second GC to update the perfomance counters again, since 114.45 + // the call pool.getUsage().getInit() could have allocated some 114.46 + // metadata. 114.47 System.gc(); 114.48 - mu = getMemoryUsage(memoryPoolName); 114.49 - assertEQ(getUsed(perfNS), mu.getUsed()); 114.50 - 114.51 - System.gc(); 114.52 - mu = getMemoryUsage(memoryPoolName); 114.53 - assertEQ(getCapacity(perfNS), mu.getCommitted()); 114.54 + assertEQ(getUsed(perfNS), pool.getUsage().getUsed()); 114.55 + assertEQ(getCapacity(perfNS), pool.getUsage().getCommitted()); 114.56 } 114.57 114.58 private static long getMinCapacity(String ns) throws Exception {
115.1 --- a/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java Sat Oct 05 03:14:53 2013 +0200 115.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java Fri Oct 04 21:00:43 2013 -0700 115.3 @@ -36,8 +36,7 @@ 115.4 import java.nio.file.attribute.*; 115.5 115.6 /** 115.7 - * * Handler for dirs containing classes to compile. 115.8 - * @author igor.ignatyev@oracle.com 115.9 + * Handler for dirs containing classes to compile. 115.10 */ 115.11 public class ClassPathDirEntry extends PathHandler { 115.12
116.1 --- a/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java Sat Oct 05 03:14:53 2013 +0200 116.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java Fri Oct 04 21:00:43 2013 -0700 116.3 @@ -35,7 +35,6 @@ 116.4 116.5 /** 116.6 * Handler for jar-files containing classes to compile. 116.7 - * @author igor.ignatyev@oracle.com 116.8 */ 116.9 public class ClassPathJarEntry extends PathHandler { 116.10
117.1 --- a/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java Sat Oct 05 03:14:53 2013 +0200 117.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java Fri Oct 04 21:00:43 2013 -0700 117.3 @@ -31,8 +31,6 @@ 117.4 117.5 /** 117.6 * Handler for dirs containing jar-files with classes to compile. 117.7 - * 117.8 - * @author igor.ignatyev@oracle.com 117.9 */ 117.10 public class ClassPathJarInDirEntry extends PathHandler { 117.11
118.1 --- a/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java Sat Oct 05 03:14:53 2013 +0200 118.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java Fri Oct 04 21:00:43 2013 -0700 118.3 @@ -32,8 +32,6 @@ 118.4 118.5 /** 118.6 * Handler for files containing a list of classes to compile. 118.7 - * 118.8 - * @author igor.ignatyev@oracle.com 118.9 */ 118.10 public class ClassesListInFile extends PathHandler { 118.11 public ClassesListInFile(Path root, Executor executor) {
119.1 --- a/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java Sat Oct 05 03:14:53 2013 +0200 119.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java Fri Oct 04 21:00:43 2013 -0700 119.3 @@ -32,9 +32,6 @@ 119.4 import java.util.List; 119.5 import java.util.concurrent.*; 119.6 119.7 -/** 119.8 - * @author igor.ignatyev@oracle.com 119.9 - */ 119.10 public class CompileTheWorld { 119.11 /** 119.12 * Entry point. Compiles classes in {@code args}, or all classes in
120.1 --- a/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java Sat Oct 05 03:14:53 2013 +0200 120.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java Fri Oct 04 21:00:43 2013 -0700 120.3 @@ -36,8 +36,6 @@ 120.4 /** 120.5 * Provide method to compile whole class. 120.6 * Also contains compiled methods and classes counters. 120.7 - * 120.8 - * @author igor.ignatyev@oracle.com 120.9 */ 120.10 public class Compiler { 120.11 private Compiler() { }
121.1 --- a/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java Sat Oct 05 03:14:53 2013 +0200 121.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java Fri Oct 04 21:00:43 2013 -0700 121.3 @@ -35,10 +35,7 @@ 121.4 121.5 /** 121.6 * Abstract handler for path. 121.7 - * <p/> 121.8 * Concrete subclasses should implement method {@link #process()}. 121.9 - * 121.10 - * @author igor.ignatyev@oracle.com 121.11 */ 121.12 public abstract class PathHandler { 121.13 private static final Pattern JAR_IN_DIR_PATTERN
122.1 --- a/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java Sat Oct 05 03:14:53 2013 +0200 122.2 +++ b/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java Fri Oct 04 21:00:43 2013 -0700 122.3 @@ -31,8 +31,6 @@ 122.4 122.5 /** 122.6 * Auxiliary methods. 122.7 - * 122.8 - * @author igor.ignatyev@oracle.com 122.9 */ 122.10 public class Utils { 122.11 /**