This commit is contained in:
J. Duke 2017-07-05 17:26:43 +02:00
commit 7159e1b97a
392 changed files with 29023 additions and 12684 deletions

View File

@ -91,3 +91,4 @@ c1df968c4527bfab5f97662a89245f15d12d378b jdk7-b113
27985a5c6e5268014d25d55886e0ecb96af4763d jdk7-b114
e8ebdf41b9c01a26642848f4134f5504e8fb3233 jdk7-b115
94e9a1bfba8b8d1fe0bfd43b88629b1f27b02a76 jdk7-b116
7220e60b097fa027e922f1aeecdd330f3e37409f jdk7-b117

View File

@ -127,3 +127,5 @@ beef35b96b81129c375d572357fb9548d9020db1 jdk7-b113
5511edd5d719f3fc9fdd04879482026a3d2c8652 hs20-b01
bdbc48857210a509b3c50a3291ecb9dd6a72e016 jdk7-b115
96b3f2a7add0b445b8aa421f6823cff5a2e2fe03 jdk7-b116
52f19c724d9634af79044a2e0defbe4a5f1adbda hs20-b02
806d0c037e6bbb88dac0699673f4ba55ee8c02da jdk7-b117

View File

@ -664,7 +664,7 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
// Use temps to avoid kills
LIR_Opr t1 = FrameMap::G1_opr;
LIR_Opr t2 = FrameMap::G3_opr;
LIR_Opr addr = (type == objectType) ? new_register(T_OBJECT) : new_pointer_register();
LIR_Opr addr = new_pointer_register();
// get address of field
obj.load_item();

View File

@ -62,3 +62,5 @@ define_pd_global(intx, PreInflateSpin, 40); // Determined by running desi
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
define_pd_global(bool, UseMembar, false);

View File

@ -499,7 +499,7 @@ void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
Register new_val_reg = new_val()->as_register();
__ cmpptr(new_val_reg, (int32_t) NULL_WORD);
__ jcc(Assembler::equal, _continuation);
ce->store_parameter(addr()->as_register(), 0);
ce->store_parameter(addr()->as_pointer_register(), 0);
__ call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_post_barrier_slow_id)));
__ jmp(_continuation);
}

View File

@ -765,7 +765,7 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
ShouldNotReachHere();
}
LIR_Opr addr = (type == objectType) ? new_register(T_OBJECT) : new_pointer_register();
LIR_Opr addr = new_pointer_register();
LIR_Address* a;
if(offset.result()->is_constant()) {
a = new LIR_Address(obj.result(),

View File

@ -63,3 +63,5 @@ define_pd_global(intx, PreInflateSpin, 10);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
define_pd_global(bool, UseMembar, false);

View File

@ -45,3 +45,5 @@ define_pd_global(intx, StackShadowPages, 5 LP64_ONLY(+1) DEBUG_ONLY(+3));
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);
define_pd_global(bool, UseMembar, false);

View File

@ -176,10 +176,10 @@ int LinuxAttachListener::init() {
int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d",
os::get_temp_directory(), os::current_process_id());
if (n <= (int)UNIX_PATH_MAX) {
if (n < (int)UNIX_PATH_MAX) {
n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path);
}
if (n > (int)UNIX_PATH_MAX) {
if (n >= (int)UNIX_PATH_MAX) {
return -1;
}

View File

@ -1,23 +0,0 @@
/*
* Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -827,8 +827,10 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
switch (thr_type) {
case os::java_thread:
// Java threads use ThreadStackSize which default value can be changed with the flag -Xss
if (JavaThread::stack_size_at_create() > 0) stack_size = JavaThread::stack_size_at_create();
// Java threads use ThreadStackSize which default value can be
// changed with the flag -Xss
assert (JavaThread::stack_size_at_create() > 0, "this should be set");
stack_size = JavaThread::stack_size_at_create();
break;
case os::compiler_thread:
if (CompilerThreadStackSize > 0) {
@ -3922,12 +3924,21 @@ jint os::init_2(void)
Linux::signal_sets_init();
Linux::install_signal_handlers();
// Check minimum allowable stack size for thread creation and to initialize
// the java system classes, including StackOverflowError - depends on page
// size. Add a page for compiler2 recursion in main thread.
// Add in 2*BytesPerWord times page size to account for VM stack during
// class initialization depending on 32 or 64 bit VM.
os::Linux::min_stack_allowed = MAX2(os::Linux::min_stack_allowed,
(size_t)(StackYellowPages+StackRedPages+StackShadowPages+
2*BytesPerWord COMPILER2_PRESENT(+1)) * Linux::page_size());
size_t threadStackSizeInBytes = ThreadStackSize * K;
if (threadStackSizeInBytes != 0 &&
threadStackSizeInBytes < Linux::min_stack_allowed) {
threadStackSizeInBytes < os::Linux::min_stack_allowed) {
tty->print_cr("\nThe stack size specified is too small, "
"Specify at least %dk",
Linux::min_stack_allowed / K);
os::Linux::min_stack_allowed/ K);
return JNI_ERR;
}
@ -4839,7 +4850,7 @@ void Parker::park(bool isAbsolute, jlong time) {
// Next, demultiplex/decode time arguments
timespec absTime;
if (time < 0) { // don't wait at all
if (time < 0 || (isAbsolute && time == 0) ) { // don't wait at all
return;
}
if (time > 0) {

View File

@ -1,23 +0,0 @@
/*
* Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/

View File

@ -1,23 +0,0 @@
/*
* Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -4878,18 +4878,17 @@ jint os::init_2(void) {
// Check minimum allowable stack size for thread creation and to initialize
// the java system classes, including StackOverflowError - depends on page
// size. Add a page for compiler2 recursion in main thread.
// Add in BytesPerWord times page size to account for VM stack during
// Add in 2*BytesPerWord times page size to account for VM stack during
// class initialization depending on 32 or 64 bit VM.
guarantee((Solaris::min_stack_allowed >=
(StackYellowPages+StackRedPages+StackShadowPages+BytesPerWord
COMPILER2_PRESENT(+1)) * page_size),
"need to increase Solaris::min_stack_allowed on this platform");
os::Solaris::min_stack_allowed = MAX2(os::Solaris::min_stack_allowed,
(size_t)(StackYellowPages+StackRedPages+StackShadowPages+
2*BytesPerWord COMPILER2_PRESENT(+1)) * page_size);
size_t threadStackSizeInBytes = ThreadStackSize * K;
if (threadStackSizeInBytes != 0 &&
threadStackSizeInBytes < Solaris::min_stack_allowed) {
threadStackSizeInBytes < os::Solaris::min_stack_allowed) {
tty->print_cr("\nThe stack size specified is too small, Specify at least %dk",
Solaris::min_stack_allowed/K);
os::Solaris::min_stack_allowed/K);
return JNI_ERR;
}
@ -5837,7 +5836,7 @@ void Parker::park(bool isAbsolute, jlong time) {
// First, demultiplex/decode time arguments
timespec absTime;
if (time < 0) { // don't wait at all
if (time < 0 || (isAbsolute && time == 0) ) { // don't wait at all
return;
}
if (time > 0) {

View File

@ -1,25 +0,0 @@
/*
* Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
private:

View File

@ -1,23 +0,0 @@
/*
* Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/

View File

@ -3311,7 +3311,6 @@ extern "C" {
}
}
// this is called _after_ the global arguments have been parsed
jint os::init_2(void) {
// Allocate a single page and mark it as readable for safepoint polling
@ -3390,6 +3389,21 @@ jint os::init_2(void) {
actual_reserve_size = default_reserve_size;
}
// Check minimum allowable stack size for thread creation and to initialize
// the java system classes, including StackOverflowError - depends on page
// size. Add a page for compiler2 recursion in main thread.
// Add in 2*BytesPerWord times page size to account for VM stack during
// class initialization depending on 32 or 64 bit VM.
size_t min_stack_allowed =
(size_t)(StackYellowPages+StackRedPages+StackShadowPages+
2*BytesPerWord COMPILER2_PRESENT(+1)) * os::vm_page_size();
if (actual_reserve_size < min_stack_allowed) {
tty->print_cr("\nThe stack size specified is too small, "
"Specify at least %dk",
min_stack_allowed / K);
return JNI_ERR;
}
JavaThread::set_stack_size_at_create(stack_commit_size);
// Calculate theoretical max. size of Threads to guard gainst artifical
@ -3992,7 +4006,7 @@ void Parker::park(bool isAbsolute, jlong time) {
if (time < 0) { // don't wait
return;
}
else if (time == 0) {
else if (time == 0 && !isAbsolute) {
time = INFINITE;
}
else if (isAbsolute) {

View File

@ -1350,7 +1350,6 @@ void LIRGenerator::G1SATBCardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_Opr
addr = ptr;
}
assert(addr->is_register(), "must be a register at this point");
assert(addr->type() == T_OBJECT, "addr should point to an object");
LIR_Opr xor_res = new_pointer_register();
LIR_Opr xor_shift_res = new_pointer_register();

View File

@ -4309,20 +4309,21 @@ int ClassFileParser::verify_legal_method_signature(symbolHandle name, symbolHand
}
// Unqualified names may not contain the characters '.', ';', or '/'.
// Method names also may not contain the characters '<' or '>', unless <init> or <clinit>.
// Note that method names may not be <init> or <clinit> in this method.
// Because these names have been checked as special cases before calling this method
// in verify_legal_method_name.
bool ClassFileParser::verify_unqualified_name(char* name, unsigned int length, int type) {
// Unqualified names may not contain the characters '.', ';', '[', or '/'.
// Method names also may not contain the characters '<' or '>', unless <init>
// or <clinit>. Note that method names may not be <init> or <clinit> in this
// method. Because these names have been checked as special cases before
// calling this method in verify_legal_method_name.
bool ClassFileParser::verify_unqualified_name(
char* name, unsigned int length, int type) {
jchar ch;
for (char* p = name; p != name + length; ) {
ch = *p;
if (ch < 128) {
p++;
if (ch == '.' || ch == ';') {
return false; // do not permit '.' or ';'
if (ch == '.' || ch == ';' || ch == '[' ) {
return false; // do not permit '.', ';', or '['
}
if (type != LegalClass && ch == '/') {
return false; // do not permit '/' unless it's class name

View File

@ -0,0 +1,916 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
// These classes represent the stack-map substructures described in the JVMS
// (hence the non-conforming naming scheme).
// These classes work with the types in their compressed form in-place (as they
// would appear in the classfile). No virtual methods or fields allowed.
class verification_type_info {
private:
// u1 tag
// u2 cpool_index || u2 bci (for ITEM_Object & ITEM_Uninitailized only)
address tag_addr() const { return (address)this; }
address cpool_index_addr() const { return tag_addr() + sizeof(u1); }
address bci_addr() const { return cpool_index_addr(); }
protected:
// No constructors - should be 'private', but GCC issues a warning if it is
verification_type_info() {}
verification_type_info(const verification_type_info&) {}
public:
static verification_type_info* at(address addr) {
return (verification_type_info*)addr;
}
static verification_type_info* create_at(address addr, u1 tag) {
verification_type_info* vti = (verification_type_info*)addr;
vti->set_tag(tag);
return vti;
}
static verification_type_info* create_object_at(address addr, u2 cp_idx) {
verification_type_info* vti = (verification_type_info*)addr;
vti->set_tag(ITEM_Object);
vti->set_cpool_index(cp_idx);
return vti;
}
static verification_type_info* create_uninit_at(address addr, u2 bci) {
verification_type_info* vti = (verification_type_info*)addr;
vti->set_tag(ITEM_Uninitialized);
vti->set_bci(bci);
return vti;
}
static size_t calculate_size(u1 tag) {
if (tag == ITEM_Object || tag == ITEM_Uninitialized) {
return sizeof(u1) + sizeof(u2);
} else {
return sizeof(u1);
}
}
static size_t max_size() { return sizeof(u1) + sizeof(u2); }
u1 tag() const { return *(u1*)tag_addr(); }
void set_tag(u1 tag) { *((u1*)tag_addr()) = tag; }
bool is_object() const { return tag() == ITEM_Object; }
bool is_uninitialized() const { return tag() == ITEM_Uninitialized; }
u2 cpool_index() const {
assert(is_object(), "This type has no cp_index");
return Bytes::get_Java_u2(cpool_index_addr());
}
void set_cpool_index(u2 idx) {
assert(is_object(), "This type has no cp_index");
Bytes::put_Java_u2(cpool_index_addr(), idx);
}
u2 bci() const {
assert(is_uninitialized(), "This type has no bci");
return Bytes::get_Java_u2(bci_addr());
}
void set_bci(u2 bci) {
assert(is_uninitialized(), "This type has no bci");
Bytes::put_Java_u2(bci_addr(), bci);
}
void copy_from(verification_type_info* from) {
set_tag(from->tag());
if (from->is_object()) {
set_cpool_index(from->cpool_index());
} else if (from->is_uninitialized()) {
set_bci(from->bci());
}
}
size_t size() const {
return calculate_size(tag());
}
verification_type_info* next() {
return (verification_type_info*)((address)this + size());
}
// This method is used when reading unverified data in order to ensure
// that we don't read past a particular memory limit. It returns false
// if any part of the data structure is outside the specified memory bounds.
bool verify(address start, address end) {
return ((address)this >= start &&
(address)this < end &&
(bci_addr() + sizeof(u2) <= end ||
!is_object() && !is_uninitialized()));
}
#ifdef ASSERT
void print_on(outputStream* st) {
switch (tag()) {
case ITEM_Top: st->print("Top"); break;
case ITEM_Integer: st->print("Integer"); break;
case ITEM_Float: st->print("Float"); break;
case ITEM_Double: st->print("Double"); break;
case ITEM_Long: st->print("Long"); break;
case ITEM_Null: st->print("Null"); break;
case ITEM_UninitializedThis:
st->print("UninitializedThis"); break;
case ITEM_Uninitialized:
st->print("Uninitialized[#%d]", bci()); break;
case ITEM_Object:
st->print("Object[#%d]", cpool_index()); break;
default:
assert(false, "Bad verification_type_info");
}
}
#endif
};
#define FOR_EACH_STACKMAP_FRAME_TYPE(macro, arg1, arg2) \
macro(same_frame, arg1, arg2) \
macro(same_frame_extended, arg1, arg2) \
macro(same_frame_1_stack_item_frame, arg1, arg2) \
macro(same_frame_1_stack_item_extended, arg1, arg2) \
macro(chop_frame, arg1, arg2) \
macro(append_frame, arg1, arg2) \
macro(full_frame, arg1, arg2)
#define SM_FORWARD_DECL(type, arg1, arg2) class type;
FOR_EACH_STACKMAP_FRAME_TYPE(SM_FORWARD_DECL, x, x)
#undef SM_FORWARD_DECL
class stack_map_frame {
protected:
address frame_type_addr() const { return (address)this; }
// No constructors - should be 'private', but GCC issues a warning if it is
stack_map_frame() {}
stack_map_frame(const stack_map_frame&) {}
public:
static stack_map_frame* at(address addr) {
return (stack_map_frame*)addr;
}
stack_map_frame* next() const {
return at((address)this + size());
}
u1 frame_type() const { return *(u1*)frame_type_addr(); }
void set_frame_type(u1 type) { *((u1*)frame_type_addr()) = type; }
// pseudo-virtual methods
inline size_t size() const;
inline int offset_delta() const;
inline void set_offset_delta(int offset_delta);
inline int number_of_types() const; // number of types contained in the frame
inline verification_type_info* types() const; // pointer to first type
inline bool is_valid_offset(int offset_delta) const;
// This method must be used when reading unverified data in order to ensure
// that we don't read past a particular memory limit. It returns false
// if any part of the data structure is outside the specified memory bounds.
inline bool verify(address start, address end) const;
#ifdef ASSERT
inline void print_on(outputStream* st) const;
#endif
// Create as_xxx and is_xxx methods for the subtypes
#define FRAME_TYPE_DECL(stackmap_frame_type, arg1, arg2) \
inline stackmap_frame_type* as_##stackmap_frame_type() const; \
bool is_##stackmap_frame_type() { \
return as_##stackmap_frame_type() != NULL; \
}
FOR_EACH_STACKMAP_FRAME_TYPE(FRAME_TYPE_DECL, x, x)
#undef FRAME_TYPE_DECL
};
class same_frame : public stack_map_frame {
private:
static int frame_type_to_offset_delta(u1 frame_type) {
return frame_type + 1; }
static u1 offset_delta_to_frame_type(int offset_delta) {
return (u1)(offset_delta - 1); }
public:
static bool is_frame_type(u1 tag) {
return tag < 64;
}
static same_frame* at(address addr) {
assert(is_frame_type(*addr), "Wrong frame id");
return (same_frame*)addr;
}
static same_frame* create_at(address addr, int offset_delta) {
same_frame* sm = (same_frame*)addr;
sm->set_offset_delta(offset_delta);
return sm;
}
static size_t calculate_size() { return sizeof(u1); }
size_t size() const { return calculate_size(); }
int offset_delta() const { return frame_type_to_offset_delta(frame_type()); }
void set_offset_delta(int offset_delta) {
assert(offset_delta <= 64, "Offset too large for same_frame");
set_frame_type(offset_delta_to_frame_type(offset_delta));
}
int number_of_types() const { return 0; }
verification_type_info* types() const { return NULL; }
bool is_valid_offset(int offset_delta) const {
return is_frame_type(offset_delta_to_frame_type(offset_delta));
}
bool verify_subtype(address start, address end) const {
return true;
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("same_frame(%d)", offset_delta());
}
#endif
};
class same_frame_extended : public stack_map_frame {
private:
enum { _frame_id = 251 };
address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); }
public:
static bool is_frame_type(u1 tag) {
return tag == _frame_id;
}
static same_frame_extended* at(address addr) {
assert(is_frame_type(*addr), "Wrong frame type");
return (same_frame_extended*)addr;
}
static same_frame_extended* create_at(address addr, u2 offset_delta) {
same_frame_extended* sm = (same_frame_extended*)addr;
sm->set_frame_type(_frame_id);
sm->set_offset_delta(offset_delta);
return sm;
}
static size_t calculate_size() { return sizeof(u1) + sizeof(u2); }
size_t size() const { return calculate_size(); }
int offset_delta() const {
return Bytes::get_Java_u2(offset_delta_addr()) + 1;
}
void set_offset_delta(int offset_delta) {
Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1);
}
int number_of_types() const { return 0; }
verification_type_info* types() const { return NULL; }
bool is_valid_offset(int offset) const { return true; }
bool verify_subtype(address start, address end) const {
return frame_type_addr() + size() <= end;
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("same_frame_extended(%d)", offset_delta());
}
#endif
};
class same_frame_1_stack_item_frame : public stack_map_frame {
private:
address type_addr() const { return frame_type_addr() + sizeof(u1); }
static int frame_type_to_offset_delta(u1 frame_type) {
return frame_type - 63; }
static u1 offset_delta_to_frame_type(int offset_delta) {
return (u1)(offset_delta + 63); }
public:
static bool is_frame_type(u1 tag) {
return tag >= 64 && tag < 128;
}
static same_frame_1_stack_item_frame* at(address addr) {
assert(is_frame_type(*addr), "Wrong frame id");
return (same_frame_1_stack_item_frame*)addr;
}
static same_frame_1_stack_item_frame* create_at(
address addr, int offset_delta, verification_type_info* vti) {
same_frame_1_stack_item_frame* sm = (same_frame_1_stack_item_frame*)addr;
sm->set_offset_delta(offset_delta);
if (vti != NULL) {
sm->set_type(vti);
}
return sm;
}
static size_t calculate_size(verification_type_info* vti) {
return sizeof(u1) + vti->size();
}
static size_t max_size() {
return sizeof(u1) + verification_type_info::max_size();
}
size_t size() const { return calculate_size(types()); }
int offset_delta() const { return frame_type_to_offset_delta(frame_type()); }
void set_offset_delta(int offset_delta) {
assert(offset_delta > 0 && offset_delta <= 64,
"Offset too large for this frame type");
set_frame_type(offset_delta_to_frame_type(offset_delta));
}
void set_type(verification_type_info* vti) {
verification_type_info* cur = types();
cur->copy_from(vti);
}
int number_of_types() const { return 1; }
verification_type_info* types() const {
return verification_type_info::at(type_addr());
}
bool is_valid_offset(int offset_delta) const {
return is_frame_type(offset_delta_to_frame_type(offset_delta));
}
bool verify_subtype(address start, address end) const {
return types()->verify(start, end);
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("same_frame_1_stack_item_frame(%d,", offset_delta());
types()->print_on(st);
st->print(")");
}
#endif
};
class same_frame_1_stack_item_extended : public stack_map_frame {
private:
address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); }
address type_addr() const { return offset_delta_addr() + sizeof(u2); }
enum { _frame_id = 247 };
public:
static bool is_frame_type(u1 tag) {
return tag == _frame_id;
}
static same_frame_1_stack_item_extended* at(address addr) {
assert(is_frame_type(*addr), "Wrong frame id");
return (same_frame_1_stack_item_extended*)addr;
}
static same_frame_1_stack_item_extended* create_at(
address addr, int offset_delta, verification_type_info* vti) {
same_frame_1_stack_item_extended* sm =
(same_frame_1_stack_item_extended*)addr;
sm->set_frame_type(_frame_id);
sm->set_offset_delta(offset_delta);
if (vti != NULL) {
sm->set_type(vti);
}
return sm;
}
static size_t calculate_size(verification_type_info* vti) {
return sizeof(u1) + sizeof(u2) + vti->size();
}
size_t size() const { return calculate_size(types()); }
int offset_delta() const {
return Bytes::get_Java_u2(offset_delta_addr()) + 1;
}
void set_offset_delta(int offset_delta) {
Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1);
}
void set_type(verification_type_info* vti) {
verification_type_info* cur = types();
cur->copy_from(vti);
}
int number_of_types() const { return 1; }
verification_type_info* types() const {
return verification_type_info::at(type_addr());
}
bool is_valid_offset(int offset) { return true; }
bool verify_subtype(address start, address end) const {
return type_addr() < end && types()->verify(start, end);
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("same_frame_1_stack_item_extended(%d,", offset_delta());
types()->print_on(st);
st->print(")");
}
#endif
};
class chop_frame : public stack_map_frame {
private:
address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); }
static int frame_type_to_chops(u1 frame_type) {
int chop = 251 - frame_type;
return chop;
}
static u1 chops_to_frame_type(int chop) {
return 251 - chop;
}
public:
static bool is_frame_type(u1 tag) {
return frame_type_to_chops(tag) > 0 && frame_type_to_chops(tag) < 4;
}
static chop_frame* at(address addr) {
assert(is_frame_type(*addr), "Wrong frame id");
return (chop_frame*)addr;
}
static chop_frame* create_at(address addr, int offset_delta, int chops) {
chop_frame* sm = (chop_frame*)addr;
sm->set_chops(chops);
sm->set_offset_delta(offset_delta);
return sm;
}
static size_t calculate_size() {
return sizeof(u1) + sizeof(u2);
}
size_t size() const { return calculate_size(); }
int offset_delta() const {
return Bytes::get_Java_u2(offset_delta_addr()) + 1;
}
void set_offset_delta(int offset_delta) {
Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1);
}
int chops() const {
int chops = frame_type_to_chops(frame_type());
assert(chops > 0 && chops < 4, "Invalid number of chops in frame");
return chops;
}
void set_chops(int chops) {
assert(chops > 0 && chops <= 3, "Bad number of chops");
set_frame_type(chops_to_frame_type(chops));
}
int number_of_types() const { return 0; }
verification_type_info* types() const { return NULL; }
bool is_valid_offset(int offset) { return true; }
bool verify_subtype(address start, address end) const {
return frame_type_addr() + size() <= end;
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("chop_frame(%d,%d)", offset_delta(), chops());
}
#endif
};
class append_frame : public stack_map_frame {
private:
address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); }
address types_addr() const { return offset_delta_addr() + sizeof(u2); }
static int frame_type_to_appends(u1 frame_type) {
int append = frame_type - 251;
return append;
}
static u1 appends_to_frame_type(int appends) {
assert(appends > 0 && appends < 4, "Invalid append amount");
return 251 + appends;
}
public:
static bool is_frame_type(u1 tag) {
return frame_type_to_appends(tag) > 0 && frame_type_to_appends(tag) < 4;
}
static append_frame* at(address addr) {
assert(is_frame_type(*addr), "Wrong frame id");
return (append_frame*)addr;
}
static append_frame* create_at(
address addr, int offset_delta, int appends,
verification_type_info* types) {
append_frame* sm = (append_frame*)addr;
sm->set_appends(appends);
sm->set_offset_delta(offset_delta);
if (types != NULL) {
verification_type_info* cur = sm->types();
for (int i = 0; i < appends; ++i) {
cur->copy_from(types);
cur = cur->next();
types = types->next();
}
}
return sm;
}
static size_t calculate_size(int appends, verification_type_info* types) {
size_t sz = sizeof(u1) + sizeof(u2);
for (int i = 0; i < appends; ++i) {
sz += types->size();
types = types->next();
}
return sz;
}
static size_t max_size() {
return sizeof(u1) + sizeof(u2) + 3 * verification_type_info::max_size();
}
size_t size() const { return calculate_size(number_of_types(), types()); }
int offset_delta() const {
return Bytes::get_Java_u2(offset_delta_addr()) + 1;
}
void set_offset_delta(int offset_delta) {
Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1);
}
void set_appends(int appends) {
assert(appends > 0 && appends < 4, "Bad number of appends");
set_frame_type(appends_to_frame_type(appends));
}
int number_of_types() const {
int appends = frame_type_to_appends(frame_type());
assert(appends > 0 && appends < 4, "Invalid number of appends in frame");
return appends;
}
verification_type_info* types() const {
return verification_type_info::at(types_addr());
}
bool is_valid_offset(int offset) const { return true; }
bool verify_subtype(address start, address end) const {
verification_type_info* vti = types();
if ((address)vti < end && vti->verify(start, end)) {
int nof = number_of_types();
vti = vti->next();
if (nof < 2 || vti->verify(start, end)) {
vti = vti->next();
if (nof < 3 || vti->verify(start, end)) {
return true;
}
}
}
return false;
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("append_frame(%d,", offset_delta());
verification_type_info* vti = types();
for (int i = 0; i < number_of_types(); ++i) {
vti->print_on(st);
if (i != number_of_types() - 1) {
st->print(",");
}
vti = vti->next();
}
st->print(")");
}
#endif
};
class full_frame : public stack_map_frame {
private:
address offset_delta_addr() const { return frame_type_addr() + sizeof(u1); }
address num_locals_addr() const { return offset_delta_addr() + sizeof(u2); }
address locals_addr() const { return num_locals_addr() + sizeof(u2); }
address stack_slots_addr(address end_of_locals) const {
return end_of_locals; }
address stack_addr(address end_of_locals) const {
return stack_slots_addr(end_of_locals) + sizeof(u2); }
enum { _frame_id = 255 };
public:
static bool is_frame_type(u1 tag) {
return tag == _frame_id;
}
static full_frame* at(address addr) {
assert(is_frame_type(*addr), "Wrong frame id");
return (full_frame*)addr;
}
static full_frame* create_at(
address addr, int offset_delta, int num_locals,
verification_type_info* locals,
int stack_slots, verification_type_info* stack) {
full_frame* sm = (full_frame*)addr;
sm->set_frame_type(_frame_id);
sm->set_offset_delta(offset_delta);
sm->set_num_locals(num_locals);
if (locals != NULL) {
verification_type_info* cur = sm->locals();
for (int i = 0; i < num_locals; ++i) {
cur->copy_from(locals);
cur = cur->next();
locals = locals->next();
}
address end_of_locals = (address)cur;
sm->set_stack_slots(end_of_locals, stack_slots);
cur = sm->stack(end_of_locals);
for (int i = 0; i < stack_slots; ++i) {
cur->copy_from(stack);
cur = cur->next();
stack = stack->next();
}
}
return sm;
}
static size_t calculate_size(
int num_locals, verification_type_info* locals,
int stack_slots, verification_type_info* stack) {
size_t sz = sizeof(u1) + sizeof(u2) + sizeof(u2) + sizeof(u2);
verification_type_info* vti = locals;
for (int i = 0; i < num_locals; ++i) {
sz += vti->size();
vti = vti->next();
}
vti = stack;
for (int i = 0; i < stack_slots; ++i) {
sz += vti->size();
vti = vti->next();
}
return sz;
}
static size_t max_size(int locals, int stack) {
return sizeof(u1) + 3 * sizeof(u2) +
(locals + stack) * verification_type_info::max_size();
}
size_t size() const {
address eol = end_of_locals();
return calculate_size(num_locals(), locals(), stack_slots(eol), stack(eol));
}
int offset_delta() const {
return Bytes::get_Java_u2(offset_delta_addr()) + 1;
}
int num_locals() const { return Bytes::get_Java_u2(num_locals_addr()); }
verification_type_info* locals() const {
return verification_type_info::at(locals_addr());
}
address end_of_locals() const {
verification_type_info* vti = locals();
for (int i = 0; i < num_locals(); ++i) {
vti = vti->next();
}
return (address)vti;
}
int stack_slots(address end_of_locals) const {
return Bytes::get_Java_u2(stack_slots_addr(end_of_locals));
}
verification_type_info* stack(address end_of_locals) const {
return verification_type_info::at(stack_addr(end_of_locals));
}
void set_offset_delta(int offset_delta) {
Bytes::put_Java_u2(offset_delta_addr(), offset_delta - 1);
}
void set_num_locals(int num_locals) {
Bytes::put_Java_u2(num_locals_addr(), num_locals);
}
void set_stack_slots(address end_of_locals, int stack_slots) {
Bytes::put_Java_u2(stack_slots_addr(end_of_locals), stack_slots);
}
// These return only the locals. Extra processing is required for stack
// types of full frames.
int number_of_types() const { return num_locals(); }
verification_type_info* types() const { return locals(); }
bool is_valid_offset(int offset) { return true; }
bool verify_subtype(address start, address end) const {
verification_type_info* vti = types();
if ((address)vti >= end) {
return false;
}
int count = number_of_types();
for (int i = 0; i < count; ++i) {
if (!vti->verify(start, end)) {
return false;
}
vti = vti->next();
}
address eol = (address)vti;
if (eol + sizeof(u2) > end) {
return false;
}
count = stack_slots(eol);
vti = stack(eol);
for (int i = 0; i < stack_slots(eol); ++i) {
if (!vti->verify(start, end)) {
return false;
}
vti = vti->next();
}
return true;
}
#ifdef ASSERT
void print_on(outputStream* st) const {
st->print("full_frame(%d,{", offset_delta());
verification_type_info* vti = locals();
for (int i = 0; i < num_locals(); ++i) {
vti->print_on(st);
if (i != num_locals() - 1) {
st->print(",");
}
vti = vti->next();
}
st->print("},{");
address end_of_locals = (address)vti;
vti = stack(end_of_locals);
int ss = stack_slots(end_of_locals);
for (int i = 0; i < ss; ++i) {
vti->print_on(st);
if (i != ss - 1) {
st->print(",");
}
vti = vti->next();
}
st->print("})");
}
#endif
};
#define VIRTUAL_DISPATCH(stack_frame_type, func_name, args) \
stack_frame_type* item_##stack_frame_type = as_##stack_frame_type(); \
if (item_##stack_frame_type != NULL) { \
return item_##stack_frame_type->func_name args; \
}
#define VOID_VIRTUAL_DISPATCH(stack_frame_type, func_name, args) \
stack_frame_type* item_##stack_frame_type = as_##stack_frame_type(); \
if (item_##stack_frame_type != NULL) { \
item_##stack_frame_type->func_name args; \
return; \
}
size_t stack_map_frame::size() const {
FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, size, ());
return 0;
}
int stack_map_frame::offset_delta() const {
FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, offset_delta, ());
return 0;
}
void stack_map_frame::set_offset_delta(int offset_delta) {
FOR_EACH_STACKMAP_FRAME_TYPE(
VOID_VIRTUAL_DISPATCH, set_offset_delta, (offset_delta));
}
int stack_map_frame::number_of_types() const {
FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, number_of_types, ());
return 0;
}
verification_type_info* stack_map_frame::types() const {
FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, types, ());
return NULL;
}
bool stack_map_frame::is_valid_offset(int offset) const {
FOR_EACH_STACKMAP_FRAME_TYPE(VIRTUAL_DISPATCH, is_valid_offset, (offset));
return true;
}
bool stack_map_frame::verify(address start, address end) const {
if (frame_type_addr() >= start && frame_type_addr() < end) {
FOR_EACH_STACKMAP_FRAME_TYPE(
VIRTUAL_DISPATCH, verify_subtype, (start, end));
}
return false;
}
#ifdef ASSERT
void stack_map_frame::print_on(outputStream* st) const {
FOR_EACH_STACKMAP_FRAME_TYPE(VOID_VIRTUAL_DISPATCH, print_on, (st));
}
#endif
#undef VIRTUAL_DISPATCH
#undef VOID_VIRTUAL_DISPATCH
#define AS_SUBTYPE_DEF(stack_frame_type, arg1, arg2) \
stack_frame_type* stack_map_frame::as_##stack_frame_type() const { \
if (stack_frame_type::is_frame_type(frame_type())) { \
return (stack_frame_type*)this; \
} else { \
return NULL; \
} \
}
FOR_EACH_STACKMAP_FRAME_TYPE(AS_SUBTYPE_DEF, x, x)
#undef AS_SUBTYPE_DEF
class stack_map_table_attribute {
private:
address name_index_addr() const {
return (address)this; }
address attribute_length_addr() const {
return name_index_addr() + sizeof(u2); }
address number_of_entries_addr() const {
return attribute_length_addr() + sizeof(u4); }
address entries_addr() const {
return number_of_entries_addr() + sizeof(u2); }
protected:
// No constructors - should be 'private', but GCC issues a warning if it is
stack_map_table_attribute() {}
stack_map_table_attribute(const stack_map_table_attribute&) {}
public:
static stack_map_table_attribute* at(address addr) {
return (stack_map_table_attribute*)addr;
}
u2 name_index() const {
return Bytes::get_Java_u2(name_index_addr()); }
u4 attribute_length() const {
return Bytes::get_Java_u4(attribute_length_addr()); }
u2 number_of_entries() const {
return Bytes::get_Java_u2(number_of_entries_addr()); }
stack_map_frame* entries() const {
return stack_map_frame::at(entries_addr());
}
static size_t header_size() {
return sizeof(u2) + sizeof(u4);
}
void set_name_index(u2 idx) {
Bytes::put_Java_u2(name_index_addr(), idx);
}
void set_attribute_length(u4 len) {
Bytes::put_Java_u4(attribute_length_addr(), len);
}
void set_number_of_entries(u2 num) {
Bytes::put_Java_u2(number_of_entries_addr(), num);
}
};

View File

@ -354,12 +354,8 @@ void CMSStats::adjust_cms_free_adjustment_factor(bool fail, size_t free) {
double CMSStats::time_until_cms_gen_full() const {
size_t cms_free = _cms_gen->cmsSpace()->free();
GenCollectedHeap* gch = GenCollectedHeap::heap();
size_t expected_promotion = gch->get_gen(0)->capacity();
if (HandlePromotionFailure) {
expected_promotion = MIN2(
(size_t) _cms_gen->gc_stats()->avg_promoted()->padded_average(),
expected_promotion);
}
size_t expected_promotion = MIN2(gch->get_gen(0)->capacity(),
(size_t) _cms_gen->gc_stats()->avg_promoted()->padded_average());
if (cms_free > expected_promotion) {
// Start a cms collection if there isn't enough space to promote
// for the next minor collection. Use the padded average as
@ -865,57 +861,18 @@ size_t ConcurrentMarkSweepGeneration::max_available() const {
return free() + _virtual_space.uncommitted_size();
}
bool ConcurrentMarkSweepGeneration::promotion_attempt_is_safe(
size_t max_promotion_in_bytes,
bool younger_handles_promotion_failure) const {
// This is the most conservative test. Full promotion is
// guaranteed if this is used. The multiplicative factor is to
// account for the worst case "dilatation".
double adjusted_max_promo_bytes = _dilatation_factor * max_promotion_in_bytes;
if (adjusted_max_promo_bytes > (double)max_uintx) { // larger than size_t
adjusted_max_promo_bytes = (double)max_uintx;
bool ConcurrentMarkSweepGeneration::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const {
size_t available = max_available();
size_t av_promo = (size_t)gc_stats()->avg_promoted()->padded_average();
bool res = (available >= av_promo) || (available >= max_promotion_in_bytes);
if (PrintGC && Verbose) {
gclog_or_tty->print_cr(
"CMS: promo attempt is%s safe: available("SIZE_FORMAT") %s av_promo("SIZE_FORMAT"),"
"max_promo("SIZE_FORMAT")",
res? "":" not", available, res? ">=":"<",
av_promo, max_promotion_in_bytes);
}
bool result = (max_contiguous_available() >= (size_t)adjusted_max_promo_bytes);
if (younger_handles_promotion_failure && !result) {
// Full promotion is not guaranteed because fragmentation
// of the cms generation can prevent the full promotion.
result = (max_available() >= (size_t)adjusted_max_promo_bytes);
if (!result) {
// With promotion failure handling the test for the ability
// to support the promotion does not have to be guaranteed.
// Use an average of the amount promoted.
result = max_available() >= (size_t)
gc_stats()->avg_promoted()->padded_average();
if (PrintGC && Verbose && result) {
gclog_or_tty->print_cr(
"\nConcurrentMarkSweepGeneration::promotion_attempt_is_safe"
" max_available: " SIZE_FORMAT
" avg_promoted: " SIZE_FORMAT,
max_available(), (size_t)
gc_stats()->avg_promoted()->padded_average());
}
} else {
if (PrintGC && Verbose) {
gclog_or_tty->print_cr(
"\nConcurrentMarkSweepGeneration::promotion_attempt_is_safe"
" max_available: " SIZE_FORMAT
" adj_max_promo_bytes: " SIZE_FORMAT,
max_available(), (size_t)adjusted_max_promo_bytes);
}
}
} else {
if (PrintGC && Verbose) {
gclog_or_tty->print_cr(
"\nConcurrentMarkSweepGeneration::promotion_attempt_is_safe"
" contiguous_available: " SIZE_FORMAT
" adj_max_promo_bytes: " SIZE_FORMAT,
max_contiguous_available(), (size_t)adjusted_max_promo_bytes);
}
}
return result;
return res;
}
// At a promotion failure dump information on block layout in heap
@ -6091,23 +6048,14 @@ void CMSCollector::sweep(bool asynch) {
assert(_collectorState == Resizing, "Change of collector state to"
" Resizing must be done under the freelistLocks (plural)");
// Now that sweeping has been completed, if the GCH's
// incremental_collection_will_fail flag is set, clear it,
// Now that sweeping has been completed, we clear
// the incremental_collection_failed flag,
// thus inviting a younger gen collection to promote into
// this generation. If such a promotion may still fail,
// the flag will be set again when a young collection is
// attempted.
// I think the incremental_collection_will_fail flag's use
// is specific to a 2 generation collection policy, so i'll
// assert that that's the configuration we are operating within.
// The use of the flag can and should be generalized appropriately
// in the future to deal with a general n-generation system.
GenCollectedHeap* gch = GenCollectedHeap::heap();
assert(gch->collector_policy()->is_two_generation_policy(),
"Resetting of incremental_collection_will_fail flag"
" may be incorrect otherwise");
gch->clear_incremental_collection_will_fail();
gch->clear_incremental_collection_failed(); // Worth retrying as fresh space may have been freed up
gch->update_full_collections_completed(_collection_count_start);
}

View File

@ -1185,8 +1185,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
virtual void par_promote_alloc_done(int thread_num);
virtual void par_oop_since_save_marks_iterate_done(int thread_num);
virtual bool promotion_attempt_is_safe(size_t promotion_in_bytes,
bool younger_handles_promotion_failure) const;
virtual bool promotion_attempt_is_safe(size_t promotion_in_bytes) const;
// Inform this (non-young) generation that a promotion failure was
// encountered during a collection of a younger generation that

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -272,12 +272,16 @@ void ConcurrentMarkSweepThread::desynchronize(bool is_cms_thread) {
}
}
// Wait until the next synchronous GC or a timeout, whichever is earlier.
void ConcurrentMarkSweepThread::wait_on_cms_lock(long t) {
// Wait until the next synchronous GC, a concurrent full gc request,
// or a timeout, whichever is earlier.
void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) {
MutexLockerEx x(CGC_lock,
Mutex::_no_safepoint_check_flag);
if (_should_terminate || _collector->_full_gc_requested) {
return;
}
set_CMS_flag(CMS_cms_wants_token); // to provoke notifies
CGC_lock->wait(Mutex::_no_safepoint_check_flag, t);
CGC_lock->wait(Mutex::_no_safepoint_check_flag, t_millis);
clear_CMS_flag(CMS_cms_wants_token);
assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),
"Should not be set");
@ -289,7 +293,8 @@ void ConcurrentMarkSweepThread::sleepBeforeNextCycle() {
icms_wait();
return;
} else {
// Wait until the next synchronous GC or a timeout, whichever is earlier
// Wait until the next synchronous GC, a concurrent full gc
// request or a timeout, whichever is earlier.
wait_on_cms_lock(CMSWaitDuration);
}
// Check if we should start a CMS collection cycle

View File

@ -120,8 +120,10 @@ class ConcurrentMarkSweepThread: public ConcurrentGCThread {
}
// Wait on CMS lock until the next synchronous GC
// or given timeout, whichever is earlier.
void wait_on_cms_lock(long t); // milliseconds
// or given timeout, whichever is earlier. A timeout value
// of 0 indicates that there is no upper bound on the wait time.
// A concurrent full gc request terminates the wait.
void wait_on_cms_lock(long t_millis);
// The CMS thread will yield during the work portion of its cycle
// only when requested to. Both synchronous and asychronous requests

View File

@ -2418,6 +2418,8 @@ void ConcurrentMark::clear_marking_state() {
for (int i = 0; i < (int)_max_task_num; ++i) {
OopTaskQueue* queue = _task_queues->queue(i);
queue->set_empty();
// Clear any partial regions from the CMTasks
_tasks[i]->clear_aborted_region();
}
}
@ -2706,7 +2708,6 @@ void ConcurrentMark::abort() {
clear_marking_state();
for (int i = 0; i < (int)_max_task_num; ++i) {
_tasks[i]->clear_region_fields();
_tasks[i]->clear_aborted_region();
}
_has_aborted = true;
@ -2985,7 +2986,7 @@ void CMTask::reset(CMBitMap* nextMarkBitMap) {
_nextMarkBitMap = nextMarkBitMap;
clear_region_fields();
clear_aborted_region();
assert(_aborted_region.is_empty(), "should have been cleared");
_calls = 0;
_elapsed_time_ms = 0.0;

View File

@ -175,7 +175,7 @@ G1BlockOffsetArray::set_remainder_to_point_to_start_incl(size_t start_card, size
}
assert(start_card > _array->index_for(_bottom), "Cannot be first card");
assert(_array->offset_array(start_card-1) <= N_words,
"Offset card has an unexpected value");
"Offset card has an unexpected value");
size_t start_card_for_region = start_card;
u_char offset = max_jubyte;
for (int i = 0; i < BlockOffsetArray::N_powers; i++) {
@ -577,6 +577,16 @@ void G1BlockOffsetArray::alloc_block_work2(HeapWord** threshold_, size_t* index_
#endif
}
void
G1BlockOffsetArray::set_for_starts_humongous(HeapWord* new_end) {
assert(_end == new_end, "_end should have already been updated");
// The first BOT entry should have offset 0.
_array->set_offset_array(_array->index_for(_bottom), 0);
// The rest should point to the first one.
set_remainder_to_point_to_start(_bottom + N_words, new_end);
}
//////////////////////////////////////////////////////////////////////
// G1BlockOffsetArrayContigSpace
//////////////////////////////////////////////////////////////////////
@ -626,3 +636,12 @@ void G1BlockOffsetArrayContigSpace::zero_bottom_entry() {
"Precondition of call");
_array->set_offset_array(bottom_index, 0);
}
void
G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_end) {
G1BlockOffsetArray::set_for_starts_humongous(new_end);
// Make sure _next_offset_threshold and _next_offset_index point to new_end.
_next_offset_threshold = new_end;
_next_offset_index = _array->index_for(new_end);
}

View File

@ -436,6 +436,8 @@ public:
}
void check_all_cards(size_t left_card, size_t right_card) const;
virtual void set_for_starts_humongous(HeapWord* new_end);
};
// A subtype of BlockOffsetArray that takes advantage of the fact
@ -484,4 +486,6 @@ class G1BlockOffsetArrayContigSpace: public G1BlockOffsetArray {
HeapWord* block_start_unsafe(const void* addr);
HeapWord* block_start_unsafe_const(const void* addr) const;
virtual void set_for_starts_humongous(HeapWord* new_end);
};

View File

@ -791,7 +791,7 @@ class RebuildRSOutOfRegionClosure: public HeapRegionClosure {
int _worker_i;
public:
RebuildRSOutOfRegionClosure(G1CollectedHeap* g1, int worker_i = 0) :
_cl(g1->g1_rem_set()->as_HRInto_G1RemSet(), worker_i),
_cl(g1->g1_rem_set(), worker_i),
_worker_i(worker_i),
_g1h(g1)
{ }
@ -890,7 +890,7 @@ void G1CollectedHeap::do_collection(bool explicit_gc,
abandon_cur_alloc_region();
abandon_gc_alloc_regions();
assert(_cur_alloc_region == NULL, "Invariant.");
g1_rem_set()->as_HRInto_G1RemSet()->cleanupHRRS();
g1_rem_set()->cleanupHRRS();
tear_down_region_lists();
set_used_regions_to_need_zero_fill();
@ -1506,15 +1506,11 @@ jint G1CollectedHeap::initialize() {
}
// Also create a G1 rem set.
if (G1UseHRIntoRS) {
if (mr_bs()->is_a(BarrierSet::CardTableModRef)) {
_g1_rem_set = new HRInto_G1RemSet(this, (CardTableModRefBS*)mr_bs());
} else {
vm_exit_during_initialization("G1 requires a cardtable mod ref bs.");
return JNI_ENOMEM;
}
if (mr_bs()->is_a(BarrierSet::CardTableModRef)) {
_g1_rem_set = new G1RemSet(this, (CardTableModRefBS*)mr_bs());
} else {
_g1_rem_set = new StupidG1RemSet(this);
vm_exit_during_initialization("G1 requires a cardtable mod ref bs.");
return JNI_ENOMEM;
}
// Carve out the G1 part of the heap.
@ -2706,8 +2702,7 @@ size_t G1CollectedHeap::max_pending_card_num() {
}
size_t G1CollectedHeap::cards_scanned() {
HRInto_G1RemSet* g1_rset = (HRInto_G1RemSet*) g1_rem_set();
return g1_rset->cardsScanned();
return g1_rem_set()->cardsScanned();
}
void
@ -3850,6 +3845,54 @@ G1ParScanThreadState::print_termination_stats(int i,
undo_waste() * HeapWordSize / K);
}
#ifdef ASSERT
bool G1ParScanThreadState::verify_ref(narrowOop* ref) const {
assert(ref != NULL, "invariant");
assert(UseCompressedOops, "sanity");
assert(!has_partial_array_mask(ref), err_msg("ref=" PTR_FORMAT, ref));
oop p = oopDesc::load_decode_heap_oop(ref);
assert(_g1h->is_in_g1_reserved(p),
err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, ref, intptr_t(p)));
return true;
}
bool G1ParScanThreadState::verify_ref(oop* ref) const {
assert(ref != NULL, "invariant");
if (has_partial_array_mask(ref)) {
// Must be in the collection set--it's already been copied.
oop p = clear_partial_array_mask(ref);
assert(_g1h->obj_in_cs(p),
err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, ref, intptr_t(p)));
} else {
oop p = oopDesc::load_decode_heap_oop(ref);
assert(_g1h->is_in_g1_reserved(p),
err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, ref, intptr_t(p)));
}
return true;
}
bool G1ParScanThreadState::verify_task(StarTask ref) const {
if (ref.is_narrow()) {
return verify_ref((narrowOop*) ref);
} else {
return verify_ref((oop*) ref);
}
}
#endif // ASSERT
void G1ParScanThreadState::trim_queue() {
StarTask ref;
do {
// Drain the overflow stack first, so other threads can steal.
while (refs()->pop_overflow(ref)) {
deal_with_reference(ref);
}
while (refs()->pop_local(ref)) {
deal_with_reference(ref);
}
} while (!refs()->is_empty());
}
G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
_g1(g1), _g1_rem(_g1->g1_rem_set()), _cm(_g1->concurrent_mark()),
_par_scan_state(par_scan_state) { }
@ -4052,39 +4095,44 @@ public:
: _g1h(g1h), _par_scan_state(par_scan_state),
_queues(queues), _terminator(terminator) {}
void do_void() {
G1ParScanThreadState* pss = par_scan_state();
while (true) {
pss->trim_queue();
void do_void();
StarTask stolen_task;
if (queues()->steal(pss->queue_num(), pss->hash_seed(), stolen_task)) {
// slightly paranoid tests; I'm trying to catch potential
// problems before we go into push_on_queue to know where the
// problem is coming from
assert((oop*)stolen_task != NULL, "Error");
if (stolen_task.is_narrow()) {
assert(UseCompressedOops, "Error");
narrowOop* p = (narrowOop*) stolen_task;
assert(has_partial_array_mask(p) ||
_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->is_in_g1_reserved(*p), "Error");
pss->push_on_queue(p);
}
continue;
}
pss->start_term_time();
if (terminator()->offer_termination()) break;
pss->end_term_time();
}
pss->end_term_time();
pss->retire_alloc_buffers();
}
private:
inline bool offer_termination();
};
bool G1ParEvacuateFollowersClosure::offer_termination() {
G1ParScanThreadState* const pss = par_scan_state();
pss->start_term_time();
const bool res = terminator()->offer_termination();
pss->end_term_time();
return res;
}
void G1ParEvacuateFollowersClosure::do_void() {
StarTask stolen_task;
G1ParScanThreadState* const pss = par_scan_state();
pss->trim_queue();
do {
while (queues()->steal(pss->queue_num(), pss->hash_seed(), stolen_task)) {
assert(pss->verify_task(stolen_task), "sanity");
if (stolen_task.is_narrow()) {
pss->deal_with_reference((narrowOop*) stolen_task);
} else {
pss->deal_with_reference((oop*) stolen_task);
}
// We've just processed a reference and we might have made
// available new entries on the queues. So we have to make sure
// we drain the queues as necessary.
pss->trim_queue();
}
} while (!offer_termination());
pss->retire_alloc_buffers();
}
class G1ParTask : public AbstractGangTask {
protected:
G1CollectedHeap* _g1h;
@ -4182,8 +4230,7 @@ public:
pss.print_termination_stats(i);
}
assert(pss.refs_to_scan() == 0, "Task queue should be empty");
assert(pss.overflowed_refs_to_scan() == 0, "Overflow queue should be empty");
assert(pss.refs()->is_empty(), "should be empty");
double end_time_ms = os::elapsedTime() * 1000.0;
_g1h->g1_policy()->record_gc_worker_end_time(i, end_time_ms);
}

View File

@ -1651,49 +1651,17 @@ public:
size_t alloc_buffer_waste() const { return _alloc_buffer_waste; }
size_t undo_waste() const { return _undo_waste; }
template <class T> void push_on_queue(T* ref) {
assert(ref != NULL, "invariant");
assert(has_partial_array_mask(ref) ||
_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);
// Verify that we point into the CS
assert(_g1h->obj_in_cs(p), "Should be in CS");
}
#endif
bool verify_ref(narrowOop* ref) const;
bool verify_ref(oop* ref) const;
bool verify_task(StarTask ref) const;
#endif // ASSERT
template <class T> void push_on_queue(T* ref) {
assert(verify_ref(ref), "sanity");
refs()->push(ref);
}
void pop_from_queue(StarTask& ref) {
if (refs()->pop_local(ref)) {
assert((oop*)ref != NULL, "pop_local() returned true");
assert(UseCompressedOops || !ref.is_narrow(), "Error");
assert(has_partial_array_mask((oop*)ref) ||
_g1h->is_in_g1_reserved(ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)ref)
: oopDesc::load_decode_heap_oop((oop*)ref)),
"invariant");
} else {
StarTask null_task;
ref = null_task;
}
}
void pop_from_overflow_queue(StarTask& ref) {
StarTask new_ref;
refs()->pop_overflow(new_ref);
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->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;
}
int refs_to_scan() { return (int)refs()->size(); }
int overflowed_refs_to_scan() { return (int)refs()->overflow_stack()->size(); }
template <class T> void update_rs(HeapRegion* from, T* p, int tid) {
if (G1DeferredRSUpdate) {
deferred_rs_update(from, p, tid);
@ -1804,7 +1772,6 @@ public:
}
}
private:
template <class T> void deal_with_reference(T* ref_to_scan) {
if (has_partial_array_mask(ref_to_scan)) {
_partial_scan_cl->do_oop_nv(ref_to_scan);
@ -1818,59 +1785,15 @@ private:
}
}
public:
void trim_queue() {
// I've replicated the loop twice, first to drain the overflow
// queue, second to drain the task queue. This is better than
// having a single loop, which checks both conditions and, inside
// it, either pops the overflow queue or the task queue, as each
// loop is tighter. Also, the decision to drain the overflow queue
// first is not arbitrary, as the overflow queue is not visible
// to the other workers, whereas the task queue is. So, we want to
// drain the "invisible" entries first, while allowing the other
// workers to potentially steal the "visible" entries.
while (refs_to_scan() > 0 || overflowed_refs_to_scan() > 0) {
while (overflowed_refs_to_scan() > 0) {
StarTask ref_to_scan;
assert((oop*)ref_to_scan == NULL, "Constructed above");
pop_from_overflow_queue(ref_to_scan);
// We shouldn't have pushed it on the queue if it was not
// pointing into the CSet.
assert((oop*)ref_to_scan != NULL, "Follows from inner loop invariant");
if (ref_to_scan.is_narrow()) {
assert(UseCompressedOops, "Error");
narrowOop* p = (narrowOop*)ref_to_scan;
assert(!has_partial_array_mask(p) &&
_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->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);
}
}
while (refs_to_scan() > 0) {
StarTask ref_to_scan;
assert((oop*)ref_to_scan == NULL, "Constructed above");
pop_from_queue(ref_to_scan);
if ((oop*)ref_to_scan != NULL) {
if (ref_to_scan.is_narrow()) {
assert(UseCompressedOops, "Error");
narrowOop* p = (narrowOop*)ref_to_scan;
assert(!has_partial_array_mask(p) &&
_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->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity");
deal_with_reference(p);
}
}
}
void deal_with_reference(StarTask ref) {
assert(verify_task(ref), "sanity");
if (ref.is_narrow()) {
deal_with_reference((narrowOop*)ref);
} else {
deal_with_reference((oop*)ref);
}
}
public:
void trim_queue();
};

View File

@ -25,8 +25,6 @@
class HeapRegion;
class G1CollectedHeap;
class G1RemSet;
class HRInto_G1RemSet;
class G1RemSet;
class ConcurrentMark;
class DirtyCardToOopClosure;
class CMBitMap;

View File

@ -97,13 +97,6 @@ public:
}
};
void
StupidG1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
int worker_i) {
IntoCSRegionClosure rc(_g1, oc);
_g1->heap_region_iterate(&rc);
}
class VerifyRSCleanCardOopClosure: public OopClosure {
G1CollectedHeap* _g1;
public:
@ -119,8 +112,9 @@ public:
}
};
HRInto_G1RemSet::HRInto_G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
: G1RemSet(g1), _ct_bs(ct_bs), _g1p(_g1->g1_policy()),
G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
: _g1(g1), _conc_refine_cards(0),
_ct_bs(ct_bs), _g1p(_g1->g1_policy()),
_cg1r(g1->concurrent_g1_refine()),
_traversal_in_progress(false),
_cset_rs_update_cl(NULL),
@ -134,7 +128,7 @@ HRInto_G1RemSet::HRInto_G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs)
}
}
HRInto_G1RemSet::~HRInto_G1RemSet() {
G1RemSet::~G1RemSet() {
delete _seq_task;
for (uint i = 0; i < n_workers(); i++) {
assert(_cset_rs_update_cl[i] == NULL, "it should be");
@ -277,7 +271,7 @@ public:
// p threads
// Then thread t will start at region t * floor (n/p)
HeapRegion* HRInto_G1RemSet::calculateStartRegion(int worker_i) {
HeapRegion* G1RemSet::calculateStartRegion(int worker_i) {
HeapRegion* result = _g1p->collection_set();
if (ParallelGCThreads > 0) {
size_t cs_size = _g1p->collection_set_size();
@ -290,7 +284,7 @@ HeapRegion* HRInto_G1RemSet::calculateStartRegion(int worker_i) {
return result;
}
void HRInto_G1RemSet::scanRS(OopsInHeapRegionClosure* oc, int worker_i) {
void G1RemSet::scanRS(OopsInHeapRegionClosure* oc, int worker_i) {
double rs_time_start = os::elapsedTime();
HeapRegion *startRegion = calculateStartRegion(worker_i);
@ -340,7 +334,7 @@ public:
}
};
void HRInto_G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) {
void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, int worker_i) {
double start = os::elapsedTime();
// Apply the given closure to all remaining log entries.
RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq);
@ -439,12 +433,11 @@ public:
}
};
void HRInto_G1RemSet::cleanupHRRS() {
void G1RemSet::cleanupHRRS() {
HeapRegionRemSet::cleanup();
}
void
HRInto_G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
int worker_i) {
#if CARD_REPEAT_HISTO
ct_freq_update_histo_and_reset();
@ -508,8 +501,7 @@ HRInto_G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
_cset_rs_update_cl[worker_i] = NULL;
}
void HRInto_G1RemSet::
prepare_for_oops_into_collection_set_do() {
void G1RemSet::prepare_for_oops_into_collection_set_do() {
#if G1_REM_SET_LOGGING
PrintRSClosure cl;
_g1->collection_set_iterate(&cl);
@ -581,7 +573,7 @@ public:
// RSet updating,
// * the post-write barrier shouldn't be logging updates to young
// regions (but there is a situation where this can happen - see
// the comment in HRInto_G1RemSet::concurrentRefineOneCard below -
// the comment in G1RemSet::concurrentRefineOneCard below -
// that should not be applicable here), and
// * during actual RSet updating, the filtering of cards in young
// regions in HeapRegion::oops_on_card_seq_iterate_careful is
@ -601,7 +593,7 @@ public:
}
};
void HRInto_G1RemSet::cleanup_after_oops_into_collection_set_do() {
void G1RemSet::cleanup_after_oops_into_collection_set_do() {
guarantee( _cards_scanned != NULL, "invariant" );
_total_cards_scanned = 0;
for (uint i = 0; i < n_workers(); ++i)
@ -692,12 +684,12 @@ public:
}
};
void HRInto_G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm) {
void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm) {
ScrubRSClosure scrub_cl(region_bm, card_bm);
_g1->heap_region_iterate(&scrub_cl);
}
void HRInto_G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm,
void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm,
int worker_num, int claim_val) {
ScrubRSClosure scrub_cl(region_bm, card_bm);
_g1->heap_region_par_iterate_chunked(&scrub_cl, worker_num, claim_val);
@ -741,7 +733,7 @@ public:
virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
};
bool HRInto_G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i,
bool G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i,
bool check_for_refs_into_cset) {
// Construct the region representing the card.
HeapWord* start = _ct_bs->addr_for(card_ptr);
@ -820,7 +812,7 @@ bool HRInto_G1RemSet::concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i
return trigger_cl.value();
}
bool HRInto_G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i,
bool G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i,
bool check_for_refs_into_cset) {
// If the card is no longer dirty, nothing to do.
if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
@ -995,7 +987,7 @@ public:
}
};
void HRInto_G1RemSet::print_summary_info() {
void G1RemSet::print_summary_info() {
G1CollectedHeap* g1 = G1CollectedHeap::heap();
#if CARD_REPEAT_HISTO
@ -1029,30 +1021,26 @@ void HRInto_G1RemSet::print_summary_info() {
g1->concurrent_g1_refine()->threads_do(&p);
gclog_or_tty->print_cr("");
if (G1UseHRIntoRS) {
HRRSStatsIter blk;
g1->heap_region_iterate(&blk);
gclog_or_tty->print_cr(" Total heap region rem set sizes = " SIZE_FORMAT "K."
" Max = " SIZE_FORMAT "K.",
blk.total_mem_sz()/K, blk.max_mem_sz()/K);
gclog_or_tty->print_cr(" Static structures = " SIZE_FORMAT "K,"
" free_lists = " SIZE_FORMAT "K.",
HeapRegionRemSet::static_mem_size()/K,
HeapRegionRemSet::fl_mem_size()/K);
gclog_or_tty->print_cr(" %d occupied cards represented.",
blk.occupied());
gclog_or_tty->print_cr(" Max sz region = [" PTR_FORMAT ", " PTR_FORMAT " )"
", cap = " SIZE_FORMAT "K, occ = " SIZE_FORMAT "K.",
blk.max_mem_sz_region()->bottom(), blk.max_mem_sz_region()->end(),
(blk.max_mem_sz_region()->rem_set()->mem_size() + K - 1)/K,
(blk.max_mem_sz_region()->rem_set()->occupied() + K - 1)/K);
gclog_or_tty->print_cr(" Did %d coarsenings.",
HeapRegionRemSet::n_coarsenings());
}
HRRSStatsIter blk;
g1->heap_region_iterate(&blk);
gclog_or_tty->print_cr(" Total heap region rem set sizes = " SIZE_FORMAT "K."
" Max = " SIZE_FORMAT "K.",
blk.total_mem_sz()/K, blk.max_mem_sz()/K);
gclog_or_tty->print_cr(" Static structures = " SIZE_FORMAT "K,"
" free_lists = " SIZE_FORMAT "K.",
HeapRegionRemSet::static_mem_size()/K,
HeapRegionRemSet::fl_mem_size()/K);
gclog_or_tty->print_cr(" %d occupied cards represented.",
blk.occupied());
gclog_or_tty->print_cr(" Max sz region = [" PTR_FORMAT ", " PTR_FORMAT " )"
", cap = " SIZE_FORMAT "K, occ = " SIZE_FORMAT "K.",
blk.max_mem_sz_region()->bottom(), blk.max_mem_sz_region()->end(),
(blk.max_mem_sz_region()->rem_set()->mem_size() + K - 1)/K,
(blk.max_mem_sz_region()->rem_set()->occupied() + K - 1)/K);
gclog_or_tty->print_cr(" Did %d coarsenings.", HeapRegionRemSet::n_coarsenings());
}
void HRInto_G1RemSet::prepare_for_verify() {
void G1RemSet::prepare_for_verify() {
if (G1HRRSFlushLogBuffersOnVerify &&
(VerifyBeforeGC || VerifyAfterGC)
&& !_g1->full_collection()) {

View File

@ -27,107 +27,18 @@
class G1CollectedHeap;
class CardTableModRefBarrierSet;
class HRInto_G1RemSet;
class ConcurrentG1Refine;
// A G1RemSet in which each heap region has a rem set that records the
// external heap references into it. Uses a mod ref bs to track updates,
// so that they can be used to update the individual region remsets.
class G1RemSet: public CHeapObj {
protected:
G1CollectedHeap* _g1;
unsigned _conc_refine_cards;
size_t n_workers();
public:
G1RemSet(G1CollectedHeap* g1) :
_g1(g1), _conc_refine_cards(0)
{}
// Invoke "blk->do_oop" on all pointers into the CS in object in regions
// outside the CS (having invoked "blk->set_region" to set the "from"
// region correctly beforehand.) The "worker_i" param is for the
// parallel case where the number of the worker thread calling this
// function can be helpful in partitioning the work to be done. It
// should be the same as the "i" passed to the calling thread's
// work(i) function. In the sequential case this param will be ingored.
virtual void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
int worker_i) = 0;
// Prepare for and cleanup after an oops_into_collection_set_do
// call. Must call each of these once before and after (in sequential
// code) any threads call oops into collection set do. (This offers an
// opportunity to sequential setup and teardown of structures needed by a
// parallel iteration over the CS's RS.)
virtual void prepare_for_oops_into_collection_set_do() = 0;
virtual void cleanup_after_oops_into_collection_set_do() = 0;
// If "this" is of the given subtype, return "this", else "NULL".
virtual HRInto_G1RemSet* as_HRInto_G1RemSet() { return NULL; }
// Record, if necessary, the fact that *p (where "p" is in region "from",
// and is, a fortiori, required to be non-NULL) has changed to its new value.
virtual void write_ref(HeapRegion* from, oop* p) = 0;
virtual void write_ref(HeapRegion* from, narrowOop* p) = 0;
virtual void par_write_ref(HeapRegion* from, oop* p, int tid) = 0;
virtual void par_write_ref(HeapRegion* from, narrowOop* p, int tid) = 0;
// Requires "region_bm" and "card_bm" to be bitmaps with 1 bit per region
// or card, respectively, such that a region or card with a corresponding
// 0 bit contains no part of any live object. Eliminates any remembered
// set entries that correspond to dead heap ranges.
virtual void scrub(BitMap* region_bm, BitMap* card_bm) = 0;
// Like the above, but assumes is called in parallel: "worker_num" is the
// parallel thread id of the current thread, and "claim_val" is the
// value that should be used to claim heap regions.
virtual void scrub_par(BitMap* region_bm, BitMap* card_bm,
int worker_num, int claim_val) = 0;
// Refine the card corresponding to "card_ptr". If "sts" is non-NULL,
// join and leave around parts that must be atomic wrt GC. (NULL means
// being done at a safepoint.)
// With some implementations of this routine, when check_for_refs_into_cset
// is true, a true result may be returned if the given card contains oops
// that have references into the current collection set.
virtual bool concurrentRefineOneCard(jbyte* card_ptr, int worker_i,
bool check_for_refs_into_cset) {
return false;
}
// Print any relevant summary info.
virtual void print_summary_info() {}
// Prepare remebered set for verification.
virtual void prepare_for_verify() {};
};
// The simplest possible G1RemSet: iterates over all objects in non-CS
// regions, searching for pointers into the CS.
class StupidG1RemSet: public G1RemSet {
public:
StupidG1RemSet(G1CollectedHeap* g1) : G1RemSet(g1) {}
void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
int worker_i);
void prepare_for_oops_into_collection_set_do() {}
void cleanup_after_oops_into_collection_set_do() {}
// Nothing is necessary in the version below.
void write_ref(HeapRegion* from, oop* p) {}
void write_ref(HeapRegion* from, narrowOop* p) {}
void par_write_ref(HeapRegion* from, oop* p, int tid) {}
void par_write_ref(HeapRegion* from, narrowOop* p, int tid) {}
void scrub(BitMap* region_bm, BitMap* card_bm) {}
void scrub_par(BitMap* region_bm, BitMap* card_bm,
int worker_num, int claim_val) {}
};
// A G1RemSet in which each heap region has a rem set that records the
// external heap references into it. Uses a mod ref bs to track updates,
// so that they can be used to update the individual region remsets.
class HRInto_G1RemSet: public G1RemSet {
protected:
enum SomePrivateConstants {
UpdateRStoMergeSync = 0,
@ -175,27 +86,31 @@ public:
// scanned.
void cleanupHRRS();
HRInto_G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs);
~HRInto_G1RemSet();
G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs);
~G1RemSet();
// Invoke "blk->do_oop" on all pointers into the CS in objects in regions
// outside the CS (having invoked "blk->set_region" to set the "from"
// region correctly beforehand.) The "worker_i" param is for the
// parallel case where the number of the worker thread calling this
// function can be helpful in partitioning the work to be done. It
// should be the same as the "i" passed to the calling thread's
// work(i) function. In the sequential case this param will be ingored.
void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
int worker_i);
// Prepare for and cleanup after an oops_into_collection_set_do
// call. Must call each of these once before and after (in sequential
// code) any threads call oops_into_collection_set_do. (This offers an
// opportunity to sequential setup and teardown of structures needed by a
// parallel iteration over the CS's RS.)
void prepare_for_oops_into_collection_set_do();
void cleanup_after_oops_into_collection_set_do();
void scanRS(OopsInHeapRegionClosure* oc, int worker_i);
template <class T> void scanNewRefsRS_work(OopsInHeapRegionClosure* oc, int worker_i);
void scanNewRefsRS(OopsInHeapRegionClosure* oc, int worker_i) {
if (UseCompressedOops) {
scanNewRefsRS_work<narrowOop>(oc, worker_i);
} else {
scanNewRefsRS_work<oop>(oc, worker_i);
}
}
void updateRS(DirtyCardQueue* into_cset_dcq, int worker_i);
HeapRegion* calculateStartRegion(int i);
HRInto_G1RemSet* as_HRInto_G1RemSet() { return this; }
void scanRS(OopsInHeapRegionClosure* oc, int worker_i);
void updateRS(DirtyCardQueue* into_cset_dcq, int worker_i);
HeapRegion* calculateStartRegion(int i);
CardTableModRefBS* ct_bs() { return _ct_bs; }
size_t cardsScanned() { return _total_cards_scanned; }
@ -219,17 +134,31 @@ public:
bool self_forwarded(oop obj);
// Requires "region_bm" and "card_bm" to be bitmaps with 1 bit per region
// or card, respectively, such that a region or card with a corresponding
// 0 bit contains no part of any live object. Eliminates any remembered
// set entries that correspond to dead heap ranges.
void scrub(BitMap* region_bm, BitMap* card_bm);
// Like the above, but assumes is called in parallel: "worker_num" is the
// parallel thread id of the current thread, and "claim_val" is the
// value that should be used to claim heap regions.
void scrub_par(BitMap* region_bm, BitMap* card_bm,
int worker_num, int claim_val);
// If check_for_refs_into_cset is true then a true result is returned
// if the card contains oops that have references into the current
// collection set.
// Refine the card corresponding to "card_ptr". If "sts" is non-NULL,
// join and leave around parts that must be atomic wrt GC. (NULL means
// being done at a safepoint.)
// If check_for_refs_into_cset is true, a true result is returned
// if the given card contains oops that have references into the
// current collection set.
virtual bool concurrentRefineOneCard(jbyte* card_ptr, int worker_i,
bool check_for_refs_into_cset);
// Print any relevant summary info.
virtual void print_summary_info();
// Prepare remembered set for verification.
virtual void prepare_for_verify();
};
@ -250,13 +179,13 @@ public:
class UpdateRSOopClosure: public OopClosure {
HeapRegion* _from;
HRInto_G1RemSet* _rs;
G1RemSet* _rs;
int _worker_i;
template <class T> void do_oop_work(T* p);
public:
UpdateRSOopClosure(HRInto_G1RemSet* rs, int worker_i = 0) :
UpdateRSOopClosure(G1RemSet* rs, int worker_i = 0) :
_from(NULL), _rs(rs), _worker_i(worker_i) {
guarantee(_rs != NULL, "Requires an HRIntoG1RemSet");
}

View File

@ -30,16 +30,18 @@ inline size_t G1RemSet::n_workers() {
}
}
template <class T> inline void HRInto_G1RemSet::write_ref_nv(HeapRegion* from, T* p) {
template <class T>
inline void G1RemSet::write_ref_nv(HeapRegion* from, T* p) {
par_write_ref_nv(from, p, 0);
}
inline bool HRInto_G1RemSet::self_forwarded(oop obj) {
inline bool G1RemSet::self_forwarded(oop obj) {
bool result = (obj->is_forwarded() && (obj->forwardee()== obj));
return result;
}
template <class T> inline void HRInto_G1RemSet::par_write_ref_nv(HeapRegion* from, T* p, int tid) {
template <class T>
inline void G1RemSet::par_write_ref_nv(HeapRegion* from, T* p, int tid) {
oop obj = oopDesc::load_decode_heap_oop(p);
#ifdef ASSERT
// can't do because of races
@ -77,7 +79,7 @@ template <class T> inline void HRInto_G1RemSet::par_write_ref_nv(HeapRegion* fro
// Deferred updates to the CSet are either discarded (in the normal case),
// or processed (if an evacuation failure occurs) at the end
// of the collection.
// See HRInto_G1RemSet::cleanup_after_oops_into_collection_set_do().
// See G1RemSet::cleanup_after_oops_into_collection_set_do().
} else {
#if G1_REM_SET_LOGGING
gclog_or_tty->print_cr("Adding " PTR_FORMAT " (" PTR_FORMAT ") to RS"
@ -91,12 +93,14 @@ template <class T> inline void HRInto_G1RemSet::par_write_ref_nv(HeapRegion* fro
}
}
template <class T> inline void UpdateRSOopClosure::do_oop_work(T* p) {
template <class T>
inline void UpdateRSOopClosure::do_oop_work(T* p) {
assert(_from != NULL, "from region must be non-NULL");
_rs->par_write_ref(_from, p, _worker_i);
}
template <class T> inline void UpdateRSetImmediate::do_oop_work(T* p) {
template <class T>
inline void UpdateRSetImmediate::do_oop_work(T* p) {
assert(_from->is_in_reserved(p), "paranoia");
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop) && !_from->is_survivor()) {

View File

@ -40,9 +40,6 @@
develop(intx, G1PolicyVerbose, 0, \
"The verbosity level on G1 policy decisions") \
\
develop(bool, G1UseHRIntoRS, true, \
"Determines whether the 'advanced' HR Into rem set is used.") \
\
develop(intx, G1MarkingVerboseLevel, 0, \
"Level (0-4) of verboseness of the marking code") \
\

View File

@ -377,10 +377,26 @@ void HeapRegion::calc_gc_efficiency() {
}
// </PREDICTION>
void HeapRegion::set_startsHumongous() {
void HeapRegion::set_startsHumongous(HeapWord* new_end) {
assert(end() == _orig_end,
"Should be normal before the humongous object allocation");
assert(top() == bottom(), "should be empty");
_humongous_type = StartsHumongous;
_humongous_start_region = this;
assert(end() == _orig_end, "Should be normal before alloc.");
set_end(new_end);
_offsets.set_for_starts_humongous(new_end);
}
void HeapRegion::set_continuesHumongous(HeapRegion* start) {
assert(end() == _orig_end,
"Should be normal before the humongous object allocation");
assert(top() == bottom(), "should be empty");
assert(start->startsHumongous(), "pre-condition");
_humongous_type = ContinuesHumongous;
_humongous_start_region = start;
}
bool HeapRegion::claimHeapRegion(jint claimValue) {
@ -500,23 +516,6 @@ CompactibleSpace* HeapRegion::next_compaction_space() const {
return blk.result();
}
void HeapRegion::set_continuesHumongous(HeapRegion* start) {
// The order is important here.
start->add_continuingHumongousRegion(this);
_humongous_type = ContinuesHumongous;
_humongous_start_region = start;
}
void HeapRegion::add_continuingHumongousRegion(HeapRegion* cont) {
// Must join the blocks of the current H region seq with the block of the
// added region.
offsets()->join_blocks(bottom(), cont->bottom());
arrayOop obj = (arrayOop)(bottom());
obj->set_length((int) (obj->length() + cont->capacity()/jintSize));
set_end(cont->end());
set_top(cont->end());
}
void HeapRegion::save_marks() {
set_saved_mark();
}

View File

@ -395,14 +395,12 @@ class HeapRegion: public G1OffsetTableContigSpace {
// Causes the current region to represent a humongous object spanning "n"
// regions.
virtual void set_startsHumongous();
void set_startsHumongous(HeapWord* new_end);
// The regions that continue a humongous sequence should be added using
// this method, in increasing address order.
void set_continuesHumongous(HeapRegion* start);
void add_continuingHumongousRegion(HeapRegion* cont);
// If the region has a remembered set, return a pointer to it.
HeapRegionRemSet* rem_set() const {
return _rem_set;
@ -733,13 +731,6 @@ class HeapRegion: public G1OffsetTableContigSpace {
FilterOutOfRegionClosure* cl,
bool filter_young);
// The region "mr" is entirely in "this", and starts and ends at block
// boundaries. The caller declares that all the contained blocks are
// coalesced into one.
void declare_filled_region_to_BOT(MemRegion mr) {
_offsets.single_block(mr.start(), mr.end());
}
// A version of block start that is guaranteed to find *some* block
// boundary at or before "p", but does not object iteration, and may
// therefore be used safely when the heap is unparseable.

View File

@ -1159,9 +1159,7 @@ HeapRegionRemSetIterator() :
_hrrs(NULL),
_g1h(G1CollectedHeap::heap()),
_bosa(NULL),
_sparse_iter(size_t(G1CollectedHeap::heap()->reserved_region().start())
>> CardTableModRefBS::card_shift)
{}
_sparse_iter() { }
void HeapRegionRemSetIterator::initialize(const HeapRegionRemSet* hrrs) {
_hrrs = hrrs;

View File

@ -91,34 +91,118 @@ HeapRegionSeq::alloc_obj_from_region_index(int ind, size_t word_size) {
}
if (sumSizes >= word_size) {
_alloc_search_start = cur;
// Mark the allocated regions as allocated.
// We need to initialize the region(s) we just discovered. This is
// a bit tricky given that it can happen concurrently with
// refinement threads refining cards on these regions and
// potentially wanting to refine the BOT as they are scanning
// those cards (this can happen shortly after a cleanup; see CR
// 6991377). So we have to set up the region(s) carefully and in
// a specific order.
// Currently, allocs_are_zero_filled() returns false. The zero
// filling infrastructure will be going away soon (see CR 6977804).
// So no need to do anything else here.
bool zf = G1CollectedHeap::heap()->allocs_are_zero_filled();
assert(!zf, "not supported");
// This will be the "starts humongous" region.
HeapRegion* first_hr = _regions.at(first);
for (int i = first; i < cur; i++) {
HeapRegion* hr = _regions.at(i);
if (zf)
hr->ensure_zero_filled();
{
MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
first_hr->set_zero_fill_allocated();
}
// The header of the new object will be placed at the bottom of
// the first region.
HeapWord* new_obj = first_hr->bottom();
// This will be the new end of the first region in the series that
// should also match the end of the last region in the seriers.
// (Note: sumSizes = "region size" x "number of regions we found").
HeapWord* new_end = new_obj + sumSizes;
// This will be the new top of the first region that will reflect
// this allocation.
HeapWord* new_top = new_obj + word_size;
// First, we need to zero the header of the space that we will be
// allocating. When we update top further down, some refinement
// threads might try to scan the region. By zeroing the header we
// ensure that any thread that will try to scan the region will
// come across the zero klass word and bail out.
//
// NOTE: It would not have been correct to have used
// CollectedHeap::fill_with_object() and make the space look like
// an int array. The thread that is doing the allocation will
// later update the object header to a potentially different array
// type and, for a very short period of time, the klass and length
// fields will be inconsistent. This could cause a refinement
// thread to calculate the object size incorrectly.
Copy::fill_to_words(new_obj, oopDesc::header_size(), 0);
// We will set up the first region as "starts humongous". This
// will also update the BOT covering all the regions to reflect
// that there is a single object that starts at the bottom of the
// first region.
first_hr->set_startsHumongous(new_end);
// Then, if there are any, we will set up the "continues
// humongous" regions.
HeapRegion* hr = NULL;
for (int i = first + 1; i < cur; ++i) {
hr = _regions.at(i);
{
MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
hr->set_zero_fill_allocated();
}
size_t sz = hr->capacity() / HeapWordSize;
HeapWord* tmp = hr->allocate(sz);
assert(tmp != NULL, "Humongous allocation failure");
MemRegion mr = MemRegion(tmp, sz);
CollectedHeap::fill_with_object(mr);
hr->declare_filled_region_to_BOT(mr);
if (i == first) {
first_hr->set_startsHumongous();
hr->set_continuesHumongous(first_hr);
}
// If we have "continues humongous" regions (hr != NULL), then the
// end of the last one should match new_end.
assert(hr == NULL || hr->end() == new_end, "sanity");
// Up to this point no concurrent thread would have been able to
// do any scanning on any region in this series. All the top
// fields still point to bottom, so the intersection between
// [bottom,top] and [card_start,card_end] will be empty. Before we
// update the top fields, we'll do a storestore to make sure that
// no thread sees the update to top before the zeroing of the
// object header and the BOT initialization.
OrderAccess::storestore();
// Now that the BOT and the object header have been initialized,
// we can update top of the "starts humongous" region.
assert(first_hr->bottom() < new_top && new_top <= first_hr->end(),
"new_top should be in this region");
first_hr->set_top(new_top);
// Now, we will update the top fields of the "continues humongous"
// regions. The reason we need to do this is that, otherwise,
// these regions would look empty and this will confuse parts of
// G1. For example, the code that looks for a consecutive number
// of empty regions will consider them empty and try to
// re-allocate them. We can extend is_empty() to also include
// !continuesHumongous(), but it is easier to just update the top
// fields here.
hr = NULL;
for (int i = first + 1; i < cur; ++i) {
hr = _regions.at(i);
if ((i + 1) == cur) {
// last continues humongous region
assert(hr->bottom() < new_top && new_top <= hr->end(),
"new_top should fall on this region");
hr->set_top(new_top);
} else {
assert(i > first, "sanity");
hr->set_continuesHumongous(first_hr);
// not last one
assert(new_top > hr->end(), "new_top should be above this region");
hr->set_top(hr->end());
}
}
HeapWord* first_hr_bot = first_hr->bottom();
HeapWord* obj_end = first_hr_bot + word_size;
first_hr->set_top(obj_end);
return first_hr_bot;
// If we have continues humongous regions (hr != NULL), then the
// end of the last one should match new_end and its top should
// match new_top.
assert(hr == NULL ||
(hr->end() == new_end && hr->top() == new_top), "sanity");
return new_obj;
} else {
// If we started from the beginning, we want to know why we can't alloc.
return NULL;

View File

@ -308,7 +308,7 @@ void RSHashTable::add_entry(SparsePRTEntry* e) {
assert(e2->num_valid_cards() > 0, "Postcondition.");
}
CardIdx_t /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() {
CardIdx_t RSHashTableIter::find_first_card_in_list() {
CardIdx_t res;
while (_bl_ind != RSHashTable::NullEntry) {
res = _rsht->entry(_bl_ind)->card(0);
@ -322,14 +322,11 @@ CardIdx_t /* RSHashTable:: */ RSHashTableIter::find_first_card_in_list() {
return SparsePRTEntry::NullEntry;
}
size_t /* RSHashTable:: */ RSHashTableIter::compute_card_ind(CardIdx_t ci) {
return
_heap_bot_card_ind
+ (_rsht->entry(_bl_ind)->r_ind() * HeapRegion::CardsPerRegion)
+ ci;
size_t RSHashTableIter::compute_card_ind(CardIdx_t ci) {
return (_rsht->entry(_bl_ind)->r_ind() * HeapRegion::CardsPerRegion) + ci;
}
bool /* RSHashTable:: */ RSHashTableIter::has_next(size_t& card_index) {
bool RSHashTableIter::has_next(size_t& card_index) {
_card_ind++;
CardIdx_t ci;
if (_card_ind < SparsePRTEntry::cards_num() &&

View File

@ -169,7 +169,6 @@ class RSHashTableIter VALUE_OBJ_CLASS_SPEC {
int _bl_ind; // [-1, 0.._rsht->_capacity)
short _card_ind; // [0..SparsePRTEntry::cards_num())
RSHashTable* _rsht;
size_t _heap_bot_card_ind;
// If the bucket list pointed to by _bl_ind contains a card, sets
// _bl_ind to the index of that entry, and returns the card.
@ -183,13 +182,11 @@ class RSHashTableIter VALUE_OBJ_CLASS_SPEC {
size_t compute_card_ind(CardIdx_t ci);
public:
RSHashTableIter(size_t heap_bot_card_ind) :
RSHashTableIter() :
_tbl_ind(RSHashTable::NullEntry),
_bl_ind(RSHashTable::NullEntry),
_card_ind((SparsePRTEntry::cards_num() - 1)),
_rsht(NULL),
_heap_bot_card_ind(heap_bot_card_ind)
{}
_rsht(NULL) {}
void init(RSHashTable* rsht) {
_rsht = rsht;
@ -280,20 +277,11 @@ public:
bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const {
return _next->contains_card(region_id, card_index);
}
#if 0
void verify_is_cleared();
void print();
#endif
};
class SparsePRTIter: public /* RSHashTable:: */RSHashTableIter {
class SparsePRTIter: public RSHashTableIter {
public:
SparsePRTIter(size_t heap_bot_card_ind) :
/* RSHashTable:: */RSHashTableIter(heap_bot_card_ind)
{}
void init(const SparsePRT* sprt) {
RSHashTableIter::init(sprt->cur());
}

View File

@ -310,10 +310,16 @@ heapRegionSeq.hpp heapRegion.hpp
heapRegionSeq.inline.hpp heapRegionSeq.hpp
instanceKlass.cpp g1RemSet.inline.hpp
instanceRefKlass.cpp g1RemSet.inline.hpp
klass.hpp g1OopClosures.hpp
memoryService.cpp g1MemoryPool.hpp
objArrayKlass.cpp g1RemSet.inline.hpp
ptrQueue.cpp allocation.hpp
ptrQueue.cpp allocation.inline.hpp
ptrQueue.cpp mutex.hpp

View File

@ -846,7 +846,7 @@ void ParNewGeneration::collect(bool full,
// from this generation, pass on collection; let the next generation
// do it.
if (!collection_attempt_is_safe()) {
gch->set_incremental_collection_will_fail();
gch->set_incremental_collection_failed(); // slight lie, in that we did not even attempt one
return;
}
assert(to()->is_empty(), "Else not collection_attempt_is_safe");
@ -935,8 +935,6 @@ void ParNewGeneration::collect(bool full,
assert(to()->is_empty(), "to space should be empty now");
} else {
assert(HandlePromotionFailure,
"Should only be here if promotion failure handling is on");
assert(_promo_failure_scan_stack.is_empty(), "post condition");
_promo_failure_scan_stack.clear(true); // Clear cached segments.
@ -947,7 +945,7 @@ void ParNewGeneration::collect(bool full,
// All the spaces are in play for mark-sweep.
swap_spaces(); // Make life simpler for CMS || rescan; see 6483690.
from()->set_next_compaction_space(to());
gch->set_incremental_collection_will_fail();
gch->set_incremental_collection_failed();
// Inform the next generation that a promotion failure occurred.
_next_gen->promotion_failure_occurred();
@ -1092,11 +1090,6 @@ oop ParNewGeneration::copy_to_survivor_space_avoiding_promotion_undo(
old, m, sz);
if (new_obj == NULL) {
if (!HandlePromotionFailure) {
// A failed promotion likely means the MaxLiveObjectEvacuationRatio flag
// is incorrectly set. In any case, its seriously wrong to be here!
vm_exit_out_of_memory(sz*wordSize, "promotion");
}
// promotion failed, forward to self
_promotion_failed = true;
new_obj = old;
@ -1206,12 +1199,6 @@ oop ParNewGeneration::copy_to_survivor_space_with_undo(
old, m, sz);
if (new_obj == NULL) {
if (!HandlePromotionFailure) {
// A failed promotion likely means the MaxLiveObjectEvacuationRatio
// flag is incorrectly set. In any case, its seriously wrong to be
// here!
vm_exit_out_of_memory(sz*wordSize, "promotion");
}
// promotion failed, forward to self
forward_ptr = old->forward_to_atomic(old);
new_obj = old;

View File

@ -301,6 +301,7 @@ c1_MacroAssembler.hpp assembler.hpp
c1_MacroAssembler.hpp assembler_<arch>.inline.hpp
c1_MacroAssembler_<arch>.cpp arrayOop.hpp
c1_MacroAssembler_<arch>.cpp basicLock.hpp
c1_MacroAssembler_<arch>.cpp biasedLocking.hpp
c1_MacroAssembler_<arch>.cpp c1_MacroAssembler.hpp
c1_MacroAssembler_<arch>.cpp c1_Runtime1.hpp
@ -309,7 +310,6 @@ c1_MacroAssembler_<arch>.cpp interpreter.hpp
c1_MacroAssembler_<arch>.cpp markOop.hpp
c1_MacroAssembler_<arch>.cpp os.hpp
c1_MacroAssembler_<arch>.cpp stubRoutines.hpp
c1_MacroAssembler_<arch>.cpp synchronizer.hpp
c1_MacroAssembler_<arch>.cpp systemDictionary.hpp
c1_MacroAssembler_<arch>.hpp generate_platform_dependent_include

View File

@ -300,10 +300,17 @@ barrierSet.hpp oopsHierarchy.hpp
barrierSet.inline.hpp barrierSet.hpp
barrierSet.inline.hpp cardTableModRefBS.hpp
basicLock.cpp basicLock.hpp
basicLock.cpp synchronizer.hpp
basicLock.hpp handles.hpp
basicLock.hpp markOop.hpp
basicLock.hpp top.hpp
biasedLocking.cpp basicLock.hpp
biasedLocking.cpp biasedLocking.hpp
biasedLocking.cpp klass.inline.hpp
biasedLocking.cpp markOop.hpp
biasedLocking.cpp synchronizer.hpp
biasedLocking.cpp task.hpp
biasedLocking.cpp vframe.hpp
biasedLocking.cpp vmThread.hpp
@ -404,13 +411,13 @@ bytecodeInterpreter_<arch>.cpp vframeArray.hpp
bytecodeInterpreterWithChecks.cpp bytecodeInterpreter.cpp
bytecodeInterpreter.hpp allocation.hpp
bytecodeInterpreter.hpp basicLock.hpp
bytecodeInterpreter.hpp bytes_<arch>.hpp
bytecodeInterpreter.hpp frame.hpp
bytecodeInterpreter.hpp globalDefinitions.hpp
bytecodeInterpreter.hpp globals.hpp
bytecodeInterpreter.hpp methodDataOop.hpp
bytecodeInterpreter.hpp methodOop.hpp
bytecodeInterpreter.hpp synchronizer.hpp
bytecodeInterpreter.inline.hpp bytecodeInterpreter.hpp
bytecodeInterpreter.inline.hpp stubRoutines.hpp
@ -1667,10 +1674,10 @@ frame.cpp stubRoutines.hpp
frame.cpp universe.inline.hpp
frame.hpp assembler.hpp
frame.hpp basicLock.hpp
frame.hpp methodOop.hpp
frame.hpp monitorChunk.hpp
frame.hpp registerMap.hpp
frame.hpp synchronizer.hpp
frame.hpp top.hpp
frame.inline.hpp bytecodeInterpreter.hpp
@ -2120,6 +2127,7 @@ interfaceSupport.hpp vmThread.hpp
interfaceSupport_<os_family>.hpp generate_platform_dependent_include
interp_masm_<arch_model>.cpp arrayOop.hpp
interp_masm_<arch_model>.cpp basicLock.hpp
interp_masm_<arch_model>.cpp biasedLocking.hpp
interp_masm_<arch_model>.cpp interp_masm_<arch_model>.hpp
interp_masm_<arch_model>.cpp interpreterRuntime.hpp
@ -2131,7 +2139,6 @@ interp_masm_<arch_model>.cpp markOop.hpp
interp_masm_<arch_model>.cpp methodDataOop.hpp
interp_masm_<arch_model>.cpp methodOop.hpp
interp_masm_<arch_model>.cpp sharedRuntime.hpp
interp_masm_<arch_model>.cpp synchronizer.hpp
interp_masm_<arch_model>.cpp thread_<os_family>.inline.hpp
interp_masm_<arch_model>.hpp assembler_<arch>.inline.hpp
@ -3094,25 +3101,26 @@ objArrayOop.cpp oop.inline.hpp
objArrayOop.hpp arrayOop.hpp
objectMonitor.cpp dtrace.hpp
objectMonitor.cpp handles.inline.hpp
objectMonitor.cpp interfaceSupport.hpp
objectMonitor.cpp markOop.hpp
objectMonitor.cpp mutexLocker.hpp
objectMonitor.cpp objectMonitor.hpp
objectMonitor.cpp objectMonitor.inline.hpp
objectMonitor.cpp oop.inline.hpp
objectMonitor.cpp osThread.hpp
objectMonitor.cpp os_<os_family>.inline.hpp
objectMonitor.cpp preserveException.hpp
objectMonitor.cpp resourceArea.hpp
objectMonitor.cpp stubRoutines.hpp
objectMonitor.cpp thread.hpp
objectMonitor.cpp thread_<os_family>.inline.hpp
objectMonitor.cpp threadService.hpp
objectMonitor.cpp vmSymbols.hpp
objectMonitor.hpp os.hpp
objectMonitor_<os_family>.cpp dtrace.hpp
objectMonitor_<os_family>.cpp interfaceSupport.hpp
objectMonitor_<os_family>.cpp objectMonitor.hpp
objectMonitor_<os_family>.cpp objectMonitor.inline.hpp
objectMonitor_<os_family>.cpp oop.inline.hpp
objectMonitor_<os_family>.cpp osThread.hpp
objectMonitor_<os_family>.cpp os_<os_family>.inline.hpp
objectMonitor_<os_family>.cpp threadService.hpp
objectMonitor_<os_family>.cpp thread_<os_family>.inline.hpp
objectMonitor_<os_family>.cpp vmSymbols.hpp
objectMonitor_<os_family>.hpp generate_platform_dependent_include
objectMonitor_<os_family>.hpp os_<os_family>.inline.hpp
objectMonitor_<os_family>.hpp thread_<os_family>.inline.hpp
objectMonitor_<os_family>.hpp top.hpp
objectMonitor_<os_family>.inline.hpp generate_platform_dependent_include
objectMonitor.hpp perfData.hpp
oop.cpp copy.hpp
oop.cpp handles.inline.hpp
@ -3231,6 +3239,7 @@ orderAccess.hpp allocation.hpp
orderAccess.hpp os.hpp
orderAccess_<os_arch>.inline.hpp orderAccess.hpp
orderAccess_<os_arch>.inline.hpp vm_version_<arch>.hpp
os.cpp allocation.inline.hpp
os.cpp arguments.hpp
@ -3328,7 +3337,6 @@ os_<os_family>.cpp mutex_<os_family>.inline.hpp
os_<os_family>.cpp nativeInst_<arch>.hpp
os_<os_family>.cpp no_precompiled_headers
os_<os_family>.cpp objectMonitor.hpp
os_<os_family>.cpp objectMonitor.inline.hpp
os_<os_family>.cpp oop.inline.hpp
os_<os_family>.cpp osThread.hpp
os_<os_family>.cpp os_share_<os_family>.hpp
@ -3388,6 +3396,12 @@ ostream.cpp xmlstream.hpp
ostream.hpp allocation.hpp
ostream.hpp timer.hpp
// include thread.hpp to prevent cyclic includes
park.cpp thread.hpp
park.hpp debug.hpp
park.hpp globalDefinitions.hpp
pcDesc.cpp debugInfoRec.hpp
pcDesc.cpp nmethod.hpp
pcDesc.cpp pcDesc.hpp
@ -3600,7 +3614,9 @@ relocInfo_<arch>.hpp generate_platform_dependent_include
relocator.cpp bytecodes.hpp
relocator.cpp handles.inline.hpp
relocator.cpp oop.inline.hpp
relocator.cpp oopFactory.hpp
relocator.cpp relocator.hpp
relocator.cpp stackMapTableFormat.hpp
relocator.cpp universe.inline.hpp
relocator.hpp bytecodes.hpp
@ -3907,6 +3923,8 @@ stackMapTable.hpp globalDefinitions.hpp
stackMapTable.hpp methodOop.hpp
stackMapTable.hpp stackMapFrame.hpp
stackMapTableFormat.hpp verificationType.hpp
stackValue.cpp debugInfo.hpp
stackValue.cpp frame.inline.hpp
stackValue.cpp handles.inline.hpp
@ -4062,10 +4080,10 @@ synchronizer.cpp preserveException.hpp
synchronizer.cpp resourceArea.hpp
synchronizer.cpp stubRoutines.hpp
synchronizer.cpp synchronizer.hpp
synchronizer.cpp threadService.hpp
synchronizer.cpp thread_<os_family>.inline.hpp
synchronizer.cpp vmSymbols.hpp
synchronizer.hpp basicLock.hpp
synchronizer.hpp handles.hpp
synchronizer.hpp markOop.hpp
synchronizer.hpp perfData.hpp
@ -4237,7 +4255,6 @@ thread.cpp memprofiler.hpp
thread.cpp mutexLocker.hpp
thread.cpp objArrayOop.hpp
thread.cpp objectMonitor.hpp
thread.cpp objectMonitor.inline.hpp
thread.cpp oop.inline.hpp
thread.cpp oopFactory.hpp
thread.cpp osThread.hpp
@ -4275,6 +4292,7 @@ thread.hpp mutexLocker.hpp
thread.hpp oop.hpp
thread.hpp os.hpp
thread.hpp osThread.hpp
thread.hpp park.hpp
thread.hpp safepoint.hpp
thread.hpp stubRoutines.hpp
thread.hpp threadLocalAllocBuffer.hpp
@ -4586,6 +4604,7 @@ vframeArray.hpp frame.inline.hpp
vframeArray.hpp growableArray.hpp
vframeArray.hpp monitorChunk.hpp
vframe_hp.cpp basicLock.hpp
vframe_hp.cpp codeCache.hpp
vframe_hp.cpp debugInfoRec.hpp
vframe_hp.cpp handles.inline.hpp
@ -4599,7 +4618,6 @@ vframe_hp.cpp pcDesc.hpp
vframe_hp.cpp scopeDesc.hpp
vframe_hp.cpp signature.hpp
vframe_hp.cpp stubRoutines.hpp
vframe_hp.cpp synchronizer.hpp
vframe_hp.cpp vframeArray.hpp
vframe_hp.cpp vframe_hp.hpp
@ -4751,6 +4769,7 @@ workgroup.cpp os.hpp
workgroup.cpp workgroup.hpp
workgroup.hpp taskqueue.hpp
workgroup.hpp thread_<os_family>.inline.hpp
xmlstream.cpp allocation.hpp

View File

@ -184,6 +184,13 @@ jvmtiImpl.hpp stackValueCollection.hpp
jvmtiImpl.hpp systemDictionary.hpp
jvmtiImpl.hpp vm_operations.hpp
jvmtiRawMonitor.cpp interfaceSupport.hpp
jvmtiRawMonitor.cpp jvmtiRawMonitor.hpp
jvmtiRawMonitor.cpp thread.hpp
jvmtiRawMonitor.hpp growableArray.hpp
jvmtiRawMonitor.hpp objectMonitor.hpp
jvmtiTagMap.cpp biasedLocking.hpp
jvmtiTagMap.cpp javaCalls.hpp
jvmtiTagMap.cpp jniHandles.hpp

View File

@ -35,6 +35,7 @@ jvmtiClassFileReconstituter.hpp jvmtiEnv.hpp
// jvmtiCodeBlobEvents is jck optional, please put deps in includeDB_features
jvmtiEnter.cpp jvmtiEnter.hpp
jvmtiEnter.cpp jvmtiRawMonitor.hpp
jvmtiEnter.cpp jvmtiUtil.hpp
jvmtiEnter.hpp interfaceSupport.hpp
@ -44,6 +45,7 @@ jvmtiEnter.hpp resourceArea.hpp
jvmtiEnter.hpp systemDictionary.hpp
jvmtiEnterTrace.cpp jvmtiEnter.hpp
jvmtiEnterTrace.cpp jvmtiRawMonitor.hpp
jvmtiEnterTrace.cpp jvmtiUtil.hpp
jvmtiEnv.cpp arguments.hpp
@ -66,11 +68,11 @@ jvmtiEnv.cpp jvmtiExtensions.hpp
jvmtiEnv.cpp jvmtiGetLoadedClasses.hpp
jvmtiEnv.cpp jvmtiImpl.hpp
jvmtiEnv.cpp jvmtiManageCapabilities.hpp
jvmtiEnv.cpp jvmtiRawMonitor.hpp
jvmtiEnv.cpp jvmtiRedefineClasses.hpp
jvmtiEnv.cpp jvmtiTagMap.hpp
jvmtiEnv.cpp jvmtiThreadState.inline.hpp
jvmtiEnv.cpp jvmtiUtil.hpp
jvmtiEnv.cpp objectMonitor.inline.hpp
jvmtiEnv.cpp osThread.hpp
jvmtiEnv.cpp preserveException.hpp
jvmtiEnv.cpp reflectionUtils.hpp
@ -178,11 +180,13 @@ jvmtiExport.cpp jvmtiEventController.inline.hpp
jvmtiExport.cpp jvmtiExport.hpp
jvmtiExport.cpp jvmtiImpl.hpp
jvmtiExport.cpp jvmtiManageCapabilities.hpp
jvmtiExport.cpp jvmtiRawMonitor.hpp
jvmtiExport.cpp jvmtiTagMap.hpp
jvmtiExport.cpp jvmtiThreadState.inline.hpp
jvmtiExport.cpp nmethod.hpp
jvmtiExport.cpp objArrayKlass.hpp
jvmtiExport.cpp objArrayOop.hpp
jvmtiExport.cpp objectMonitor.hpp
jvmtiExport.cpp objectMonitor.inline.hpp
jvmtiExport.cpp pcDesc.hpp
jvmtiExport.cpp resourceArea.hpp
@ -210,6 +214,8 @@ jvmtiManageCapabilities.cpp jvmtiManageCapabilities.hpp
jvmtiManageCapabilities.hpp allocation.hpp
jvmtiManageCapabilities.hpp jvmti.h
// jvmtiRawMonitor is jck optional, please put deps in includeDB_features
jvmtiRedefineClasses.cpp bitMap.inline.hpp
jvmtiRedefineClasses.cpp codeCache.hpp
jvmtiRedefineClasses.cpp deoptimization.hpp

View File

@ -659,9 +659,6 @@ HeapWord* GenCollectorPolicy::satisfy_failed_allocation(size_t size,
}
return result; // could be null if we are out of space
} else if (!gch->incremental_collection_will_fail()) {
// The gc_prologues have not executed yet. The value
// for incremental_collection_will_fail() is the remanent
// of the last collection.
// Do an incremental collection.
gch->do_collection(false /* full */,
false /* clear_all_soft_refs */,
@ -739,9 +736,8 @@ bool GenCollectorPolicy::should_try_older_generation_allocation(
GenCollectedHeap* gch = GenCollectedHeap::heap();
size_t gen0_capacity = gch->get_gen(0)->capacity_before_gc();
return (word_size > heap_word_size(gen0_capacity))
|| (GC_locker::is_active_and_needs_gc())
|| ( gch->last_incremental_collection_failed()
&& gch->incremental_collection_will_fail());
|| GC_locker::is_active_and_needs_gc()
|| gch->incremental_collection_failed();
}

View File

@ -510,7 +510,7 @@ void DefNewGeneration::collect(bool full,
// from this generation, pass on collection; let the next generation
// do it.
if (!collection_attempt_is_safe()) {
gch->set_incremental_collection_will_fail();
gch->set_incremental_collection_failed(); // Slight lie: we did not even attempt one
return;
}
assert(to()->is_empty(), "Else not collection_attempt_is_safe");
@ -596,9 +596,8 @@ void DefNewGeneration::collect(bool full,
if (PrintGC && !PrintGCDetails) {
gch->print_heap_change(gch_prev_used);
}
assert(!gch->incremental_collection_failed(), "Should be clear");
} else {
assert(HandlePromotionFailure,
"Should not be here unless promotion failure handling is on");
assert(_promo_failure_scan_stack.is_empty(), "post condition");
_promo_failure_scan_stack.clear(true); // Clear cached segments.
@ -613,7 +612,7 @@ void DefNewGeneration::collect(bool full,
// and from-space.
swap_spaces(); // For uniformity wrt ParNewGeneration.
from()->set_next_compaction_space(to());
gch->set_incremental_collection_will_fail();
gch->set_incremental_collection_failed();
// Inform the next generation that a promotion failure occurred.
_next_gen->promotion_failure_occurred();
@ -700,12 +699,6 @@ oop DefNewGeneration::copy_to_survivor_space(oop old) {
if (obj == NULL) {
obj = _next_gen->promote(old, s);
if (obj == NULL) {
if (!HandlePromotionFailure) {
// A failed promotion likely means the MaxLiveObjectEvacuationRatio flag
// is incorrectly set. In any case, its seriously wrong to be here!
vm_exit_out_of_memory(s*wordSize, "promotion");
}
handle_promotion_failure(old);
return old;
}
@ -812,47 +805,43 @@ bool DefNewGeneration::collection_attempt_is_safe() {
assert(_next_gen != NULL,
"This must be the youngest gen, and not the only gen");
}
// Decide if there's enough room for a full promotion
// When using extremely large edens, we effectively lose a
// large amount of old space. Use the "MaxLiveObjectEvacuationRatio"
// flag to reduce the minimum evacuation space requirements. If
// there is not enough space to evacuate eden during a scavenge,
// the VM will immediately exit with an out of memory error.
// This flag has not been tested
// with collectors other than simple mark & sweep.
//
// Note that with the addition of promotion failure handling, the
// VM will not immediately exit but will undo the young generation
// collection. The parameter is left here for compatibility.
const double evacuation_ratio = MaxLiveObjectEvacuationRatio / 100.0;
// worst_case_evacuation is based on "used()". For the case where this
// method is called after a collection, this is still appropriate because
// the case that needs to be detected is one in which a full collection
// has been done and has overflowed into the young generation. In that
// case a minor collection will fail (the overflow of the full collection
// means there is no space in the old generation for any promotion).
size_t worst_case_evacuation = (size_t)(used() * evacuation_ratio);
return _next_gen->promotion_attempt_is_safe(worst_case_evacuation,
HandlePromotionFailure);
return _next_gen->promotion_attempt_is_safe(used());
}
void DefNewGeneration::gc_epilogue(bool full) {
DEBUG_ONLY(static bool seen_incremental_collection_failed = false;)
assert(!GC_locker::is_active(), "We should not be executing here");
// Check if the heap is approaching full after a collection has
// been done. Generally the young generation is empty at
// a minimum at the end of a collection. If it is not, then
// the heap is approaching full.
GenCollectedHeap* gch = GenCollectedHeap::heap();
clear_should_allocate_from_space();
if (collection_attempt_is_safe()) {
gch->clear_incremental_collection_will_fail();
} else {
gch->set_incremental_collection_will_fail();
if (full) { // we seem to be running out of space
set_should_allocate_from_space();
if (full) {
DEBUG_ONLY(seen_incremental_collection_failed = false;)
if (!collection_attempt_is_safe()) {
gch->set_incremental_collection_failed(); // Slight lie: a full gc left us in that state
set_should_allocate_from_space(); // we seem to be running out of space
} else {
gch->clear_incremental_collection_failed(); // We just did a full collection
clear_should_allocate_from_space(); // if set
}
} else {
#ifdef ASSERT
// It is possible that incremental_collection_failed() == true
// here, because an attempted scavenge did not succeed. The policy
// is normally expected to cause a full collection which should
// clear that condition, so we should not be here twice in a row
// with incremental_collection_failed() == true without having done
// a full collection in between.
if (!seen_incremental_collection_failed &&
gch->incremental_collection_failed()) {
seen_incremental_collection_failed = true;
} else if (seen_incremental_collection_failed) {
assert(!gch->incremental_collection_failed(), "Twice in a row");
seen_incremental_collection_failed = false;
}
#endif // ASSERT
}
if (ZapUnusedHeapArea) {

View File

@ -82,12 +82,6 @@ protected:
Stack<oop> _objs_with_preserved_marks;
Stack<markOop> _preserved_marks_of_objs;
// Returns true if the collection can be safely attempted.
// If this method returns false, a collection is not
// guaranteed to fail but the system may not be able
// to recover from the failure.
bool collection_attempt_is_safe();
// Promotion failure handling
OopClosure *_promo_failure_scan_stack_closure;
void set_promo_failure_scan_stack_closure(OopClosure *scan_stack_closure) {
@ -304,6 +298,14 @@ protected:
// GC support
virtual void compute_new_size();
// Returns true if the collection is likely to be safely
// completed. Even if this method returns true, a collection
// may not be guaranteed to succeed, and the system should be
// able to safely unwind and recover from that failure, albeit
// at some additional cost. Override superclass's implementation.
virtual bool collection_attempt_is_safe();
virtual void collect(bool full,
bool clear_all_soft_refs,
size_t size,

View File

@ -142,8 +142,7 @@ jint GenCollectedHeap::initialize() {
}
_perm_gen = perm_gen_spec->init(heap_rs, PermSize, rem_set());
clear_incremental_collection_will_fail();
clear_last_incremental_collection_failed();
clear_incremental_collection_failed();
#ifndef SERIALGC
// If we are running CMS, create the collector responsible
@ -1347,17 +1346,6 @@ class GenGCEpilogueClosure: public GenCollectedHeap::GenClosure {
};
void GenCollectedHeap::gc_epilogue(bool full) {
// Remember if a partial collection of the heap failed, and
// we did a complete collection.
if (full && incremental_collection_will_fail()) {
set_last_incremental_collection_failed();
} else {
clear_last_incremental_collection_failed();
}
// Clear the flag, if set; the generation gc_epilogues will set the
// flag again if the condition persists despite the collection.
clear_incremental_collection_will_fail();
#ifdef COMPILER2
assert(DerivedPointerTable::is_empty(), "derived pointer present");
size_t actual_gap = pointer_delta((HeapWord*) (max_uintx-3), *(end_addr()));

View File

@ -62,11 +62,10 @@ public:
// The generational collector policy.
GenCollectorPolicy* _gen_policy;
// If a generation would bail out of an incremental collection,
// it sets this flag. If the flag is set, satisfy_failed_allocation
// will attempt allocating in all generations before doing a full GC.
bool _incremental_collection_will_fail;
bool _last_incremental_collection_failed;
// Indicates that the most recent previous incremental collection failed.
// The flag is cleared when an action is taken that might clear the
// condition that caused that incremental collection to fail.
bool _incremental_collection_failed;
// In support of ExplicitGCInvokesConcurrent functionality
unsigned int _full_collections_completed;
@ -469,26 +468,26 @@ public:
// call to "save_marks".
bool no_allocs_since_save_marks(int level);
// If a generation bails out of an incremental collection,
// it sets this flag.
// Returns true if an incremental collection is likely to fail.
bool incremental_collection_will_fail() {
return _incremental_collection_will_fail;
}
void set_incremental_collection_will_fail() {
_incremental_collection_will_fail = true;
}
void clear_incremental_collection_will_fail() {
_incremental_collection_will_fail = false;
// Assumes a 2-generation system; the first disjunct remembers if an
// incremental collection failed, even when we thought (second disjunct)
// that it would not.
assert(heap()->collector_policy()->is_two_generation_policy(),
"the following definition may not be suitable for an n(>2)-generation system");
return incremental_collection_failed() || !get_gen(0)->collection_attempt_is_safe();
}
bool last_incremental_collection_failed() const {
return _last_incremental_collection_failed;
// If a generation bails out of an incremental collection,
// it sets this flag.
bool incremental_collection_failed() const {
return _incremental_collection_failed;
}
void set_last_incremental_collection_failed() {
_last_incremental_collection_failed = true;
void set_incremental_collection_failed() {
_incremental_collection_failed = true;
}
void clear_last_incremental_collection_failed() {
_last_incremental_collection_failed = false;
void clear_incremental_collection_failed() {
_incremental_collection_failed = false;
}
// Promotion of obj into gen failed. Try to promote obj to higher non-perm

View File

@ -165,15 +165,16 @@ size_t Generation::max_contiguous_available() const {
return max;
}
bool Generation::promotion_attempt_is_safe(size_t promotion_in_bytes,
bool not_used) const {
bool Generation::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const {
size_t available = max_contiguous_available();
bool res = (available >= max_promotion_in_bytes);
if (PrintGC && Verbose) {
gclog_or_tty->print_cr("Generation::promotion_attempt_is_safe"
" contiguous_available: " SIZE_FORMAT
" promotion_in_bytes: " SIZE_FORMAT,
max_contiguous_available(), promotion_in_bytes);
gclog_or_tty->print_cr(
"Generation: promo attempt is%s safe: available("SIZE_FORMAT") %s max_promo("SIZE_FORMAT")",
res? "":" not", available, res? ">=":"<",
max_promotion_in_bytes);
}
return max_contiguous_available() >= promotion_in_bytes;
return res;
}
// Ignores "ref" and calls allocate().

View File

@ -173,15 +173,11 @@ class Generation: public CHeapObj {
// The largest number of contiguous free bytes in this or any higher generation.
virtual size_t max_contiguous_available() const;
// Returns true if promotions of the specified amount can
// be attempted safely (without a vm failure).
// Returns true if promotions of the specified amount are
// likely to succeed without a promotion failure.
// Promotion of the full amount is not guaranteed but
// can be attempted.
// younger_handles_promotion_failure
// is true if the younger generation handles a promotion
// failure.
virtual bool promotion_attempt_is_safe(size_t promotion_in_bytes,
bool younger_handles_promotion_failure) const;
// might be attempted in the worst case.
virtual bool promotion_attempt_is_safe(size_t max_promotion_in_bytes) const;
// For a non-young generation, this interface can be used to inform a
// generation that a promotion attempt into that generation failed.
@ -358,6 +354,16 @@ class Generation: public CHeapObj {
return (full || should_allocate(word_size, is_tlab));
}
// Returns true if the collection is likely to be safely
// completed. Even if this method returns true, a collection
// may not be guaranteed to succeed, and the system should be
// able to safely unwind and recover from that failure, albeit
// at some additional cost.
virtual bool collection_attempt_is_safe() {
guarantee(false, "Are you sure you want to call this method?");
return true;
}
// Perform a garbage collection.
// If full is true attempt a full garbage collection of this generation.
// Otherwise, attempting to (at least) free enough space to support an

View File

@ -419,29 +419,16 @@ void TenuredGeneration::retire_alloc_buffers_before_full_gc() {}
void TenuredGeneration::verify_alloc_buffers_clean() {}
#endif // SERIALGC
bool TenuredGeneration::promotion_attempt_is_safe(
size_t max_promotion_in_bytes,
bool younger_handles_promotion_failure) const {
bool result = max_contiguous_available() >= max_promotion_in_bytes;
if (younger_handles_promotion_failure && !result) {
result = max_contiguous_available() >=
(size_t) gc_stats()->avg_promoted()->padded_average();
if (PrintGC && Verbose && result) {
gclog_or_tty->print_cr("TenuredGeneration::promotion_attempt_is_safe"
" contiguous_available: " SIZE_FORMAT
" avg_promoted: " SIZE_FORMAT,
max_contiguous_available(),
gc_stats()->avg_promoted()->padded_average());
}
} else {
if (PrintGC && Verbose) {
gclog_or_tty->print_cr("TenuredGeneration::promotion_attempt_is_safe"
" contiguous_available: " SIZE_FORMAT
" promotion_in_bytes: " SIZE_FORMAT,
max_contiguous_available(), max_promotion_in_bytes);
}
bool TenuredGeneration::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const {
size_t available = max_contiguous_available();
size_t av_promo = (size_t)gc_stats()->avg_promoted()->padded_average();
bool res = (available >= av_promo) || (available >= max_promotion_in_bytes);
if (PrintGC && Verbose) {
gclog_or_tty->print_cr(
"Tenured: promo attempt is%s safe: available("SIZE_FORMAT") %s av_promo("SIZE_FORMAT"),"
"max_promo("SIZE_FORMAT")",
res? "":" not", available, res? ">=":"<",
av_promo, max_promotion_in_bytes);
}
return result;
return res;
}

View File

@ -101,8 +101,7 @@ class TenuredGeneration: public OneContigSpaceCardGeneration {
virtual void update_gc_stats(int level, bool full);
virtual bool promotion_attempt_is_safe(size_t max_promoted_in_bytes,
bool younger_handles_promotion_failure) const;
virtual bool promotion_attempt_is_safe(size_t max_promoted_in_bytes) const;
void verify_alloc_buffers_clean();
};

View File

@ -247,6 +247,10 @@ class methodOopDesc : public oopDesc {
return constMethod()->stackmap_data();
}
void set_stackmap_data(typeArrayOop sd) {
constMethod()->set_stackmap_data(sd);
}
// exception handler table
typeArrayOop exception_table() const
{ return constMethod()->exception_table(); }

View File

@ -25,26 +25,6 @@
# include "incls/_precompiled.incl"
# include "incls/_jvmtiImpl.cpp.incl"
GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP) GrowableArray<JvmtiRawMonitor*>(1,true);
void JvmtiPendingMonitors::transition_raw_monitors() {
assert((Threads::number_of_threads()==1),
"Java thread has not created yet or more than one java thread \
is running. Raw monitor transition will not work");
JavaThread *current_java_thread = JavaThread::current();
assert(current_java_thread->thread_state() == _thread_in_vm, "Must be in vm");
{
ThreadBlockInVM __tbivm(current_java_thread);
for(int i=0; i< count(); i++) {
JvmtiRawMonitor *rmonitor = monitors()->at(i);
int r = rmonitor->raw_enter(current_java_thread);
assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked");
}
}
// pending monitors are converted to real monitor so delete them all.
dispose();
}
//
// class JvmtiAgentThread
//
@ -216,57 +196,6 @@ void GrowableCache::gc_epilogue() {
}
}
//
// class JvmtiRawMonitor
//
JvmtiRawMonitor::JvmtiRawMonitor(const char *name) {
#ifdef ASSERT
_name = strcpy(NEW_C_HEAP_ARRAY(char, strlen(name) + 1), name);
#else
_name = NULL;
#endif
_magic = JVMTI_RM_MAGIC;
}
JvmtiRawMonitor::~JvmtiRawMonitor() {
#ifdef ASSERT
FreeHeap(_name);
#endif
_magic = 0;
}
bool
JvmtiRawMonitor::is_valid() {
int value = 0;
// This object might not be a JvmtiRawMonitor so we can't assume
// the _magic field is properly aligned. Get the value in a safe
// way and then check against JVMTI_RM_MAGIC.
switch (sizeof(_magic)) {
case 2:
value = Bytes::get_native_u2((address)&_magic);
break;
case 4:
value = Bytes::get_native_u4((address)&_magic);
break;
case 8:
value = Bytes::get_native_u8((address)&_magic);
break;
default:
guarantee(false, "_magic field is an unexpected size");
}
return value == JVMTI_RM_MAGIC;
}
//
// class JvmtiBreakpoint
//

View File

@ -26,7 +26,6 @@
// Forward Declarations
//
class JvmtiRawMonitor;
class JvmtiBreakpoint;
class JvmtiBreakpoints;
@ -327,76 +326,6 @@ bool JvmtiCurrentBreakpoints::is_breakpoint(address bcp) {
return false;
}
///////////////////////////////////////////////////////////////
//
// class JvmtiRawMonitor
//
// Used by JVMTI methods: All RawMonitor methods (CreateRawMonitor, EnterRawMonitor, etc.)
//
// Wrapper for ObjectMonitor class that saves the Monitor's name
//
class JvmtiRawMonitor : public ObjectMonitor {
private:
int _magic;
char * _name;
// JVMTI_RM_MAGIC is set in contructor and unset in destructor.
enum { JVMTI_RM_MAGIC = (int)(('T' << 24) | ('I' << 16) | ('R' << 8) | 'M') };
public:
JvmtiRawMonitor(const char *name);
~JvmtiRawMonitor();
int magic() { return _magic; }
const char *get_name() { return _name; }
bool is_valid();
};
// Onload pending raw monitors
// Class is used to cache onload or onstart monitor enter
// which will transition into real monitor when
// VM is fully initialized.
class JvmtiPendingMonitors : public AllStatic {
private:
static GrowableArray<JvmtiRawMonitor*> *_monitors; // Cache raw monitor enter
inline static GrowableArray<JvmtiRawMonitor*>* monitors() { return _monitors; }
static void dispose() {
delete monitors();
}
public:
static void enter(JvmtiRawMonitor *monitor) {
monitors()->append(monitor);
}
static int count() {
return monitors()->length();
}
static void destroy(JvmtiRawMonitor *monitor) {
while (monitors()->contains(monitor)) {
monitors()->remove(monitor);
}
}
// Return false if monitor is not found in the list.
static bool exit(JvmtiRawMonitor *monitor) {
if (monitors()->contains(monitor)) {
monitors()->remove(monitor);
return true;
} else {
return false;
}
}
static void transition_raw_monitors();
};
///////////////////////////////////////////////////////////////
// The get/set local operations must only be done by the VM thread
// because the interpreter version needs to access oop maps, which can

View File

@ -0,0 +1,420 @@
/*
* Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
# include "incls/_precompiled.incl"
# include "incls/_jvmtiRawMonitor.cpp.incl"
GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP) GrowableArray<JvmtiRawMonitor*>(1,true);
void JvmtiPendingMonitors::transition_raw_monitors() {
assert((Threads::number_of_threads()==1),
"Java thread has not created yet or more than one java thread \
is running. Raw monitor transition will not work");
JavaThread *current_java_thread = JavaThread::current();
assert(current_java_thread->thread_state() == _thread_in_vm, "Must be in vm");
{
ThreadBlockInVM __tbivm(current_java_thread);
for(int i=0; i< count(); i++) {
JvmtiRawMonitor *rmonitor = monitors()->at(i);
int r = rmonitor->raw_enter(current_java_thread);
assert(r == ObjectMonitor::OM_OK, "raw_enter should have worked");
}
}
// pending monitors are converted to real monitor so delete them all.
dispose();
}
//
// class JvmtiRawMonitor
//
JvmtiRawMonitor::JvmtiRawMonitor(const char *name) {
#ifdef ASSERT
_name = strcpy(NEW_C_HEAP_ARRAY(char, strlen(name) + 1), name);
#else
_name = NULL;
#endif
_magic = JVMTI_RM_MAGIC;
}
JvmtiRawMonitor::~JvmtiRawMonitor() {
#ifdef ASSERT
FreeHeap(_name);
#endif
_magic = 0;
}
bool
JvmtiRawMonitor::is_valid() {
int value = 0;
// This object might not be a JvmtiRawMonitor so we can't assume
// the _magic field is properly aligned. Get the value in a safe
// way and then check against JVMTI_RM_MAGIC.
switch (sizeof(_magic)) {
case 2:
value = Bytes::get_native_u2((address)&_magic);
break;
case 4:
value = Bytes::get_native_u4((address)&_magic);
break;
case 8:
value = Bytes::get_native_u8((address)&_magic);
break;
default:
guarantee(false, "_magic field is an unexpected size");
}
return value == JVMTI_RM_MAGIC;
}
// -------------------------------------------------------------------------
// The raw monitor subsystem is entirely distinct from normal
// java-synchronization or jni-synchronization. raw monitors are not
// associated with objects. They can be implemented in any manner
// that makes sense. The original implementors decided to piggy-back
// the raw-monitor implementation on the existing Java objectMonitor mechanism.
// This flaw needs to fixed. We should reimplement raw monitors as sui-generis.
// Specifically, we should not implement raw monitors via java monitors.
// Time permitting, we should disentangle and deconvolve the two implementations
// and move the resulting raw monitor implementation over to the JVMTI directories.
// Ideally, the raw monitor implementation would be built on top of
// park-unpark and nothing else.
//
// raw monitors are used mainly by JVMTI
// The raw monitor implementation borrows the ObjectMonitor structure,
// but the operators are degenerate and extremely simple.
//
// Mixed use of a single objectMonitor instance -- as both a raw monitor
// and a normal java monitor -- is not permissible.
//
// Note that we use the single RawMonitor_lock to protect queue operations for
// _all_ raw monitors. This is a scalability impediment, but since raw monitor usage
// is deprecated and rare, this is not of concern. The RawMonitor_lock can not
// be held indefinitely. The critical sections must be short and bounded.
//
// -------------------------------------------------------------------------
int JvmtiRawMonitor::SimpleEnter (Thread * Self) {
for (;;) {
if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
return OS_OK ;
}
ObjectWaiter Node (Self) ;
Self->_ParkEvent->reset() ; // strictly optional
Node.TState = ObjectWaiter::TS_ENTER ;
RawMonitor_lock->lock_without_safepoint_check() ;
Node._next = _EntryList ;
_EntryList = &Node ;
OrderAccess::fence() ;
if (_owner == NULL && Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
_EntryList = Node._next ;
RawMonitor_lock->unlock() ;
return OS_OK ;
}
RawMonitor_lock->unlock() ;
while (Node.TState == ObjectWaiter::TS_ENTER) {
Self->_ParkEvent->park() ;
}
}
}
int JvmtiRawMonitor::SimpleExit (Thread * Self) {
guarantee (_owner == Self, "invariant") ;
OrderAccess::release_store_ptr (&_owner, NULL) ;
OrderAccess::fence() ;
if (_EntryList == NULL) return OS_OK ;
ObjectWaiter * w ;
RawMonitor_lock->lock_without_safepoint_check() ;
w = _EntryList ;
if (w != NULL) {
_EntryList = w->_next ;
}
RawMonitor_lock->unlock() ;
if (w != NULL) {
guarantee (w ->TState == ObjectWaiter::TS_ENTER, "invariant") ;
ParkEvent * ev = w->_event ;
w->TState = ObjectWaiter::TS_RUN ;
OrderAccess::fence() ;
ev->unpark() ;
}
return OS_OK ;
}
int JvmtiRawMonitor::SimpleWait (Thread * Self, jlong millis) {
guarantee (_owner == Self , "invariant") ;
guarantee (_recursions == 0, "invariant") ;
ObjectWaiter Node (Self) ;
Node._notified = 0 ;
Node.TState = ObjectWaiter::TS_WAIT ;
RawMonitor_lock->lock_without_safepoint_check() ;
Node._next = _WaitSet ;
_WaitSet = &Node ;
RawMonitor_lock->unlock() ;
SimpleExit (Self) ;
guarantee (_owner != Self, "invariant") ;
int ret = OS_OK ;
if (millis <= 0) {
Self->_ParkEvent->park();
} else {
ret = Self->_ParkEvent->park(millis);
}
// If thread still resides on the waitset then unlink it.
// Double-checked locking -- the usage is safe in this context
// as we TState is volatile and the lock-unlock operators are
// serializing (barrier-equivalent).
if (Node.TState == ObjectWaiter::TS_WAIT) {
RawMonitor_lock->lock_without_safepoint_check() ;
if (Node.TState == ObjectWaiter::TS_WAIT) {
// Simple O(n) unlink, but performance isn't critical here.
ObjectWaiter * p ;
ObjectWaiter * q = NULL ;
for (p = _WaitSet ; p != &Node; p = p->_next) {
q = p ;
}
guarantee (p == &Node, "invariant") ;
if (q == NULL) {
guarantee (p == _WaitSet, "invariant") ;
_WaitSet = p->_next ;
} else {
guarantee (p == q->_next, "invariant") ;
q->_next = p->_next ;
}
Node.TState = ObjectWaiter::TS_RUN ;
}
RawMonitor_lock->unlock() ;
}
guarantee (Node.TState == ObjectWaiter::TS_RUN, "invariant") ;
SimpleEnter (Self) ;
guarantee (_owner == Self, "invariant") ;
guarantee (_recursions == 0, "invariant") ;
return ret ;
}
int JvmtiRawMonitor::SimpleNotify (Thread * Self, bool All) {
guarantee (_owner == Self, "invariant") ;
if (_WaitSet == NULL) return OS_OK ;
// We have two options:
// A. Transfer the threads from the WaitSet to the EntryList
// B. Remove the thread from the WaitSet and unpark() it.
//
// We use (B), which is crude and results in lots of futile
// context switching. In particular (B) induces lots of contention.
ParkEvent * ev = NULL ; // consider using a small auto array ...
RawMonitor_lock->lock_without_safepoint_check() ;
for (;;) {
ObjectWaiter * w = _WaitSet ;
if (w == NULL) break ;
_WaitSet = w->_next ;
if (ev != NULL) { ev->unpark(); ev = NULL; }
ev = w->_event ;
OrderAccess::loadstore() ;
w->TState = ObjectWaiter::TS_RUN ;
OrderAccess::storeload();
if (!All) break ;
}
RawMonitor_lock->unlock() ;
if (ev != NULL) ev->unpark();
return OS_OK ;
}
// Any JavaThread will enter here with state _thread_blocked
int JvmtiRawMonitor::raw_enter(TRAPS) {
TEVENT (raw_enter) ;
void * Contended ;
// don't enter raw monitor if thread is being externally suspended, it will
// surprise the suspender if a "suspended" thread can still enter monitor
JavaThread * jt = (JavaThread *)THREAD;
if (THREAD->is_Java_thread()) {
jt->SR_lock()->lock_without_safepoint_check();
while (jt->is_external_suspend()) {
jt->SR_lock()->unlock();
jt->java_suspend_self();
jt->SR_lock()->lock_without_safepoint_check();
}
// guarded by SR_lock to avoid racing with new external suspend requests.
Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;
jt->SR_lock()->unlock();
} else {
Contended = Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) ;
}
if (Contended == THREAD) {
_recursions ++ ;
return OM_OK ;
}
if (Contended == NULL) {
guarantee (_owner == THREAD, "invariant") ;
guarantee (_recursions == 0, "invariant") ;
return OM_OK ;
}
THREAD->set_current_pending_monitor(this);
if (!THREAD->is_Java_thread()) {
// No other non-Java threads besides VM thread would acquire
// a raw monitor.
assert(THREAD->is_VM_thread(), "must be VM thread");
SimpleEnter (THREAD) ;
} else {
guarantee (jt->thread_state() == _thread_blocked, "invariant") ;
for (;;) {
jt->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or
// java_suspend_self()
SimpleEnter (THREAD) ;
// were we externally suspended while we were waiting?
if (!jt->handle_special_suspend_equivalent_condition()) break ;
// This thread was externally suspended
//
// This logic isn't needed for JVMTI raw monitors,
// but doesn't hurt just in case the suspend rules change. This
// logic is needed for the JvmtiRawMonitor.wait() reentry phase.
// We have reentered the contended monitor, but while we were
// waiting another thread suspended us. We don't want to reenter
// the monitor while suspended because that would surprise the
// thread that suspended us.
//
// Drop the lock -
SimpleExit (THREAD) ;
jt->java_suspend_self();
}
assert(_owner == THREAD, "Fatal error with monitor owner!");
assert(_recursions == 0, "Fatal error with monitor recursions!");
}
THREAD->set_current_pending_monitor(NULL);
guarantee (_recursions == 0, "invariant") ;
return OM_OK;
}
// Used mainly for JVMTI raw monitor implementation
// Also used for JvmtiRawMonitor::wait().
int JvmtiRawMonitor::raw_exit(TRAPS) {
TEVENT (raw_exit) ;
if (THREAD != _owner) {
return OM_ILLEGAL_MONITOR_STATE;
}
if (_recursions > 0) {
--_recursions ;
return OM_OK ;
}
void * List = _EntryList ;
SimpleExit (THREAD) ;
return OM_OK;
}
// Used for JVMTI raw monitor implementation.
// All JavaThreads will enter here with state _thread_blocked
int JvmtiRawMonitor::raw_wait(jlong millis, bool interruptible, TRAPS) {
TEVENT (raw_wait) ;
if (THREAD != _owner) {
return OM_ILLEGAL_MONITOR_STATE;
}
// To avoid spurious wakeups we reset the parkevent -- This is strictly optional.
// The caller must be able to tolerate spurious returns from raw_wait().
THREAD->_ParkEvent->reset() ;
OrderAccess::fence() ;
// check interrupt event
if (interruptible && Thread::is_interrupted(THREAD, true)) {
return OM_INTERRUPTED;
}
intptr_t save = _recursions ;
_recursions = 0 ;
_waiters ++ ;
if (THREAD->is_Java_thread()) {
guarantee (((JavaThread *) THREAD)->thread_state() == _thread_blocked, "invariant") ;
((JavaThread *)THREAD)->set_suspend_equivalent();
}
int rv = SimpleWait (THREAD, millis) ;
_recursions = save ;
_waiters -- ;
guarantee (THREAD == _owner, "invariant") ;
if (THREAD->is_Java_thread()) {
JavaThread * jSelf = (JavaThread *) THREAD ;
for (;;) {
if (!jSelf->handle_special_suspend_equivalent_condition()) break ;
SimpleExit (THREAD) ;
jSelf->java_suspend_self();
SimpleEnter (THREAD) ;
jSelf->set_suspend_equivalent() ;
}
}
guarantee (THREAD == _owner, "invariant") ;
if (interruptible && Thread::is_interrupted(THREAD, true)) {
return OM_INTERRUPTED;
}
return OM_OK ;
}
int JvmtiRawMonitor::raw_notify(TRAPS) {
TEVENT (raw_notify) ;
if (THREAD != _owner) {
return OM_ILLEGAL_MONITOR_STATE;
}
SimpleNotify (THREAD, false) ;
return OM_OK;
}
int JvmtiRawMonitor::raw_notifyAll(TRAPS) {
TEVENT (raw_notifyAll) ;
if (THREAD != _owner) {
return OM_ILLEGAL_MONITOR_STATE;
}
SimpleNotify (THREAD, true) ;
return OM_OK;
}

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
//
// class JvmtiRawMonitor
//
// Used by JVMTI methods: All RawMonitor methods (CreateRawMonitor, EnterRawMonitor, etc.)
//
// Wrapper for ObjectMonitor class that saves the Monitor's name
//
class JvmtiRawMonitor : public ObjectMonitor {
private:
int _magic;
char * _name;
// JVMTI_RM_MAGIC is set in contructor and unset in destructor.
enum { JVMTI_RM_MAGIC = (int)(('T' << 24) | ('I' << 16) | ('R' << 8) | 'M') };
int SimpleEnter (Thread * Self) ;
int SimpleExit (Thread * Self) ;
int SimpleWait (Thread * Self, jlong millis) ;
int SimpleNotify (Thread * Self, bool All) ;
public:
JvmtiRawMonitor(const char *name);
~JvmtiRawMonitor();
int raw_enter(TRAPS);
int raw_exit(TRAPS);
int raw_wait(jlong millis, bool interruptable, TRAPS);
int raw_notify(TRAPS);
int raw_notifyAll(TRAPS);
int magic() { return _magic; }
const char *get_name() { return _name; }
bool is_valid();
};
// Onload pending raw monitors
// Class is used to cache onload or onstart monitor enter
// which will transition into real monitor when
// VM is fully initialized.
class JvmtiPendingMonitors : public AllStatic {
private:
static GrowableArray<JvmtiRawMonitor*> *_monitors; // Cache raw monitor enter
inline static GrowableArray<JvmtiRawMonitor*>* monitors() { return _monitors; }
static void dispose() {
delete monitors();
}
public:
static void enter(JvmtiRawMonitor *monitor) {
monitors()->append(monitor);
}
static int count() {
return monitors()->length();
}
static void destroy(JvmtiRawMonitor *monitor) {
while (monitors()->contains(monitor)) {
monitors()->remove(monitor);
}
}
// Return false if monitor is not found in the list.
static bool exit(JvmtiRawMonitor *monitor) {
if (monitors()->contains(monitor)) {
monitors()->remove(monitor);
return true;
} else {
return false;
}
}
static void transition_raw_monitors();
};

View File

@ -119,11 +119,8 @@ void Arguments::init_system_properties() {
PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.version", "1.0", false));
PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.name",
"Java Virtual Machine Specification", false));
PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.vendor",
JDK_Version::is_gte_jdk17x_version() ? "Oracle Corporation" : "Sun Microsystems Inc.", false));
PropertyList_add(&_system_properties, new SystemProperty("java.vm.version", VM_Version::vm_release(), false));
PropertyList_add(&_system_properties, new SystemProperty("java.vm.name", VM_Version::vm_name(), false));
PropertyList_add(&_system_properties, new SystemProperty("java.vm.vendor", VM_Version::vm_vendor(), false));
PropertyList_add(&_system_properties, new SystemProperty("java.vm.info", VM_Version::vm_info_string(), true));
// following are JVMTI agent writeable properties.
@ -151,6 +148,14 @@ void Arguments::init_system_properties() {
os::init_system_properties_values();
}
// Update/Initialize System properties after JDK version number is known
void Arguments::init_version_specific_system_properties() {
PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.vendor",
JDK_Version::is_gte_jdk17x_version() ? "Oracle Corporation" : "Sun Microsystems Inc.", false));
PropertyList_add(&_system_properties, new SystemProperty("java.vm.vendor", VM_Version::vm_vendor(), false));
}
/**
* Provide a slightly more user-friendly way of eliminating -XX flags.
* When a flag is eliminated, it can be added to this list in order to
@ -185,6 +190,10 @@ static ObsoleteFlag obsolete_jvm_flags[] = {
JDK_Version::jdk_update(6,18), JDK_Version::jdk(7) },
{ "UseDepthFirstScavengeOrder",
JDK_Version::jdk_update(6,22), JDK_Version::jdk(7) },
{ "HandlePromotionFailure",
JDK_Version::jdk_update(6,24), JDK_Version::jdk(8) },
{ "MaxLiveObjectEvacuationRatio",
JDK_Version::jdk_update(6,24), JDK_Version::jdk(8) },
{ NULL, JDK_Version(0), JDK_Version(0) }
};
@ -948,26 +957,65 @@ static void no_shared_spaces() {
}
}
void Arguments::check_compressed_oops_compat() {
#ifdef _LP64
assert(UseCompressedOops, "Precondition");
# if defined(COMPILER1) && !defined(TIERED)
// Until c1 supports compressed oops turn them off.
FLAG_SET_DEFAULT(UseCompressedOops, false);
# else
// Is it on by default or set on ergonomically
bool is_on_by_default = FLAG_IS_DEFAULT(UseCompressedOops) || FLAG_IS_ERGO(UseCompressedOops);
// Tiered currently doesn't work with compressed oops
if (TieredCompilation) {
if (is_on_by_default) {
FLAG_SET_DEFAULT(UseCompressedOops, false);
return;
} else {
vm_exit_during_initialization(
"Tiered compilation is not supported with compressed oops yet", NULL);
}
}
// XXX JSR 292 currently does not support compressed oops
if (EnableMethodHandles) {
if (is_on_by_default) {
FLAG_SET_DEFAULT(UseCompressedOops, false);
return;
} else {
vm_exit_during_initialization(
"JSR292 is not supported with compressed oops yet", NULL);
}
}
// If dumping an archive or forcing its use, disable compressed oops if possible
if (DumpSharedSpaces || RequireSharedSpaces) {
if (is_on_by_default) {
FLAG_SET_DEFAULT(UseCompressedOops, false);
return;
} else {
vm_exit_during_initialization(
"Class Data Sharing is not supported with compressed oops yet", NULL);
}
} else if (UseSharedSpaces) {
// UseSharedSpaces is on by default. With compressed oops, we turn it off.
FLAG_SET_DEFAULT(UseSharedSpaces, false);
}
# endif // defined(COMPILER1) && !defined(TIERED)
#endif // _LP64
}
void Arguments::set_tiered_flags() {
if (FLAG_IS_DEFAULT(CompilationPolicyChoice)) {
FLAG_SET_DEFAULT(CompilationPolicyChoice, 2);
}
if (CompilationPolicyChoice < 2) {
vm_exit_during_initialization(
"Incompatible compilation policy selected", NULL);
}
#ifdef _LP64
if (FLAG_IS_DEFAULT(UseCompressedOops) || FLAG_IS_ERGO(UseCompressedOops)) {
UseCompressedOops = false;
}
if (UseCompressedOops) {
vm_exit_during_initialization(
"Tiered compilation is not supported with compressed oops yet", NULL);
}
#endif
// Increase the code cache size - tiered compiles a lot more.
// Increase the code cache size - tiered compiles a lot more.
if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) {
FLAG_SET_DEFAULT(ReservedCodeCacheSize, ReservedCodeCacheSize * 2);
}
@ -1676,7 +1724,8 @@ bool Arguments::check_stack_pages()
bool status = true;
status = status && verify_min_value(StackYellowPages, 1, "StackYellowPages");
status = status && verify_min_value(StackRedPages, 1, "StackRedPages");
status = status && verify_min_value(StackShadowPages, 1, "StackShadowPages");
// greater stack shadow pages can't generate instruction to bang stack
status = status && verify_interval(StackShadowPages, 1, 50, "StackShadowPages");
return status;
}
@ -1722,8 +1771,6 @@ bool Arguments::check_vm_args_consistency() {
status = false;
}
status = status && verify_percentage(MaxLiveObjectEvacuationRatio,
"MaxLiveObjectEvacuationRatio");
status = status && verify_percentage(AdaptiveSizePolicyWeight,
"AdaptiveSizePolicyWeight");
status = status && verify_percentage(AdaptivePermSizeWeight, "AdaptivePermSizeWeight");
@ -2827,6 +2874,7 @@ jint Arguments::parse_options_environment_variable(const char* name, SysClassPat
return JNI_OK;
}
// Parse entry point called from JNI_CreateJavaVM
jint Arguments::parse(const JavaVMInitArgs* args) {
@ -2969,10 +3017,6 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
PrintGC = true;
}
#if defined(_LP64) && defined(COMPILER1) && !defined(TIERED)
UseCompressedOops = false;
#endif
// Set object alignment values.
set_object_alignment();
@ -2987,13 +3031,10 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
set_ergonomics_flags();
#ifdef _LP64
// XXX JSR 292 currently does not support compressed oops.
if (EnableMethodHandles && UseCompressedOops) {
if (FLAG_IS_DEFAULT(UseCompressedOops) || FLAG_IS_ERGO(UseCompressedOops)) {
UseCompressedOops = false;
}
if (UseCompressedOops) {
check_compressed_oops_compat();
}
#endif // _LP64
#endif
// Check the GC selections again.
if (!check_gc_consistency()) {

View File

@ -291,6 +291,8 @@ class Arguments : AllStatic {
// Tiered
static void set_tiered_flags();
// Check compressed oops compatibility with other flags
static void check_compressed_oops_compat();
// CMS/ParNew garbage collectors
static void set_parnew_gc_flags();
static void set_cms_and_parnew_gc_flags();
@ -484,6 +486,9 @@ class Arguments : AllStatic {
// System properties
static void init_system_properties();
// Update/Initialize System properties after JDK version number is known
static void init_version_specific_system_properties();
// Property List manipulation
static void PropertyList_add(SystemProperty** plist, SystemProperty *element);
static void PropertyList_add(SystemProperty** plist, const char* k, char* v);

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
# include "incls/_precompiled.incl"
# include "incls/_basicLock.cpp.incl"
void BasicLock::print_on(outputStream* st) const {
st->print("monitor");
}
void BasicLock::move_to(oop obj, BasicLock* dest) {
// Check to see if we need to inflate the lock. This is only needed
// if an object is locked using "this" lightweight monitor. In that
// case, the displaced_header() is unlocked, because the
// displaced_header() contains the header for the originally unlocked
// object. However the object could have already been inflated. But it
// does not matter, the inflation will just a no-op. For other cases,
// the displaced header will be either 0x0 or 0x3, which are location
// independent, therefore the BasicLock is free to move.
//
// During OSR we may need to relocate a BasicLock (which contains a
// displaced word) from a location in an interpreter frame to a
// new location in a compiled frame. "this" refers to the source
// basiclock in the interpreter frame. "dest" refers to the destination
// basiclock in the new compiled frame. We *always* inflate in move_to().
// The always-Inflate policy works properly, but in 1.5.0 it can sometimes
// cause performance problems in code that makes heavy use of a small # of
// uncontended locks. (We'd inflate during OSR, and then sync performance
// would subsequently plummet because the thread would be forced thru the slow-path).
// This problem has been made largely moot on IA32 by inlining the inflated fast-path
// operations in Fast_Lock and Fast_Unlock in i486.ad.
//
// Note that there is a way to safely swing the object's markword from
// one stack location to another. This avoids inflation. Obviously,
// we need to ensure that both locations refer to the current thread's stack.
// There are some subtle concurrency issues, however, and since the benefit is
// is small (given the support for inflated fast-path locking in the fast_lock, etc)
// we'll leave that optimization for another time.
if (displaced_header()->is_neutral()) {
ObjectSynchronizer::inflate_helper(obj);
// WARNING: We can not put check here, because the inflation
// will not update the displaced header. Once BasicLock is inflated,
// no one should ever look at its content.
} else {
// Typically the displaced header will be 0 (recursive stack lock) or
// unused_mark. Naively we'd like to assert that the displaced mark
// value is either 0, neutral, or 3. But with the advent of the
// store-before-CAS avoidance in fast_lock/compiler_lock_object
// we can find any flavor mark in the displaced mark.
}
// [RGV] The next line appears to do nothing!
intptr_t dh = (intptr_t) displaced_header();
dest->set_displaced_header(displaced_header());
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
class BasicLock VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
private:
volatile markOop _displaced_header;
public:
markOop displaced_header() const { return _displaced_header; }
void set_displaced_header(markOop header) { _displaced_header = header; }
void print_on(outputStream* st) const;
// move a basic lock (used during deoptimization
void move_to(oop obj, BasicLock* dest);
static int displaced_header_offset_in_bytes() { return offset_of(BasicLock, _displaced_header); }
};
// A BasicObjectLock associates a specific Java object with a BasicLock.
// It is currently embedded in an interpreter frame.
// Because some machines have alignment restrictions on the control stack,
// the actual space allocated by the interpreter may include padding words
// after the end of the BasicObjectLock. Also, in order to guarantee
// alignment of the embedded BasicLock objects on such machines, we
// put the embedded BasicLock at the beginning of the struct.
class BasicObjectLock VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
private:
BasicLock _lock; // the lock, must be double word aligned
oop _obj; // object holds the lock;
public:
// Manipulation
oop obj() const { return _obj; }
void set_obj(oop obj) { _obj = obj; }
BasicLock* lock() { return &_lock; }
// Note: Use frame::interpreter_frame_monitor_size() for the size of BasicObjectLocks
// in interpreter activation frames since it includes machine-specific padding.
static int size() { return sizeof(BasicObjectLock)/wordSize; }
// GC support
void oops_do(OopClosure* f) { f->do_oop(&_obj); }
static int obj_offset_in_bytes() { return offset_of(BasicObjectLock, _obj); }
static int lock_offset_in_bytes() { return offset_of(BasicObjectLock, _lock); }
};

View File

@ -327,10 +327,10 @@ class CommandLineFlags {
/* UseMembar is theoretically a temp flag used for memory barrier \
* removal testing. It was supposed to be removed before FCS but has \
* been re-added (see 6401008) */ \
product(bool, UseMembar, false, \
product_pd(bool, UseMembar, \
"(Unstable) Issues membars on thread state transitions") \
\
/* Temporary: See 6948537 */ \
/* Temporary: See 6948537 */ \
experimental(bool, UseMemSetInBOT, true, \
"(Unstable) uses memset in BOT updates in GC code") \
\
@ -822,6 +822,9 @@ class CommandLineFlags {
develop(bool, PrintJVMWarnings, false, \
"Prints warnings for unimplemented JVM functions") \
\
product(bool, PrintWarnings, true, \
"Prints JVM warnings to output stream") \
\
notproduct(uintx, WarnOnStalledSpinLock, 0, \
"Prints warnings for stalled SpinLocks") \
\
@ -1585,7 +1588,7 @@ class CommandLineFlags {
"(Temporary, subject to experimentation)" \
"Nominal minimum work per abortable preclean iteration") \
\
product(intx, CMSAbortablePrecleanWaitMillis, 100, \
manageable(intx, CMSAbortablePrecleanWaitMillis, 100, \
"(Temporary, subject to experimentation)" \
" Time that we sleep between iterations when not given" \
" enough work per iteration") \
@ -1677,7 +1680,7 @@ class CommandLineFlags {
product(uintx, CMSWorkQueueDrainThreshold, 10, \
"Don't drain below this size per parallel worker/thief") \
\
product(intx, CMSWaitDuration, 2000, \
manageable(intx, CMSWaitDuration, 2000, \
"Time in milliseconds that CMS thread waits for young GC") \
\
product(bool, CMSYield, true, \
@ -1786,10 +1789,6 @@ class CommandLineFlags {
notproduct(bool, GCALotAtAllSafepoints, false, \
"Enforce ScavengeALot/GCALot at all potential safepoints") \
\
product(bool, HandlePromotionFailure, true, \
"The youngest generation collection does not require " \
"a guarantee of full promotion of all live objects.") \
\
product(bool, PrintPromotionFailure, false, \
"Print additional diagnostic information following " \
" promotion failure") \
@ -3003,9 +3002,6 @@ class CommandLineFlags {
product(intx, NewRatio, 2, \
"Ratio of new/old generation sizes") \
\
product(uintx, MaxLiveObjectEvacuationRatio, 100, \
"Max percent of eden objects that will be live at scavenge") \
\
product_pd(uintx, NewSizeThreadIncrease, \
"Additional size added to desired new generation size per " \
"non-daemon thread (in bytes)") \
@ -3542,7 +3538,7 @@ class CommandLineFlags {
product(uintx, SharedDummyBlockSize, 512*M, \
"Size of dummy block used to shift heap addresses (in bytes)") \
\
product(uintx, SharedReadWriteSize, 12*M, \
product(uintx, SharedReadWriteSize, NOT_LP64(12*M) LP64_ONLY(13*M), \
"Size of read-write space in permanent generation (in bytes)") \
\
product(uintx, SharedReadOnlySize, 10*M, \

View File

@ -265,48 +265,3 @@ class Mutex : public Monitor { // degenerate Monitor
}
};
/*
* Per-thread blocking support for JSR166. See the Java-level
* Documentation for rationale. Basically, park acts like wait, unpark
* like notify.
*
* 6271289 --
* To avoid errors where an os thread expires but the JavaThread still
* exists, Parkers are immortal (type-stable) and are recycled across
* new threads. This parallels the ParkEvent implementation.
* Because park-unpark allow spurious wakeups it is harmless if an
* unpark call unparks a new thread using the old Parker reference.
*
* In the future we'll want to think about eliminating Parker and using
* ParkEvent instead. There's considerable duplication between the two
* services.
*
*/
class Parker : public os::PlatformParker {
private:
volatile int _counter ;
Parker * FreeNext ;
JavaThread * AssociatedWith ; // Current association
public:
Parker() : PlatformParker() {
_counter = 0 ;
FreeNext = NULL ;
AssociatedWith = NULL ;
}
protected:
~Parker() { ShouldNotReachHere(); }
public:
// For simplicity of interface with Java, all forms of park (indefinite,
// relative, and absolute) are multiplexed into one call.
void park(bool isAbsolute, jlong time);
void unpark();
// Lifecycle operators
static Parker * Allocate (JavaThread * t) ;
static void Release (Parker * e) ;
private:
static Parker * volatile FreeList ;
static volatile int ListLock ;
};

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,32 @@
*
*/
// ObjectWaiter serves as a "proxy" or surrogate thread.
// TODO-FIXME: Eliminate ObjectWaiter and use the thread-specific
// ParkEvent instead. Beware, however, that the JVMTI code
// knows about ObjectWaiters, so we'll have to reconcile that code.
// See next_waiter(), first_waiter(), etc.
class ObjectWaiter : public StackObj {
public:
enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ } ;
enum Sorted { PREPEND, APPEND, SORTED } ;
ObjectWaiter * volatile _next;
ObjectWaiter * volatile _prev;
Thread* _thread;
ParkEvent * _event;
volatile int _notified ;
volatile TStates TState ;
Sorted _Sorted ; // List placement disposition
bool _active ; // Contention monitoring is enabled
public:
ObjectWaiter(Thread* thread);
void wait_reenter_begin(ObjectMonitor *mon);
void wait_reenter_end(ObjectMonitor *mon);
};
// WARNING:
// This is a very sensitive and fragile class. DO NOT make any
// change unless you are fully aware of the underlying semantics.
@ -38,8 +64,6 @@
// It is also used as RawMonitor by the JVMTI
class ObjectWaiter;
class ObjectMonitor {
public:
enum {
@ -74,13 +98,16 @@ class ObjectMonitor {
public:
ObjectMonitor();
~ObjectMonitor();
markOop header() const;
void set_header(markOop hdr);
intptr_t is_busy() const;
intptr_t is_busy() const {
// TODO-FIXME: merge _count and _waiters.
// TODO-FIXME: assert _owner == null implies _recursions = 0
// TODO-FIXME: assert _WaitSet != null implies _count > 0
return _count|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList ) ;
}
intptr_t is_entered(Thread* current) const;
void* owner() const;
@ -91,13 +118,58 @@ class ObjectMonitor {
intptr_t count() const;
void set_count(intptr_t count);
intptr_t contentions() const ;
intptr_t recursions() const { return _recursions; }
// JVM/DI GetMonitorInfo() needs this
Thread * thread_of_waiter (ObjectWaiter *) ;
ObjectWaiter * first_waiter () ;
ObjectWaiter * next_waiter(ObjectWaiter* o);
ObjectWaiter* first_waiter() { return _WaitSet; }
ObjectWaiter* next_waiter(ObjectWaiter* o) { return o->_next; }
Thread* thread_of_waiter(ObjectWaiter* o) { return o->_thread; }
intptr_t recursions() const { return _recursions; }
// initialize the monitor, exception the semaphore, all other fields
// are simple integers or pointers
ObjectMonitor() {
_header = NULL;
_count = 0;
_waiters = 0,
_recursions = 0;
_object = NULL;
_owner = NULL;
_WaitSet = NULL;
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ;
FreeNext = NULL ;
_EntryList = NULL ;
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
}
~ObjectMonitor() {
// TODO: Add asserts ...
// _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
// _count == 0 _EntryList == NULL etc
}
private:
void Recycle () {
// TODO: add stronger asserts ...
// _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
// _count == 0 EntryList == NULL
// _recursions == 0 _WaitSet == NULL
// TODO: assert (is_busy()|_recursions) == 0
_succ = NULL ;
_EntryList = NULL ;
_cxq = NULL ;
_WaitSet = NULL ;
_recursions = 0 ;
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
}
public:
void* object() const;
void* object_addr();
@ -122,22 +194,9 @@ class ObjectMonitor {
intptr_t complete_exit(TRAPS);
void reenter(intptr_t recursions, TRAPS);
int raw_enter(TRAPS);
int raw_exit(TRAPS);
int raw_wait(jlong millis, bool interruptable, TRAPS);
int raw_notify(TRAPS);
int raw_notifyAll(TRAPS);
private:
// JVMTI support -- remove ASAP
int SimpleEnter (Thread * Self) ;
int SimpleExit (Thread * Self) ;
int SimpleWait (Thread * Self, jlong millis) ;
int SimpleNotify (Thread * Self, bool All) ;
private:
void Recycle () ;
void AddWaiter (ObjectWaiter * waiter) ;
static void DeferredInitialize();
ObjectWaiter * DequeueWaiter () ;
void DequeueSpecificWaiter (ObjectWaiter * waiter) ;
@ -172,13 +231,17 @@ class ObjectMonitor {
// The VM assumes write ordering wrt these fields, which can be
// read from other threads.
protected: // protected for jvmtiRawMonitor
void * volatile _owner; // pointer to owning thread OR BasicLock
volatile intptr_t _recursions; // recursion count, 0 for first entry
private:
int OwnerIsThread ; // _owner is (Thread *) vs SP/BasicLock
ObjectWaiter * volatile _cxq ; // LL of recently-arrived threads blocked on entry.
// The list is actually composed of WaitNodes, acting
// as proxies for Threads.
protected:
ObjectWaiter * volatile _EntryList ; // Threads blocked on entry or reentry.
private:
Thread * volatile _succ ; // Heir presumptive thread - used for futile wakeup throttling
Thread * volatile _Responsible ;
int _PromptDrain ; // rqst to drain cxq into EntryList ASAP
@ -196,8 +259,12 @@ class ObjectMonitor {
volatile intptr_t _count; // reference count to prevent reclaimation/deflation
// at stop-the-world time. See deflate_idle_monitors().
// _count is approximately |_WaitSet| + |_EntryList|
protected:
volatile intptr_t _waiters; // number of waiting threads
private:
protected:
ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor
private:
volatile int _WaitSetLock; // protects Wait Queue - simple spinlock
public:
@ -205,4 +272,37 @@ class ObjectMonitor {
ObjectMonitor * FreeNext ; // Free list linkage
intptr_t StatA, StatsB ;
public:
static void Initialize () ;
static PerfCounter * _sync_ContendedLockAttempts ;
static PerfCounter * _sync_FutileWakeups ;
static PerfCounter * _sync_Parks ;
static PerfCounter * _sync_EmptyNotifications ;
static PerfCounter * _sync_Notifications ;
static PerfCounter * _sync_SlowEnter ;
static PerfCounter * _sync_SlowExit ;
static PerfCounter * _sync_SlowNotify ;
static PerfCounter * _sync_SlowNotifyAll ;
static PerfCounter * _sync_FailedSpins ;
static PerfCounter * _sync_SuccessfulSpins ;
static PerfCounter * _sync_PrivateA ;
static PerfCounter * _sync_PrivateB ;
static PerfCounter * _sync_MonInCirculation ;
static PerfCounter * _sync_MonScavenged ;
static PerfCounter * _sync_Inflations ;
static PerfCounter * _sync_Deflations ;
static PerfLongVariable * _sync_MonExtant ;
public:
static int Knob_Verbose;
static int Knob_SpinLimit;
};
#undef TEVENT
#define TEVENT(nom) {if (SyncVerbose) FEVENT(nom); }
#define FEVENT(nom) { static volatile int ctr = 0 ; int v = ++ctr ; if ((v & (v-1)) == 0) { ::printf (#nom " : %d \n", v); ::fflush(stdout); }}
#undef TEVENT
#define TEVENT(nom) {;}

View File

@ -104,7 +104,3 @@ inline void ObjectMonitor::set_owner(void* owner) {
_count = 0;
}
// here are the platform-dependent bodies:
# include "incls/_objectMonitor_pd.inline.hpp.incl"

View File

@ -0,0 +1,237 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
# include "incls/_precompiled.incl"
# include "incls/_park.cpp.incl"
// Lifecycle management for TSM ParkEvents.
// ParkEvents are type-stable (TSM).
// In our particular implementation they happen to be immortal.
//
// We manage concurrency on the FreeList with a CAS-based
// detach-modify-reattach idiom that avoids the ABA problems
// that would otherwise be present in a simple CAS-based
// push-pop implementation. (push-one and pop-all)
//
// Caveat: Allocate() and Release() may be called from threads
// other than the thread associated with the Event!
// If we need to call Allocate() when running as the thread in
// question then look for the PD calls to initialize native TLS.
// Native TLS (Win32/Linux/Solaris) can only be initialized or
// accessed by the associated thread.
// See also pd_initialize().
//
// Note that we could defer associating a ParkEvent with a thread
// until the 1st time the thread calls park(). unpark() calls to
// an unprovisioned thread would be ignored. The first park() call
// for a thread would allocate and associate a ParkEvent and return
// immediately.
volatile int ParkEvent::ListLock = 0 ;
ParkEvent * volatile ParkEvent::FreeList = NULL ;
ParkEvent * ParkEvent::Allocate (Thread * t) {
// In rare cases -- JVM_RawMonitor* operations -- we can find t == null.
ParkEvent * ev ;
// Start by trying to recycle an existing but unassociated
// ParkEvent from the global free list.
for (;;) {
ev = FreeList ;
if (ev == NULL) break ;
// 1: Detach - sequester or privatize the list
// Tantamount to ev = Swap (&FreeList, NULL)
if (Atomic::cmpxchg_ptr (NULL, &FreeList, ev) != ev) {
continue ;
}
// We've detached the list. The list in-hand is now
// local to this thread. This thread can operate on the
// list without risk of interference from other threads.
// 2: Extract -- pop the 1st element from the list.
ParkEvent * List = ev->FreeNext ;
if (List == NULL) break ;
for (;;) {
// 3: Try to reattach the residual list
guarantee (List != NULL, "invariant") ;
ParkEvent * Arv = (ParkEvent *) Atomic::cmpxchg_ptr (List, &FreeList, NULL) ;
if (Arv == NULL) break ;
// New nodes arrived. Try to detach the recent arrivals.
if (Atomic::cmpxchg_ptr (NULL, &FreeList, Arv) != Arv) {
continue ;
}
guarantee (Arv != NULL, "invariant") ;
// 4: Merge Arv into List
ParkEvent * Tail = List ;
while (Tail->FreeNext != NULL) Tail = Tail->FreeNext ;
Tail->FreeNext = Arv ;
}
break ;
}
if (ev != NULL) {
guarantee (ev->AssociatedWith == NULL, "invariant") ;
} else {
// Do this the hard way -- materialize a new ParkEvent.
// In rare cases an allocating thread might detach a long list --
// installing null into FreeList -- and then stall or be obstructed.
// A 2nd thread calling Allocate() would see FreeList == null.
// The list held privately by the 1st thread is unavailable to the 2nd thread.
// In that case the 2nd thread would have to materialize a new ParkEvent,
// even though free ParkEvents existed in the system. In this case we end up
// with more ParkEvents in circulation than we need, but the race is
// rare and the outcome is benign. Ideally, the # of extant ParkEvents
// is equal to the maximum # of threads that existed at any one time.
// Because of the race mentioned above, segments of the freelist
// can be transiently inaccessible. At worst we may end up with the
// # of ParkEvents in circulation slightly above the ideal.
// Note that if we didn't have the TSM/immortal constraint, then
// when reattaching, above, we could trim the list.
ev = new ParkEvent () ;
guarantee ((intptr_t(ev) & 0xFF) == 0, "invariant") ;
}
ev->reset() ; // courtesy to caller
ev->AssociatedWith = t ; // Associate ev with t
ev->FreeNext = NULL ;
return ev ;
}
void ParkEvent::Release (ParkEvent * ev) {
if (ev == NULL) return ;
guarantee (ev->FreeNext == NULL , "invariant") ;
ev->AssociatedWith = NULL ;
for (;;) {
// Push ev onto FreeList
// The mechanism is "half" lock-free.
ParkEvent * List = FreeList ;
ev->FreeNext = List ;
if (Atomic::cmpxchg_ptr (ev, &FreeList, List) == List) break ;
}
}
// Override operator new and delete so we can ensure that the
// least significant byte of ParkEvent addresses is 0.
// Beware that excessive address alignment is undesirable
// as it can result in D$ index usage imbalance as
// well as bank access imbalance on Niagara-like platforms,
// although Niagara's hash function should help.
void * ParkEvent::operator new (size_t sz) {
return (void *) ((intptr_t (CHeapObj::operator new (sz + 256)) + 256) & -256) ;
}
void ParkEvent::operator delete (void * a) {
// ParkEvents are type-stable and immortal ...
ShouldNotReachHere();
}
// 6399321 As a temporary measure we copied & modified the ParkEvent::
// allocate() and release() code for use by Parkers. The Parker:: forms
// will eventually be removed as we consolide and shift over to ParkEvents
// for both builtin synchronization and JSR166 operations.
volatile int Parker::ListLock = 0 ;
Parker * volatile Parker::FreeList = NULL ;
Parker * Parker::Allocate (JavaThread * t) {
guarantee (t != NULL, "invariant") ;
Parker * p ;
// Start by trying to recycle an existing but unassociated
// Parker from the global free list.
for (;;) {
p = FreeList ;
if (p == NULL) break ;
// 1: Detach
// Tantamount to p = Swap (&FreeList, NULL)
if (Atomic::cmpxchg_ptr (NULL, &FreeList, p) != p) {
continue ;
}
// We've detached the list. The list in-hand is now
// local to this thread. This thread can operate on the
// list without risk of interference from other threads.
// 2: Extract -- pop the 1st element from the list.
Parker * List = p->FreeNext ;
if (List == NULL) break ;
for (;;) {
// 3: Try to reattach the residual list
guarantee (List != NULL, "invariant") ;
Parker * Arv = (Parker *) Atomic::cmpxchg_ptr (List, &FreeList, NULL) ;
if (Arv == NULL) break ;
// New nodes arrived. Try to detach the recent arrivals.
if (Atomic::cmpxchg_ptr (NULL, &FreeList, Arv) != Arv) {
continue ;
}
guarantee (Arv != NULL, "invariant") ;
// 4: Merge Arv into List
Parker * Tail = List ;
while (Tail->FreeNext != NULL) Tail = Tail->FreeNext ;
Tail->FreeNext = Arv ;
}
break ;
}
if (p != NULL) {
guarantee (p->AssociatedWith == NULL, "invariant") ;
} else {
// Do this the hard way -- materialize a new Parker..
// In rare cases an allocating thread might detach
// a long list -- installing null into FreeList --and
// then stall. Another thread calling Allocate() would see
// FreeList == null and then invoke the ctor. In this case we
// end up with more Parkers in circulation than we need, but
// the race is rare and the outcome is benign.
// Ideally, the # of extant Parkers is equal to the
// maximum # of threads that existed at any one time.
// Because of the race mentioned above, segments of the
// freelist can be transiently inaccessible. At worst
// we may end up with the # of Parkers in circulation
// slightly above the ideal.
p = new Parker() ;
}
p->AssociatedWith = t ; // Associate p with t
p->FreeNext = NULL ;
return p ;
}
void Parker::Release (Parker * p) {
if (p == NULL) return ;
guarantee (p->AssociatedWith != NULL, "invariant") ;
guarantee (p->FreeNext == NULL , "invariant") ;
p->AssociatedWith = NULL ;
for (;;) {
// Push p onto FreeList
Parker * List = FreeList ;
p->FreeNext = List ;
if (Atomic::cmpxchg_ptr (p, &FreeList, List) == List) break ;
}
}

View File

@ -0,0 +1,169 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* Per-thread blocking support for JSR166. See the Java-level
* Documentation for rationale. Basically, park acts like wait, unpark
* like notify.
*
* 6271289 --
* To avoid errors where an os thread expires but the JavaThread still
* exists, Parkers are immortal (type-stable) and are recycled across
* new threads. This parallels the ParkEvent implementation.
* Because park-unpark allow spurious wakeups it is harmless if an
* unpark call unparks a new thread using the old Parker reference.
*
* In the future we'll want to think about eliminating Parker and using
* ParkEvent instead. There's considerable duplication between the two
* services.
*
*/
class Parker : public os::PlatformParker {
private:
volatile int _counter ;
Parker * FreeNext ;
JavaThread * AssociatedWith ; // Current association
public:
Parker() : PlatformParker() {
_counter = 0 ;
FreeNext = NULL ;
AssociatedWith = NULL ;
}
protected:
~Parker() { ShouldNotReachHere(); }
public:
// For simplicity of interface with Java, all forms of park (indefinite,
// relative, and absolute) are multiplexed into one call.
void park(bool isAbsolute, jlong time);
void unpark();
// Lifecycle operators
static Parker * Allocate (JavaThread * t) ;
static void Release (Parker * e) ;
private:
static Parker * volatile FreeList ;
static volatile int ListLock ;
};
/////////////////////////////////////////////////////////////
//
// ParkEvents are type-stable and immortal.
//
// Lifecycle: Once a ParkEvent is associated with a thread that ParkEvent remains
// associated with the thread for the thread's entire lifetime - the relationship is
// stable. A thread will be associated at most one ParkEvent. When the thread
// expires, the ParkEvent moves to the EventFreeList. New threads attempt to allocate from
// the EventFreeList before creating a new Event. Type-stability frees us from
// worrying about stale Event or Thread references in the objectMonitor subsystem.
// (A reference to ParkEvent is always valid, even though the event may no longer be associated
// with the desired or expected thread. A key aspect of this design is that the callers of
// park, unpark, etc must tolerate stale references and spurious wakeups).
//
// Only the "associated" thread can block (park) on the ParkEvent, although
// any other thread can unpark a reachable parkevent. Park() is allowed to
// return spuriously. In fact park-unpark a really just an optimization to
// avoid unbounded spinning and surrender the CPU to be a polite system citizen.
// A degenerate albeit "impolite" park-unpark implementation could simply return.
// See http://blogs.sun.com/dave for more details.
//
// Eventually I'd like to eliminate Events and ObjectWaiters, both of which serve as
// thread proxies, and simply make the THREAD structure type-stable and persistent.
// Currently, we unpark events associated with threads, but ideally we'd just
// unpark threads.
//
// The base-class, PlatformEvent, is platform-specific while the ParkEvent is
// platform-independent. PlatformEvent provides park(), unpark(), etc., and
// is abstract -- that is, a PlatformEvent should never be instantiated except
// as part of a ParkEvent.
// Equivalently we could have defined a platform-independent base-class that
// exported Allocate(), Release(), etc. The platform-specific class would extend
// that base-class, adding park(), unpark(), etc.
//
// A word of caution: The JVM uses 2 very similar constructs:
// 1. ParkEvent are used for Java-level "monitor" synchronization.
// 2. Parkers are used by JSR166-JUC park-unpark.
//
// We'll want to eventually merge these redundant facilities and use ParkEvent.
class ParkEvent : public os::PlatformEvent {
private:
ParkEvent * FreeNext ;
// Current association
Thread * AssociatedWith ;
intptr_t RawThreadIdentity ; // LWPID etc
volatile int Incarnation ;
// diagnostic : keep track of last thread to wake this thread.
// this is useful for construction of dependency graphs.
void * LastWaker ;
public:
// MCS-CLH list linkage and Native Mutex/Monitor
ParkEvent * volatile ListNext ;
ParkEvent * volatile ListPrev ;
volatile intptr_t OnList ;
volatile int TState ;
volatile int Notified ; // for native monitor construct
volatile int IsWaiting ; // Enqueued on WaitSet
private:
static ParkEvent * volatile FreeList ;
static volatile int ListLock ;
// It's prudent to mark the dtor as "private"
// ensuring that it's not visible outside the package.
// Unfortunately gcc warns about such usage, so
// we revert to the less desirable "protected" visibility.
// The other compilers accept private dtors.
protected: // Ensure dtor is never invoked
~ParkEvent() { guarantee (0, "invariant") ; }
ParkEvent() : PlatformEvent() {
AssociatedWith = NULL ;
FreeNext = NULL ;
ListNext = NULL ;
ListPrev = NULL ;
OnList = 0 ;
TState = 0 ;
Notified = 0 ;
IsWaiting = 0 ;
}
// We use placement-new to force ParkEvent instances to be
// aligned on 256-byte address boundaries. This ensures that the least
// significant byte of a ParkEvent address is always 0.
void * operator new (size_t sz) ;
void operator delete (void * a) ;
public:
static ParkEvent * Allocate (Thread * t) ;
static void Release (ParkEvent * e) ;
} ;

View File

@ -435,6 +435,120 @@ void Relocator::adjust_local_var_table(int bci, int delta) {
}
}
// Create a new array, copying the src array but adding a hole at
// the specified location
static typeArrayOop insert_hole_at(
size_t where, int hole_sz, typeArrayOop src) {
Thread* THREAD = Thread::current();
Handle src_hnd(THREAD, src);
typeArrayOop dst =
oopFactory::new_permanent_byteArray(src->length() + hole_sz, CHECK_NULL);
src = (typeArrayOop)src_hnd();
address src_addr = (address)src->byte_at_addr(0);
address dst_addr = (address)dst->byte_at_addr(0);
memcpy(dst_addr, src_addr, where);
memcpy(dst_addr + where + hole_sz,
src_addr + where, src->length() - where);
return dst;
}
// The width of instruction at "bci" is changing by "delta". Adjust the stack
// map frames.
void Relocator::adjust_stack_map_table(int bci, int delta) {
if (method()->has_stackmap_table()) {
typeArrayOop data = method()->stackmap_data();
// The data in the array is a classfile representation of the stackmap
// table attribute, less the initial u2 tag and u4 attribute_length fields.
stack_map_table_attribute* attr = stack_map_table_attribute::at(
(address)data->byte_at_addr(0) - (sizeof(u2) + sizeof(u4)));
int count = attr->number_of_entries();
stack_map_frame* frame = attr->entries();
int bci_iter = -1;
bool offset_adjusted = false; // only need to adjust one offset
for (int i = 0; i < count; ++i) {
int offset_delta = frame->offset_delta();
bci_iter += offset_delta;
if (!offset_adjusted && bci_iter > bci) {
int new_offset_delta = offset_delta + delta;
if (frame->is_valid_offset(new_offset_delta)) {
frame->set_offset_delta(new_offset_delta);
} else {
assert(frame->is_same_frame() ||
frame->is_same_frame_1_stack_item_frame(),
"Frame must be one of the compressed forms");
// The new delta exceeds the capacity of the 'same_frame' or
// 'same_frame_1_stack_item_frame' frame types. We need to
// convert these frames to the extended versions, but the extended
// version is bigger and requires more room. So we allocate a
// new array and copy the data, being sure to leave u2-sized hole
// right after the 'frame_type' for the new offset field.
//
// We can safely ignore the reverse situation as a small delta
// can still be used in an extended version of the frame.
size_t frame_offset = (address)frame - (address)data->byte_at_addr(0);
data = insert_hole_at(frame_offset + 1, 2, data);
if (data == NULL) {
return; // out-of-memory?
}
address frame_addr = (address)(data->byte_at_addr(0) + frame_offset);
frame = stack_map_frame::at(frame_addr);
// Now convert the frames in place
if (frame->is_same_frame()) {
same_frame_extended::create_at(frame_addr, new_offset_delta);
} else {
same_frame_1_stack_item_extended::create_at(
frame_addr, new_offset_delta, NULL);
// the verification_info_type should already be at the right spot
}
}
offset_adjusted = true; // needs to be done only once, since subsequent
// values are offsets from the current
}
// The stack map frame may contain verification types, if so we need to
// check and update any Uninitialized type's bci (no matter where it is).
int number_of_types = frame->number_of_types();
verification_type_info* types = frame->types();
for (int i = 0; i < number_of_types; ++i) {
if (types->is_uninitialized() && types->bci() > bci) {
types->set_bci(types->bci() + delta);
}
types = types->next();
}
// Full frame has stack values too
full_frame* ff = frame->as_full_frame();
if (ff != NULL) {
address eol = (address)types;
number_of_types = ff->stack_slots(eol);
types = ff->stack(eol);
for (int i = 0; i < number_of_types; ++i) {
if (types->is_uninitialized() && types->bci() > bci) {
types->set_bci(types->bci() + delta);
}
types = types->next();
}
}
frame = frame->next();
}
method()->set_stackmap_data(data); // in case it has changed
}
}
bool Relocator::expand_code_array(int delta) {
int length = MAX2(code_length() + delta, code_length() * (100+code_slop_pct()) / 100);
@ -499,6 +613,9 @@ bool Relocator::relocate_code(int bci, int ilen, int delta) {
// And local variable table...
adjust_local_var_table(bci, delta);
// Adjust stack maps
adjust_stack_map_table(bci, delta);
// Relocate the pending change stack...
for (int j = 0; j < _changes->length(); j++) {
ChangeItem* ci = _changes->at(j);
@ -641,6 +758,7 @@ bool Relocator::handle_switch_pad(int bci, int old_pad, bool is_lookup_switch) {
memmove(addr_at(bci +1 + new_pad),
addr_at(bci +1 + old_pad),
len * 4);
memset(addr_at(bci + 1), 0, new_pad); // pad must be 0
}
}
return true;

View File

@ -105,6 +105,7 @@ class Relocator : public ResourceObj {
void adjust_exception_table(int bci, int delta);
void adjust_line_no_table (int bci, int delta);
void adjust_local_var_table(int bci, int delta);
void adjust_stack_map_table(int bci, int delta);
int get_orig_switch_pad (int bci, bool is_lookup_switch);
int rc_instr_len (int bci);
bool expand_code_array (int delta);

View File

@ -302,6 +302,9 @@ double SharedRuntime::dabs(double f) {
return (f <= (double)0.0) ? (double)0.0 - f : f;
}
#endif
#if defined(__SOFTFP__) || defined(PPC)
double SharedRuntime::dsqrt(double f) {
return sqrt(f);
}

View File

@ -116,6 +116,9 @@ class SharedRuntime: AllStatic {
#if defined(__SOFTFP__) || defined(E500V2)
static double dabs(double f);
#endif
#if defined(__SOFTFP__) || defined(PPC)
static double dsqrt(double f);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -22,53 +22,6 @@
*
*/
class BasicLock VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
private:
volatile markOop _displaced_header;
public:
markOop displaced_header() const { return _displaced_header; }
void set_displaced_header(markOop header) { _displaced_header = header; }
void print_on(outputStream* st) const;
// move a basic lock (used during deoptimization
void move_to(oop obj, BasicLock* dest);
static int displaced_header_offset_in_bytes() { return offset_of(BasicLock, _displaced_header); }
};
// A BasicObjectLock associates a specific Java object with a BasicLock.
// It is currently embedded in an interpreter frame.
// Because some machines have alignment restrictions on the control stack,
// the actual space allocated by the interpreter may include padding words
// after the end of the BasicObjectLock. Also, in order to guarantee
// alignment of the embedded BasicLock objects on such machines, we
// put the embedded BasicLock at the beginning of the struct.
class BasicObjectLock VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
private:
BasicLock _lock; // the lock, must be double word aligned
oop _obj; // object holds the lock;
public:
// Manipulation
oop obj() const { return _obj; }
void set_obj(oop obj) { _obj = obj; }
BasicLock* lock() { return &_lock; }
// Note: Use frame::interpreter_frame_monitor_size() for the size of BasicObjectLocks
// in interpreter activation frames since it includes machine-specific padding.
static int size() { return sizeof(BasicObjectLock)/wordSize; }
// GC support
void oops_do(OopClosure* f) { f->do_oop(&_obj); }
static int obj_offset_in_bytes() { return offset_of(BasicObjectLock, _obj); }
static int lock_offset_in_bytes() { return offset_of(BasicObjectLock, _lock); }
};
class ObjectMonitor;
@ -163,6 +116,8 @@ class ObjectSynchronizer : AllStatic {
static void verify() PRODUCT_RETURN;
static int verify_objmon_isinpool(ObjectMonitor *addr) PRODUCT_RETURN0;
static void RegisterSpinCallback (int (*)(intptr_t, int), intptr_t) ;
private:
enum { _BLOCKSIZE = 128 };
static ObjectMonitor* gBlockList;
@ -170,30 +125,6 @@ class ObjectSynchronizer : AllStatic {
static ObjectMonitor * volatile gOmInUseList; // for moribund thread, so monitors they inflated still get scanned
static int gOmInUseCount;
public:
static void Initialize () ;
static PerfCounter * _sync_ContendedLockAttempts ;
static PerfCounter * _sync_FutileWakeups ;
static PerfCounter * _sync_Parks ;
static PerfCounter * _sync_EmptyNotifications ;
static PerfCounter * _sync_Notifications ;
static PerfCounter * _sync_SlowEnter ;
static PerfCounter * _sync_SlowExit ;
static PerfCounter * _sync_SlowNotify ;
static PerfCounter * _sync_SlowNotifyAll ;
static PerfCounter * _sync_FailedSpins ;
static PerfCounter * _sync_SuccessfulSpins ;
static PerfCounter * _sync_PrivateA ;
static PerfCounter * _sync_PrivateB ;
static PerfCounter * _sync_MonInCirculation ;
static PerfCounter * _sync_MonScavenged ;
static PerfCounter * _sync_Inflations ;
static PerfCounter * _sync_Deflations ;
static PerfLongVariable * _sync_MonExtant ;
public:
static void RegisterSpinCallback (int (*)(intptr_t, int), intptr_t) ;
};
// ObjectLocker enforced balanced locking and can never thrown an

View File

@ -2921,6 +2921,9 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
// So that JDK version can be used as a discrimintor when parsing arguments
JDK_Version_init();
// Update/Initialize System properties after JDK version number is known
Arguments::init_version_specific_system_properties();
// Parse arguments
jint parse_result = Arguments::parse(args);
if (parse_result != JNI_OK) return parse_result;
@ -2992,8 +2995,8 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
// crash Linux VM, see notes in os_linux.cpp.
main_thread->create_stack_guard_pages();
// Initialize Java-Leve synchronization subsystem
ObjectSynchronizer::Initialize() ;
// Initialize Java-Level synchronization subsystem
ObjectMonitor::Initialize() ;
// Initialize global modules
jint status = init_globals();
@ -3962,215 +3965,272 @@ void Threads::print_on_error(outputStream* st, Thread* current, char* buf, int b
}
}
// Internal SpinLock and Mutex
// Based on ParkEvent
// Lifecycle management for TSM ParkEvents.
// ParkEvents are type-stable (TSM).
// In our particular implementation they happen to be immortal.
// Ad-hoc mutual exclusion primitives: SpinLock and Mux
//
// We manage concurrency on the FreeList with a CAS-based
// detach-modify-reattach idiom that avoids the ABA problems
// that would otherwise be present in a simple CAS-based
// push-pop implementation. (push-one and pop-all)
// We employ SpinLocks _only for low-contention, fixed-length
// short-duration critical sections where we're concerned
// about native mutex_t or HotSpot Mutex:: latency.
// The mux construct provides a spin-then-block mutual exclusion
// mechanism.
//
// Caveat: Allocate() and Release() may be called from threads
// other than the thread associated with the Event!
// If we need to call Allocate() when running as the thread in
// question then look for the PD calls to initialize native TLS.
// Native TLS (Win32/Linux/Solaris) can only be initialized or
// accessed by the associated thread.
// See also pd_initialize().
// Testing has shown that contention on the ListLock guarding gFreeList
// is common. If we implement ListLock as a simple SpinLock it's common
// for the JVM to devolve to yielding with little progress. This is true
// despite the fact that the critical sections protected by ListLock are
// extremely short.
//
// Note that we could defer associating a ParkEvent with a thread
// until the 1st time the thread calls park(). unpark() calls to
// an unprovisioned thread would be ignored. The first park() call
// for a thread would allocate and associate a ParkEvent and return
// immediately.
// TODO-FIXME: ListLock should be of type SpinLock.
// We should make this a 1st-class type, integrated into the lock
// hierarchy as leaf-locks. Critically, the SpinLock structure
// should have sufficient padding to avoid false-sharing and excessive
// cache-coherency traffic.
volatile int ParkEvent::ListLock = 0 ;
ParkEvent * volatile ParkEvent::FreeList = NULL ;
ParkEvent * ParkEvent::Allocate (Thread * t) {
// In rare cases -- JVM_RawMonitor* operations -- we can find t == null.
ParkEvent * ev ;
typedef volatile int SpinLockT ;
// Start by trying to recycle an existing but unassociated
// ParkEvent from the global free list.
void Thread::SpinAcquire (volatile int * adr, const char * LockName) {
if (Atomic::cmpxchg (1, adr, 0) == 0) {
return ; // normal fast-path return
}
// Slow-path : We've encountered contention -- Spin/Yield/Block strategy.
TEVENT (SpinAcquire - ctx) ;
int ctr = 0 ;
int Yields = 0 ;
for (;;) {
ev = FreeList ;
if (ev == NULL) break ;
// 1: Detach - sequester or privatize the list
// Tantamount to ev = Swap (&FreeList, NULL)
if (Atomic::cmpxchg_ptr (NULL, &FreeList, ev) != ev) {
continue ;
}
// We've detached the list. The list in-hand is now
// local to this thread. This thread can operate on the
// list without risk of interference from other threads.
// 2: Extract -- pop the 1st element from the list.
ParkEvent * List = ev->FreeNext ;
if (List == NULL) break ;
for (;;) {
// 3: Try to reattach the residual list
guarantee (List != NULL, "invariant") ;
ParkEvent * Arv = (ParkEvent *) Atomic::cmpxchg_ptr (List, &FreeList, NULL) ;
if (Arv == NULL) break ;
// New nodes arrived. Try to detach the recent arrivals.
if (Atomic::cmpxchg_ptr (NULL, &FreeList, Arv) != Arv) {
continue ;
while (*adr != 0) {
++ctr ;
if ((ctr & 0xFFF) == 0 || !os::is_MP()) {
if (Yields > 5) {
// Consider using a simple NakedSleep() instead.
// Then SpinAcquire could be called by non-JVM threads
Thread::current()->_ParkEvent->park(1) ;
} else {
os::NakedYield() ;
++Yields ;
}
} else {
SpinPause() ;
}
guarantee (Arv != NULL, "invariant") ;
// 4: Merge Arv into List
ParkEvent * Tail = List ;
while (Tail->FreeNext != NULL) Tail = Tail->FreeNext ;
Tail->FreeNext = Arv ;
}
break ;
}
if (Atomic::cmpxchg (1, adr, 0) == 0) return ;
}
if (ev != NULL) {
guarantee (ev->AssociatedWith == NULL, "invariant") ;
} else {
// Do this the hard way -- materialize a new ParkEvent.
// In rare cases an allocating thread might detach a long list --
// installing null into FreeList -- and then stall or be obstructed.
// A 2nd thread calling Allocate() would see FreeList == null.
// The list held privately by the 1st thread is unavailable to the 2nd thread.
// In that case the 2nd thread would have to materialize a new ParkEvent,
// even though free ParkEvents existed in the system. In this case we end up
// with more ParkEvents in circulation than we need, but the race is
// rare and the outcome is benign. Ideally, the # of extant ParkEvents
// is equal to the maximum # of threads that existed at any one time.
// Because of the race mentioned above, segments of the freelist
// can be transiently inaccessible. At worst we may end up with the
// # of ParkEvents in circulation slightly above the ideal.
// Note that if we didn't have the TSM/immortal constraint, then
// when reattaching, above, we could trim the list.
ev = new ParkEvent () ;
guarantee ((intptr_t(ev) & 0xFF) == 0, "invariant") ;
}
ev->reset() ; // courtesy to caller
ev->AssociatedWith = t ; // Associate ev with t
ev->FreeNext = NULL ;
return ev ;
}
void ParkEvent::Release (ParkEvent * ev) {
if (ev == NULL) return ;
guarantee (ev->FreeNext == NULL , "invariant") ;
ev->AssociatedWith = NULL ;
void Thread::SpinRelease (volatile int * adr) {
assert (*adr != 0, "invariant") ;
OrderAccess::fence() ; // guarantee at least release consistency.
// Roach-motel semantics.
// It's safe if subsequent LDs and STs float "up" into the critical section,
// but prior LDs and STs within the critical section can't be allowed
// to reorder or float past the ST that releases the lock.
*adr = 0 ;
}
// muxAcquire and muxRelease:
//
// * muxAcquire and muxRelease support a single-word lock-word construct.
// The LSB of the word is set IFF the lock is held.
// The remainder of the word points to the head of a singly-linked list
// of threads blocked on the lock.
//
// * The current implementation of muxAcquire-muxRelease uses its own
// dedicated Thread._MuxEvent instance. If we're interested in
// minimizing the peak number of extant ParkEvent instances then
// we could eliminate _MuxEvent and "borrow" _ParkEvent as long
// as certain invariants were satisfied. Specifically, care would need
// to be taken with regards to consuming unpark() "permits".
// A safe rule of thumb is that a thread would never call muxAcquire()
// if it's enqueued (cxq, EntryList, WaitList, etc) and will subsequently
// park(). Otherwise the _ParkEvent park() operation in muxAcquire() could
// consume an unpark() permit intended for monitorenter, for instance.
// One way around this would be to widen the restricted-range semaphore
// implemented in park(). Another alternative would be to provide
// multiple instances of the PlatformEvent() for each thread. One
// instance would be dedicated to muxAcquire-muxRelease, for instance.
//
// * Usage:
// -- Only as leaf locks
// -- for short-term locking only as muxAcquire does not perform
// thread state transitions.
//
// Alternatives:
// * We could implement muxAcquire and muxRelease with MCS or CLH locks
// but with parking or spin-then-park instead of pure spinning.
// * Use Taura-Oyama-Yonenzawa locks.
// * It's possible to construct a 1-0 lock if we encode the lockword as
// (List,LockByte). Acquire will CAS the full lockword while Release
// will STB 0 into the LockByte. The 1-0 scheme admits stranding, so
// acquiring threads use timers (ParkTimed) to detect and recover from
// the stranding window. Thread/Node structures must be aligned on 256-byte
// boundaries by using placement-new.
// * Augment MCS with advisory back-link fields maintained with CAS().
// Pictorially: LockWord -> T1 <-> T2 <-> T3 <-> ... <-> Tn <-> Owner.
// The validity of the backlinks must be ratified before we trust the value.
// If the backlinks are invalid the exiting thread must back-track through the
// the forward links, which are always trustworthy.
// * Add a successor indication. The LockWord is currently encoded as
// (List, LOCKBIT:1). We could also add a SUCCBIT or an explicit _succ variable
// to provide the usual futile-wakeup optimization.
// See RTStt for details.
// * Consider schedctl.sc_nopreempt to cover the critical section.
//
typedef volatile intptr_t MutexT ; // Mux Lock-word
enum MuxBits { LOCKBIT = 1 } ;
void Thread::muxAcquire (volatile intptr_t * Lock, const char * LockName) {
intptr_t w = Atomic::cmpxchg_ptr (LOCKBIT, Lock, 0) ;
if (w == 0) return ;
if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
return ;
}
TEVENT (muxAcquire - Contention) ;
ParkEvent * const Self = Thread::current()->_MuxEvent ;
assert ((intptr_t(Self) & LOCKBIT) == 0, "invariant") ;
for (;;) {
// Push ev onto FreeList
// The mechanism is "half" lock-free.
ParkEvent * List = FreeList ;
ev->FreeNext = List ;
if (Atomic::cmpxchg_ptr (ev, &FreeList, List) == List) break ;
}
}
int its = (os::is_MP() ? 100 : 0) + 1 ;
// Override operator new and delete so we can ensure that the
// least significant byte of ParkEvent addresses is 0.
// Beware that excessive address alignment is undesirable
// as it can result in D$ index usage imbalance as
// well as bank access imbalance on Niagara-like platforms,
// although Niagara's hash function should help.
// Optional spin phase: spin-then-park strategy
while (--its >= 0) {
w = *Lock ;
if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
return ;
}
}
void * ParkEvent::operator new (size_t sz) {
return (void *) ((intptr_t (CHeapObj::operator new (sz + 256)) + 256) & -256) ;
}
void ParkEvent::operator delete (void * a) {
// ParkEvents are type-stable and immortal ...
ShouldNotReachHere();
}
// 6399321 As a temporary measure we copied & modified the ParkEvent::
// allocate() and release() code for use by Parkers. The Parker:: forms
// will eventually be removed as we consolide and shift over to ParkEvents
// for both builtin synchronization and JSR166 operations.
volatile int Parker::ListLock = 0 ;
Parker * volatile Parker::FreeList = NULL ;
Parker * Parker::Allocate (JavaThread * t) {
guarantee (t != NULL, "invariant") ;
Parker * p ;
// Start by trying to recycle an existing but unassociated
// Parker from the global free list.
for (;;) {
p = FreeList ;
if (p == NULL) break ;
// 1: Detach
// Tantamount to p = Swap (&FreeList, NULL)
if (Atomic::cmpxchg_ptr (NULL, &FreeList, p) != p) {
continue ;
}
// We've detached the list. The list in-hand is now
// local to this thread. This thread can operate on the
// list without risk of interference from other threads.
// 2: Extract -- pop the 1st element from the list.
Parker * List = p->FreeNext ;
if (List == NULL) break ;
for (;;) {
// 3: Try to reattach the residual list
guarantee (List != NULL, "invariant") ;
Parker * Arv = (Parker *) Atomic::cmpxchg_ptr (List, &FreeList, NULL) ;
if (Arv == NULL) break ;
// New nodes arrived. Try to detach the recent arrivals.
if (Atomic::cmpxchg_ptr (NULL, &FreeList, Arv) != Arv) {
continue ;
Self->reset() ;
Self->OnList = intptr_t(Lock) ;
// The following fence() isn't _strictly necessary as the subsequent
// CAS() both serializes execution and ratifies the fetched *Lock value.
OrderAccess::fence();
for (;;) {
w = *Lock ;
if ((w & LOCKBIT) == 0) {
if (Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
Self->OnList = 0 ; // hygiene - allows stronger asserts
return ;
}
continue ; // Interference -- *Lock changed -- Just retry
}
guarantee (Arv != NULL, "invariant") ;
// 4: Merge Arv into List
Parker * Tail = List ;
while (Tail->FreeNext != NULL) Tail = Tail->FreeNext ;
Tail->FreeNext = Arv ;
}
break ;
}
assert (w & LOCKBIT, "invariant") ;
Self->ListNext = (ParkEvent *) (w & ~LOCKBIT );
if (Atomic::cmpxchg_ptr (intptr_t(Self)|LOCKBIT, Lock, w) == w) break ;
}
if (p != NULL) {
guarantee (p->AssociatedWith == NULL, "invariant") ;
} else {
// Do this the hard way -- materialize a new Parker..
// In rare cases an allocating thread might detach
// a long list -- installing null into FreeList --and
// then stall. Another thread calling Allocate() would see
// FreeList == null and then invoke the ctor. In this case we
// end up with more Parkers in circulation than we need, but
// the race is rare and the outcome is benign.
// Ideally, the # of extant Parkers is equal to the
// maximum # of threads that existed at any one time.
// Because of the race mentioned above, segments of the
// freelist can be transiently inaccessible. At worst
// we may end up with the # of Parkers in circulation
// slightly above the ideal.
p = new Parker() ;
while (Self->OnList != 0) {
Self->park() ;
}
}
p->AssociatedWith = t ; // Associate p with t
p->FreeNext = NULL ;
return p ;
}
void Thread::muxAcquireW (volatile intptr_t * Lock, ParkEvent * ev) {
intptr_t w = Atomic::cmpxchg_ptr (LOCKBIT, Lock, 0) ;
if (w == 0) return ;
if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
return ;
}
void Parker::Release (Parker * p) {
if (p == NULL) return ;
guarantee (p->AssociatedWith != NULL, "invariant") ;
guarantee (p->FreeNext == NULL , "invariant") ;
p->AssociatedWith = NULL ;
TEVENT (muxAcquire - Contention) ;
ParkEvent * ReleaseAfter = NULL ;
if (ev == NULL) {
ev = ReleaseAfter = ParkEvent::Allocate (NULL) ;
}
assert ((intptr_t(ev) & LOCKBIT) == 0, "invariant") ;
for (;;) {
// Push p onto FreeList
Parker * List = FreeList ;
p->FreeNext = List ;
if (Atomic::cmpxchg_ptr (p, &FreeList, List) == List) break ;
guarantee (ev->OnList == 0, "invariant") ;
int its = (os::is_MP() ? 100 : 0) + 1 ;
// Optional spin phase: spin-then-park strategy
while (--its >= 0) {
w = *Lock ;
if ((w & LOCKBIT) == 0 && Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
if (ReleaseAfter != NULL) {
ParkEvent::Release (ReleaseAfter) ;
}
return ;
}
}
ev->reset() ;
ev->OnList = intptr_t(Lock) ;
// The following fence() isn't _strictly necessary as the subsequent
// CAS() both serializes execution and ratifies the fetched *Lock value.
OrderAccess::fence();
for (;;) {
w = *Lock ;
if ((w & LOCKBIT) == 0) {
if (Atomic::cmpxchg_ptr (w|LOCKBIT, Lock, w) == w) {
ev->OnList = 0 ;
// We call ::Release while holding the outer lock, thus
// artificially lengthening the critical section.
// Consider deferring the ::Release() until the subsequent unlock(),
// after we've dropped the outer lock.
if (ReleaseAfter != NULL) {
ParkEvent::Release (ReleaseAfter) ;
}
return ;
}
continue ; // Interference -- *Lock changed -- Just retry
}
assert (w & LOCKBIT, "invariant") ;
ev->ListNext = (ParkEvent *) (w & ~LOCKBIT );
if (Atomic::cmpxchg_ptr (intptr_t(ev)|LOCKBIT, Lock, w) == w) break ;
}
while (ev->OnList != 0) {
ev->park() ;
}
}
}
// Release() must extract a successor from the list and then wake that thread.
// It can "pop" the front of the list or use a detach-modify-reattach (DMR) scheme
// similar to that used by ParkEvent::Allocate() and ::Release(). DMR-based
// Release() would :
// (A) CAS() or swap() null to *Lock, releasing the lock and detaching the list.
// (B) Extract a successor from the private list "in-hand"
// (C) attempt to CAS() the residual back into *Lock over null.
// If there were any newly arrived threads and the CAS() would fail.
// In that case Release() would detach the RATs, re-merge the list in-hand
// with the RATs and repeat as needed. Alternately, Release() might
// detach and extract a successor, but then pass the residual list to the wakee.
// The wakee would be responsible for reattaching and remerging before it
// competed for the lock.
//
// Both "pop" and DMR are immune from ABA corruption -- there can be
// multiple concurrent pushers, but only one popper or detacher.
// This implementation pops from the head of the list. This is unfair,
// but tends to provide excellent throughput as hot threads remain hot.
// (We wake recently run threads first).
void Thread::muxRelease (volatile intptr_t * Lock) {
for (;;) {
const intptr_t w = Atomic::cmpxchg_ptr (0, Lock, LOCKBIT) ;
assert (w & LOCKBIT, "invariant") ;
if (w == LOCKBIT) return ;
ParkEvent * List = (ParkEvent *) (w & ~LOCKBIT) ;
assert (List != NULL, "invariant") ;
assert (List->OnList == intptr_t(Lock), "invariant") ;
ParkEvent * nxt = List->ListNext ;
// The following CAS() releases the lock and pops the head element.
if (Atomic::cmpxchg_ptr (intptr_t(nxt), Lock, w) != w) {
continue ;
}
List->OnList = 0 ;
OrderAccess::fence() ;
List->unpark () ;
return ;
}
}
void Threads::verify() {
ALL_JAVA_THREADS(p) {
p->verify();

View File

@ -30,6 +30,7 @@ class JvmtiGetLoadedClassesClosure;
class ThreadStatistics;
class ConcurrentLocksDump;
class ParkEvent ;
class Parker;
class ciEnv;
class CompileThread;
@ -544,7 +545,6 @@ public:
static void muxAcquire (volatile intptr_t * Lock, const char * Name) ;
static void muxAcquireW (volatile intptr_t * Lock, ParkEvent * ev) ;
static void muxRelease (volatile intptr_t * Lock) ;
};
// Inline implementation of Thread::current()
@ -1769,100 +1769,3 @@ public:
}
};
// ParkEvents are type-stable and immortal.
//
// Lifecycle: Once a ParkEvent is associated with a thread that ParkEvent remains
// associated with the thread for the thread's entire lifetime - the relationship is
// stable. A thread will be associated at most one ParkEvent. When the thread
// expires, the ParkEvent moves to the EventFreeList. New threads attempt to allocate from
// the EventFreeList before creating a new Event. Type-stability frees us from
// worrying about stale Event or Thread references in the objectMonitor subsystem.
// (A reference to ParkEvent is always valid, even though the event may no longer be associated
// with the desired or expected thread. A key aspect of this design is that the callers of
// park, unpark, etc must tolerate stale references and spurious wakeups).
//
// Only the "associated" thread can block (park) on the ParkEvent, although
// any other thread can unpark a reachable parkevent. Park() is allowed to
// return spuriously. In fact park-unpark a really just an optimization to
// avoid unbounded spinning and surrender the CPU to be a polite system citizen.
// A degenerate albeit "impolite" park-unpark implementation could simply return.
// See http://blogs.sun.com/dave for more details.
//
// Eventually I'd like to eliminate Events and ObjectWaiters, both of which serve as
// thread proxies, and simply make the THREAD structure type-stable and persistent.
// Currently, we unpark events associated with threads, but ideally we'd just
// unpark threads.
//
// The base-class, PlatformEvent, is platform-specific while the ParkEvent is
// platform-independent. PlatformEvent provides park(), unpark(), etc., and
// is abstract -- that is, a PlatformEvent should never be instantiated except
// as part of a ParkEvent.
// Equivalently we could have defined a platform-independent base-class that
// exported Allocate(), Release(), etc. The platform-specific class would extend
// that base-class, adding park(), unpark(), etc.
//
// A word of caution: The JVM uses 2 very similar constructs:
// 1. ParkEvent are used for Java-level "monitor" synchronization.
// 2. Parkers are used by JSR166-JUC park-unpark.
//
// We'll want to eventually merge these redundant facilities and use ParkEvent.
class ParkEvent : public os::PlatformEvent {
private:
ParkEvent * FreeNext ;
// Current association
Thread * AssociatedWith ;
intptr_t RawThreadIdentity ; // LWPID etc
volatile int Incarnation ;
// diagnostic : keep track of last thread to wake this thread.
// this is useful for construction of dependency graphs.
void * LastWaker ;
public:
// MCS-CLH list linkage and Native Mutex/Monitor
ParkEvent * volatile ListNext ;
ParkEvent * volatile ListPrev ;
volatile intptr_t OnList ;
volatile int TState ;
volatile int Notified ; // for native monitor construct
volatile int IsWaiting ; // Enqueued on WaitSet
private:
static ParkEvent * volatile FreeList ;
static volatile int ListLock ;
// It's prudent to mark the dtor as "private"
// ensuring that it's not visible outside the package.
// Unfortunately gcc warns about such usage, so
// we revert to the less desirable "protected" visibility.
// The other compilers accept private dtors.
protected: // Ensure dtor is never invoked
~ParkEvent() { guarantee (0, "invariant") ; }
ParkEvent() : PlatformEvent() {
AssociatedWith = NULL ;
FreeNext = NULL ;
ListNext = NULL ;
ListPrev = NULL ;
OnList = 0 ;
TState = 0 ;
Notified = 0 ;
IsWaiting = 0 ;
}
// We use placement-new to force ParkEvent instances to be
// aligned on 256-byte address boundaries. This ensures that the least
// significant byte of a ParkEvent address is always 0.
void * operator new (size_t sz) ;
void operator delete (void * a) ;
public:
static ParkEvent * Allocate (Thread * t) ;
static void Release (ParkEvent * e) ;
} ;

View File

@ -51,14 +51,16 @@
void warning(const char* format, ...) {
// In case error happens before init or during shutdown
if (tty == NULL) ostream_init();
if (PrintWarnings) {
// In case error happens before init or during shutdown
if (tty == NULL) ostream_init();
tty->print("%s warning: ", VM_Version::vm_name());
va_list ap;
va_start(ap, format);
tty->vprint_cr(format, ap);
va_end(ap);
tty->print("%s warning: ", VM_Version::vm_name());
va_list ap;
va_start(ap, format);
tty->vprint_cr(format, ap);
va_end(ap);
}
if (BreakAtWarning) BREAKPOINT;
}

View File

@ -61,6 +61,18 @@ bool Exceptions::special_exception(Thread* thread, const char* file, int line, H
ShouldNotReachHere();
}
#ifdef ASSERT
// Check for trying to throw stack overflow before initialization is complete
// to prevent infinite recursion trying to initialize stack overflow without
// adequate stack space.
// This can happen with stress testing a large value of StackShadowPages
if (h_exception()->klass() == SystemDictionary::StackOverflowError_klass()) {
instanceKlass* ik = instanceKlass::cast(h_exception->klass());
assert(ik->is_initialized(),
"need to increase min_stack_allowed calculation");
}
#endif // ASSERT
if (thread->is_VM_thread()
|| thread->is_Compiler_thread() ) {
// We do not care what kind of exception we get for the vm-thread or a thread which
@ -91,7 +103,6 @@ bool Exceptions::special_exception(Thread* thread, const char* file, int line, s
thread->set_pending_exception(Universe::vm_exception(), file, line);
return true;
}
return false;
}
@ -193,6 +204,7 @@ void Exceptions::throw_stack_overflow_exception(Thread* THREAD, const char* file
klassOop k = SystemDictionary::StackOverflowError_klass();
oop e = instanceKlass::cast(k)->allocate_instance(CHECK);
exception = Handle(THREAD, e); // fill_in_stack trace does gc
assert(instanceKlass::cast(k)->is_initialized(), "need to increase min_stack_allowed calculation");
if (StackTraceInThrowable) {
java_lang_Throwable::fill_in_stack_trace(exception);
}

View File

@ -91,3 +91,4 @@ b53f226b1d91473ac54184afa827be07b87e0319 jdk7-b112
e250cef36ea05e627e7e6f7d75e5e19f529e2ba3 jdk7-b114
449bad8d67b5808ecf0f927683acc0a5940f8c85 jdk7-b115
1657ed4e1d86c8aa2028ab5a41f9da1ac4a369f8 jdk7-b116
3e6726bbf80a4254ecd01051c8ed77ee19325e46 jdk7-b117

View File

@ -413,6 +413,7 @@ JAVA_JAVA_java = \
java/io/FilePermission.java \
java/io/Serializable.java \
java/io/Externalizable.java \
java/io/SerialCallbackContext.java \
java/io/Bits.java \
java/io/ObjectInput.java \
java/io/ObjectInputStream.java \

View File

@ -148,14 +148,9 @@ include $(BUILDDIR)/common/Library.gmk
#
ifeq ($(PLATFORM), windows)
STATIC_LIBRARY_DIR = $(OBJDIR)/static
STATIC_LIBRARY_NAME = $(LIBPREFIX)$(LIBRARY).lib
STATIC_LIBRARY = $(STATIC_LIBRARY_DIR)/$(STATIC_LIBRARY_NAME)
STATIC_LIBRARY = $(OBJDIR)/static/$(LIBPREFIX)$(LIBRARY).lib
$(STATIC_LIBRARY_DIR): $(OBJDIR)
@$(MKDIR) $(STATIC_LIBRARY_DIR)
$(STATIC_LIBRARY): $(STATIC_LIBRARY_DIR)
$(STATIC_LIBRARY): $(FILES_o)
@$(prep-target)
$(LIBEXE) -nologo -out:$@ $(FILES_o)

View File

@ -33,7 +33,6 @@ FILES_src = \
java/nio/channels/AsynchronousByteChannel.java \
java/nio/channels/AsynchronousChannel.java \
java/nio/channels/AsynchronousChannelGroup.java \
java/nio/channels/AsynchronousDatagramChannel.java \
java/nio/channels/AsynchronousFileChannel.java \
java/nio/channels/AsynchronousServerSocketChannel.java \
java/nio/channels/AsynchronousSocketChannel.java \
@ -207,7 +206,6 @@ FILES_src = \
sun/nio/ch/SelChImpl.java \
sun/nio/ch/ServerSocketAdaptor.java \
sun/nio/ch/ServerSocketChannelImpl.java \
sun/nio/ch/SimpleAsynchronousDatagramChannelImpl.java \
sun/nio/ch/SinkChannelImpl.java \
sun/nio/ch/SocketAdaptor.java \
sun/nio/ch/SocketChannelImpl.java \

View File

@ -53,7 +53,7 @@ FILES_export = \
#
# Extra cc/linker flags.
#
LDLIBS += dsound.lib winmm.lib user32.lib
LDLIBS += dsound.lib winmm.lib user32.lib ole32.lib
CPPFLAGS += \
-DUSE_DAUDIO=TRUE \
-I$(SHARE_SRC)/native/com/sun/media/sound \

View File

@ -48,8 +48,8 @@ jar.jmx.name = jmx.jar
jar.jmx.sealed = true
jar.jmx.spec.title = JSR 003, 160, 255 - JMX API
jar.jmx.spec.version = ${project.spec.version}
jar.jmx.spec.vendor = Sun Microsystems, Inc.
jar.jmx.impl.title = JSR 003, 160, 255 - OpenJDK 7 JMX API
jar.jmx.spec.vendor = Oracle Corporation
jar.jmx.impl.title = JSR 003, 160, 255 - OpenJDK 7 JMX API
jar.jmx.impl.vendor = Project OpenJDK
javadoc.options=-J-Xmx256m

View File

@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
tzdata2010l
tzdata2010o

View File

@ -569,8 +569,8 @@ Rule HK 1953 only - Nov 1 3:30 0 -
Rule HK 1954 1964 - Mar Sun>=18 3:30 1:00 S
Rule HK 1954 only - Oct 31 3:30 0 -
Rule HK 1955 1964 - Nov Sun>=1 3:30 0 -
Rule HK 1965 1977 - Apr Sun>=16 3:30 1:00 S
Rule HK 1965 1977 - Oct Sun>=16 3:30 0 -
Rule HK 1965 1976 - Apr Sun>=16 3:30 1:00 S
Rule HK 1965 1976 - Oct Sun>=16 3:30 0 -
Rule HK 1973 only - Dec 30 3:30 1:00 S
Rule HK 1979 only - May Sun>=8 3:30 1:00 S
Rule HK 1979 only - Oct Sun>=16 3:30 0 -

View File

@ -306,13 +306,26 @@ Zone Indian/Cocos 6:27:40 - LMT 1900
# http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html
# </a>
# From Alexander Krivenyshev (2010-10-24):
# According to Radio Fiji and Fiji Times online, Fiji will end DST 3
# weeks earlier than expected - on March 6, 2011, not March 27, 2011...
# Here is confirmation from Government of the Republic of the Fiji Islands,
# Ministry of Information (fiji.gov.fj) web site:
# <a href="http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155">
# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155
# </a>
# or
# <a href="http://www.worldtimezone.com/dst_news/dst_news_fiji04.html">
# http://www.worldtimezone.com/dst_news/dst_news_fiji04.html
# </a>
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 S
Rule Fiji 1999 2000 - Feb lastSun 3:00 0 -
Rule Fiji 2009 only - Nov 29 2:00 1:00 S
Rule Fiji 2010 only - Mar lastSun 3:00 0 -
Rule Fiji 2010 only - Oct 24 2:00 1:00 S
Rule Fiji 2011 only - Mar lastSun 3:00 0 -
Rule Fiji 2011 only - Mar Sun>=1 3:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Pacific/Fiji 11:53:40 - LMT 1915 Oct 26 # Suva
12:00 Fiji FJ%sT # Fiji Time
@ -509,11 +522,21 @@ Zone Pacific/Pago_Pago 12:37:12 - LMT 1879 Jul 5
# http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf
# </a>
# From Raymond Hughes (2010-10-07):
# Please see
# <a href="http://www.mcil.gov.ws">
# http://www.mcil.gov.ws
# </a>,
# the Ministry of Commerce, Industry and Labour (sideframe) "Last Sunday
# September 2010 (26/09/10) - adjust clocks forward from 12:00 midnight
# to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks
# backwards from 1:00am to 12:00am"
Zone Pacific/Apia 12:33:04 - LMT 1879 Jul 5
-11:26:56 - LMT 1911
-11:30 - SAMT 1950 # Samoa Time
-11:00 - WST 2010 Sep 26
-11:00 1:00 WSDT 2011 Apr 3
-11:00 1:00 WSDT 2011 Apr 3 1:00
-11:00 - WST
# Solomon Is

View File

@ -63,7 +63,7 @@ AQ -6448-06406 Antarctica/Palmer Palmer Station, Anvers Island
AQ -6736+06253 Antarctica/Mawson Mawson Station, Holme Bay
AQ -6835+07758 Antarctica/Davis Davis Station, Vestfold Hills
AQ -6617+11031 Antarctica/Casey Casey Station, Bailey Peninsula
AQ -7824+10654 Antarctica/Vostok Vostok Station, S Magnetic Pole
AQ -7824+10654 Antarctica/Vostok Vostok Station, Lake Vostok
AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville Station, Terre Adelie
AQ -690022+0393524 Antarctica/Syowa Syowa Station, E Ongul I
AQ -5430+15857 Antarctica/Macquarie Macquarie Island Station, Macquarie Island

View File

@ -355,7 +355,6 @@ JavaMain(void * _args)
JavaVM *vm = 0;
JNIEnv *env = 0;
jstring mainClassName;
jclass mainClass;
jmethodID mainID;
jobjectArray mainArgs;

View File

@ -72,7 +72,7 @@ inflate_file(int fd, zentry *entry, int *size_out)
if (entry->how == STORED) {
*(char *)((size_t)in + entry->csize) = '\0';
if (size_out) {
*size_out = entry->csize;
*size_out = (int)entry->csize;
}
return (in);
} else if (entry->how == DEFLATED) {
@ -103,7 +103,7 @@ inflate_file(int fd, zentry *entry, int *size_out)
return (NULL);
}
if (size_out) {
*size_out = entry->isize;
*size_out = (int)entry->isize;
}
return (out);
} else
@ -317,7 +317,7 @@ find_file(int fd, zentry *entry, const char *file_name)
* manifest. If so, build the entry record from the data found in
* the header located and return success.
*/
if (CENNAM(p) == JLI_StrLen(file_name) &&
if ((size_t)CENNAM(p) == JLI_StrLen(file_name) &&
memcmp((p + CENHDR), file_name, JLI_StrLen(file_name)) == 0) {
if (lseek(fd, base_offset + CENOFF(p), SEEK_SET) < (off_t)0) {
free(buffer);
@ -606,8 +606,5 @@ JLI_ManifestIterate(const char *jarfile, attribute_closure ac, void *user_data)
}
free(mp);
close(fd);
if (rc == 0)
return (0);
else
return (-2);
return (rc == 0) ? 0 : -2;
}

View File

@ -290,12 +290,12 @@ FileList_join(FileList fl, char sep)
char *path;
char *p;
for (i = 0, size = 1; i < fl->size; i++)
size += JLI_StrLen(fl->files[i]) + 1;
size += (int)JLI_StrLen(fl->files[i]) + 1;
path = JLI_MemAlloc(size);
for (i = 0, p = path; i < fl->size; i++) {
int len = JLI_StrLen(fl->files[i]);
int len = (int)JLI_StrLen(fl->files[i]);
if (i > 0) *p++ = sep;
memcpy(p, fl->files[i], len);
p += len;
@ -309,7 +309,7 @@ static FileList
FileList_split(const char *path, char sep)
{
const char *p, *q;
int len = JLI_StrLen(path);
int len = (int)JLI_StrLen(path);
int count;
FileList fl;
for (count = 1, p = path; p < path + len; p++)
@ -330,7 +330,7 @@ FileList_split(const char *path, char sep)
static int
isJarFileName(const char *filename)
{
int len = JLI_StrLen(filename);
int len = (int)JLI_StrLen(filename);
return (len >= 4) &&
(filename[len - 4] == '.') &&
(equal(filename + len - 3, "jar") ||
@ -342,8 +342,8 @@ isJarFileName(const char *filename)
static char *
wildcardConcat(const char *wildcard, const char *basename)
{
int wildlen = JLI_StrLen(wildcard);
int baselen = JLI_StrLen(basename);
int wildlen = (int)JLI_StrLen(wildcard);
int baselen = (int)JLI_StrLen(basename);
char *filename = (char *) JLI_MemAlloc(wildlen + baselen);
/* Replace the trailing '*' with basename */
memcpy(filename, wildcard, wildlen-1);
@ -369,7 +369,7 @@ wildcardFileList(const char *wildcard)
static int
isWildcard(const char *filename)
{
int len = JLI_StrLen(filename);
int len = (int)JLI_StrLen(filename);
return (len > 0) &&
(filename[len - 1] == '*') &&
(len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) &&

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -253,7 +253,8 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
for (j = 0; j < 8; j++) {
if (AA[i][j] != 0) {
AA[i][j] = (byte)
alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF]) % 255];
alog[(255 + log[AA[i][j] & 0xFF] - log[pivot & 0xFF])
% 255];
}
}
for (t = 0; t < 4; t++) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -92,7 +92,8 @@ public final class ARCFOURCipher extends CipherSpi {
}
// core crypt code. OFB style, so works for both encryption and decryption
private void crypt(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) {
private void crypt(byte[] in, int inOfs, int inLen, byte[] out,
int outOfs) {
if (is < 0) {
// doFinal() was called, need to reset the cipher to initial state
init(lastKey);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,8 +31,8 @@ import javax.crypto.*;
import javax.crypto.spec.*;
/**
* This class implements the DESede algorithm (DES-EDE, tripleDES) in its various
* modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,
* This class implements the DESede algorithm (DES-EDE, tripleDES) in
* its various modes (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>,
* <code>CBC</code>, <code>PCBC</code>) and padding schemes
* (<code>PKCS5Padding</code>, <code>NoPadding</code>,
* <code>ISO10126Padding</code>).

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -190,7 +190,8 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
ike.initCause(e);
throw ike;
} catch (IOException e) {
InvalidKeyException ike = new InvalidKeyException("Error parsing key encoding: " + e.getMessage());
InvalidKeyException ike = new InvalidKeyException(
"Error parsing key encoding: " + e.getMessage());
ike.initCause(e);
throw ike;
}
@ -300,7 +301,8 @@ javax.crypto.interfaces.DHPrivateKey, Serializable {
DerInputStream in = new DerInputStream(this.key);
this.x = in.getBigInteger();
} catch (IOException e) {
InvalidKeyException ike = new InvalidKeyException("Error parsing key encoding: " + e.getMessage());
InvalidKeyException ike = new InvalidKeyException(
"Error parsing key encoding: " + e.getMessage());
ike.initCause(e);
throw ike;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -180,7 +180,8 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
throw new InvalidKeyException("Private-value length too big");
} catch (IOException e) {
throw new InvalidKeyException("Error parsing key encoding: " + e.toString());
throw new InvalidKeyException(
"Error parsing key encoding: " + e.toString());
}
}
@ -281,7 +282,8 @@ javax.crypto.interfaces.DHPublicKey, Serializable {
DerInputStream in = new DerInputStream(this.key);
this.y = in.getBigInteger();
} catch (IOException e) {
throw new InvalidKeyException("Error parsing key encoding: " + e.toString());
throw new InvalidKeyException(
"Error parsing key encoding: " + e.toString());
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -764,7 +764,8 @@ public final class JceKeyStore extends KeyStoreSpi {
cf = (CertificateFactory)cfs.get(certType);
} else {
// create new certificate factory
cf = CertificateFactory.getInstance(certType);
cf = CertificateFactory.getInstance(
certType);
// store the certificate factory so we can
// reuse it later
cfs.put(certType, cf);
@ -863,8 +864,9 @@ public final class JceKeyStore extends KeyStoreSpi {
dis.readFully(actual);
for (int i = 0; i < computed.length; i++) {
if (computed[i] != actual[i]) {
throw new IOException("Keystore was tampered with, or "
+ "password was incorrect");
throw new IOException(
"Keystore was tampered with, or "
+ "password was incorrect");
}
}
}

Some files were not shown because too many files have changed in this diff Show More