--- a/.hgtags Thu Mar 04 10:38:12 2010 +0800
+++ b/.hgtags Thu Mar 04 13:40:03 2010 -0800
@@ -58,3 +58,4 @@
dcc938ac40cc45f1ef454d76020b5db5d943001c jdk7-b81
a30062be6d9ca1d48579826f870f85974300004e jdk7-b82
34c8199936a1682aa8587857f44cfaf37c2b6381 jdk7-b83
+b1e55627a6980b9508854ed0c0f21d4f981b4494 jdk7-b84
--- a/.hgtags-top-repo Thu Mar 04 10:38:12 2010 +0800
+++ b/.hgtags-top-repo Thu Mar 04 13:40:03 2010 -0800
@@ -58,3 +58,4 @@
8403096d1fe7ff5318df9708cfec84a3fd3e1cf9 jdk7-b81
e1176f86805fe07fd9fb9da065dc51b47712ce76 jdk7-b82
6880a3af9addb41541e80ebe8cde6f79ec402a58 jdk7-b83
+2f3ea057d1ad56cf3b269cdc4de2741411151982 jdk7-b84
--- a/corba/.hgtags Thu Mar 04 10:38:12 2010 +0800
+++ b/corba/.hgtags Thu Mar 04 13:40:03 2010 -0800
@@ -58,3 +58,4 @@
e08a42a2a94d97ea8eedb187a94dbff822c8fbba jdk7-b81
1e8c1bfad1abb4b81407a0f2645e0fb85764ca48 jdk7-b82
fde0df7a2384f7fe33204a79678989807d9c2b98 jdk7-b83
+68c8961a82e4a3ad2a67991e5d834192a81eb4cd jdk7-b84
--- a/hotspot/.hgtags Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/.hgtags Thu Mar 04 13:40:03 2010 -0800
@@ -80,3 +80,4 @@
9ab385cb0c42997e16a7761ebcd25c90560a2714 hs15-b04
fafab5d5349c7c066d677538db67a1ee0fb33bd2 hs15-b05
3f370a32906eb5ba993fabd7b4279be7f31052b9 jdk7-b83
+ffc8d176b84bcfb5ac21302b4feb3b0c0d69b97c jdk7-b84
--- a/hotspot/make/hotspot_version Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/make/hotspot_version Thu Mar 04 13:40:03 2010 -0800
@@ -35,7 +35,7 @@
HS_MAJOR_VER=17
HS_MINOR_VER=0
-HS_BUILD_NUMBER=09
+HS_BUILD_NUMBER=10
JDK_MAJOR_VER=1
JDK_MINOR_VER=7
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -2730,9 +2730,6 @@
}
Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()) - mdo_offset_bias);
- __ lduw(counter_addr, tmp1);
- __ add(tmp1, DataLayout::counter_increment, tmp1);
- __ stw(tmp1, counter_addr);
Bytecodes::Code bc = method->java_code_at_bci(bci);
// Perform additional virtual call profiling for invokevirtual and
// invokeinterface bytecodes
@@ -2822,15 +2819,23 @@
__ set(DataLayout::counter_increment, tmp1);
__ st_ptr(tmp1, mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) -
mdo_offset_bias);
- if (i < (VirtualCallData::row_limit() - 1)) {
- __ br(Assembler::always, false, Assembler::pt, update_done);
- __ delayed()->nop();
- }
+ __ br(Assembler::always, false, Assembler::pt, update_done);
+ __ delayed()->nop();
__ bind(next_test);
}
+ // Receiver did not match any saved receiver and there is no empty row for it.
+ // Increment total counter to indicate polymorphic case.
+ __ lduw(counter_addr, tmp1);
+ __ add(tmp1, DataLayout::counter_increment, tmp1);
+ __ stw(tmp1, counter_addr);
__ bind(update_done);
}
+ } else {
+ // Static call
+ __ lduw(counter_addr, tmp1);
+ __ add(tmp1, DataLayout::counter_increment, tmp1);
+ __ stw(tmp1, counter_addr);
}
}
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1733,7 +1733,7 @@
brx(Assembler::zero, false, Assembler::pn, found_null);
delayed()->nop();
// Receiver did not match any saved receiver and there is no empty row for it.
- // Increment total counter to indicate polimorphic case.
+ // Increment total counter to indicate polymorphic case.
increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch);
ba(false, done);
delayed()->nop();
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -851,10 +851,10 @@
__ set(reg2offset(r_1) + extraspace + bias, ld_off);
#else
int ld_off = reg2offset(r_1) + extraspace + bias;
+#endif // _LP64
#ifdef ASSERT
G1_forced = true;
#endif // ASSERT
-#endif // _LP64
r_1 = G1_scratch->as_VMReg();// as part of the load/store shuffle
if (!r_2->is_valid()) __ ld (base, ld_off, G1_scratch);
else __ ldx(base, ld_off, G1_scratch);
@@ -865,9 +865,11 @@
if (sig_bt[i] == T_OBJECT || sig_bt[i] == T_ARRAY) {
store_c2i_object(r, base, st_off);
} else if (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) {
+#ifndef _LP64
if (TieredCompilation) {
assert(G1_forced || sig_bt[i] != T_LONG, "should not use register args for longs");
}
+#endif // _LP64
store_c2i_long(r, base, st_off, r_2->is_stack());
} else {
store_c2i_int(r, base, st_off);
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -3279,7 +3279,7 @@
__ bind(next_test);
}
// Receiver did not match any saved receiver and there is no empty row for it.
- // Increment total counter to indicate polimorphic case.
+ // Increment total counter to indicate polymorphic case.
__ addl(counter_addr, DataLayout::counter_increment);
__ bind(update_done);
--- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -233,7 +233,8 @@
} else {
// sp() may have been extended or shrunk by an adapter. At least
// check that we don't fall behind the legal region.
- assert(last_sp < (intptr_t*) interpreter_frame_monitor_begin(), "bad tos");
+ // For top deoptimized frame last_sp == interpreter_frame_monitor_end.
+ assert(last_sp <= (intptr_t*) interpreter_frame_monitor_end(), "bad tos");
return last_sp;
}
}
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1308,7 +1308,7 @@
if (is_virtual_call) {
jccb(Assembler::zero, found_null);
// Receiver did not match any saved receiver and there is no empty row for it.
- // Increment total counter to indicate polimorphic case.
+ // Increment total counter to indicate polymorphic case.
increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
jmp(done);
bind(found_null);
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1341,7 +1341,7 @@
if (is_virtual_call) {
jccb(Assembler::zero, found_null);
// Receiver did not match any saved receiver and there is no empty row for it.
- // Increment total counter to indicate polimorphic case.
+ // Increment total counter to indicate polymorphic case.
increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
jmp(done);
bind(found_null);
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -3238,17 +3238,19 @@
__ xorl(rcx, rcx); // use zero reg to clear memory (shorter code)
__ store_klass_gap(rax, rcx); // zero klass gap for compressed oops
__ store_klass(rax, rsi); // store klass last
+
+ {
+ SkipIfEqual skip(_masm, &DTraceAllocProbes, false);
+ // Trigger dtrace event for fastpath
+ __ push(atos); // save the return value
+ __ call_VM_leaf(
+ CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), rax);
+ __ pop(atos); // restore the return value
+
+ }
__ jmp(done);
}
- {
- SkipIfEqual skip(_masm, &DTraceAllocProbes, false);
- // Trigger dtrace event for fastpath
- __ push(atos); // save the return value
- __ call_VM_leaf(
- CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), rax);
- __ pop(atos); // restore the return value
- }
// slow case
__ bind(slow_case);
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,6 +1,6 @@
/*
* Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright 2007, 2008, 2009 Red Hat, Inc.
+ * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -145,7 +145,7 @@
}
else if (istate->msg() == BytecodeInterpreter::return_from_method) {
// Copy the result into the caller's frame
- result_slots = type2size[method->result_type()];
+ result_slots = type2size[result_type_of(method)];
assert(result_slots >= 0 && result_slots <= 2, "what?");
result = istate->stack() + result_slots;
break;
@@ -394,9 +394,10 @@
// Push our result
if (!HAS_PENDING_EXCEPTION) {
- stack->set_sp(stack->sp() - type2size[method->result_type()]);
+ BasicType type = result_type_of(method);
+ stack->set_sp(stack->sp() - type2size[type]);
- switch (method->result_type()) {
+ switch (type) {
case T_VOID:
break;
@@ -707,6 +708,26 @@
return i;
}
+BasicType CppInterpreter::result_type_of(methodOop method) {
+ BasicType t;
+ switch (method->result_index()) {
+ case 0 : t = T_BOOLEAN; break;
+ case 1 : t = T_CHAR; break;
+ case 2 : t = T_BYTE; break;
+ case 3 : t = T_SHORT; break;
+ case 4 : t = T_INT; break;
+ case 5 : t = T_LONG; break;
+ case 6 : t = T_VOID; break;
+ case 7 : t = T_FLOAT; break;
+ case 8 : t = T_DOUBLE; break;
+ case 9 : t = T_OBJECT; break;
+ default: ShouldNotReachHere();
+ }
+ assert(AbstractInterpreter::BasicType_as_index(t) == method->result_index(),
+ "out of step with AbstractInterpreter::BasicType_as_index");
+ return t;
+}
+
address InterpreterGenerator::generate_empty_entry() {
if (!UseFastEmptyMethods)
return NULL;
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,6 +1,6 @@
/*
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright 2007, 2008 Red Hat, Inc.
+ * Copyright 2007, 2008, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,3 +41,7 @@
private:
// Stack overflow checks
static bool stack_overflow_imminent(JavaThread *thread);
+
+ private:
+ // Fast result type determination
+ static BasicType result_type_of(methodOop method);
--- a/hotspot/src/cpu/zero/vm/globals_zero.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,6 +1,6 @@
/*
* Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright 2007, 2008, 2009 Red Hat, Inc.
+ * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,7 @@
define_pd_global(intx, StackYellowPages, 2);
define_pd_global(intx, StackRedPages, 1);
-define_pd_global(intx, StackShadowPages, 3 LP64_ONLY(+3) DEBUG_ONLY(+3));
+define_pd_global(intx, StackShadowPages, 5 LP64_ONLY(+1) DEBUG_ONLY(+3));
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
--- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,6 +1,6 @@
/*
* Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
- * Copyright 2007, 2008 Red Hat, Inc.
+ * Copyright 2007, 2008, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,13 @@
"stfd %0, 0(%2)\n"
: "=f"(tmp)
: "b"(src), "b"(dst));
+#elif defined(S390) && !defined(_LP64)
+ double tmp;
+ asm volatile ("ld %0, 0(%1)\n"
+ "std %0, 0(%2)\n"
+ : "=r"(tmp)
+ : "a"(src), "a"(dst));
#else
*(jlong *) dst = *(jlong *) src;
-#endif // PPC && !_LP64
+#endif
}
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -730,11 +730,12 @@
st->print(", RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]);
st->print(", RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]);
st->cr();
- st->print(", R8=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]);
+ st->print( "R8=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]);
st->print(", R9=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]);
st->print(", R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]);
st->print(", R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]);
- st->print(", R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]);
+ st->cr();
+ st->print( "R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]);
st->print(", R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]);
st->print(", R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]);
st->print(", R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]);
--- a/hotspot/src/share/vm/c1/c1_IR.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/c1/c1_IR.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -253,7 +253,8 @@
// reexecute allowed only for the topmost frame
bool reexecute = topmost ? should_reexecute() : false;
bool is_method_handle_invoke = false;
- recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, locvals, expvals, monvals);
+ bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis.
+ recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, return_oop, locvals, expvals, monvals);
}
};
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1075,6 +1075,7 @@
};
+// Below length is the # elements copied.
template <class T> int obj_arraycopy_work(oopDesc* src, T* src_addr,
oopDesc* dst, T* dst_addr,
int length) {
@@ -1083,22 +1084,22 @@
// barrier. The assert will fail if this is not the case.
// Note that we use the non-virtual inlineable variant of write_ref_array.
BarrierSet* bs = Universe::heap()->barrier_set();
- assert(bs->has_write_ref_array_opt(),
- "Barrier set must have ref array opt");
+ assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
+ assert(bs->has_write_ref_array_pre_opt(), "For pre-barrier as well.");
if (src == dst) {
// same object, no check
+ bs->write_ref_array_pre(dst_addr, length);
Copy::conjoint_oops_atomic(src_addr, dst_addr, length);
- bs->write_ref_array(MemRegion((HeapWord*)dst_addr,
- (HeapWord*)(dst_addr + length)));
+ bs->write_ref_array((HeapWord*)dst_addr, length);
return ac_ok;
} else {
klassOop bound = objArrayKlass::cast(dst->klass())->element_klass();
klassOop stype = objArrayKlass::cast(src->klass())->element_klass();
if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) {
// Elements are guaranteed to be subtypes, so no check necessary
+ bs->write_ref_array_pre(dst_addr, length);
Copy::conjoint_oops_atomic(src_addr, dst_addr, length);
- bs->write_ref_array(MemRegion((HeapWord*)dst_addr,
- (HeapWord*)(dst_addr + length)));
+ bs->write_ref_array((HeapWord*)dst_addr, length);
return ac_ok;
}
}
@@ -1162,9 +1163,16 @@
#endif
if (num == 0) return;
+ BarrierSet* bs = Universe::heap()->barrier_set();
+ assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
+ assert(bs->has_write_ref_array_pre_opt(), "For pre-barrier as well.");
+ if (UseCompressedOops) {
+ bs->write_ref_array_pre((narrowOop*)dst, num);
+ } else {
+ bs->write_ref_array_pre((oop*)dst, num);
+ }
Copy::conjoint_oops_atomic((oop*) src, (oop*) dst, num);
- BarrierSet* bs = Universe::heap()->barrier_set();
- bs->write_ref_array(MemRegion(dst, dst + num));
+ bs->write_ref_array(dst, num);
JRT_END
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -445,7 +445,8 @@
(morphism == ciCallProfile::MorphismLimit && count == 0)) {
#ifdef ASSERT
if (count > 0) {
- tty->print_cr("bci: %d", bci);
+ this->print_short_name(tty);
+ tty->print_cr(" @ bci:%d", bci);
this->print_codes();
assert(false, "this call site should not be polymorphic");
}
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1121,10 +1121,23 @@
}
void flush() {
+ // The following appears to have been an optimization to save from
+ // doing a barrier for each individual store into the _methods array,
+ // but rather to do it for the entire array after the series of writes.
+ // That optimization seems to have been lost when compressed oops was
+ // implemented. However, the extra card-marks below was left in place,
+ // but is now redundant because the individual stores into the
+ // _methods array already execute the barrier code. CR 6918185 has
+ // been filed so the original code may be restored by deferring the
+ // barriers until after the entire sequence of stores, thus re-enabling
+ // the intent of the original optimization. In the meantime the redundant
+ // card mark below is now disabled.
if (_dirty && _methods != NULL) {
+#if 0
BarrierSet* bs = Universe::heap()->barrier_set();
assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
bs->write_ref_array((HeapWord*)_methods->base(), _methods->length());
+#endif
_dirty = false;
}
}
@@ -1168,9 +1181,7 @@
method = mhandle();
}
- _methods->obj_at_put(_index, method);
- // bad for UseCompressedOops
- // *_methods->obj_at_addr(_index) = method;
+ _methods->obj_at_put(_index, method);
_bcis->ushort_at_put(_index, bci);
_index++;
_dirty = true;
--- a/hotspot/src/share/vm/classfile/loaderConstraints.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/classfile/loaderConstraints.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -457,7 +457,8 @@
}
-void LoaderConstraintTable::verify(Dictionary* dictionary) {
+void LoaderConstraintTable::verify(Dictionary* dictionary,
+ PlaceholderTable* placeholders) {
Thread *thread = Thread::current();
for (int cindex = 0; cindex < _loader_constraint_size; cindex++) {
for (LoaderConstraintEntry* probe = bucket(cindex);
@@ -472,7 +473,23 @@
unsigned int d_hash = dictionary->compute_hash(name, loader);
int d_index = dictionary->hash_to_index(d_hash);
klassOop k = dictionary->find_class(d_index, d_hash, name, loader);
- guarantee(k == probe->klass(), "klass should be in dictionary");
+ if (k != NULL) {
+ // We found the class in the system dictionary, so we should
+ // make sure that the klassOop matches what we already have.
+ guarantee(k == probe->klass(), "klass should be in dictionary");
+ } else {
+ // If we don't find the class in the system dictionary, it
+ // has to be in the placeholders table.
+ unsigned int p_hash = placeholders->compute_hash(name, loader);
+ int p_index = placeholders->hash_to_index(p_hash);
+ PlaceholderEntry* entry = placeholders->get_entry(p_index, p_hash,
+ name, loader);
+
+ // The instanceKlass might not be on the entry, so the only
+ // thing we can check here is whether we were successful in
+ // finding the class in the placeholders table.
+ guarantee(entry != NULL, "klass should be in the placeholders");
+ }
}
for (int n = 0; n< probe->num_loaders(); n++) {
guarantee(probe->loader(n)->is_oop_or_null(), "should be oop");
--- a/hotspot/src/share/vm/classfile/loaderConstraints.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/classfile/loaderConstraints.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -84,7 +84,7 @@
void purge_loader_constraints(BoolObjectClosure* is_alive);
- void verify(Dictionary* dictionary);
+ void verify(Dictionary* dictionary, PlaceholderTable* placeholders);
#ifndef PRODUCT
void print();
#endif
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -2573,7 +2573,7 @@
// Verify constraint table
guarantee(constraints() != NULL, "Verify of loader constraints failed");
- constraints()->verify(dictionary());
+ constraints()->verify(dictionary(), placeholders());
}
--- a/hotspot/src/share/vm/code/debugInfoRec.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/code/debugInfoRec.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -282,6 +282,7 @@
int bci,
bool reexecute,
bool is_method_handle_invoke,
+ bool return_oop,
DebugToken* locals,
DebugToken* expressions,
DebugToken* monitors) {
@@ -296,6 +297,7 @@
// Record flags into pcDesc.
last_pd->set_should_reexecute(reexecute);
last_pd->set_is_method_handle_invoke(is_method_handle_invoke);
+ last_pd->set_return_oop(return_oop);
// serialize sender stream offest
stream()->write_int(sender_stream_offset);
--- a/hotspot/src/share/vm/code/debugInfoRec.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/code/debugInfoRec.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -89,6 +89,7 @@
int bci,
bool reexecute,
bool is_method_handle_invoke = false,
+ bool return_oop = false,
DebugToken* locals = NULL,
DebugToken* expressions = NULL,
DebugToken* monitors = NULL);
--- a/hotspot/src/share/vm/code/nmethod.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/code/nmethod.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -988,7 +988,8 @@
PcDesc* pd = pc_desc_at(pc);
guarantee(pd != NULL, "scope must be present");
return new ScopeDesc(this, pd->scope_decode_offset(),
- pd->obj_decode_offset(), pd->should_reexecute());
+ pd->obj_decode_offset(), pd->should_reexecute(),
+ pd->return_oop());
}
@@ -2010,7 +2011,10 @@
print_pcs();
}
#endif
- guarantee(cont_offset != 0, "unhandled implicit exception in compiled code");
+ if (cont_offset == 0) {
+ // Let the normal error handling report the exception
+ return NULL;
+ }
return instructions_begin() + cont_offset;
}
@@ -2156,7 +2160,8 @@
PcDesc* pd = pc_desc_at(ic->end_of_call());
assert(pd != NULL, "PcDesc must exist");
for (ScopeDesc* sd = new ScopeDesc(this, pd->scope_decode_offset(),
- pd->obj_decode_offset(), pd->should_reexecute());
+ pd->obj_decode_offset(), pd->should_reexecute(),
+ pd->return_oop());
!sd->is_top(); sd = sd->sender()) {
sd->verify();
}
@@ -2421,7 +2426,8 @@
PcDesc* p = pc_desc_near(begin+1);
if (p != NULL && p->real_pc(this) <= end) {
return new ScopeDesc(this, p->scope_decode_offset(),
- p->obj_decode_offset(), p->should_reexecute());
+ p->obj_decode_offset(), p->should_reexecute(),
+ p->return_oop());
}
return NULL;
}
--- a/hotspot/src/share/vm/code/pcDesc.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/code/pcDesc.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -52,7 +52,8 @@
tty->print(" ");
sd->method()->print_short_name(tty);
tty->print(" @%d", sd->bci());
- tty->print(" reexecute=%s", sd->should_reexecute()?"true":"false");
+ if (sd->should_reexecute())
+ tty->print(" reexecute=true");
tty->cr();
}
#endif
--- a/hotspot/src/share/vm/code/pcDesc.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/code/pcDesc.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -39,6 +39,7 @@
struct {
unsigned int reexecute: 1;
unsigned int is_method_handle_invoke: 1;
+ unsigned int return_oop: 1;
} bits;
bool operator ==(const PcDescFlags& other) { return word == other.word; }
} _flags;
@@ -76,6 +77,9 @@
bool is_method_handle_invoke() const { return _flags.bits.is_method_handle_invoke; }
void set_is_method_handle_invoke(bool z) { _flags.bits.is_method_handle_invoke = z; }
+ bool return_oop() const { return _flags.bits.return_oop; }
+ void set_return_oop(bool z) { _flags.bits.return_oop = z; }
+
// Returns the real pc
address real_pc(const nmethod* code) const;
--- a/hotspot/src/share/vm/code/scopeDesc.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/code/scopeDesc.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -26,19 +26,21 @@
# include "incls/_scopeDesc.cpp.incl"
-ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute) {
+ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop) {
_code = code;
_decode_offset = decode_offset;
_objects = decode_object_values(obj_decode_offset);
_reexecute = reexecute;
+ _return_oop = return_oop;
decode_body();
}
-ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute) {
+ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop) {
_code = code;
_decode_offset = decode_offset;
_objects = decode_object_values(DebugInformationRecorder::serialized_null);
_reexecute = reexecute;
+ _return_oop = return_oop;
decode_body();
}
@@ -48,6 +50,7 @@
_decode_offset = parent->_sender_decode_offset;
_objects = parent->_objects;
_reexecute = false; //reexecute only applies to the first scope
+ _return_oop = false;
decode_body();
}
--- a/hotspot/src/share/vm/code/scopeDesc.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/code/scopeDesc.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -52,17 +52,18 @@
class ScopeDesc : public ResourceObj {
public:
// Constructor
- ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute);
+ ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop);
// Calls above, giving default value of "serialized_null" to the
// "obj_decode_offset" argument. (We don't use a default argument to
// avoid a .hpp-.hpp dependency.)
- ScopeDesc(const nmethod* code, int decode_offset, bool reexecute);
+ ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop);
// JVM state
methodHandle method() const { return _method; }
int bci() const { return _bci; }
bool should_reexecute() const { return _reexecute; }
+ bool return_oop() const { return _return_oop; }
GrowableArray<ScopeValue*>* locals();
GrowableArray<ScopeValue*>* expressions();
@@ -88,6 +89,7 @@
methodHandle _method;
int _bci;
bool _reexecute;
+ bool _return_oop;
// Decoding offsets
int _decode_offset;
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -300,7 +300,23 @@
int count;
jbyte* cached_ptr = add_card_count(card_ptr, &count, defer);
assert(cached_ptr != NULL, "bad cached card ptr");
- assert(!is_young_card(cached_ptr), "shouldn't get a card in young region");
+
+ if (is_young_card(cached_ptr)) {
+ // The region containing cached_ptr has been freed during a clean up
+ // pause, reallocated, and tagged as young.
+ assert(cached_ptr != card_ptr, "shouldn't be");
+
+ // We've just inserted a new old-gen card pointer into the card count
+ // cache and evicted the previous contents of that count slot.
+ // The evicted card pointer has been determined to be in a young region
+ // and so cannot be the newly inserted card pointer (that will be
+ // in an old region).
+ // The count for newly inserted card will be set to zero during the
+ // insertion, so we don't want to defer the cleaning of the newly
+ // inserted card pointer.
+ assert(*defer == false, "deferring non-hot card");
+ return NULL;
+ }
// The card pointer we obtained from card count cache is not hot
// so do not store it in the cache; return it for immediate
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -2505,6 +2505,7 @@
}
void G1CollectedHeap::gc_prologue(bool full /* Ignored */) {
+ // always_do_update_barrier = false;
assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer");
// Call allocation profiler
AllocationProfiler::iterate_since_last_gc();
@@ -2518,6 +2519,7 @@
// is set.
COMPILER2_PRESENT(assert(DerivedPointerTable::is_empty(),
"derived pointer present"));
+ // always_do_update_barrier = true;
}
void G1CollectedHeap::do_collection_pause() {
@@ -2644,6 +2646,13 @@
// </NEW PREDICTION>
+struct PrepareForRSScanningClosure : public HeapRegionClosure {
+ bool doHeapRegion(HeapRegion *r) {
+ r->rem_set()->set_iter_claimed(0);
+ return false;
+ }
+};
+
void
G1CollectedHeap::do_collection_pause_at_safepoint() {
if (PrintHeapAtGC) {
@@ -2782,6 +2791,8 @@
gclog_or_tty->print_cr("\nAfter pause, heap:");
print();
#endif
+ PrepareForRSScanningClosure prepare_for_rs_scan;
+ collection_set_iterate(&prepare_for_rs_scan);
setup_surviving_young_words();
@@ -3779,22 +3790,16 @@
return obj;
}
-template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee, bool skip_cset_test>
+template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_forwardee>
template <class T>
-void G1ParCopyClosure <do_gen_barrier, barrier, do_mark_forwardee, skip_cset_test>
+void G1ParCopyClosure <do_gen_barrier, barrier, do_mark_forwardee>
::do_oop_work(T* p) {
oop obj = oopDesc::load_decode_heap_oop(p);
assert(barrier != G1BarrierRS || obj != NULL,
"Precondition: G1BarrierRS implies obj is nonNull");
- // The only time we skip the cset test is when we're scanning
- // references popped from the queue. And we only push on the queue
- // references that we know point into the cset, so no point in
- // checking again. But we'll leave an assert here for peace of mind.
- assert(!skip_cset_test || _g1->obj_in_cs(obj), "invariant");
-
// here the null check is implicit in the cset_fast_test() test
- if (skip_cset_test || _g1->in_cset_fast_test(obj)) {
+ if (_g1->in_cset_fast_test(obj)) {
#if G1_REM_SET_LOGGING
gclog_or_tty->print_cr("Loc "PTR_FORMAT" contains pointer "PTR_FORMAT" "
"into CS.", p, (void*) obj);
@@ -3811,7 +3816,6 @@
}
}
- // When scanning moved objs, must look at all oops.
if (barrier == G1BarrierEvac && obj != NULL) {
_par_scan_state->update_rs(_from, p, _par_scan_state->queue_num());
}
@@ -3821,8 +3825,8 @@
}
}
-template void G1ParCopyClosure<false, G1BarrierEvac, false, true>::do_oop_work(oop* p);
-template void G1ParCopyClosure<false, G1BarrierEvac, false, true>::do_oop_work(narrowOop* p);
+template void G1ParCopyClosure<false, G1BarrierEvac, false>::do_oop_work(oop* p);
+template void G1ParCopyClosure<false, G1BarrierEvac, false>::do_oop_work(narrowOop* p);
template <class T> void G1ParScanPartialArrayClosure::do_oop_nv(T* p) {
assert(has_partial_array_mask(p), "invariant");
@@ -3894,11 +3898,11 @@
assert(UseCompressedOops, "Error");
narrowOop* p = (narrowOop*) stolen_task;
assert(has_partial_array_mask(p) ||
- _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "Error");
+ _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "Error");
pss->push_on_queue(p);
} else {
oop* p = (oop*) stolen_task;
- assert(has_partial_array_mask(p) || _g1h->obj_in_cs(*p), "Error");
+ assert(has_partial_array_mask(p) || _g1h->is_in_g1_reserved(*p), "Error");
pss->push_on_queue(p);
}
continue;
@@ -3960,6 +3964,7 @@
G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss);
G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss);
G1ParScanHeapRSClosure only_scan_heap_rs_cl(_g1h, &pss);
+ G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss);
G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss);
G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss);
@@ -3983,7 +3988,7 @@
_g1h->g1_process_strong_roots(/* not collecting perm */ false,
SharedHeap::SO_AllClasses,
scan_root_cl,
- &only_scan_heap_rs_cl,
+ &push_heap_rs_cl,
scan_so_cl,
scan_perm_cl,
i);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -1623,7 +1623,7 @@
template <class T> void push_on_queue(T* ref) {
assert(ref != NULL, "invariant");
assert(has_partial_array_mask(ref) ||
- _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(ref)), "invariant");
+ _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(ref)), "invariant");
#ifdef ASSERT
if (has_partial_array_mask(ref)) {
oop p = clear_partial_array_mask(ref);
@@ -1644,9 +1644,9 @@
assert((oop*)ref != NULL, "pop_local() returned true");
assert(UseCompressedOops || !ref.is_narrow(), "Error");
assert(has_partial_array_mask((oop*)ref) ||
- _g1h->obj_in_cs(ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)ref)
- : oopDesc::load_decode_heap_oop((oop*)ref)),
- "invariant");
+ _g1h->is_in_g1_reserved(ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)ref)
+ : oopDesc::load_decode_heap_oop((oop*)ref)),
+ "invariant");
IF_G1_DETAILED_STATS(note_pop());
} else {
StarTask null_task;
@@ -1659,9 +1659,9 @@
assert((oop*)new_ref != NULL, "pop() from a local non-empty stack");
assert(UseCompressedOops || !new_ref.is_narrow(), "Error");
assert(has_partial_array_mask((oop*)new_ref) ||
- _g1h->obj_in_cs(new_ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)new_ref)
- : oopDesc::load_decode_heap_oop((oop*)new_ref)),
- "invariant");
+ _g1h->is_in_g1_reserved(new_ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)new_ref)
+ : oopDesc::load_decode_heap_oop((oop*)new_ref)),
+ "invariant");
ref = new_ref;
}
@@ -1825,12 +1825,12 @@
assert(UseCompressedOops, "Error");
narrowOop* p = (narrowOop*)ref_to_scan;
assert(!has_partial_array_mask(p) &&
- _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity");
+ _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity");
deal_with_reference(p);
} else {
oop* p = (oop*)ref_to_scan;
- assert((has_partial_array_mask(p) && _g1h->obj_in_cs(clear_partial_array_mask(p))) ||
- _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity");
+ assert((has_partial_array_mask(p) && _g1h->is_in_g1_reserved(clear_partial_array_mask(p))) ||
+ _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity");
deal_with_reference(p);
}
}
@@ -1844,12 +1844,12 @@
assert(UseCompressedOops, "Error");
narrowOop* p = (narrowOop*)ref_to_scan;
assert(!has_partial_array_mask(p) &&
- _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity");
+ _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity");
deal_with_reference(p);
} else {
oop* p = (oop*)ref_to_scan;
assert((has_partial_array_mask(p) && _g1h->obj_in_cs(clear_partial_array_mask(p))) ||
- _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity");
+ _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity");
deal_with_reference(p);
}
}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -205,6 +205,7 @@
// policy is created before the heap, we have to set this up here,
// so it's done as soon as possible.
HeapRegion::setup_heap_region_size(Arguments::min_heap_size());
+ HeapRegionRemSet::setup_remset_size();
_recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime());
_prev_collection_pause_end_ms = os::elapsedTime() * 1000.0;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -53,6 +53,15 @@
bool apply_to_weak_ref_discovered_field() { return true; }
};
+class G1ParPushHeapRSClosure : public G1ParClosureSuper {
+public:
+ G1ParPushHeapRSClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
+ G1ParClosureSuper(g1, par_scan_state) { }
+ template <class T> void do_oop_nv(T* p);
+ virtual void do_oop(oop* p) { do_oop_nv(p); }
+ virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
+};
+
class G1ParScanClosure : public G1ParClosureSuper {
public:
G1ParScanClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
@@ -100,7 +109,7 @@
};
template<bool do_gen_barrier, G1Barrier barrier,
- bool do_mark_forwardee, bool skip_cset_test>
+ bool do_mark_forwardee>
class G1ParCopyClosure : public G1ParCopyHelper {
G1ParScanClosure _scanner;
template <class T> void do_oop_work(T* p);
@@ -116,12 +125,13 @@
virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
};
-typedef G1ParCopyClosure<false, G1BarrierNone, false, false> G1ParScanExtRootClosure;
-typedef G1ParCopyClosure<true, G1BarrierNone, false, false> G1ParScanPermClosure;
-typedef G1ParCopyClosure<false, G1BarrierRS, false, false> G1ParScanHeapRSClosure;
-typedef G1ParCopyClosure<false, G1BarrierNone, true, false> G1ParScanAndMarkExtRootClosure;
-typedef G1ParCopyClosure<true, G1BarrierNone, true, false> G1ParScanAndMarkPermClosure;
-typedef G1ParCopyClosure<false, G1BarrierRS, true, false> G1ParScanAndMarkHeapRSClosure;
+typedef G1ParCopyClosure<false, G1BarrierNone, false> G1ParScanExtRootClosure;
+typedef G1ParCopyClosure<true, G1BarrierNone, false> G1ParScanPermClosure;
+typedef G1ParCopyClosure<false, G1BarrierRS, false> G1ParScanHeapRSClosure;
+typedef G1ParCopyClosure<false, G1BarrierNone, true> G1ParScanAndMarkExtRootClosure;
+typedef G1ParCopyClosure<true, G1BarrierNone, true> G1ParScanAndMarkPermClosure;
+typedef G1ParCopyClosure<false, G1BarrierRS, true> G1ParScanAndMarkHeapRSClosure;
+
// This is the only case when we set skip_cset_test. Basically, this
// closure is (should?) only be called directly while we're draining
// the overflow and task queues. In that case we know that the
@@ -132,7 +142,7 @@
// We need a separate closure to handle references during evacuation
// failure processing, as we cannot asume that the reference already
// points into the collection set (like G1ParScanHeapEvacClosure does).
-typedef G1ParCopyClosure<false, G1BarrierEvac, false, false> G1ParScanHeapEvacFailureClosure;
+typedef G1ParCopyClosure<false, G1BarrierEvac, false> G1ParScanHeapEvacFailureClosure;
class FilterIntoCSClosure: public OopClosure {
G1CollectedHeap* _g1;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -104,3 +104,16 @@
}
}
}
+
+template <class T> inline void G1ParPushHeapRSClosure::do_oop_nv(T* p) {
+ T heap_oop = oopDesc::load_heap_oop(p);
+
+ if (!oopDesc::is_null(heap_oop)) {
+ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+ if (_g1->in_cset_fast_test(obj)) {
+ Prefetch::write(obj->mark_addr(), 0);
+ Prefetch::read(obj->mark_addr(), (HeapWordSize*2));
+ _par_scan_state->push_on_queue(p);
+ }
+ }
+}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -155,8 +155,8 @@
G1BlockOffsetSharedArray* _bot_shared;
CardTableModRefBS *_ct_bs;
int _worker_i;
+ int _block_size;
bool _try_claimed;
- size_t _min_skip_distance, _max_skip_distance;
public:
ScanRSClosure(OopsInHeapRegionClosure* oc, int worker_i) :
_oc(oc),
@@ -168,8 +168,7 @@
_g1h = G1CollectedHeap::heap();
_bot_shared = _g1h->bot_shared();
_ct_bs = (CardTableModRefBS*) (_g1h->barrier_set());
- _min_skip_distance = 16;
- _max_skip_distance = 2 * _g1h->n_par_threads() * _min_skip_distance;
+ _block_size = MAX2<int>(G1RSetScanBlockSize, 1);
}
void set_try_claimed() { _try_claimed = true; }
@@ -225,12 +224,15 @@
HeapRegionRemSetIterator* iter = _g1h->rem_set_iterator(_worker_i);
hrrs->init_iterator(iter);
size_t card_index;
- size_t skip_distance = 0, current_card = 0, jump_to_card = 0;
- while (iter->has_next(card_index)) {
- if (current_card < jump_to_card) {
- ++current_card;
- continue;
+
+ // We claim cards in block so as to recude the contention. The block size is determined by
+ // the G1RSetScanBlockSize parameter.
+ size_t jump_to_card = hrrs->iter_claimed_next(_block_size);
+ for (size_t current_card = 0; iter->has_next(card_index); current_card++) {
+ if (current_card >= jump_to_card + _block_size) {
+ jump_to_card = hrrs->iter_claimed_next(_block_size);
}
+ if (current_card < jump_to_card) continue;
HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index);
#if 0
gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n",
@@ -247,22 +249,14 @@
// If the card is dirty, then we will scan it during updateRS.
if (!card_region->in_collection_set() && !_ct_bs->is_card_dirty(card_index)) {
- if (!_ct_bs->is_card_claimed(card_index) && _ct_bs->claim_card(card_index)) {
- scanCard(card_index, card_region);
- } else if (_try_claimed) {
- if (jump_to_card == 0 || jump_to_card != current_card) {
- // We did some useful work in the previous iteration.
- // Decrease the distance.
- skip_distance = MAX2(skip_distance >> 1, _min_skip_distance);
- } else {
- // Previous iteration resulted in a claim failure.
- // Increase the distance.
- skip_distance = MIN2(skip_distance << 1, _max_skip_distance);
- }
- jump_to_card = current_card + skip_distance;
- }
+ // We make the card as "claimed" lazily (so races are possible but they're benign),
+ // which reduces the number of duplicate scans (the rsets of the regions in the cset
+ // can intersect).
+ if (!_ct_bs->is_card_claimed(card_index)) {
+ _ct_bs->set_card_claimed(card_index);
+ scanCard(card_index, card_region);
+ }
}
- ++current_card;
}
if (!_try_claimed) {
hrrs->set_iter_complete();
@@ -299,30 +293,18 @@
double rs_time_start = os::elapsedTime();
HeapRegion *startRegion = calculateStartRegion(worker_i);
- BufferingOopsInHeapRegionClosure boc(oc);
- ScanRSClosure scanRScl(&boc, worker_i);
+ ScanRSClosure scanRScl(oc, worker_i);
_g1->collection_set_iterate_from(startRegion, &scanRScl);
scanRScl.set_try_claimed();
_g1->collection_set_iterate_from(startRegion, &scanRScl);
- boc.done();
- double closure_app_time_sec = boc.closure_app_seconds();
- double scan_rs_time_sec = (os::elapsedTime() - rs_time_start) -
- closure_app_time_sec;
- double closure_app_time_ms = closure_app_time_sec * 1000.0;
+ double scan_rs_time_sec = os::elapsedTime() - rs_time_start;
assert( _cards_scanned != NULL, "invariant" );
_cards_scanned[worker_i] = scanRScl.cards_done();
_g1p->record_scan_rs_start_time(worker_i, rs_time_start * 1000.0);
_g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0);
-
- double scan_new_refs_time_ms = _g1p->get_scan_new_refs_time(worker_i);
- if (scan_new_refs_time_ms > 0.0) {
- closure_app_time_ms += scan_new_refs_time_ms;
- }
-
- _g1p->record_obj_copy_time(worker_i, closure_app_time_ms);
}
void HRInto_G1RemSet::updateRS(int worker_i) {
@@ -449,9 +431,8 @@
oc->do_oop(p);
}
}
- _g1p->record_scan_new_refs_time(worker_i,
- (os::elapsedTime() - scan_new_refs_start_sec)
- * 1000.0);
+ double scan_new_refs_time_ms = (os::elapsedTime() - scan_new_refs_start_sec) * 1000.0;
+ _g1p->record_scan_new_refs_time(worker_i, scan_new_refs_time_ms);
}
void HRInto_G1RemSet::cleanupHRRS() {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -207,8 +207,20 @@
develop(bool, G1PrintOopAppls, false, \
"When true, print applications of closures to external locs.") \
\
- develop(intx, G1LogRSRegionEntries, 7, \
- "Log_2 of max number of regions for which we keep bitmaps.") \
+ develop(intx, G1RSetRegionEntriesBase, 256, \
+ "Max number of regions in a fine-grain table per MB.") \
+ \
+ product(intx, G1RSetRegionEntries, 0, \
+ "Max number of regions for which we keep bitmaps." \
+ "Will be set ergonomically by default") \
+ \
+ develop(intx, G1RSetSparseRegionEntriesBase, 4, \
+ "Max number of entries per region in a sparse table " \
+ "per MB.") \
+ \
+ product(intx, G1RSetSparseRegionEntries, 0, \
+ "Max number of entries per region in a sparse table." \
+ "Will be set ergonomically by default.") \
\
develop(bool, G1RecordHRRSOops, false, \
"When true, record recent calls to rem set operations.") \
@@ -293,6 +305,10 @@
develop(bool, G1VerifyCTCleanup, false, \
"Verify card table cleanup.") \
\
+ product(uintx, G1RSetScanBlockSize, 64, \
+ "Size of a work unit of cards claimed by a worker thread" \
+ "during RSet scanning.") \
+ \
develop(bool, ReduceInitialCardMarksForG1, false, \
"When ReduceInitialCardMarks is true, this flag setting " \
" controls whether G1 allows the RICM optimization")
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -33,11 +33,12 @@
};
template<bool do_gen_barrier, G1Barrier barrier,
- bool do_mark_forwardee, bool skip_cset_test>
+ bool do_mark_forwardee>
class G1ParCopyClosure;
class G1ParScanClosure;
+class G1ParPushHeapRSClosure;
-typedef G1ParCopyClosure<false, G1BarrierEvac, false, true> G1ParScanHeapEvacClosure;
+typedef G1ParCopyClosure<false, G1BarrierEvac, false> G1ParScanHeapEvacClosure;
class FilterIntoCSClosure;
class FilterOutOfRegionClosure;
@@ -51,6 +52,7 @@
#define FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES(f) \
f(G1ParScanHeapEvacClosure,_nv) \
f(G1ParScanClosure,_nv) \
+ f(G1ParPushHeapRSClosure,_nv) \
f(FilterIntoCSClosure,_nv) \
f(FilterOutOfRegionClosure,_nv) \
f(FilterInHeapRegionAndIntoCSClosure,_nv) \
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -258,42 +258,6 @@
ReserveParTableExpansion = 1
};
- void par_expand() {
- int n = HeapRegionRemSet::num_par_rem_sets()-1;
- if (n <= 0) return;
- if (_par_tables == NULL) {
- PerRegionTable* res =
- (PerRegionTable*)
- Atomic::cmpxchg_ptr((PerRegionTable*)ReserveParTableExpansion,
- &_par_tables, NULL);
- if (res != NULL) return;
- // Otherwise, we reserved the right to do the expansion.
-
- PerRegionTable** ptables = NEW_C_HEAP_ARRAY(PerRegionTable*, n);
- for (int i = 0; i < n; i++) {
- PerRegionTable* ptable = PerRegionTable::alloc(hr());
- ptables[i] = ptable;
- }
- // Here we do not need an atomic.
- _par_tables = ptables;
-#if COUNT_PAR_EXPANDS
- print_par_expand();
-#endif
- // We must put this table on the expanded list.
- PosParPRT* exp_head = _par_expanded_list;
- while (true) {
- set_next_par_expanded(exp_head);
- PosParPRT* res =
- (PosParPRT*)
- Atomic::cmpxchg_ptr(this, &_par_expanded_list, exp_head);
- if (res == exp_head) return;
- // Otherwise.
- exp_head = res;
- }
- ShouldNotReachHere();
- }
- }
-
void par_contract() {
assert(_par_tables != NULL, "Precondition.");
int n = HeapRegionRemSet::num_par_rem_sets()-1;
@@ -391,13 +355,49 @@
void set_next(PosParPRT* nxt) { _next = nxt; }
PosParPRT** next_addr() { return &_next; }
+ bool should_expand(int tid) {
+ return par_tables() == NULL && tid > 0 && hr()->is_gc_alloc_region();
+ }
+
+ void par_expand() {
+ int n = HeapRegionRemSet::num_par_rem_sets()-1;
+ if (n <= 0) return;
+ if (_par_tables == NULL) {
+ PerRegionTable* res =
+ (PerRegionTable*)
+ Atomic::cmpxchg_ptr((PerRegionTable*)ReserveParTableExpansion,
+ &_par_tables, NULL);
+ if (res != NULL) return;
+ // Otherwise, we reserved the right to do the expansion.
+
+ PerRegionTable** ptables = NEW_C_HEAP_ARRAY(PerRegionTable*, n);
+ for (int i = 0; i < n; i++) {
+ PerRegionTable* ptable = PerRegionTable::alloc(hr());
+ ptables[i] = ptable;
+ }
+ // Here we do not need an atomic.
+ _par_tables = ptables;
+#if COUNT_PAR_EXPANDS
+ print_par_expand();
+#endif
+ // We must put this table on the expanded list.
+ PosParPRT* exp_head = _par_expanded_list;
+ while (true) {
+ set_next_par_expanded(exp_head);
+ PosParPRT* res =
+ (PosParPRT*)
+ Atomic::cmpxchg_ptr(this, &_par_expanded_list, exp_head);
+ if (res == exp_head) return;
+ // Otherwise.
+ exp_head = res;
+ }
+ ShouldNotReachHere();
+ }
+ }
+
void add_reference(OopOrNarrowOopStar from, int tid) {
// Expand if necessary.
PerRegionTable** pt = par_tables();
- if (par_tables() == NULL && tid > 0 && hr()->is_gc_alloc_region()) {
- par_expand();
- pt = par_tables();
- }
if (pt != NULL) {
// We always have to assume that mods to table 0 are in parallel,
// because of the claiming scheme in parallel expansion. A thread
@@ -505,12 +505,13 @@
typedef PosParPRT* PosParPRTPtr;
if (_max_fine_entries == 0) {
assert(_mod_max_fine_entries_mask == 0, "Both or none.");
- _max_fine_entries = (size_t)(1 << G1LogRSRegionEntries);
+ size_t max_entries_log = (size_t)log2_long((jlong)G1RSetRegionEntries);
+ _max_fine_entries = (size_t)(1 << max_entries_log);
_mod_max_fine_entries_mask = _max_fine_entries - 1;
#if SAMPLE_FOR_EVICTION
assert(_fine_eviction_sample_size == 0
&& _fine_eviction_stride == 0, "All init at same time.");
- _fine_eviction_sample_size = MAX2((size_t)4, (size_t)G1LogRSRegionEntries);
+ _fine_eviction_sample_size = MAX2((size_t)4, max_entries_log);
_fine_eviction_stride = _max_fine_entries / _fine_eviction_sample_size;
#endif
}
@@ -655,13 +656,6 @@
#endif
}
- // Otherwise, transfer from sparse to fine-grain.
- CardIdx_t cards[SparsePRTEntry::CardsPerEntry];
- if (G1HRRSUseSparseTable) {
- bool res = _sparse_table.get_cards(from_hrs_ind, &cards[0]);
- assert(res, "There should have been an entry");
- }
-
if (_n_fine_entries == _max_fine_entries) {
prt = delete_region_table();
} else {
@@ -676,10 +670,12 @@
_fine_grain_regions[ind] = prt;
_n_fine_entries++;
- // Add in the cards from the sparse table.
if (G1HRRSUseSparseTable) {
- for (int i = 0; i < SparsePRTEntry::CardsPerEntry; i++) {
- CardIdx_t c = cards[i];
+ // Transfer from sparse to fine-grain.
+ SparsePRTEntry *sprt_entry = _sparse_table.get_entry(from_hrs_ind);
+ assert(sprt_entry != NULL, "There should have been an entry");
+ for (int i = 0; i < SparsePRTEntry::cards_num(); i++) {
+ CardIdx_t c = sprt_entry->card(i);
if (c != SparsePRTEntry::NullEntry) {
prt->add_card(c);
}
@@ -696,7 +692,21 @@
// OtherRegionsTable for why this is OK.
assert(prt != NULL, "Inv");
- prt->add_reference(from, tid);
+ if (prt->should_expand(tid)) {
+ MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
+ HeapRegion* prt_hr = prt->hr();
+ if (prt_hr == from_hr) {
+ // Make sure the table still corresponds to the same region
+ prt->par_expand();
+ prt->add_reference(from, tid);
+ }
+ // else: The table has been concurrently coarsened, evicted, and
+ // the table data structure re-used for another table. So, we
+ // don't need to add the reference any more given that the table
+ // has been coarsened and the whole region will be scanned anyway.
+ } else {
+ prt->add_reference(from, tid);
+ }
if (G1RecordHRRSOops) {
HeapRegionRemSet::record(hr(), from);
#if HRRS_VERBOSE
@@ -1070,6 +1080,19 @@
{}
+void HeapRegionRemSet::setup_remset_size() {
+ // Setup sparse and fine-grain tables sizes.
+ // table_size = base * (log(region_size / 1M) + 1)
+ int region_size_log_mb = MAX2((int)HeapRegion::LogOfHRGrainBytes - (int)LOG_M, 0);
+ if (FLAG_IS_DEFAULT(G1RSetSparseRegionEntries)) {
+ G1RSetSparseRegionEntries = G1RSetSparseRegionEntriesBase * (region_size_log_mb + 1);
+ }
+ if (FLAG_IS_DEFAULT(G1RSetRegionEntries)) {
+ G1RSetRegionEntries = G1RSetRegionEntriesBase * (region_size_log_mb + 1);
+ }
+ guarantee(G1RSetSparseRegionEntries > 0 && G1RSetRegionEntries > 0 , "Sanity");
+}
+
void HeapRegionRemSet::init_for_par_iteration() {
_iter_state = Unclaimed;
}
@@ -1385,7 +1408,7 @@
os::sleep(Thread::current(), (jlong)5000, false);
G1CollectedHeap* g1h = G1CollectedHeap::heap();
- // Run with "-XX:G1LogRSRegionEntries=2", so that 1 and 5 end up in same
+ // Run with "-XX:G1LogRSetRegionEntries=2", so that 1 and 5 end up in same
// hash bucket.
HeapRegion* hr0 = g1h->region_at(0);
HeapRegion* hr1 = g1h->region_at(1);
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -187,7 +187,8 @@
void clear_outgoing_entries();
enum ParIterState { Unclaimed, Claimed, Complete };
- ParIterState _iter_state;
+ volatile ParIterState _iter_state;
+ volatile jlong _iter_claimed;
// Unused unless G1RecordHRRSOops is true.
@@ -209,6 +210,7 @@
HeapRegion* hr);
static int num_par_rem_sets();
+ static void setup_remset_size();
HeapRegion* hr() const {
return _other_regions.hr();
@@ -272,6 +274,19 @@
// Returns "true" iff the region's iteration is complete.
bool iter_is_complete();
+ // Support for claiming blocks of cards during iteration
+ void set_iter_claimed(size_t x) { _iter_claimed = (jlong)x; }
+ size_t iter_claimed() const { return (size_t)_iter_claimed; }
+ // Claim the next block of cards
+ size_t iter_claimed_next(size_t step) {
+ size_t current, next;
+ do {
+ current = iter_claimed();
+ next = current + step;
+ } while (Atomic::cmpxchg((jlong)next, &_iter_claimed, (jlong)current) != (jlong)current);
+ return current;
+ }
+
// Initialize the given iterator to iterate over this rem set.
void init_iterator(HeapRegionRemSetIterator* iter) const;
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -27,7 +27,7 @@
#define SPARSE_PRT_VERBOSE 0
-#define UNROLL_CARD_LOOPS 1
+#define UNROLL_CARD_LOOPS 1
void SparsePRT::init_iterator(SparsePRTIter* sprt_iter) {
sprt_iter->init(this);
@@ -36,27 +36,32 @@
void SparsePRTEntry::init(RegionIdx_t region_ind) {
_region_ind = region_ind;
_next_index = NullEntry;
+
#if UNROLL_CARD_LOOPS
- assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll.");
- _cards[0] = NullEntry;
- _cards[1] = NullEntry;
- _cards[2] = NullEntry;
- _cards[3] = NullEntry;
+ assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry");
+ for (int i = 0; i < cards_num(); i += UnrollFactor) {
+ _cards[i] = NullEntry;
+ _cards[i + 1] = NullEntry;
+ _cards[i + 2] = NullEntry;
+ _cards[i + 3] = NullEntry;
+ }
#else
- for (int i = 0; i < CardsPerEntry; i++)
+ for (int i = 0; i < cards_num(); i++)
_cards[i] = NullEntry;
#endif
}
bool SparsePRTEntry::contains_card(CardIdx_t card_index) const {
#if UNROLL_CARD_LOOPS
- assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll.");
- if (_cards[0] == card_index) return true;
- if (_cards[1] == card_index) return true;
- if (_cards[2] == card_index) return true;
- if (_cards[3] == card_index) return true;
+ assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry");
+ for (int i = 0; i < cards_num(); i += UnrollFactor) {
+ if (_cards[i] == card_index ||
+ _cards[i + 1] == card_index ||
+ _cards[i + 2] == card_index ||
+ _cards[i + 3] == card_index) return true;
+ }
#else
- for (int i = 0; i < CardsPerEntry; i++) {
+ for (int i = 0; i < cards_num(); i++) {
if (_cards[i] == card_index) return true;
}
#endif
@@ -67,14 +72,16 @@
int SparsePRTEntry::num_valid_cards() const {
int sum = 0;
#if UNROLL_CARD_LOOPS
- assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll.");
- if (_cards[0] != NullEntry) sum++;
- if (_cards[1] != NullEntry) sum++;
- if (_cards[2] != NullEntry) sum++;
- if (_cards[3] != NullEntry) sum++;
+ assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry");
+ for (int i = 0; i < cards_num(); i += UnrollFactor) {
+ sum += (_cards[i] != NullEntry);
+ sum += (_cards[i + 1] != NullEntry);
+ sum += (_cards[i + 2] != NullEntry);
+ sum += (_cards[i + 3] != NullEntry);
+ }
#else
- for (int i = 0; i < CardsPerEntry; i++) {
- if (_cards[i] != NulLEntry) sum++;
+ for (int i = 0; i < cards_num(); i++) {
+ sum += (_cards[i] != NullEntry);
}
#endif
// Otherwise, we're full.
@@ -83,27 +90,27 @@
SparsePRTEntry::AddCardResult SparsePRTEntry::add_card(CardIdx_t card_index) {
#if UNROLL_CARD_LOOPS
- assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll.");
- CardIdx_t c = _cards[0];
- if (c == card_index) return found;
- if (c == NullEntry) { _cards[0] = card_index; return added; }
- c = _cards[1];
- if (c == card_index) return found;
- if (c == NullEntry) { _cards[1] = card_index; return added; }
- c = _cards[2];
- if (c == card_index) return found;
- if (c == NullEntry) { _cards[2] = card_index; return added; }
- c = _cards[3];
- if (c == card_index) return found;
- if (c == NullEntry) { _cards[3] = card_index; return added; }
+ assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry");
+ CardIdx_t c;
+ for (int i = 0; i < cards_num(); i += UnrollFactor) {
+ c = _cards[i];
+ if (c == card_index) return found;
+ if (c == NullEntry) { _cards[i] = card_index; return added; }
+ c = _cards[i + 1];
+ if (c == card_index) return found;
+ if (c == NullEntry) { _cards[i + 1] = card_index; return added; }
+ c = _cards[i + 2];
+ if (c == card_index) return found;
+ if (c == NullEntry) { _cards[i + 2] = card_index; return added; }
+ c = _cards[i + 3];
+ if (c == card_index) return found;
+ if (c == NullEntry) { _cards[i + 3] = card_index; return added; }
+ }
#else
- for (int i = 0; i < CardsPerEntry; i++) {
+ for (int i = 0; i < cards_num(); i++) {
CardIdx_t c = _cards[i];
if (c == card_index) return found;
- if (c == NullEntry) {
- _cards[i] = card_index;
- return added;
- }
+ if (c == NullEntry) { _cards[i] = card_index; return added; }
}
#endif
// Otherwise, we're full.
@@ -112,13 +119,15 @@
void SparsePRTEntry::copy_cards(CardIdx_t* cards) const {
#if UNROLL_CARD_LOOPS
- assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll.");
- cards[0] = _cards[0];
- cards[1] = _cards[1];
- cards[2] = _cards[2];
- cards[3] = _cards[3];
+ assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry");
+ for (int i = 0; i < cards_num(); i += UnrollFactor) {
+ cards[i] = _cards[i];
+ cards[i + 1] = _cards[i + 1];
+ cards[i + 2] = _cards[i + 2];
+ cards[i + 3] = _cards[i + 3];
+ }
#else
- for (int i = 0; i < CardsPerEntry; i++) {
+ for (int i = 0; i < cards_num(); i++) {
cards[i] = _cards[i];
}
#endif
@@ -133,7 +142,7 @@
RSHashTable::RSHashTable(size_t capacity) :
_capacity(capacity), _capacity_mask(capacity-1),
_occupied_entries(0), _occupied_cards(0),
- _entries(NEW_C_HEAP_ARRAY(SparsePRTEntry, capacity)),
+ _entries((SparsePRTEntry*)NEW_C_HEAP_ARRAY(char, SparsePRTEntry::size() * capacity)),
_buckets(NEW_C_HEAP_ARRAY(int, capacity)),
_free_list(NullEntry), _free_region(0)
{
@@ -161,8 +170,8 @@
"_capacity too large");
// This will put -1 == NullEntry in the key field of all entries.
- memset(_entries, -1, _capacity * sizeof(SparsePRTEntry));
- memset(_buckets, -1, _capacity * sizeof(int));
+ memset(_entries, NullEntry, _capacity * SparsePRTEntry::size());
+ memset(_buckets, NullEntry, _capacity * sizeof(int));
_free_list = NullEntry;
_free_region = 0;
}
@@ -175,8 +184,8 @@
if (res == SparsePRTEntry::added) _occupied_cards++;
#if SPARSE_PRT_VERBOSE
gclog_or_tty->print_cr(" after add_card[%d]: valid-cards = %d.",
- pointer_delta(e, _entries, sizeof(SparsePRTEntry)),
- e->num_valid_cards());
+ pointer_delta(e, _entries, SparsePRTEntry::size()),
+ e->num_valid_cards());
#endif
assert(e->num_valid_cards() > 0, "Postcondition");
return res != SparsePRTEntry::overflow;
@@ -199,6 +208,22 @@
return true;
}
+SparsePRTEntry* RSHashTable::get_entry(RegionIdx_t region_ind) {
+ int ind = (int) (region_ind & capacity_mask());
+ int cur_ind = _buckets[ind];
+ SparsePRTEntry* cur;
+ while (cur_ind != NullEntry &&
+ (cur = entry(cur_ind))->r_ind() != region_ind) {
+ cur_ind = cur->next_index();
+ }
+
+ if (cur_ind == NullEntry) return NULL;
+ // Otherwise...
+ assert(cur->r_ind() == region_ind, "Postcondition of loop + test above.");
+ assert(cur->num_valid_cards() > 0, "Inv");
+ return cur;
+}
+
bool RSHashTable::delete_entry(RegionIdx_t region_ind) {
int ind = (int) (region_ind & capacity_mask());
int* prev_loc = &_buckets[ind];
@@ -225,20 +250,8 @@
int ind = (int) (region_ind & capacity_mask());
int cur_ind = _buckets[ind];
SparsePRTEntry* cur;
- // XXX
- // int k = 0;
while (cur_ind != NullEntry &&
(cur = entry(cur_ind))->r_ind() != region_ind) {
- /*
- k++;
- if (k > 10) {
- gclog_or_tty->print_cr("RSHashTable::entry_for_region_ind(%d): "
- "k = %d, cur_ind = %d.", region_ind, k, cur_ind);
- if (k >= 1000) {
- while (1) ;
- }
- }
- */
cur_ind = cur->next_index();
}
@@ -319,7 +332,7 @@
bool /* RSHashTable:: */ RSHashTableIter::has_next(size_t& card_index) {
_card_ind++;
CardIdx_t ci;
- if (_card_ind < SparsePRTEntry::CardsPerEntry &&
+ if (_card_ind < SparsePRTEntry::cards_num() &&
((ci = _rsht->entry(_bl_ind)->card(_card_ind)) !=
SparsePRTEntry::NullEntry)) {
card_index = compute_card_ind(ci);
@@ -359,7 +372,7 @@
size_t RSHashTable::mem_size() const {
return sizeof(this) +
- capacity() * (sizeof(SparsePRTEntry) + sizeof(int));
+ capacity() * (SparsePRTEntry::size() + sizeof(int));
}
// ----------------------------------------------------------------------
@@ -446,6 +459,10 @@
return _next->get_cards(region_id, cards);
}
+SparsePRTEntry* SparsePRT::get_entry(RegionIdx_t region_id) {
+ return _next->get_entry(region_id);
+}
+
bool SparsePRT::delete_entry(RegionIdx_t region_id) {
return _next->delete_entry(region_id);
}
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -32,21 +32,28 @@
// insertions only enqueue old versions for deletions, but do not delete
// old versions synchronously.
-
class SparsePRTEntry: public CHeapObj {
public:
-
enum SomePublicConstants {
- CardsPerEntry = 4,
- NullEntry = -1
+ NullEntry = -1,
+ UnrollFactor = 4
};
-
private:
RegionIdx_t _region_ind;
int _next_index;
- CardIdx_t _cards[CardsPerEntry];
-
+ CardIdx_t _cards[1];
+ // WARNING: Don't put any data members beyond this line. Card array has, in fact, variable length.
+ // It should always be the last data member.
public:
+ // Returns the size of the entry, used for entry allocation.
+ static size_t size() { return sizeof(SparsePRTEntry) + sizeof(CardIdx_t) * (cards_num() - 1); }
+ // Returns the size of the card array.
+ static int cards_num() {
+ // The number of cards should be a multiple of 4, because that's our current
+ // unrolling factor.
+ static const int s = MAX2<int>(G1RSetSparseRegionEntries & ~(UnrollFactor - 1), UnrollFactor);
+ return s;
+ }
// Set the region_ind to the given value, and delete all cards.
inline void init(RegionIdx_t region_ind);
@@ -134,12 +141,15 @@
bool add_card(RegionIdx_t region_id, CardIdx_t card_index);
bool get_cards(RegionIdx_t region_id, CardIdx_t* cards);
+
bool delete_entry(RegionIdx_t region_id);
bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const;
void add_entry(SparsePRTEntry* e);
+ SparsePRTEntry* get_entry(RegionIdx_t region_id);
+
void clear();
size_t capacity() const { return _capacity; }
@@ -148,7 +158,7 @@
size_t occupied_cards() const { return _occupied_cards; }
size_t mem_size() const;
- SparsePRTEntry* entry(int i) const { return &_entries[i]; }
+ SparsePRTEntry* entry(int i) const { return (SparsePRTEntry*)((char*)_entries + SparsePRTEntry::size() * i); }
void print();
};
@@ -157,7 +167,7 @@
class RSHashTableIter VALUE_OBJ_CLASS_SPEC {
int _tbl_ind; // [-1, 0.._rsht->_capacity)
int _bl_ind; // [-1, 0.._rsht->_capacity)
- short _card_ind; // [0..CardsPerEntry)
+ short _card_ind; // [0..SparsePRTEntry::cards_num())
RSHashTable* _rsht;
size_t _heap_bot_card_ind;
@@ -176,7 +186,7 @@
RSHashTableIter(size_t heap_bot_card_ind) :
_tbl_ind(RSHashTable::NullEntry),
_bl_ind(RSHashTable::NullEntry),
- _card_ind((SparsePRTEntry::CardsPerEntry-1)),
+ _card_ind((SparsePRTEntry::cards_num() - 1)),
_rsht(NULL),
_heap_bot_card_ind(heap_bot_card_ind)
{}
@@ -185,7 +195,7 @@
_rsht = rsht;
_tbl_ind = -1; // So that first increment gets to 0.
_bl_ind = RSHashTable::NullEntry;
- _card_ind = (SparsePRTEntry::CardsPerEntry-1);
+ _card_ind = (SparsePRTEntry::cards_num() - 1);
}
bool has_next(size_t& card_index);
@@ -241,9 +251,13 @@
// If the table hold an entry for "region_ind", Copies its
// cards into "cards", which must be an array of length at least
- // "CardsPerEntry", and returns "true"; otherwise, returns "false".
+ // "SparePRTEntry::cards_num()", and returns "true"; otherwise,
+ // returns "false".
bool get_cards(RegionIdx_t region_ind, CardIdx_t* cards);
+ // Return the pointer to the entry associated with the given region.
+ SparsePRTEntry* get_entry(RegionIdx_t region_ind);
+
// If there is an entry for "region_ind", removes it and return "true";
// otherwise returns "false."
bool delete_entry(RegionIdx_t region_ind);
--- a/hotspot/src/share/vm/includeDB_core Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/includeDB_core Thu Mar 04 13:40:03 2010 -0800
@@ -175,6 +175,7 @@
arguments.cpp management.hpp
arguments.cpp oop.inline.hpp
arguments.cpp os_<os_family>.inline.hpp
+arguments.cpp referenceProcessor.hpp
arguments.cpp universe.inline.hpp
arguments.cpp vm_version_<arch>.hpp
@@ -1483,6 +1484,7 @@
deoptimization.cpp vframe.hpp
deoptimization.cpp vframeArray.hpp
deoptimization.cpp vframe_hp.hpp
+deoptimization.cpp vmreg_<arch>.inline.hpp
deoptimization.cpp xmlstream.hpp
deoptimization.hpp allocation.hpp
@@ -2653,6 +2655,7 @@
loaderConstraints.cpp safepoint.hpp
loaderConstraints.hpp dictionary.hpp
+loaderConstraints.hpp placeholders.hpp
loaderConstraints.hpp hashtable.hpp
location.cpp debugInfo.hpp
--- a/hotspot/src/share/vm/memory/barrierSet.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/memory/barrierSet.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -124,8 +124,6 @@
// Below length is the # array elements being written
virtual void write_ref_array_pre( oop* dst, int length) {}
virtual void write_ref_array_pre(narrowOop* dst, int length) {}
- // Below MemRegion mr is expected to be HeapWord-aligned
- inline void write_ref_array(MemRegion mr);
// Below count is the # array elements being written, starting
// at the address "start", which may not necessarily be HeapWord-aligned
inline void write_ref_array(HeapWord* start, size_t count);
--- a/hotspot/src/share/vm/memory/barrierSet.inline.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/memory/barrierSet.inline.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -42,16 +42,6 @@
}
}
-void BarrierSet::write_ref_array(MemRegion mr) {
- assert((HeapWord*)align_size_down((uintptr_t)mr.start(), HeapWordSize) == mr.start() , "Unaligned start");
- assert((HeapWord*)align_size_up ((uintptr_t)mr.end(), HeapWordSize) == mr.end(), "Unaligned end" );
- if (kind() == CardTableModRef) {
- ((CardTableModRefBS*)this)->inline_write_ref_array(mr);
- } else {
- write_ref_array_work(mr);
- }
-}
-
// count is number of array elements being written
void BarrierSet::write_ref_array(HeapWord* start, size_t count) {
assert(count <= (size_t)max_intx, "count too large");
@@ -61,12 +51,12 @@
// strictly necessary for current uses, but a case of good hygiene and,
// if you will, aesthetics) and the second upward (this is essential for
// current uses) to a HeapWord boundary, so we mark all cards overlapping
- // this write. In the event that this evolves in the future to calling a
+ // this write. If this evolves in the future to calling a
// logging barrier of narrow oop granularity, like the pre-barrier for G1
// (mentioned here merely by way of example), we will need to change this
- // interface, much like the pre-barrier one above, so it is "exactly precise"
- // (if i may be allowed the adverbial redundancy for emphasis) and does not
- // include narrow oop slots not included in the original write interval.
+ // interface, so it is "exactly precise" (if i may be allowed the adverbial
+ // redundancy for emphasis) and does not include narrow oop slots not
+ // included in the original write interval.
HeapWord* aligned_start = (HeapWord*)align_size_down((uintptr_t)start, HeapWordSize);
HeapWord* aligned_end = (HeapWord*)align_size_up ((uintptr_t)end, HeapWordSize);
// If compressed oops were not being used, these should already be aligned
--- a/hotspot/src/share/vm/memory/cardTableModRefBS.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/memory/cardTableModRefBS.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -339,6 +339,16 @@
return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val();
}
+ void set_card_claimed(size_t card_index) {
+ jbyte val = _byte_map[card_index];
+ if (val == clean_card_val()) {
+ val = (jbyte)claimed_card_val();
+ } else {
+ val |= (jbyte)claimed_card_val();
+ }
+ _byte_map[card_index] = val;
+ }
+
bool claim_card(size_t card_index);
bool is_card_clean(size_t card_index) {
--- a/hotspot/src/share/vm/memory/referenceProcessor.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -263,10 +263,13 @@
int parallel_gc_threads = 1,
bool mt_processing = false,
bool discovered_list_needs_barrier = false);
+
// RefDiscoveryPolicy values
- enum {
+ enum DiscoveryPolicy {
ReferenceBasedDiscovery = 0,
- ReferentBasedDiscovery = 1
+ ReferentBasedDiscovery = 1,
+ DiscoveryPolicyMin = ReferenceBasedDiscovery,
+ DiscoveryPolicyMax = ReferentBasedDiscovery
};
static void init_statics();
--- a/hotspot/src/share/vm/oops/methodDataOop.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/oops/methodDataOop.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -545,6 +545,10 @@
return cell_offset(counter_cell_count);
}
+ void set_count(uint count) {
+ set_uint_at(count_off, count);
+ }
+
#ifndef PRODUCT
void print_data_on(outputStream* st);
#endif
@@ -692,6 +696,23 @@
void clear_row(uint row) {
assert(row < row_limit(), "oob");
+ // Clear total count - indicator of polymorphic call site.
+ // The site may look like as monomorphic after that but
+ // it allow to have more accurate profiling information because
+ // there was execution phase change since klasses were unloaded.
+ // If the site is still polymorphic then MDO will be updated
+ // to reflect it. But it could be the case that the site becomes
+ // only bimorphic. Then keeping total count not 0 will be wrong.
+ // Even if we use monomorphic (when it is not) for compilation
+ // we will only have trap, deoptimization and recompile again
+ // with updated MDO after executing method in Interpreter.
+ // An additional receiver will be recorded in the cleaned row
+ // during next call execution.
+ //
+ // Note: our profiling logic works with empty rows in any slot.
+ // We do sorting a profiling info (ciCallProfile) for compilation.
+ //
+ set_count(0);
set_receiver(row, NULL);
set_receiver_count(row, 0);
}
--- a/hotspot/src/share/vm/opto/callGenerator.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -136,8 +136,10 @@
}
// Mark the call node as virtual, sort of:
call->set_optimized_virtual(true);
- if (method()->is_method_handle_invoke())
+ if (method()->is_method_handle_invoke()) {
call->set_method_handle_invoke(true);
+ kit.C->set_has_method_handle_invokes(true);
+ }
}
kit.set_arguments_for_java_call(call);
kit.set_edges_for_java_call(call, false, _separate_io_proj);
@@ -194,6 +196,7 @@
call->set_optimized_virtual(true);
// Take extra care (in the presence of argument motion) not to trash the SP:
call->set_method_handle_invoke(true);
+ kit.C->set_has_method_handle_invokes(true);
// Pass the target MethodHandle as first argument and shift the
// other arguments.
--- a/hotspot/src/share/vm/opto/compile.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/opto/compile.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -465,6 +465,7 @@
_code_buffer("Compile::Fill_buffer"),
_orig_pc_slot(0),
_orig_pc_slot_offset_in_bytes(0),
+ _has_method_handle_invokes(false),
_node_bundling_limit(0),
_node_bundling_base(NULL),
_java_calls(0),
@@ -759,6 +760,7 @@
_do_escape_analysis(false),
_failure_reason(NULL),
_code_buffer("Compile::Fill_buffer"),
+ _has_method_handle_invokes(false),
_node_bundling_limit(0),
_node_bundling_base(NULL),
_java_calls(0),
--- a/hotspot/src/share/vm/opto/compile.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/opto/compile.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -166,6 +166,9 @@
bool _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing
#endif
+ // JSR 292
+ bool _has_method_handle_invokes; // True if this method has MethodHandle invokes.
+
// Compilation environment.
Arena _comp_arena; // Arena with lifetime equivalent to Compile
ciEnv* _env; // CI interface
@@ -336,6 +339,10 @@
void set_parsed_irreducible_loop(bool z) { _parsed_irreducible_loop = z; }
#endif
+ // JSR 292
+ bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
+ void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; }
+
void begin_method() {
#ifndef PRODUCT
if (_printer) _printer->begin_method(this);
--- a/hotspot/src/share/vm/opto/doCall.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/opto/doCall.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1998-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -70,7 +70,7 @@
CompileLog* log = this->log();
if (log != NULL) {
int rid = (receiver_count >= 0)? log->identify(profile.receiver(0)): -1;
- int r2id = (profile.morphism() == 2)? log->identify(profile.receiver(1)):-1;
+ int r2id = (rid != -1 && profile.has_receiver(1))? log->identify(profile.receiver(1)):-1;
log->begin_elem("call method='%d' count='%d' prof_factor='%g'",
log->identify(call_method), site_count, prof_factor);
if (call_is_virtual) log->print(" virtual='1'");
--- a/hotspot/src/share/vm/opto/graphKit.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -780,12 +780,20 @@
// Helper function for enforcing certain bytecodes to reexecute if
// deoptimization happens
-static bool should_reexecute_implied_by_bytecode(JVMState *jvms) {
+static bool should_reexecute_implied_by_bytecode(JVMState *jvms, bool is_anewarray) {
ciMethod* cur_method = jvms->method();
int cur_bci = jvms->bci();
if (cur_method != NULL && cur_bci != InvocationEntryBci) {
Bytecodes::Code code = cur_method->java_code_at_bci(cur_bci);
- return Interpreter::bytecode_should_reexecute(code);
+ return Interpreter::bytecode_should_reexecute(code) ||
+ is_anewarray && code == Bytecodes::_multianewarray;
+ // Reexecute _multianewarray bytecode which was replaced with
+ // sequence of [a]newarray. See Parse::do_multianewarray().
+ //
+ // Note: interpreter should not have it set since this optimization
+ // is limited by dimensions and guarded by flag so in some cases
+ // multianewarray() runtime calls will be generated and
+ // the bytecode should not be reexecutes (stack will not be reset).
} else
return false;
}
@@ -836,7 +844,7 @@
// For a known set of bytecodes, the interpreter should reexecute them if
// deoptimization happens. We set the reexecute state for them here
if (out_jvms->is_reexecute_undefined() && //don't change if already specified
- should_reexecute_implied_by_bytecode(out_jvms)) {
+ should_reexecute_implied_by_bytecode(out_jvms, call->is_AllocateArray())) {
out_jvms->set_should_reexecute(true); //NOTE: youngest_jvms not changed
}
--- a/hotspot/src/share/vm/opto/loopopts.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/opto/loopopts.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,7 @@
int offset = t_oop->offset();
phi = new (C,region->req()) PhiNode(region, type, NULL, iid, index, offset);
} else {
- phi = new (C,region->req()) PhiNode(region, type);
+ phi = PhiNode::make_blank(region, n);
}
uint old_unique = C->unique();
for( uint i = 1; i < region->req(); i++ ) {
--- a/hotspot/src/share/vm/opto/output.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/opto/output.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -795,6 +795,7 @@
int safepoint_pc_offset = current_offset;
bool is_method_handle_invoke = false;
+ bool return_oop = false;
// Add the safepoint in the DebugInfoRecorder
if( !mach->is_MachCall() ) {
@@ -804,9 +805,18 @@
mcall = mach->as_MachCall();
// Is the call a MethodHandle call?
- if (mcall->is_MachCallJava())
- is_method_handle_invoke = mcall->as_MachCallJava()->_method_handle_invoke;
-
+ if (mcall->is_MachCallJava()) {
+ if (mcall->as_MachCallJava()->_method_handle_invoke) {
+ assert(has_method_handle_invokes(), "must have been set during call generation");
+ is_method_handle_invoke = true;
+ }
+ }
+
+ // Check if a call returns an object.
+ if (mcall->return_value_is_used() &&
+ mcall->tf()->range()->field_at(TypeFunc::Parms)->isa_ptr()) {
+ return_oop = true;
+ }
safepoint_pc_offset += mcall->ret_addr_offset();
debug_info()->add_safepoint(safepoint_pc_offset, mcall->_oop_map);
}
@@ -919,7 +929,7 @@
assert(jvms->bci() >= InvocationEntryBci && jvms->bci() <= 0x10000, "must be a valid or entry BCI");
assert(!jvms->should_reexecute() || depth == max_depth, "reexecute allowed only for the youngest");
// Now we can describe the scope.
- debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, locvals, expvals, monvals);
+ debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, return_oop, locvals, expvals, monvals);
} // End jvms loop
// Mark the end of the scope set.
@@ -1086,9 +1096,21 @@
deopt_handler_req += MAX_stubs_size; // add marginal slop for handler
stub_req += MAX_stubs_size; // ensure per-stub margin
code_req += MAX_inst_size; // ensure per-instruction margin
+
if (StressCodeBuffers)
code_req = const_req = stub_req = exception_handler_req = deopt_handler_req = 0x10; // force expansion
- int total_req = code_req + pad_req + stub_req + exception_handler_req + deopt_handler_req + const_req;
+
+ int total_req =
+ code_req +
+ pad_req +
+ stub_req +
+ exception_handler_req +
+ deopt_handler_req + // deopt handler
+ const_req;
+
+ if (has_method_handle_invokes())
+ total_req += deopt_handler_req; // deopt MH handler
+
CodeBuffer* cb = code_buffer();
cb->initialize(total_req, locs_req);
@@ -1430,10 +1452,13 @@
_code_offsets.set_value(CodeOffsets::Exceptions, emit_exception_handler(*cb));
// Emit the deopt handler code.
_code_offsets.set_value(CodeOffsets::Deopt, emit_deopt_handler(*cb));
- // Emit the MethodHandle deopt handler code. We can use the same
- // code as for the normal deopt handler, we just need a different
- // entry point address.
- _code_offsets.set_value(CodeOffsets::DeoptMH, emit_deopt_handler(*cb));
+
+ // Emit the MethodHandle deopt handler code (if required).
+ if (has_method_handle_invokes()) {
+ // We can use the same code as for the normal deopt handler, we
+ // just need a different entry point address.
+ _code_offsets.set_value(CodeOffsets::DeoptMH, emit_deopt_handler(*cb));
+ }
}
// One last check for failed CodeBuffer::expand:
--- a/hotspot/src/share/vm/opto/parse1.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/opto/parse1.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -824,7 +824,6 @@
case Bytecodes::_ddiv:
case Bytecodes::_checkcast:
case Bytecodes::_instanceof:
- case Bytecodes::_athrow:
case Bytecodes::_anewarray:
case Bytecodes::_newarray:
case Bytecodes::_multianewarray:
@@ -834,6 +833,8 @@
return true;
break;
+ // Don't rerun athrow since it's part of the exception path.
+ case Bytecodes::_athrow:
case Bytecodes::_invokestatic:
case Bytecodes::_invokedynamic:
case Bytecodes::_invokespecial:
--- a/hotspot/src/share/vm/opto/parse3.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/opto/parse3.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1998-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -439,8 +439,18 @@
// Can use multianewarray instead of [a]newarray if only one dimension,
// or if all non-final dimensions are small constants.
- if (expand_count == 1 || (1 <= expand_count && expand_count <= expand_limit)) {
- Node* obj = expand_multianewarray(array_klass, &length[0], ndimensions, ndimensions);
+ if (ndimensions == 1 || (1 <= expand_count && expand_count <= expand_limit)) {
+ Node* obj = NULL;
+ // Set the original stack and the reexecute bit for the interpreter
+ // to reexecute the multianewarray bytecode if deoptimization happens.
+ // Do it unconditionally even for one dimension multianewarray.
+ // Note: the reexecute bit will be set in GraphKit::add_safepoint_edges()
+ // when AllocateArray node for newarray is created.
+ { PreserveReexecuteState preexecs(this);
+ _sp += ndimensions;
+ // Pass 0 as nargs since uncommon trap code does not need to restore stack.
+ obj = expand_multianewarray(array_klass, &length[0], ndimensions, 0);
+ } //original reexecute and sp are set back here
push(obj);
return;
}
--- a/hotspot/src/share/vm/opto/runtime.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/opto/runtime.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -708,7 +708,7 @@
*(mdp + count_off) = DataLayout::counter_increment;
} else {
// Receiver did not match any saved receiver and there is no empty row for it.
- // Increment total counter to indicate polimorphic case.
+ // Increment total counter to indicate polymorphic case.
intptr_t* count_p = (intptr_t*)(((byte*)(data)) + in_bytes(CounterData::count_offset()));
*count_p += DataLayout::counter_increment;
}
--- a/hotspot/src/share/vm/opto/stringopts.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/opto/stringopts.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1073,7 +1073,7 @@
kit.set_control(head);
kit.set_memory(mem, char_adr_idx);
- Node* q = __ DivI(kit.null(), i_phi, __ intcon(10));
+ Node* q = __ DivI(NULL, i_phi, __ intcon(10));
Node* r = __ SubI(i_phi, __ AddI(__ LShiftI(q, __ intcon(3)),
__ LShiftI(q, __ intcon(1))));
Node* m1 = __ SubI(charPos, __ intcon(1));
@@ -1270,14 +1270,15 @@
// length = length + (s.count - s.offset);
RegionNode *r = new (C, 3) RegionNode(3);
kit.gvn().set_type(r, Type::CONTROL);
- Node *phi = new (C, 3) PhiNode(r, type->join(TypeInstPtr::NOTNULL));
+ Node *phi = new (C, 3) PhiNode(r, type);
kit.gvn().set_type(phi, phi->bottom_type());
Node* p = __ Bool(__ CmpP(arg, kit.null()), BoolTest::ne);
IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_MIN, COUNT_UNKNOWN);
Node* notnull = __ IfTrue(iff);
Node* isnull = __ IfFalse(iff);
+ kit.set_control(notnull); // set control for the cast_not_null
r->init_req(1, notnull);
- phi->init_req(1, arg);
+ phi->init_req(1, kit.cast_not_null(arg, false));
r->init_req(2, isnull);
phi->init_req(2, null_string);
kit.set_control(r);
--- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -402,7 +402,7 @@
address scopes_data = nm->scopes_data_begin();
for( pcd = nm->scopes_pcs_begin(); pcd < nm->scopes_pcs_end(); ++pcd ) {
- ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute());
+ ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute(), pcd->return_oop());
ScopeDesc *sd = &sc0;
while( !sd->is_top() ) { sd = sd->sender(); }
int bci = sd->bci();
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1487,6 +1487,20 @@
//===========================================================================================================
// Parsing of main arguments
+bool Arguments::verify_interval(uintx val, uintx min,
+ uintx max, const char* name) {
+ // Returns true iff value is in the inclusive interval [min..max]
+ // false, otherwise.
+ if (val >= min && val <= max) {
+ return true;
+ }
+ jio_fprintf(defaultStream::error_stream(),
+ "%s of " UINTX_FORMAT " is invalid; must be between " UINTX_FORMAT
+ " and " UINTX_FORMAT "\n",
+ name, val, min, max);
+ return false;
+}
+
bool Arguments::verify_percentage(uintx value, const char* name) {
if (value <= 100) {
return true;
@@ -1723,6 +1737,16 @@
status = false;
}
+ status = status && verify_interval(RefDiscoveryPolicy,
+ ReferenceProcessor::DiscoveryPolicyMin,
+ ReferenceProcessor::DiscoveryPolicyMax,
+ "RefDiscoveryPolicy");
+
+ // Limit the lower bound of this flag to 1 as it is used in a division
+ // expression.
+ status = status && verify_interval(TLABWasteTargetPercent,
+ 1, 100, "TLABWasteTargetPercent");
+
return status;
}
@@ -2500,6 +2524,9 @@
SOLARIS_ONLY(FLAG_SET_DEFAULT(UseISM, false));
}
+ // Tiered compilation is undefined with C1.
+ TieredCompilation = false;
+
#else
if (!FLAG_IS_DEFAULT(OptoLoopAlignment) && FLAG_IS_DEFAULT(MaxLoopPad)) {
FLAG_SET_DEFAULT(MaxLoopPad, OptoLoopAlignment-1);
--- a/hotspot/src/share/vm/runtime/arguments.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -336,6 +336,8 @@
static bool is_bad_option(const JavaVMOption* option, jboolean ignore) {
return is_bad_option(option, ignore, NULL);
}
+ static bool verify_interval(uintx val, uintx min,
+ uintx max, const char* name);
static bool verify_percentage(uintx value, const char* name);
static void describe_range_error(ArgsRange errcode);
static ArgsRange check_memory_size(julong size, julong min_size);
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -145,6 +145,27 @@
if (EliminateAllocations) {
assert (chunk->at(0)->scope() != NULL,"expect only compiled java frames");
GrowableArray<ScopeValue*>* objects = chunk->at(0)->scope()->objects();
+
+ // The flag return_oop() indicates call sites which return oop
+ // in compiled code. Such sites include java method calls,
+ // runtime calls (for example, used to allocate new objects/arrays
+ // on slow code path) and any other calls generated in compiled code.
+ // It is not guaranteed that we can get such information here only
+ // by analyzing bytecode in deoptimized frames. This is why this flag
+ // is set during method compilation (see Compile::Process_OopMap_Node()).
+ bool save_oop_result = chunk->at(0)->scope()->return_oop();
+ Handle return_value;
+ if (save_oop_result) {
+ // Reallocation may trigger GC. If deoptimization happened on return from
+ // call which returns oop we need to save it since it is not in oopmap.
+ oop result = deoptee.saved_oop_result(&map);
+ assert(result == NULL || result->is_oop(), "must be oop");
+ return_value = Handle(thread, result);
+ assert(Universe::heap()->is_in_or_null(result), "must be heap pointer");
+ if (TraceDeoptimization) {
+ tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, result, thread);
+ }
+ }
bool reallocated = false;
if (objects != NULL) {
JRT_BLOCK
@@ -158,8 +179,12 @@
ttyLocker ttyl;
tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, thread);
print_objects(objects);
+ }
+#endif
}
-#endif
+ if (save_oop_result) {
+ // Restore result.
+ deoptee.set_saved_oop_result(&map, return_value());
}
}
if (EliminateLocks) {
@@ -913,21 +938,6 @@
if (TraceDeoptimization) {
ttyLocker ttyl;
tty->print_cr(" Created vframeArray " INTPTR_FORMAT, array);
- if (Verbose) {
- int count = 0;
- // this used to leak deoptimizedVFrame like it was going out of style!!!
- for (int index = 0; index < array->frames(); index++ ) {
- vframeArrayElement* e = array->element(index);
- e->print(tty);
-
- /*
- No printing yet.
- array->vframe_at(index)->print_activation(count++);
- // better as...
- array->print_activation_for(index, count++);
- */
- }
- }
}
#endif // PRODUCT
--- a/hotspot/src/share/vm/runtime/frame.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/runtime/frame.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -606,12 +606,12 @@
for (BasicObjectLock* current = interpreter_frame_monitor_end();
current < interpreter_frame_monitor_begin();
current = next_monitor_in_interpreter_frame(current)) {
- st->print_cr(" [ - obj ");
+ st->print(" - obj [");
current->obj()->print_value_on(st);
- st->cr();
- st->print_cr(" - lock ");
+ st->print_cr("]");
+ st->print(" - lock [");
current->lock()->print_on(st);
- st->cr();
+ st->print_cr("]");
}
// monitor
st->print_cr(" - monitor[" INTPTR_FORMAT "]", interpreter_frame_monitor_begin());
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -607,7 +607,9 @@
_implicit_null_throws++;
#endif
target_pc = nm->continuation_for_implicit_exception(pc);
- guarantee(target_pc != 0, "must have a continuation point");
+ // If there's an unexpected fault, target_pc might be NULL,
+ // in which case we want to fall through into the normal
+ // error handling code.
}
break; // fall through
@@ -621,14 +623,15 @@
_implicit_div0_throws++;
#endif
target_pc = nm->continuation_for_implicit_exception(pc);
- guarantee(target_pc != 0, "must have a continuation point");
+ // If there's an unexpected fault, target_pc might be NULL,
+ // in which case we want to fall through into the normal
+ // error handling code.
break; // fall through
}
default: ShouldNotReachHere();
}
- guarantee(target_pc != NULL, "must have computed destination PC for implicit exception");
assert(exception_kind == IMPLICIT_NULL || exception_kind == IMPLICIT_DIVIDE_BY_ZERO, "wrong implicit exception kind");
// for AbortVMOnException flag
@@ -1944,7 +1947,7 @@
private:
-#ifdef ASSERT
+#ifndef PRODUCT
static int _lookups; // number of calls to lookup
static int _buckets; // number of buckets checked
static int _equals; // number of buckets checked with matching hash
@@ -1980,16 +1983,16 @@
// Find a entry with the same fingerprint if it exists
AdapterHandlerEntry* lookup(int total_args_passed, BasicType* sig_bt) {
- debug_only(_lookups++);
+ NOT_PRODUCT(_lookups++);
AdapterFingerPrint fp(total_args_passed, sig_bt);
unsigned int hash = fp.compute_hash();
int index = hash_to_index(hash);
for (AdapterHandlerEntry* e = bucket(index); e != NULL; e = e->next()) {
- debug_only(_buckets++);
+ NOT_PRODUCT(_buckets++);
if (e->hash() == hash) {
- debug_only(_equals++);
+ NOT_PRODUCT(_equals++);
if (fp.equals(e->fingerprint())) {
-#ifdef ASSERT
+#ifndef PRODUCT
if (fp.is_compact()) _compact++;
_hits++;
#endif
@@ -2000,6 +2003,7 @@
return NULL;
}
+#ifndef PRODUCT
void print_statistics() {
ResourceMark rm;
int longest = 0;
@@ -2018,15 +2022,14 @@
}
tty->print_cr("AdapterHandlerTable: empty %d longest %d total %d average %f",
empty, longest, total, total / (double)nonempty);
-#ifdef ASSERT
tty->print_cr("AdapterHandlerTable: lookups %d buckets %d equals %d hits %d compact %d",
_lookups, _buckets, _equals, _hits, _compact);
+ }
#endif
- }
};
-#ifdef ASSERT
+#ifndef PRODUCT
int AdapterHandlerTable::_lookups;
int AdapterHandlerTable::_buckets;
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -196,11 +196,19 @@
// Default versions of arraycopy functions
//
+static void gen_arraycopy_barrier_pre(oop* dest, size_t count) {
+ assert(count != 0, "count should be non-zero");
+ assert(count <= (size_t)max_intx, "count too large");
+ BarrierSet* bs = Universe::heap()->barrier_set();
+ assert(bs->has_write_ref_array_pre_opt(), "Must have pre-barrier opt");
+ bs->write_ref_array_pre(dest, (int)count);
+}
+
static void gen_arraycopy_barrier(oop* dest, size_t count) {
assert(count != 0, "count should be non-zero");
BarrierSet* bs = Universe::heap()->barrier_set();
assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt");
- bs->write_ref_array(MemRegion((HeapWord*)dest, (HeapWord*)(dest + count)));
+ bs->write_ref_array((HeapWord*)dest, count);
}
JRT_LEAF(void, StubRoutines::jbyte_copy(jbyte* src, jbyte* dest, size_t count))
@@ -240,6 +248,7 @@
SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy
#endif // !PRODUCT
assert(count != 0, "count should be non-zero");
+ gen_arraycopy_barrier_pre(dest, count);
Copy::conjoint_oops_atomic(src, dest, count);
gen_arraycopy_barrier(dest, count);
JRT_END
@@ -281,6 +290,7 @@
SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy
#endif // !PRODUCT
assert(count != 0, "count should be non-zero");
+ gen_arraycopy_barrier_pre((oop *) dest, count);
Copy::arrayof_conjoint_oops(src, dest, count);
gen_arraycopy_barrier((oop *) dest, count);
JRT_END
--- a/hotspot/src/share/vm/runtime/vframeArray.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/runtime/vframeArray.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -186,7 +186,7 @@
int popframe_preserved_args_size_in_bytes = 0;
int popframe_preserved_args_size_in_words = 0;
if (is_top_frame) {
- JvmtiThreadState *state = thread->jvmti_thread_state();
+ JvmtiThreadState *state = thread->jvmti_thread_state();
if (JvmtiExport::can_pop_frame() &&
(thread->has_pending_popframe() || thread->popframe_forcing_deopt_reexecution())) {
if (thread->has_pending_popframe()) {
@@ -381,7 +381,6 @@
RegisterMap map(thread);
vframe* f = vframe::new_vframe(iframe(), &map, thread);
f->print();
- iframe()->interpreter_frame_print_on(tty);
tty->print_cr("locals size %d", locals()->size());
tty->print_cr("expression size %d", expressions()->size());
@@ -582,7 +581,7 @@
}
void vframeArrayElement::print(outputStream* st) {
- st->print_cr(" - interpreter_frame -> sp: ", INTPTR_FORMAT, iframe()->sp());
+ st->print_cr(" - interpreter_frame -> sp: " INTPTR_FORMAT, iframe()->sp());
}
void vframeArray::print_value_on(outputStream* st) const {
--- a/hotspot/src/share/vm/runtime/vmThread.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/runtime/vmThread.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1998-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -426,11 +426,6 @@
// follow that also require a safepoint
if (_cur_vm_operation->evaluate_at_safepoint()) {
- if (PrintGCApplicationConcurrentTime) {
- gclog_or_tty->print_cr("Application time: %3.7f seconds",
- RuntimeService::last_application_time_sec());
- }
-
_vm_queue->set_drain_list(safepoint_ops); // ensure ops can be scanned
SafepointSynchronize::begin();
@@ -477,12 +472,6 @@
// Complete safepoint synchronization
SafepointSynchronize::end();
- if (PrintGCApplicationStoppedTime) {
- gclog_or_tty->print_cr("Total time for which application threads "
- "were stopped: %3.7f seconds",
- RuntimeService::last_safepoint_time_sec());
- }
-
} else { // not a safepoint operation
if (TraceLongCompiles) {
elapsedTimer t;
--- a/hotspot/src/share/vm/services/runtimeService.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/services/runtimeService.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -104,6 +104,13 @@
void RuntimeService::record_safepoint_begin() {
HS_DTRACE_PROBE(hs_private, safepoint__begin);
+
+ // Print the time interval in which the app was executing
+ if (PrintGCApplicationConcurrentTime) {
+ gclog_or_tty->print_cr("Application time: %3.7f seconds",
+ last_application_time_sec());
+ }
+
// update the time stamp to begin recording safepoint time
_safepoint_timer.update();
if (UsePerfData) {
@@ -122,6 +129,15 @@
void RuntimeService::record_safepoint_end() {
HS_DTRACE_PROBE(hs_private, safepoint__end);
+
+ // Print the time interval for which the app was stopped
+ // during the current safepoint operation.
+ if (PrintGCApplicationStoppedTime) {
+ gclog_or_tty->print_cr("Total time for which application threads "
+ "were stopped: %3.7f seconds",
+ last_safepoint_time_sec());
+ }
+
// update the time stamp to begin recording app time
_app_timer.update();
if (UsePerfData) {
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Thu Mar 04 10:38:12 2010 +0800
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Thu Mar 04 13:40:03 2010 -0800
@@ -139,6 +139,10 @@
const size_t G = M*K;
const size_t HWperKB = K / sizeof(HeapWord);
+const size_t LOG_K = 10;
+const size_t LOG_M = 2 * LOG_K;
+const size_t LOG_G = 2 * LOG_M;
+
const jint min_jint = (jint)1 << (sizeof(jint)*BitsPerByte-1); // 0x80000000 == smallest jint
const jint max_jint = (juint)min_jint - 1; // 0x7FFFFFFF == largest jint
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6910605/Test.java Thu Mar 04 13:40:03 2010 -0800
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6910605
+ * @summary C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
+ *
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot -Xbatch Test
+ *
+ * original test: nsk/coverage/runtime/runtime007
+ */
+
+import java.io.*;
+
+public class Test {
+ public static int buf=0;
+
+ public static void main( String argv[] ) {
+ System.exit(run(argv, System.out)+95);
+ }
+
+ public static int run(String argv[],PrintStream out) {
+ int ret=0, retx=0, bad=0;
+
+ for( int i=0; (i < 100000) && (bad < 10) ; i++ ) {
+ retx = OptoRuntime_f2i_Type(out);
+ ret += retx;
+ if( retx !=0 ) {
+ out.println("i="+i);
+ bad++;
+ }
+ }
+ return ret==0 ? 0 : 2 ;
+ }
+
+ public static int OptoRuntime_f2i_Type(PrintStream out) {
+ int c1=2, c2=3, c3=4, c4=5, c5=6;
+ int j=0, k=0;
+ try {
+ int[][] iii=(int[][])(new int[c1][c2]);
+
+ for( j=0; j<c1; j++ ) {
+ for( k=0; k<c2; k++ ) {
+ iii[j][k]=(int)((float)(j+1)/(float)(k+1));
+ }
+ }
+ } catch (Throwable e) {
+ out.println("Unexpected exception " + e);
+ e.printStackTrace(out);
+ out.println("j="+j+", k="+k);
+ return 1;
+ }
+ return 0;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6910618/Test.java Thu Mar 04 13:40:03 2010 -0800
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6910605
+ * @summary C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
+ *
+ * @run main/othervm -Xmx64m -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot -XX:+DoEscapeAnalysis -Xbatch -XX:InlineSmallCode=2000 Test
+ *
+ */
+
+/*
+ * Added InlineSmallCode=2000 to guaranty inlining of StringBuilder::append() to allow scalar replace StringBuilder object.
+ *
+ * original test: gc/gctests/StringGC
+ */
+
+public class Test {
+ private final String toAdd = "0123456789abcdef";
+ private int maxLength;
+ private static final int numberOfThreads = 8;
+
+ private class StringAdder extends Thread {
+ private String s;
+
+ public void test() {
+ s = s + toAdd;
+ }
+ public void run() {
+ do {
+ test();
+ } while (s.length() < maxLength);
+ }
+ }
+
+ public void test() throws InterruptedException {
+ maxLength = toAdd.length() * 15000/ numberOfThreads;
+ StringAdder[] sa = new StringAdder[numberOfThreads];
+ for (int i = 0; i < numberOfThreads; i++) {
+ sa[i] = new StringAdder();
+ sa[i].start();
+ }
+ for (int i = 0; i < numberOfThreads; i++) {
+ sa[i].join();
+ }
+ }
+
+ public static void main(String[] args) throws InterruptedException {
+ Test t = new Test();
+ t.test();
+ }
+}
--- a/jaxp/.hgtags Thu Mar 04 10:38:12 2010 +0800
+++ b/jaxp/.hgtags Thu Mar 04 13:40:03 2010 -0800
@@ -58,3 +58,4 @@
204e59d488cdaa9eafa8cb7164ea955b5a9d4a51 jdk7-b81
c876ad22e4bf9d3c6460080db7ace478e29a3ff9 jdk7-b82
309a0a7fc6ceb1c9fc3a85b3608e97ef8f7b0dfd jdk7-b83
+32c0cf01d555747918529a6ff9e06b0090c7a474 jdk7-b84
--- a/jaxws/.hgtags Thu Mar 04 10:38:12 2010 +0800
+++ b/jaxws/.hgtags Thu Mar 04 13:40:03 2010 -0800
@@ -58,3 +58,4 @@
f051045fe94a48fae1097f90cbd9227e6aae6b7e jdk7-b81
31573ae8eed15a6c170f3f0d1abd0b9109c0e086 jdk7-b82
371e3ded591d09112a9f231e37cb072781c486ac jdk7-b83
+8bc02839eee4ef02cd1b50e87638874368a26535 jdk7-b84
--- a/jdk/.hgtags Thu Mar 04 10:38:12 2010 +0800
+++ b/jdk/.hgtags Thu Mar 04 13:40:03 2010 -0800
@@ -58,3 +58,4 @@
10b993d417fcdb40480dad7032ac241f4b87f1af jdk7-b81
69ef657320ad5c35cfa12e4d8322d877e778f8b3 jdk7-b82
9027c6b9d7e2c9ca04a1add691b5b50d0f22b1aa jdk7-b83
+7cb9388bb1a16365fa5118c5efa38b1cd58be40d jdk7-b84
--- a/jdk/src/share/classes/java/awt/FileDialog.java Thu Mar 04 10:38:12 2010 +0800
+++ b/jdk/src/share/classes/java/awt/FileDialog.java Thu Mar 04 13:40:03 2010 -0800
@@ -28,6 +28,8 @@
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.ObjectInputStream;
+import java.io.File;
+import sun.awt.AWTAccessor;
/**
* The <code>FileDialog</code> class displays a dialog window
@@ -93,6 +95,25 @@
*/
String file;
+ /**
+ * Contains the File instances for all the files that the user selects.
+ *
+ * @serial
+ * @see getFiles
+ * @since 1.7
+ */
+ private File[] files;
+
+ /**
+ * Represents whether the file dialog allows the multiple file selection.
+ *
+ * @serial
+ * @see #setMultipleMode
+ * @see #isMultipleMode
+ * @since 1.7
+ */
+ private boolean multipleMode = false;
+
/*
* The filter used as the file dialog's filename filter.
* The file dialog will only be displaying files whose
@@ -123,6 +144,26 @@
}
}
+ static {
+ AWTAccessor.setFileDialogAccessor(
+ new AWTAccessor.FileDialogAccessor() {
+ public void setFiles(FileDialog fileDialog, String directory, String files[]) {
+ fileDialog.setFiles(directory, files);
+ }
+ public void setFile(FileDialog fileDialog, String file) {
+ fileDialog.file = ("".equals(file)) ? null : file;
+ }
+ public void setDirectory(FileDialog fileDialog, String directory) {
+ fileDialog.dir = ("".equals(directory)) ? null : directory;
+ }
+ public boolean isMultipleMode(FileDialog fileDialog) {
+ synchronized (fileDialog.getObjectLock()) {
+ return fileDialog.multipleMode;
+ }
+ }
+ });
+ }
+
/**
* Initialize JNI field and method IDs for fields that may be
accessed from C.
@@ -371,6 +412,51 @@
}
/**
+ * Returns files that the user selects.
+ * <p>
+ * If the user cancels the file dialog,
+ * then the method returns an empty array.
+ *
+ * @return files that the user selects or an empty array
+ * if the user cancels the file dialog.
+ * @see #setFile(String)
+ * @see #getFile
+ * @since 1.7
+ */
+ public File[] getFiles() {
+ synchronized (getObjectLock()) {
+ if (files != null) {
+ return files.clone();
+ } else {
+ return new File[0];
+ }
+ }
+ }
+
+ /**
+ * Stores the names of all the files that the user selects.
+ *
+ * Note that the method is private and it's intended to be used
+ * by the peers through the AWTAccessor API.
+ *
+ * @param directory the current directory
+ * @param files the array that contains the short names of
+ * all the files that the user selects.
+ *
+ * @see #getFiles
+ * @since 1.7
+ */
+ private void setFiles(String directory, String files[]) {
+ synchronized (getObjectLock()) {
+ int filesNumber = (files != null) ? files.length : 0;
+ this.files = new File[filesNumber];
+ for (int i = 0; i < filesNumber; i++) {
+ this.files[i] = new File(directory, files[i]);
+ }
+ }
+ }
+
+ /**
* Sets the selected file for this file dialog window to be the
* specified file. This file becomes the default file if it is set
* before the file dialog window is first shown.
@@ -380,7 +466,8 @@
* as the file.
*
* @param file the file being set
- * @see java.awt.FileDialog#getFile
+ * @see #getFile
+ * @see #getFiles
*/
public void setFile(String file) {
this.file = (file != null && file.equals("")) ? null : file;
@@ -391,6 +478,34 @@
}
/**
+ * Enables or disables multiple file selection for the file dialog.
+ *
+ * @param enable if {@code true}, multiple file selection is enabled;
+ * {@code false} - disabled.
+ * @see #isMultipleMode
+ * @since 1.7
+ */
+ public void setMultipleMode(boolean enable) {
+ synchronized (getObjectLock()) {
+ this.multipleMode = enable;
+ }
+ }
+
+ /**
+ * Returns whether the file dialog allows the multiple file selection.
+ *
+ * @return {@code true} if the file dialog allows the multiple
+ * file selection; {@code false} otherwise.
+ * @see #setMultipleMode
+ * @since 1.7
+ */
+ public boolean isMultipleMode() {
+ synchronized (getObjectLock()) {
+ return multipleMode;
+ }
+ }
+
+ /**
* Determines this file dialog's filename filter. A filename filter
* allows the user to specify which files appear in the file dialog
* window. Filename filters do not function in Sun's reference
--- a/jdk/src/share/classes/sun/awt/AWTAccessor.java Thu Mar 04 10:38:12 2010 +0800
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java Thu Mar 04 13:40:03 2010 -0800
@@ -390,6 +390,30 @@
boolean isTrayIconPopup(PopupMenu popupMenu);
}
+ /*
+ * An accessor for the FileDialog class
+ */
+ public interface FileDialogAccessor {
+ /*
+ * Sets the files the user selects
+ */
+ void setFiles(FileDialog fileDialog, String directory, String files[]);
+
+ /*
+ * Sets the file the user selects
+ */
+ void setFile(FileDialog fileDialog, String file);
+
+ /*
+ * Sets the directory the user selects
+ */
+ void setDirectory(FileDialog fileDialog, String directory);
+
+ /*
+ * Returns whether the file dialog allows the multiple file selection.
+ */
+ boolean isMultipleMode(FileDialog fileDialog);
+ }
/*
* The java.awt.Component class accessor object.
@@ -432,6 +456,11 @@
private static PopupMenuAccessor popupMenuAccessor;
/*
+ * The java.awt.FileDialog class accessor object.
+ */
+ private static FileDialogAccessor fileDialogAccessor;
+
+ /*
* Set an accessor object for the java.awt.Component class.
*/
public static void setComponentAccessor(ComponentAccessor ca) {
@@ -567,4 +596,22 @@
}
return popupMenuAccessor;
}
+
+ /*
+ * Set an accessor object for the java.awt.FileDialog class.
+ */
+ public static void setFileDialogAccessor(FileDialogAccessor fda) {
+ fileDialogAccessor = fda;
+ }
+
+ /*
+ * Retrieve the accessor object for the java.awt.FileDialog class.
+ */
+ public static FileDialogAccessor getFileDialogAccessor() {
+ if (fileDialogAccessor == null) {
+ unsafe.ensureClassInitialized(FileDialog.class);
+ }
+ return fileDialogAccessor;
+ }
+
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java Thu Mar 04 10:38:12 2010 +0800
+++ b/jdk/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java Thu Mar 04 13:40:03 2010 -0800
@@ -37,6 +37,7 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
import sun.util.logging.PlatformLogger;
+import sun.awt.AWTAccessor;
class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListener, ItemListener, KeyEventDispatcher, XChoicePeerListener {
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XFileDialogPeer");
@@ -171,6 +172,10 @@
filterField = new TextField();
selectionField = new TextField();
+ boolean isMultipleMode =
+ AWTAccessor.getFileDialogAccessor().isMultipleMode(target);
+ fileList.setMultipleMode(isMultipleMode);
+
// the insets used by the components in the fileDialog
Insets noInset = new Insets(0, 0, 0, 0);
Insets textFieldInset = new Insets(0, 8, 0, 8);
@@ -380,7 +385,8 @@
* handle the selection event
*/
void handleSelection(String file) {
- int index = file.lastIndexOf('/');
+
+ int index = file.lastIndexOf(java.io.File.separatorChar);
if (index == -1) {
savedDir = this.dir;
@@ -389,8 +395,12 @@
savedDir = file.substring(0, index+1);
savedFile = file.substring(index+1);
}
- target.setDirectory(savedDir);
- target.setFile(savedFile);
+
+ AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor();
+
+ fileDialogAccessor.setDirectory(target, savedDir);
+ fileDialogAccessor.setFile(target, savedFile);
+ fileDialogAccessor.setFiles(target, savedDir, fileList.getSelectedItems());
}
/**
@@ -404,8 +414,13 @@
setFilterField(null);
directoryList.clear();
fileList.clear();
- target.setFile(null);
- target.setDirectory(null);
+
+ AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor();
+
+ fileDialogAccessor.setDirectory(target, null);
+ fileDialogAccessor.setFile(target, null);
+ fileDialogAccessor.setFiles(target, null, null);
+
handleQuitButton();
}
--- a/jdk/src/windows/classes/sun/awt/windows/WFileDialogPeer.java Thu Mar 04 10:38:12 2010 +0800
+++ b/jdk/src/windows/classes/sun/awt/windows/WFileDialogPeer.java Thu Mar 04 13:40:03 2010 -0800
@@ -117,26 +117,57 @@
}
}
- // NOTE: This method is called by privileged threads.
- // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
- void handleSelected(final String file) {
- final FileDialog fileDialog = (FileDialog)target;
- WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
- public void run() {
- int index = file.lastIndexOf(java.io.File.separatorChar);/*2509*//*ibm*/
- String dir;
+ /*
+ * The function converts the file names (the buffer parameter)
+ * in the Windows format into the Java format and saves the results
+ * into the FileDialog instance.
+ *
+ * If it's the multi-select mode, the buffer contains the current
+ * directory followed by the short names of the files.
+ * The directory and file name strings are NULL separated.
+ * If it's the single-select mode, the buffer doesn't have the NULL
+ * separator between the path and the file name.
+ *
+ * NOTE: This method is called by privileged threads.
+ * DO NOT INVOKE CLIENT CODE ON THIS THREAD!
+ */
+ void handleSelected(final char[] buffer)
+ {
+ String[] wFiles = (new String(buffer)).split("\0"); // NULL is the delimiter
+ boolean multiple = (wFiles.length > 1);
+
+ String jDirectory = null;
+ String jFile = null;
+ String jFiles[] = null;
- if (index == -1) {
- dir = "."+java.io.File.separator;
- fileDialog.setFile(file);
- }
- else {
- dir = file.substring(0, index + 1);
- fileDialog.setFile(file.substring(index + 1));
- }
- fileDialog.setDirectory(dir);
- fileDialog.hide();
+ if (multiple) {
+ jDirectory = wFiles[0];
+ jFiles = new String[wFiles.length - 1];
+ System.arraycopy(wFiles, 1, jFiles, 0, jFiles.length);
+ jFile = jFiles[1]; // choose any file
+ } else {
+ int index = wFiles[0].lastIndexOf(java.io.File.separatorChar);
+ if (index == -1) {
+ jDirectory = "."+java.io.File.separator;
+ jFile = wFiles[0];
+ } else {
+ jDirectory = wFiles[0].substring(0, index + 1);
+ jFile = wFiles[0].substring(index + 1);
}
+ jFiles = new String[] { jFile };
+ }
+
+ final FileDialog fileDialog = (FileDialog)target;
+ AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor();
+
+ fileDialogAccessor.setDirectory(fileDialog, jDirectory);
+ fileDialogAccessor.setFile(fileDialog, jFile);
+ fileDialogAccessor.setFiles(fileDialog, jDirectory, jFiles);
+
+ WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
+ public void run() {
+ fileDialog.hide();
+ }
});
} // handleSelected()
@@ -144,11 +175,14 @@
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
void handleCancel() {
final FileDialog fileDialog = (FileDialog)target;
+
+ AWTAccessor.getFileDialogAccessor().setFile(fileDialog, null);
+ AWTAccessor.getFileDialogAccessor().setFiles(fileDialog, null, null);
+
WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() {
- public void run() {
- fileDialog.setFile(null);
- fileDialog.hide();
- }
+ public void run() {
+ fileDialog.hide();
+ }
});
} // handleCancel()
@@ -244,4 +278,9 @@
public void createScreenSurface(boolean isResize) {}
@Override
public void replaceSurfaceData() {}
+
+ public boolean isMultipleMode() {
+ FileDialog fileDialog = (FileDialog)target;
+ return AWTAccessor.getFileDialogAccessor().isMultipleMode(fileDialog);
+ }
}
--- a/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp Thu Mar 04 10:38:12 2010 +0800
+++ b/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp Thu Mar 04 13:40:03 2010 -0800
@@ -44,6 +44,7 @@
jmethodID AwtFileDialog::handleSelectedMID;
jmethodID AwtFileDialog::handleCancelMID;
jmethodID AwtFileDialog::checkFilenameFilterMID;
+jmethodID AwtFileDialog::isMultipleModeMID;
/* FileDialog ids */
jfieldID AwtFileDialog::modeID;
@@ -57,6 +58,13 @@
/* Non-localized suffix of the filter string */
static const TCHAR s_additionalString[] = TEXT(" (*.*)\0*.*\0");
+// Default limit of the output buffer.
+#define SINGLE_MODE_BUFFER_LIMIT MAX_PATH+1
+#define MULTIPLE_MODE_BUFFER_LIMIT 32768
+
+// The name of the property holding the pointer to the OPENFILENAME structure.
+static LPCTSTR OpenFileNameProp = TEXT("AWT_OFN");
+
/***********************************************************************/
void
@@ -140,6 +148,8 @@
FileDialogWndProc);
::SetProp(parent, NativeDialogWndProcProp, reinterpret_cast<HANDLE>(lpfnWndProc));
+ ::SetProp(parent, OpenFileNameProp, (void *)lParam);
+
break;
}
case WM_DESTROY: {
@@ -149,6 +159,7 @@
lpfnWndProc);
::RemoveProp(parent, ModalDialogPeerProp);
::RemoveProp(parent, NativeDialogWndProcProp);
+ ::RemoveProp(parent, OpenFileNameProp);
break;
}
case WM_NOTIFY: {
@@ -174,6 +185,30 @@
// to unblock all the windows blocked by this dialog as it will
// be closed soon
env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0);
+ } else if (notifyEx->hdr.code == CDN_SELCHANGE) {
+ // reallocate the buffer if the buffer is too small
+ LPOPENFILENAME lpofn = (LPOPENFILENAME)GetProp(parent, OpenFileNameProp);
+
+ UINT nLength = CommDlg_OpenSave_GetSpec(parent, NULL, 0) +
+ CommDlg_OpenSave_GetFolderPath(parent, NULL, 0);
+
+ if (lpofn->nMaxFile < nLength)
+ {
+ // allocate new buffer
+ LPTSTR newBuffer = new TCHAR[nLength];
+
+ if (newBuffer) {
+ memset(newBuffer, 0, nLength * sizeof(TCHAR));
+ LPTSTR oldBuffer = lpofn->lpstrFile;
+ lpofn->lpstrFile = newBuffer;
+ lpofn->nMaxFile = nLength;
+ // free the previously allocated buffer
+ if (oldBuffer) {
+ delete[] oldBuffer;
+ }
+
+ }
+ }
}
}
break;
@@ -193,7 +228,6 @@
WCHAR unicodeChar = L' ';
LPTSTR fileBuffer = NULL;
LPTSTR currentDirectory = NULL;
- OPENFILENAME ofn;
jint mode = 0;
BOOL result = FALSE;
DWORD dlgerr;
@@ -204,6 +238,10 @@
jobject target = NULL;
jobject parent = NULL;
AwtComponent* awtParent = NULL;
+ jboolean multipleMode = JNI_FALSE;
+
+ OPENFILENAME ofn;
+ memset(&ofn, 0, sizeof(ofn));
/*
* There's a situation (see bug 4906972) when InvokeFunction (by which this method is called)
@@ -233,7 +271,16 @@
(jstring)env->GetObjectField(target, AwtFileDialog::dirID);
JavaStringBuffer directoryBuffer(env, directory);
- fileBuffer = new TCHAR[MAX_PATH+1];
+ multipleMode = env->CallBooleanMethod(peer, AwtFileDialog::isMultipleModeMID);
+
+ UINT bufferLimit;
+ if (multipleMode == JNI_TRUE) {
+ bufferLimit = MULTIPLE_MODE_BUFFER_LIMIT;
+ } else {
+ bufferLimit = SINGLE_MODE_BUFFER_LIMIT;
+ }
+ LPTSTR fileBuffer = new TCHAR[bufferLimit];
+ memset(fileBuffer, 0, bufferLimit * sizeof(TCHAR));
file = (jstring)env->GetObjectField(target, AwtFileDialog::fileID);
if (file != NULL) {
@@ -244,8 +291,6 @@
fileBuffer[0] = _T('\0');
}
- memset(&ofn, 0, sizeof(ofn));
-
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFilter = s_fileFilterString;
ofn.nFilterIndex = 1;
@@ -265,19 +310,23 @@
ofn.hwndOwner = NULL;
}
ofn.lpstrFile = fileBuffer;
- ofn.nMaxFile = MAX_PATH;
+ ofn.nMaxFile = bufferLimit;
ofn.lpstrTitle = titleBuffer;
ofn.lpstrInitialDir = directoryBuffer;
ofn.Flags = OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
OFN_ENABLEHOOK | OFN_EXPLORER | OFN_ENABLESIZING;
fileFilter = env->GetObjectField(peer,
AwtFileDialog::fileFilterID);
- if (!JNU_IsNull(env,fileFilter)) {
- ofn.Flags |= OFN_ENABLEINCLUDENOTIFY;
- }
+ if (!JNU_IsNull(env,fileFilter)) {
+ ofn.Flags |= OFN_ENABLEINCLUDENOTIFY;
+ }
ofn.lCustData = (LPARAM)peer;
ofn.lpfnHook = (LPOFNHOOKPROC)FileDialogHookProc;
+ if (multipleMode == JNI_TRUE) {
+ ofn.Flags |= OFN_ALLOWMULTISELECT;
+ }
+
// Save current directory, so we can reset if it changes.
currentDirectory = new TCHAR[MAX_PATH+1];
@@ -318,11 +367,12 @@
// Report result to peer.
if (result) {
- jstring tmpJString = (_tcslen(ofn.lpstrFile) == 0 ?
- JNU_NewStringPlatform(env, L"") :
- JNU_NewStringPlatform(env, ofn.lpstrFile));
- env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, tmpJString);
- env->DeleteLocalRef(tmpJString);
+ jint length = (jint)GetBufferLength(ofn.lpstrFile, ofn.nMaxFile);
+ jcharArray jnames = env->NewCharArray(length);
+ env->SetCharArrayRegion(jnames, 0, length, (jchar*)ofn.lpstrFile);
+
+ env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, jnames);
+ env->DeleteLocalRef(jnames);
} else {
env->CallVoidMethod(peer, AwtFileDialog::handleCancelMID);
}
@@ -338,7 +388,8 @@
env->DeleteGlobalRef(peer);
delete[] currentDirectory;
- delete[] fileBuffer;
+ if (ofn.lpstrFile)
+ delete[] ofn.lpstrFile;
throw;
}
@@ -351,7 +402,8 @@
env->DeleteGlobalRef(peer);
delete[] currentDirectory;
- delete[] fileBuffer;
+ if (ofn.lpstrFile)
+ delete[] ofn.lpstrFile;
}
BOOL
@@ -416,6 +468,18 @@
env->DeleteGlobalRef(self);
}
+// Returns the length of the double null terminated output buffer
+UINT AwtFileDialog::GetBufferLength(LPTSTR buffer, UINT limit)
+{
+ UINT index = 0;
+ while ((index < limit) &&
+ (buffer[index] != NULL || buffer[index+1] != NULL))
+ {
+ index++;
+ }
+ return index;
+}
+
/************************************************************************
* WFileDialogPeer native methods
*/
@@ -434,11 +498,12 @@
AwtFileDialog::setHWndMID =
env->GetMethodID(cls, "setHWnd", "(J)V");
AwtFileDialog::handleSelectedMID =
- env->GetMethodID(cls, "handleSelected", "(Ljava/lang/String;)V");
+ env->GetMethodID(cls, "handleSelected", "([C)V");
AwtFileDialog::handleCancelMID =
env->GetMethodID(cls, "handleCancel", "()V");
AwtFileDialog::checkFilenameFilterMID =
env->GetMethodID(cls, "checkFilenameFilter", "(Ljava/lang/String;)Z");
+ AwtFileDialog::isMultipleModeMID = env->GetMethodID(cls, "isMultipleMode", "()Z");
/* java.awt.FileDialog fields */
cls = env->FindClass("java/awt/FileDialog");
@@ -455,6 +520,7 @@
DASSERT(AwtFileDialog::setHWndMID != NULL);
DASSERT(AwtFileDialog::handleSelectedMID != NULL);
DASSERT(AwtFileDialog::handleCancelMID != NULL);
+ DASSERT(AwtFileDialog::isMultipleModeMID != NULL);
DASSERT(AwtFileDialog::modeID != NULL);
DASSERT(AwtFileDialog::dirID != NULL);
--- a/jdk/src/windows/native/sun/windows/awt_FileDialog.h Thu Mar 04 10:38:12 2010 +0800
+++ b/jdk/src/windows/native/sun/windows/awt_FileDialog.h Thu Mar 04 13:40:03 2010 -0800
@@ -49,6 +49,7 @@
static jmethodID handleSelectedMID;
static jmethodID handleCancelMID;
static jmethodID checkFilenameFilterMID;
+ static jmethodID isMultipleModeMID;
/* java.awt.FileDialog field and method ids */
static jfieldID modeID;
@@ -68,6 +69,9 @@
static void _DisposeOrHide(void *param);
static void _ToFront(void *param);
static void _ToBack(void *param);
+
+private:
+ static UINT GetBufferLength(LPTSTR buffer, UINT limit);
};
#endif /* FILE_DIALOG_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FileDialog/MultipleMode/MultipleMode.html Thu Mar 04 13:40:03 2010 -0800
@@ -0,0 +1,20 @@
+<html>
+<!--
+ @test
+ @bug 6467204
+ @summary Need to implement "extended" native FileDialog for JFileChooser
+ @author dmitry.cherepanov@sun.com area=awt.filedialog
+ @run applet/manual=yesno MultipleMode.html
+ -->
+<head>
+<title> MultipleMode </title>
+</head>
+<body>
+
+<h1>MultipleMode<br>Bug ID: 6467204</h1>
+
+<p> See the dialog box (usually in upper left corner) for instructions</p>
+
+<APPLET CODE="MultipleMode.class" WIDTH=200 HEIGHT=200></APPLET>
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FileDialog/MultipleMode/MultipleMode.java Thu Mar 04 13:40:03 2010 -0800
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ test
+ @bug 6467204
+ @summary Need to implement "extended" native FileDialog for JFileChooser
+ @author dmitry.cherepanov@sun.com area=awt.filedialog
+ @run applet/manual=yesno MultipleMode.html
+*/
+
+// Note there is no @ in front of test above. This is so that the
+// harness will not mistake this file as a test file. It should
+// only see the html file as a test file. (the harness runs all
+// valid test files, so it would run this test twice if this file
+// were valid as well as the html file.)
+// Also, note the area= after Your Name in the author tag. Here, you
+// should put which functional area the test falls in. See the
+// AWT-core home page -> test areas and/or -> AWT team for a list of
+// areas.
+// There are several places where ManualYesNoTest appear. It is
+// recommended that these be changed by a global search and replace,
+// such as ESC-% in xemacs.
+
+
+
+/**
+ * MultipleMode.java
+ *
+ * summary:
+ */
+
+import java.applet.Applet;
+import java.awt.*;
+import java.awt.event.*;
+import java.io.File;
+
+
+//Manual tests should run as applet tests if possible because they
+// get their environments cleaned up, including AWT threads, any
+// test created threads, and any system resources used by the test
+// such as file descriptors. (This is normally not a problem as
+// main tests usually run in a separate VM, however on some platforms
+// such as the Mac, separate VMs are not possible and non-applet
+// tests will cause problems). Also, you don't have to worry about
+// synchronisation stuff in Applet tests the way you do in main
+// tests...
+
+
+public class MultipleMode extends Applet
+{
+ //Declare things used in the test, like buttons and labels here
+
+ public void init()
+ {
+ //Create instructions for the user here, as well as set up
+ // the environment -- set the layout manager, add buttons,
+ // etc.
+ this.setLayout (new BorderLayout ());
+
+ String[] instructions =
+ {
+ " 1. Turn the 'multiple' checkbox off and press the 'open' button ",
+ " 2. Verify that the file dialog doesn't allow the multiple file selection ",
+ " 3. Select any file and close the file dialog ",
+ " 4. The results will be displayed, verify the results ",
+ " 5. Turn the 'multiple' checkbox on and press the 'open' button ",
+ " 6. Verify that the file dialog allows the multiple file selection ",
+ " 7. Select several files and close the file dialog ",
+ " 8. The results will be displayed, verify the results "
+ };
+ Sysout.createDialogWithInstructions( instructions );
+
+ }//End init()
+
+ public void start ()
+ {
+ final Checkbox mode = new Checkbox("multiple", true);
+ Button open = new Button("open");
+ open.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ FileDialog d = new FileDialog((Frame)null);
+ d.setMultipleMode(mode.getState());
+ d.setVisible(true);
+
+ // print the results
+ Sysout.println("DIR:");
+ Sysout.println(d.getDirectory());
+ Sysout.println("FILE:");
+ Sysout.println(d.getFile());
+ Sysout.println("FILES:");
+ File files[] = d.getFiles();
+ for (File f : files) {
+ Sysout.println(String.valueOf(f));
+ }
+ }
+ });
+
+ setLayout(new FlowLayout());
+ add(mode);
+ add(open);
+
+ //Get things going. Request focus, set size, et cetera
+ setSize (200,200);
+ setVisible(true);
+ validate();
+
+ }// start()
+
+ //The rest of this class is the actions which perform the test...
+
+ //Use Sysout.println to communicate with the user NOT System.out!!
+ //Sysout.println ("Something Happened!");
+
+}// class ManualYesNoTest
+
+/* Place other classes related to the test after this line */
+
+
+
+
+
+/****************************************************
+ Standard Test Machinery
+ DO NOT modify anything below -- it's a standard
+ chunk of code whose purpose is to make user
+ interaction uniform, and thereby make it simpler
+ to read and understand someone else's test.
+ ****************************************************/
+
+/**
+ This is part of the standard test machinery.
+ It creates a dialog (with the instructions), and is the interface
+ for sending text messages to the user.
+ To print the instructions, send an array of strings to Sysout.createDialog
+ WithInstructions method. Put one line of instructions per array entry.
+ To display a message for the tester to see, simply call Sysout.println
+ with the string to be displayed.
+ This mimics System.out.println but works within the test harness as well
+ as standalone.
+ */
+
+class Sysout
+{
+ private static TestDialog dialog;
+ private static boolean numbering = false;
+ private static int messageNumber = 0;
+
+ public static void createDialogWithInstructions( String[] instructions )
+ {
+ dialog = new TestDialog( new Frame(), "Instructions" );
+ dialog.printInstructions( instructions );
+ dialog.setVisible(true);
+ println( "Any messages for the tester will display here." );
+ }
+
+ public static void createDialog( )
+ {
+ dialog = new TestDialog( new Frame(), "Instructions" );
+ String[] defInstr = { "Instructions will appear here. ", "" } ;
+ dialog.printInstructions( defInstr );
+ dialog.setVisible(true);
+ println( "Any messages for the tester will display here." );
+ }
+
+ /* Enables message counting for the tester. */
+ public static void enableNumbering(boolean enable){
+ numbering = enable;
+ }
+
+ public static void printInstructions( String[] instructions )
+ {
+ dialog.printInstructions( instructions );
+ }
+
+
+ public static void println( String messageIn )
+ {
+ if (numbering) {
+ messageIn = "" + messageNumber + " " + messageIn;
+ messageNumber++;
+ }
+ dialog.displayMessage( messageIn );
+ }
+
+}// Sysout class
+
+/**
+ This is part of the standard test machinery. It provides a place for the
+ test instructions to be displayed, and a place for interactive messages
+ to the user to be displayed.
+ To have the test instructions displayed, see Sysout.
+ To have a message to the user be displayed, see Sysout.
+ Do not call anything in this dialog directly.
+ */
+class TestDialog extends Dialog
+{
+
+ TextArea instructionsText;
+ TextArea messageText;
+ int maxStringLength = 80;
+
+ //DO NOT call this directly, go through Sysout
+ public TestDialog( Frame frame, String name )
+ {
+ super( frame, name );
+ int scrollBoth = TextArea.SCROLLBARS_BOTH;
+ instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
+ add( "North", instructionsText );
+
+ messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
+ add("Center", messageText);
+
+ pack();
+
+ setVisible(true);
+ }// TestDialog()
+
+ //DO NOT call this directly, go through Sysout
+ public void printInstructions( String[] instructions )
+ {
+ //Clear out any current instructions
+ instructionsText.setText( "" );
+
+ //Go down array of instruction strings
+
+ String printStr, remainingStr;
+ for( int i=0; i < instructions.length; i++ )
+ {
+ //chop up each into pieces maxSringLength long
+ remainingStr = instructions[ i ];
+ while( remainingStr.length() > 0 )
+ {
+ //if longer than max then chop off first max chars to print
+ if( remainingStr.length() >= maxStringLength )
+ {
+ //Try to chop on a word boundary
+ int posOfSpace = remainingStr.
+ lastIndexOf( ' ', maxStringLength - 1 );
+
+ if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
+
+ printStr = remainingStr.substring( 0, posOfSpace + 1 );
+ remainingStr = remainingStr.substring( posOfSpace + 1 );
+ }
+ //else just print
+ else
+ {
+ printStr = remainingStr;
+ remainingStr = "";
+ }
+
+ instructionsText.append( printStr + "\n" );
+
+ }// while
+
+ }// for
+
+ }//printInstructions()
+
+ //DO NOT call this directly, go through Sysout
+ public void displayMessage( String messageIn )
+ {
+ messageText.append( messageIn + "\n" );
+ System.out.println(messageIn);
+ }
+
+}// TestDialog class
--- a/langtools/.hgtags Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/.hgtags Thu Mar 04 13:40:03 2010 -0800
@@ -58,3 +58,4 @@
cfabfcf9f110ef896cbdd382903d20eefbceefe0 jdk7-b81
47003a3622f6a17756ab0338bfa8a43e36549e99 jdk7-b82
c9f4ae1f1480e89aaf7e72173184089d9cea397a jdk7-b83
+d9cd5b8286e44f3baf90da290cd295433e21c05a jdk7-b84
--- a/langtools/make/Makefile Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/make/Makefile Thu Mar 04 13:40:03 2010 -0800
@@ -70,7 +70,7 @@
endif
ifdef VERBOSE
- ANT_OPTIONS += -verbose -diagnostics
+ ANT_OPTIONS += -verbose -debug
endif
ifdef JDK_VERSION
--- a/langtools/src/share/classes/com/sun/mirror/util/SourceOrderDeclScanner.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/src/share/classes/com/sun/mirror/util/SourceOrderDeclScanner.java Thu Mar 04 13:40:03 2010 -0800
@@ -101,7 +101,11 @@
}
@SuppressWarnings("cast")
private int compareEqualPosition(Declaration d1, Declaration d2) {
- assert d1.getPosition() == d2.getPosition();
+ assert
+ (d1.getPosition() == d2.getPosition()) || // Handles two null positions.
+ (d1.getPosition().file().compareTo(d2.getPosition().file()) == 0 &&
+ d1.getPosition().line() == d2.getPosition().line() &&
+ d1.getPosition().column() == d2.getPosition().column());
DeclPartialOrder dpo1 = new DeclPartialOrder();
DeclPartialOrder dpo2 = new DeclPartialOrder();
--- a/langtools/src/share/classes/com/sun/tools/apt/comp/Apt.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/src/share/classes/com/sun/tools/apt/comp/Apt.java Thu Mar 04 13:40:03 2010 -0800
@@ -496,57 +496,12 @@
* won't match anything.
*/
Pattern importStringToPattern(String s) {
- if (s.equals("*")) {
- return allMatches;
+ if (com.sun.tools.javac.processing.JavacProcessingEnvironment.isValidImportString(s)) {
+ return com.sun.tools.javac.processing.JavacProcessingEnvironment.validImportStringToPattern(s);
} else {
- String t = s;
- boolean star = false;
-
- /*
- * Validate string from factory is legal. If the string
- * has more than one asterisks or the asterisks does not
- * appear as the last character (preceded by a period),
- * the string is not legal.
- */
-
- boolean valid = true;
- int index = t.indexOf('*');
- if (index != -1) {
- // '*' must be last character...
- if (index == t.length() -1) {
- // ... and preceeding character must be '.'
- if ( index-1 >= 0 ) {
- valid = t.charAt(index-1) == '.';
- // Strip off ".*$" for identifier checks
- t = t.substring(0, t.length()-2);
- }
- } else
- valid = false;
- }
-
- // Verify string is off the form (javaId \.)+ or javaId
- if (valid) {
- String[] javaIds = t.split("\\.", t.length()+2);
- for(String javaId: javaIds)
- valid &= isJavaIdentifier(javaId);
- }
-
- if (!valid) {
- Bark bark = Bark.instance(context);
- bark.aptWarning("MalformedSupportedString", s);
- return noMatches; // won't match any valid identifier
- }
-
- String s_prime = s.replaceAll("\\.", "\\\\.");
-
- if (s_prime.endsWith("*")) {
- s_prime = s_prime.substring(0, s_prime.length() - 1) + ".+";
- }
-
- return Pattern.compile(s_prime);
+ Bark bark = Bark.instance(context);
+ bark.aptWarning("MalformedSupportedString", s);
+ return com.sun.tools.javac.processing.JavacProcessingEnvironment.noMatches;
}
}
-
- private static final Pattern allMatches = Pattern.compile(".*");
- private static final Pattern noMatches = Pattern.compile("(\\P{all})+");
}
--- a/langtools/src/share/classes/com/sun/tools/apt/main/Main.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/src/share/classes/com/sun/tools/apt/main/Main.java Thu Mar 04 13:40:03 2010 -0800
@@ -56,6 +56,8 @@
import com.sun.tools.apt.util.Bark;
import com.sun.mirror.apt.AnnotationProcessorFactory;
+import static com.sun.tools.javac.file.Paths.pathToURLs;
+
/** This class provides a commandline interface to the apt build-time
* tool.
*
@@ -1276,59 +1278,4 @@
}
}
}
-
- // Borrowed from DocletInvoker
- /**
- * Utility method for converting a search path string to an array
- * of directory and JAR file URLs.
- *
- * @param path the search path string
- * @return the resulting array of directory and JAR file URLs
- */
- static URL[] pathToURLs(String path) {
- StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
- URL[] urls = new URL[st.countTokens()];
- int count = 0;
- while (st.hasMoreTokens()) {
- URL url = fileToURL(new File(st.nextToken()));
- if (url != null) {
- urls[count++] = url;
- }
- }
- if (urls.length != count) {
- URL[] tmp = new URL[count];
- System.arraycopy(urls, 0, tmp, 0, count);
- urls = tmp;
- }
- return urls;
- }
-
- /**
- * Returns the directory or JAR file URL corresponding to the specified
- * local file name.
- *
- * @param file the File object
- * @return the resulting directory or JAR file URL, or null if unknown
- */
- static URL fileToURL(File file) {
- String name;
- try {
- name = file.getCanonicalPath();
- } catch (IOException e) {
- name = file.getAbsolutePath();
- }
- name = name.replace(File.separatorChar, '/');
- if (!name.startsWith("/")) {
- name = "/" + name;
- }
- // If the file does not exist, then assume that it's a directory
- if (!file.isFile()) {
- name = name + "/";
- }
- try {
- return new URL("file", "", name);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException("file");
- }
- }
}
--- a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java Thu Mar 04 13:40:03 2010 -0800
@@ -27,6 +27,8 @@
import java.io.File;
import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -34,6 +36,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
+import java.util.StringTokenizer;
import java.util.zip.ZipFile;
import javax.tools.JavaFileManager.Location;
@@ -449,4 +452,60 @@
return fsInfo.isFile(file)
&& (n.endsWith(".jar") || n.endsWith(".zip"));
}
+
+ /**
+ * Utility method for converting a search path string to an array
+ * of directory and JAR file URLs.
+ *
+ * Note that this method is called by apt and the DocletInvoker.
+ *
+ * @param path the search path string
+ * @return the resulting array of directory and JAR file URLs
+ */
+ public static URL[] pathToURLs(String path) {
+ StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
+ URL[] urls = new URL[st.countTokens()];
+ int count = 0;
+ while (st.hasMoreTokens()) {
+ URL url = fileToURL(new File(st.nextToken()));
+ if (url != null) {
+ urls[count++] = url;
+ }
+ }
+ if (urls.length != count) {
+ URL[] tmp = new URL[count];
+ System.arraycopy(urls, 0, tmp, 0, count);
+ urls = tmp;
+ }
+ return urls;
+ }
+
+ /**
+ * Returns the directory or JAR file URL corresponding to the specified
+ * local file name.
+ *
+ * @param file the File object
+ * @return the resulting directory or JAR file URL, or null if unknown
+ */
+ private static URL fileToURL(File file) {
+ String name;
+ try {
+ name = file.getCanonicalPath();
+ } catch (IOException e) {
+ name = file.getAbsolutePath();
+ }
+ name = name.replace(File.separatorChar, '/');
+ if (!name.startsWith("/")) {
+ name = "/" + name;
+ }
+ // If the file does not exist, then assume that it's a directory
+ if (!file.isFile()) {
+ name = name + "/";
+ }
+ try {
+ return new URL("file", "", name);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException(file.toString());
+ }
+ }
}
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Mar 04 13:40:03 2010 -0800
@@ -25,7 +25,6 @@
package com.sun.tools.javac.processing;
-
import java.lang.reflect.*;
import java.util.*;
import java.util.regex.*;
@@ -874,20 +873,9 @@
JavaFileManager fileManager = currentContext.get(JavaFileManager.class);
- List<JavaFileObject> fileObjects = List.nil();
- for (JavaFileObject jfo : filer.getGeneratedSourceFileObjects() ) {
- fileObjects = fileObjects.prepend(jfo);
- }
-
-
compiler = JavaCompiler.instance(currentContext);
- List<JCCompilationUnit> parsedFiles = compiler.parseFiles(fileObjects);
- roots = cleanTrees(roots).reverse();
-
-
- for (JCCompilationUnit unit : parsedFiles)
- roots = roots.prepend(unit);
- roots = roots.reverse();
+ List<JCCompilationUnit> parsedFiles = sourcesToParsedFiles(compiler);
+ roots = cleanTrees(roots).appendList(parsedFiles);
// Check for errors after parsing
if (compiler.parseErrors()) {
@@ -921,11 +909,16 @@
break runAround; // No new files
}
}
- runLastRound(xout, roundNumber, errorStatus, taskListener);
+ roots = runLastRound(xout, roundNumber, errorStatus, compiler, roots, taskListener);
+ // Set error status for any files compiled and generated in
+ // the last round
+ if (compiler.parseErrors())
+ errorStatus = true;
compiler.close(false);
currentContext = contextForNextRound(currentContext, true);
compiler = JavaCompiler.instance(currentContext);
+
filer.newRound(currentContext, true);
filer.warnIfUnclosedFiles();
warnIfUnmatchedOptions();
@@ -979,10 +972,22 @@
return compiler;
}
+ private List<JCCompilationUnit> sourcesToParsedFiles(JavaCompiler compiler)
+ throws IOException {
+ List<JavaFileObject> fileObjects = List.nil();
+ for (JavaFileObject jfo : filer.getGeneratedSourceFileObjects() ) {
+ fileObjects = fileObjects.prepend(jfo);
+ }
+
+ return compiler.parseFiles(fileObjects);
+ }
+
// Call the last round of annotation processing
- private void runLastRound(PrintWriter xout,
- int roundNumber,
- boolean errorStatus,
+ private List<JCCompilationUnit> runLastRound(PrintWriter xout,
+ int roundNumber,
+ boolean errorStatus,
+ JavaCompiler compiler,
+ List<JCCompilationUnit> roots,
TaskListener taskListener) throws IOException {
roundNumber++;
List<ClassSymbol> noTopLevelClasses = List.nil();
@@ -1003,6 +1008,15 @@
if (taskListener != null)
taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND));
}
+
+ // Add any sources generated during the last round to the set
+ // of files to be compiled.
+ if (moreToDo()) {
+ List<JCCompilationUnit> parsedFiles = sourcesToParsedFiles(compiler);
+ roots = cleanTrees(roots).appendList(parsedFiles);
+ }
+
+ return roots;
}
private void updateProcessingState(Context currentContext, boolean lastRound) {
@@ -1340,115 +1354,62 @@
return specifiedPackages;
}
- // Borrowed from DocletInvoker and apt
- // TODO: remove from apt's Main
+ private static final Pattern allMatches = Pattern.compile(".*");
+ public static final Pattern noMatches = Pattern.compile("(\\P{all})+");
+
/**
- * Utility method for converting a search path string to an array
- * of directory and JAR file URLs.
- *
- * @param path the search path string
- * @return the resulting array of directory and JAR file URLs
+ * Convert import-style string for supported annotations into a
+ * regex matching that string. If the string is a valid
+ * import-style string, return a regex that won't match anything.
*/
- public static URL[] pathToURLs(String path) {
- StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
- URL[] urls = new URL[st.countTokens()];
- int count = 0;
- while (st.hasMoreTokens()) {
- URL url = fileToURL(new File(st.nextToken()));
- if (url != null) {
- urls[count++] = url;
- }
+ private static Pattern importStringToPattern(String s, Processor p, Log log) {
+ if (isValidImportString(s)) {
+ return validImportStringToPattern(s);
+ } else {
+ log.warning("proc.malformed.supported.string", s, p.getClass().getName());
+ return noMatches; // won't match any valid identifier
}
- if (urls.length != count) {
- URL[] tmp = new URL[count];
- System.arraycopy(urls, 0, tmp, 0, count);
- urls = tmp;
- }
- return urls;
}
/**
- * Returns the directory or JAR file URL corresponding to the specified
- * local file name.
- *
- * @param file the File object
- * @return the resulting directory or JAR file URL, or null if unknown
+ * Return true if the argument string is a valid import-style
+ * string specifying claimed annotations; return false otherwise.
*/
- private static URL fileToURL(File file) {
- String name;
- try {
- name = file.getCanonicalPath();
- } catch (IOException e) {
- name = file.getAbsolutePath();
+ public static boolean isValidImportString(String s) {
+ if (s.equals("*"))
+ return true;
+
+ boolean valid = true;
+ String t = s;
+ int index = t.indexOf('*');
+
+ if (index != -1) {
+ // '*' must be last character...
+ if (index == t.length() -1) {
+ // ... any and preceding character must be '.'
+ if ( index-1 >= 0 ) {
+ valid = t.charAt(index-1) == '.';
+ // Strip off ".*$" for identifier checks
+ t = t.substring(0, t.length()-2);
+ }
+ } else
+ return false;
}
- name = name.replace(File.separatorChar, '/');
- if (!name.startsWith("/")) {
- name = "/" + name;
+
+ // Verify string is off the form (javaId \.)+ or javaId
+ if (valid) {
+ String[] javaIds = t.split("\\.", t.length()+2);
+ for(String javaId: javaIds)
+ valid &= SourceVersion.isIdentifier(javaId);
}
- // If the file does not exist, then assume that it's a directory
- if (!file.isFile()) {
- name = name + "/";
- }
- try {
- return new URL("file", "", name);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException("file");
- }
+ return valid;
}
-
-
- private static final Pattern allMatches = Pattern.compile(".*");
-
- private static final Pattern noMatches = Pattern.compile("(\\P{all})+");
- /**
- * Convert import-style string to regex matching that string. If
- * the string is a valid import-style string, return a regex that
- * won't match anything.
- */
- // TODO: remove version in Apt.java
- public static Pattern importStringToPattern(String s, Processor p, Log log) {
+ public static Pattern validImportStringToPattern(String s) {
if (s.equals("*")) {
return allMatches;
} else {
- String t = s;
- boolean star = false;
-
- /*
- * Validate string from factory is legal. If the string
- * has more than one asterisks or the asterisks does not
- * appear as the last character (preceded by a period),
- * the string is not legal.
- */
-
- boolean valid = true;
- int index = t.indexOf('*');
- if (index != -1) {
- // '*' must be last character...
- if (index == t.length() -1) {
- // ... and preceeding character must be '.'
- if ( index-1 >= 0 ) {
- valid = t.charAt(index-1) == '.';
- // Strip off ".*$" for identifier checks
- t = t.substring(0, t.length()-2);
- }
- } else
- valid = false;
- }
-
- // Verify string is off the form (javaId \.)+ or javaId
- if (valid) {
- String[] javaIds = t.split("\\.", t.length()+2);
- for(String javaId: javaIds)
- valid &= SourceVersion.isIdentifier(javaId);
- }
-
- if (!valid) {
- log.warning("proc.malformed.supported.string", s, p.getClass().getName());
- return noMatches; // won't match any valid identifier
- }
-
- String s_prime = s.replaceAll("\\.", "\\\\.");
+ String s_prime = s.replace(".", "\\.");
if (s_prime.endsWith("*")) {
s_prime = s_prime.substring(0, s_prime.length() - 1) + ".+";
--- a/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java Thu Mar 04 13:40:03 2010 -0800
@@ -81,7 +81,7 @@
cpString = appendPath(System.getProperty("env.class.path"), cpString);
cpString = appendPath(System.getProperty("java.class.path"), cpString);
cpString = appendPath(docletPath, cpString);
- URL[] urls = pathToURLs(cpString);
+ URL[] urls = com.sun.tools.javac.file.Paths.pathToURLs(cpString);
if (docletParentClassLoader == null)
appClassLoader = new URLClassLoader(urls, getDelegationClassLoader(docletClassName));
else
@@ -313,58 +313,4 @@
Thread.currentThread().setContextClassLoader(savedCCL);
}
}
-
- /**
- * Utility method for converting a search path string to an array
- * of directory and JAR file URLs.
- *
- * @param path the search path string
- * @return the resulting array of directory and JAR file URLs
- */
- static URL[] pathToURLs(String path) {
- StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
- URL[] urls = new URL[st.countTokens()];
- int count = 0;
- while (st.hasMoreTokens()) {
- URL url = fileToURL(new File(st.nextToken()));
- if (url != null) {
- urls[count++] = url;
- }
- }
- if (urls.length != count) {
- URL[] tmp = new URL[count];
- System.arraycopy(urls, 0, tmp, 0, count);
- urls = tmp;
- }
- return urls;
- }
-
- /**
- * Returns the directory or JAR file URL corresponding to the specified
- * local file name.
- *
- * @param file the File object
- * @return the resulting directory or JAR file URL, or null if unknown
- */
- static URL fileToURL(File file) {
- String name;
- try {
- name = file.getCanonicalPath();
- } catch (IOException e) {
- name = file.getAbsolutePath();
- }
- name = name.replace(File.separatorChar, '/');
- if (!name.startsWith("/")) {
- name = "/" + name;
- }
- // If the file does not exist, then assume that it's a directory
- if (!file.isFile()) {
- name = name + "/";
- }
- try {
- return new URL("file", "", name);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException("file");
- }
- }
}
--- a/langtools/test/tools/javac/6341866/Anno.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/6341866/Anno.java Thu Mar 04 13:40:03 2010 -0800
@@ -27,7 +27,6 @@
import javax.lang.model.element.*;
@SupportedAnnotationTypes("*")
- @SupportedSourceVersion(SourceVersion.RELEASE_7)
public class Anno extends AbstractProcessor {
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
@@ -35,4 +34,9 @@
// System.err.println("annotation processing");
return true;
}
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
}
--- a/langtools/test/tools/javac/EarlyAssert.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/EarlyAssert.java Thu Mar 04 13:40:03 2010 -0800
@@ -27,6 +27,8 @@
* @summary Verify that assertions are enabled before the class is initialized
* and not thereafter
* @author gafter
+ * @build EarlyAssert EarlyAssertWrapper
+ * @run main EarlyAssertWrapper
*/
/*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/EarlyAssertWrapper.java Thu Mar 04 13:40:03 2010 -0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.io.*;
+import java.util.*;
+
+/*
+ * Wrapper for the EarlyAssert test to run the test in a JVM without assertions
+ * enabled.
+ */
+public class EarlyAssertWrapper {
+ public static void main(String... args) throws Exception {
+ EarlyAssertWrapper w = new EarlyAssertWrapper();
+ w.run();
+ }
+
+ void run() throws Exception {
+ List<String> cmd = new ArrayList<String>();
+ File java_home = new File(System.getProperty("java.home"));
+ if (java_home.getName().equals("jre"))
+ java_home = java_home.getParentFile();
+ cmd.add(new File(new File(java_home, "bin"), "java").getPath());
+
+ // ensure we run with the same bootclasspath as this test,
+ // in case this test is being run with -Xbootclasspath
+ cmd.add("-Xbootclasspath:" + System.getProperty("sun.boot.class.path"));
+
+ // propogate classpath
+ cmd.add("-classpath");
+ cmd.add(System.getProperty("java.class.path"));
+
+ // ensure all assertions disabled in target VM
+ cmd.add("-da");
+ cmd.add("-dsa");
+
+ cmd.add("EarlyAssert");
+
+ System.err.println("Running command: " + cmd);
+
+ ProcessBuilder pb = new ProcessBuilder(cmd);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ p.getOutputStream().close();
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+
+ String line;
+ DataInputStream in = new DataInputStream(p.getInputStream());
+ try {
+ while ((line = in.readLine()) != null)
+ pw.println(line);
+ } finally {
+ in.close();
+ }
+ pw.close();
+
+ String out = sw.toString();
+ int rc = p.waitFor();
+ if (rc != 0 || out.length() > 0)
+ throw new Error("failed: rc=" + rc + (out.length() > 0 ? ": " + out : ""));
+ }
+}
--- a/langtools/test/tools/javac/T6403466.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/T6403466.java Thu Mar 04 13:40:03 2010 -0800
@@ -41,7 +41,6 @@
@Wrap
@SupportedAnnotationTypes("Wrap")
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class T6403466 extends AbstractProcessor {
static final String testSrcDir = System.getProperty("test.src");
@@ -73,24 +72,31 @@
}
public boolean process(Set<? extends TypeElement> annos, RoundEnvironment rEnv) {
- Filer filer = processingEnv.getFiler();
- for (TypeElement anno: annos) {
- Set<? extends Element> elts = rEnv.getElementsAnnotatedWith(anno);
- System.err.println("anno: " + anno);
- System.err.println("elts: " + elts);
- for (TypeElement te: ElementFilter.typesIn(elts)) {
- try {
- Writer out = filer.createSourceFile(te.getSimpleName() + "Wrapper").openWriter();
- out.write("class " + te.getSimpleName() + "Wrapper { }");
- out.close();
- } catch (IOException ex) {
- ex.printStackTrace();
+ if (!rEnv.processingOver()) {
+ Filer filer = processingEnv.getFiler();
+ for (TypeElement anno: annos) {
+ Set<? extends Element> elts = rEnv.getElementsAnnotatedWith(anno);
+ System.err.println("anno: " + anno);
+ System.err.println("elts: " + elts);
+ for (TypeElement te: ElementFilter.typesIn(elts)) {
+ try {
+ Writer out = filer.createSourceFile(te.getSimpleName() + "Wrapper").openWriter();
+ out.write("class " + te.getSimpleName() + "Wrapper { }");
+ out.close();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
}
+
}
-
}
return true;
}
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
}
@Retention(RetentionPolicy.SOURCE)
--- a/langtools/test/tools/javac/T6406771.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/T6406771.java Thu Mar 04 13:40:03 2010 -0800
@@ -17,7 +17,7 @@
import com.sun.source.util.*;
import com.sun.tools.javac.tree.JCTree;
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
+
@SupportedAnnotationTypes("*")
public class T6406771 extends AbstractProcessor {
String[] tests = {
@@ -95,4 +95,8 @@
return true;
}
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
}
--- a/langtools/test/tools/javac/T6411379.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/T6411379.java Thu Mar 04 13:40:03 2010 -0800
@@ -37,7 +37,6 @@
import com.sun.source.util.*;
@SupportedAnnotationTypes("*")
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class T6411379 extends AbstractProcessor {
public boolean process(Set<? extends TypeElement> annoElems,
@@ -58,6 +57,11 @@
return true;
}
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
public void checkNull(Object o) {
if (o != null)
throw new AssertionError("expected null");
--- a/langtools/test/tools/javac/T6423583.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/T6423583.java Thu Mar 04 13:40:03 2010 -0800
@@ -37,7 +37,6 @@
import com.sun.source.util.*;
@SupportedAnnotationTypes("*")
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class T6423583 extends AbstractProcessor {
boolean b1 = true;
boolean b2 = false;
@@ -59,6 +58,10 @@
return true;
}
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
private static class Test extends TreeScanner<Void,Void> {
--- a/langtools/test/tools/javac/T6855236.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/T6855236.java Thu Mar 04 13:40:03 2010 -0800
@@ -38,7 +38,6 @@
import com.sun.source.tree.*;
import com.sun.source.util.*;
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("*")
public class T6855236 extends AbstractProcessor {
@@ -63,6 +62,11 @@
return true;
}
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
class CodeVisitor extends TreePathScanner<Object, Trees> {
@Override
--- a/langtools/test/tools/javac/api/6421111/T6421111.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/api/6421111/T6421111.java Thu Mar 04 13:40:03 2010 -0800
@@ -76,7 +76,6 @@
throw new AssertionError("Annotation processor failed");
}
@SupportedAnnotationTypes("*")
- @SupportedSourceVersion(SourceVersion.RELEASE_6)
static class MyProcessor extends AbstractProcessor {
void test(TypeElement element, boolean fbound) {
TypeParameterElement tpe = element.getTypeParameters().iterator().next();
@@ -96,6 +95,10 @@
test(processingEnv.getElementUtils().getTypeElement("Test2"), true);
return false;
}
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
}
public static void main(String... args) {
new T6421111().test(args);
--- a/langtools/test/tools/javac/api/6468404/T6468404.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/api/6468404/T6468404.java Thu Mar 04 13:40:03 2010 -0800
@@ -105,7 +105,6 @@
}
@SupportedAnnotationTypes("*")
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
class P extends AbstractProcessor {
boolean ran = false;
@@ -145,4 +144,9 @@
}
return true;
}
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
}
--- a/langtools/test/tools/javac/api/T6412669.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/api/T6412669.java Thu Mar 04 13:40:03 2010 -0800
@@ -38,7 +38,6 @@
import com.sun.tools.javac.api.*;
@SupportedAnnotationTypes("*")
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class T6412669 extends AbstractProcessor {
public static void main(String... args) throws IOException {
String testSrc = System.getProperty("test.src", ".");
@@ -72,4 +71,9 @@
}
return true;
}
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
}
--- a/langtools/test/tools/javac/enum/6424358/T6424358.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/enum/6424358/T6424358.java Thu Mar 04 13:40:03 2010 -0800
@@ -34,13 +34,12 @@
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.lang.model.util.*;
+import javax.lang.model.SourceVersion;
import static javax.tools.Diagnostic.Kind.*;
-import static javax.lang.model.SourceVersion.RELEASE_6;
@interface TestMe {}
@SupportedAnnotationTypes("*")
-@SupportedSourceVersion(RELEASE_6)
public class T6424358 extends AbstractProcessor {
@TestMe enum Test { FOO; }
@@ -66,4 +65,9 @@
scan.scan(e);
return true;
}
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
}
--- a/langtools/test/tools/javac/processing/6348499/A.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/processing/6348499/A.java Thu Mar 04 13:40:03 2010 -0800
@@ -28,7 +28,6 @@
import javax.lang.model.element.*;
@SupportedAnnotationTypes("*")
-@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class A extends AbstractProcessor {
public boolean process(Set<? extends TypeElement> tes, RoundEnvironment renv) {
Filer filer = processingEnv.getFiler();
@@ -40,4 +39,8 @@
}
return true;
}
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
}
--- a/langtools/test/tools/javac/processing/6414633/A.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/processing/6414633/A.java Thu Mar 04 13:40:03 2010 -0800
@@ -30,7 +30,6 @@
import javax.tools.*;
@SupportedAnnotationTypes("*")
-@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class A extends AbstractProcessor {
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
@@ -42,4 +41,9 @@
}
return true;
}
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
}
--- a/langtools/test/tools/javac/processing/6430209/T6430209.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/processing/6430209/T6430209.java Thu Mar 04 13:40:03 2010 -0800
@@ -63,7 +63,6 @@
new File(testSrc, "test0.java"), new File(testSrc, "test1.java")));
Iterable<String> opts = Arrays.asList("-proc:only",
"-processor", "b6341534",
- "-source", "1.6",
"-processorpath", testClasses);
StringWriter out = new StringWriter();
JavacTask task = tool.getTask(out, fm, dl, opts, null, files);
--- a/langtools/test/tools/javac/processing/6430209/b6341534.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/processing/6430209/b6341534.java Thu Mar 04 13:40:03 2010 -0800
@@ -22,6 +22,7 @@
*/
import javax.annotation.processing.*;
+import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.lang.model.util.*;
import static javax.lang.model.util.ElementFilter.*;
@@ -30,7 +31,6 @@
import java.util.Set;
@SupportedAnnotationTypes({"*"})
-@SupportedSourceVersion(javax.lang.model.SourceVersion.RELEASE_7)
public class b6341534 extends AbstractProcessor {
static int r = 0;
static Elements E = null;
@@ -62,4 +62,9 @@
if( renv.errorRaised() ) { msgr.printMessage(ERROR, "FAILED");}
return true;
}
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/6634138/Dummy.java Thu Mar 04 13:40:03 2010 -0800
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * A dummy class to be compiled.
+ */
+public class Dummy {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/6634138/ExerciseDependency.java Thu Mar 04 13:40:03 2010 -0800
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * Class to exercise dependencies on the two source files generated by
+ * T6634138.java, foo.WrittenAfterProcessing.java and
+ * foo.package-info.java.
+ */
+public class ExerciseDependency {
+ public static void main(String... args) {
+ foo.WrittenAfterProcessing wap = new foo.WrittenAfterProcessing();
+ java.lang.Package pkg = wap.getClass().getPackage();
+ Deprecated d = pkg.getAnnotation(Deprecated.class);
+ if (d == null)
+ throw new RuntimeException();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/6634138/T6634138.java Thu Mar 04 13:40:03 2010 -0800
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6634138
+ * @author Joseph D. Darcy
+ * @summary Verify source files output after processing is over are compiled
+ * @compile T6634138.java
+ * @compile -processor T6634138 Dummy.java
+ * @run main ExerciseDependency
+ */
+
+import java.lang.annotation.Annotation;
+import java.io.*;
+import java.util.Collections;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import javax.annotation.processing.*;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.*;
+import javax.lang.model.util.*;
+
+@SupportedAnnotationTypes("*")
+public class T6634138 extends AbstractProcessor {
+ private Filer filer;
+
+ public boolean process(Set<? extends TypeElement> annotations,
+ RoundEnvironment roundEnvironment) {
+ // Write out files *after* processing is over.
+ if (roundEnvironment.processingOver()) {
+ System.out.println("Writing out source files.");
+ try {
+ PrintWriter pw = new PrintWriter(filer.createSourceFile("foo.WrittenAfterProcessing").openWriter());
+ try {
+ pw.println("package foo;");
+ pw.println("public class WrittenAfterProcessing {");
+ pw.println(" public WrittenAfterProcessing() {super();}");
+ pw.println("}");
+ } finally {
+ pw.close();
+ }
+
+ pw = new PrintWriter(filer.createSourceFile("foo.package-info").openWriter());
+ try {
+ pw.println("@Deprecated");
+ pw.println("package foo;");
+ } finally {
+ pw.close();
+ }
+ } catch(IOException io) {
+ throw new RuntimeException(io);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
+ public void init(ProcessingEnvironment processingEnv) {
+ super.init(processingEnv);
+ filer = processingEnv.getFiler();
+ }
+}
+
+
+
--- a/langtools/test/tools/javac/processing/T6439826.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/processing/T6439826.java Thu Mar 04 13:40:03 2010 -0800
@@ -39,7 +39,6 @@
@SupportedAnnotationTypes("*")
-@SupportedSourceVersion(SourceVersion.RELEASE_7 )
public class T6439826 extends AbstractProcessor {
public static void main(String... args) {
String testSrc = System.getProperty("test.src", ".");
@@ -76,6 +75,11 @@
return false;
}
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
private void writeBadFile() {
Filer filer = processingEnv.getFiler();
Messager messager = processingEnv.getMessager();
--- a/langtools/test/tools/javac/processing/model/element/TypeParamBounds.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/processing/model/element/TypeParamBounds.java Thu Mar 04 13:40:03 2010 -0800
@@ -40,7 +40,6 @@
import javax.lang.model.type.*;
import javax.lang.model.util.*;
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("*")
public class TypeParamBounds extends AbstractProcessor {
@@ -60,6 +59,11 @@
return true;
}
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
private void doit(Set<? extends TypeElement> annoTypes,
RoundEnvironment round) {
TypeElement gen = elements.getTypeElement("TypeParamBounds.Gen");
--- a/langtools/test/tools/javac/processing/model/type/MirroredTypeEx/OverEager.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/processing/model/type/MirroredTypeEx/OverEager.java Thu Mar 04 13:40:03 2010 -0800
@@ -38,7 +38,6 @@
import javax.lang.model.util.*;
import static javax.lang.model.util.ElementFilter.*;
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("IAm")
@IAm(OverEager.class)
public class OverEager extends AbstractProcessor {
@@ -59,6 +58,11 @@
return true;
}
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
private void doit(Set<? extends TypeElement> annoTypes,
RoundEnvironment round) {
for (TypeElement t : typesIn(round.getRootElements())) {
--- a/langtools/test/tools/javac/processing/model/type/NoTypes.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/processing/model/type/NoTypes.java Thu Mar 04 13:40:03 2010 -0800
@@ -39,8 +39,6 @@
import static javax.lang.model.type.TypeKind.*;
-
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("*")
public class NoTypes extends AbstractProcessor {
@@ -60,6 +58,11 @@
return true;
}
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
private void doit(Set<? extends TypeElement> annoTypes,
RoundEnvironment round) {
--- a/langtools/test/tools/javac/processing/model/util/GetTypeElemBadArg.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/processing/model/util/GetTypeElemBadArg.java Thu Mar 04 13:40:03 2010 -0800
@@ -37,7 +37,6 @@
import javax.lang.model.type.*;
import javax.lang.model.util.*;
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("*")
public class GetTypeElemBadArg extends AbstractProcessor {
@@ -64,6 +63,12 @@
return true;
}
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
private static void tellAbout(TypeElement t) {
System.out.println(t);
System.out.println(t.getClass());
--- a/langtools/test/tools/javac/processing/model/util/OverridesSpecEx.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/processing/model/util/OverridesSpecEx.java Thu Mar 04 13:40:03 2010 -0800
@@ -40,7 +40,6 @@
import static javax.lang.model.util.ElementFilter.*;
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("*")
public class OverridesSpecEx extends AbstractProcessor {
@@ -60,6 +59,11 @@
return true;
}
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
private void doit(Set<? extends TypeElement> annoTypes,
RoundEnvironment round) {
TypeElement string = elements.getTypeElement("java.lang.String");
--- a/langtools/test/tools/javac/treepostests/TreePosTest.java Thu Mar 04 10:38:12 2010 +0800
+++ b/langtools/test/tools/javac/treepostests/TreePosTest.java Thu Mar 04 13:40:03 2010 -0800
@@ -98,7 +98,7 @@
* @test
* @bug 6919889
* @summary assorted position errors in compiler syntax trees
- * @run main TreePosTest -q -r -ef ./tools/javac/typeAnnotations -ef ./tools/javap/typeAnnotations .
+ * @run main TreePosTest -q -r -ef ./tools/javac/typeAnnotations -ef ./tools/javap/typeAnnotations -et ANNOTATED_TYPE .
*/
public class TreePosTest {
/**
@@ -150,6 +150,8 @@
tags.add(args[++i]);
else if (arg.equals("-ef") && i + 1 < args.length)
excludeFiles.add(new File(baseDir, args[++i]));
+ else if (arg.equals("-et") && i + 1 < args.length)
+ excludeTags.add(args[++i]);
else if (arg.equals("-r")) {
if (excludeFiles.size() > 0)
throw new Error("-r must be used before -ef");
@@ -199,6 +201,7 @@
out.println("-t tag Limit checks to tree nodes with this tag");
out.println(" Can be repeated if desired");
out.println("-ef file Exclude file or directory");
+ out.println("-et tag Exclude tree nodes with given tag name");
out.println("");
out.println("files may be directories or files");
out.println("directories will be scanned recursively");
@@ -304,6 +307,8 @@
Set<String> tags = new HashSet<String>();
/** Set of files and directories to be excluded from analysis. */
Set<File> excludeFiles = new HashSet<File>();
+ /** Set of tag names to be excluded from analysis. */
+ Set<String> excludeTags = new HashSet<String>();
/** Table of printable names for tree tag values. */
TagNames tagNames = new TagNames();
@@ -324,7 +329,7 @@
return;
Info self = new Info(tree, endPosTable);
- if (check(self)) {
+ if (check(encl, self)) {
// Modifiers nodes are present throughout the tree even where
// there is no corresponding source text.
// Redundant semicolons in a class definition can cause empty
@@ -392,8 +397,13 @@
super.visitVarDef(tree);
}
- boolean check(Info x) {
- return tags.size() == 0 || tags.contains(tagNames.get(x.tag));
+ boolean check(Info encl, Info self) {
+ if (excludeTags.size() > 0) {
+ if (encl != null && excludeTags.contains(tagNames.get(encl.tag))
+ || excludeTags.contains(tagNames.get(self.tag)))
+ return false;
+ }
+ return tags.size() == 0 || tags.contains(tagNames.get(self.tag));
}
void check(String label, Info encl, Info self, boolean ok) {