This commit is contained in:
J. Duke 2017-07-05 16:35:06 +02:00
commit f6f7413889
503 changed files with 21221 additions and 11239 deletions

View File

@ -1 +1,2 @@
cfeea66a3fa8ca3686a7cfa2d0ce8ab0169f168d jdk7-b24
cbc8ad9dd0e085a607427ea35411990982f19a36 jdk7-b25

View File

@ -1 +1,2 @@
55540e827aef970ecc010b7e06b912d991c8e3ce jdk7-b24
5e61d5df62586474414d1058e9186441aa908f51 jdk7-b25

View File

@ -1 +1,2 @@
a61af66fc99eb5ec9d50c05b0c599757b1289ceb jdk7-b24
7836be3e92d0a4f9ee7566f602c91f5609534e66 jdk7-b25

View File

@ -518,10 +518,10 @@ static bool core_get_lwp_regs(struct ps_prochandle* ph, lwpid_t lwp_id,
}
static ps_prochandle_ops core_ops = {
release: core_release,
p_pread: core_read_data,
p_pwrite: core_write_data,
get_lwp_regs: core_get_lwp_regs
.release= core_release,
.p_pread= core_read_data,
.p_pwrite= core_write_data,
.get_lwp_regs= core_get_lwp_regs
};
// read regs and create thread from NT_PRSTATUS entries from core file

View File

@ -291,10 +291,10 @@ static void process_cleanup(struct ps_prochandle* ph) {
}
static ps_prochandle_ops process_ops = {
release: process_cleanup,
p_pread: process_read_data,
p_pwrite: process_write_data,
get_lwp_regs: process_get_lwp_regs
.release= process_cleanup,
.p_pread= process_read_data,
.p_pwrite= process_write_data,
.get_lwp_regs= process_get_lwp_regs
};
// attach to the process. One and only one exposed stuff

View File

@ -80,6 +80,11 @@ ifneq ("$(filter $(LP64_ARCH),$(BUILDARCH))","")
MFLAGS += " LP64=1 "
endif
# pass USE_SUNCC further, through MFLAGS
ifdef USE_SUNCC
MFLAGS += " USE_SUNCC=1 "
endif
# The following renders pathnames in generated Makefiles valid on
# machines other than the machine containing the build tree.
#

View File

@ -35,6 +35,8 @@ CFLAGS += -DVM_LITTLE_ENDIAN
CFLAGS += -D_LP64=1
# The serviceability agent relies on frame pointer (%rbp) to walk thread stack
CFLAGS += -fno-omit-frame-pointer
ifndef USE_SUNCC
CFLAGS += -fno-omit-frame-pointer
endif
OPT_CFLAGS/compactingPermGenGen.o = -O1

View File

@ -63,7 +63,11 @@ QUIETLY$(MAKE_VERBOSE) = @
# For now, until the compiler is less wobbly:
TESTFLAGS = -Xbatch -showversion
PLATFORM_FILE = $(GAMMADIR)/build/$(OS_FAMILY)/platform_$(BUILDARCH)
ifdef USE_SUNCC
PLATFORM_FILE = $(GAMMADIR)/build/$(OS_FAMILY)/platform_$(BUILDARCH).suncc
else
PLATFORM_FILE = $(GAMMADIR)/build/$(OS_FAMILY)/platform_$(BUILDARCH)
endif
ifdef FORCE_TIERED
ifeq ($(VARIANT),tiered)

View File

@ -0,0 +1,93 @@
#
# Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
#
#------------------------------------------------------------------------
# CC, CPP & AS
CPP = CC
CC = cc
AS = $(CC) -c
ARCHFLAG = $(ARCHFLAG/$(BUILDARCH))
ARCHFLAG/i486 = -m32
ARCHFLAG/amd64 = -m64
CFLAGS += $(ARCHFLAG)
AOUT_FLAGS += $(ARCHFLAG)
LFLAGS += $(ARCHFLAG)
ASFLAGS += $(ARCHFLAG)
#------------------------------------------------------------------------
# Compiler flags
# position-independent code
PICFLAG = -KPIC
CFLAGS += $(PICFLAG)
# no more exceptions
CFLAGS += -features=no%except
# Reduce code bloat by reverting back to 5.0 behavior for static initializers
CFLAGS += -features=no%split_init
# allow zero sized arrays
CFLAGS += -features=zla
# Use C++ Interpreter
ifdef CC_INTERP
CFLAGS += -DCC_INTERP
endif
# We don't need libCstd.so and librwtools7.so, only libCrun.so
CFLAGS += -library=Crun
LIBS += -lCrun
CFLAGS += -mt
LFLAGS += -mt
# Compiler warnings are treated as errors
#WARNINGS_ARE_ERRORS = -errwarn=%all
CFLAGS_WARN/DEFAULT = $(WARNINGS_ARE_ERRORS)
# Special cases
CFLAGS_WARN/BYFILE = $(CFLAGS_WARN/$@)$(CFLAGS_WARN/DEFAULT$(CFLAGS_WARN/$@))
# The flags to use for an Optimized build
OPT_CFLAGS+=-xO4
OPT_CFLAGS/NOOPT=-xO0
#------------------------------------------------------------------------
# Linker flags
# Use $(MAPFLAG:FILENAME=real_file_name) to specify a map file.
MAPFLAG = -Wl,--version-script=FILENAME
# Use $(SONAMEFLAG:SONAME=soname) to specify the intrinsic name of a shared obj
SONAMEFLAG = -h SONAME
# Build shared library
SHARED_FLAG = -G
#------------------------------------------------------------------------
# Debug flags
DEBUG_CFLAGS += -g
FASTDEBUG_CFLAGS = -g0

View File

@ -0,0 +1,17 @@
os_family = linux
arch = x86
arch_model = x86_64
os_arch = linux_x86
os_arch_model = linux_x86_64
lib_arch = amd64
compiler = sparcWorks
gnu_dis_arch = amd64
sysdefs = -DLINUX -DSPARC_WORKS -D_GNU_SOURCE -DAMD64

View File

@ -0,0 +1,17 @@
os_family = linux
arch = x86
arch_model = x86_32
os_arch = linux_x86
os_arch_model = linux_x86_32
lib_arch = i386
compiler = sparcWorks
gnu_dis_arch = i386
sysdefs = -DLINUX -DSPARC_WORKS -D_GNU_SOURCE -DIA32

View File

@ -19,7 +19,7 @@
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
#
#
# Must also specify if CPU is little endian
@ -45,6 +45,10 @@ OPT_CFLAGS/os_solaris_x86_64.o = -xO1
OPT_CFLAGS/generateOptoStub.o = -xO2
OPT_CFLAGS/thread.o = -xO2
# Work around for 6624782
OPT_CFLAGS/instanceKlass.o = -Qoption ube -no_a2lf
OPT_CFLAGS/objArrayKlass.o = -Qoption ube -no_a2lf
else
ifeq ("${Platform_compiler}", "gcc")
@ -58,6 +62,6 @@ else
# error
_JUNK2_ := $(shell echo >&2 \
"*** ERROR: this compiler is not yet supported by this code base!")
@exit 1
@exit 1
endif
endif

View File

@ -44,6 +44,10 @@ CPP=cl.exe
# /Od Disable all optimizations
#
# NOTE: Normally following any of the above with a '-' will turn off that flag
#
# 6655385: For VS2003/2005 we now specify /Oy- (disable frame pointer
# omission.) This has little to no effect on performance while vastly
# improving the quality of crash log stack traces involving jvm.dll.
# These are always used in all compiles
CPP_FLAGS=/nologo /W3 /WX
@ -141,14 +145,14 @@ DEBUG_OPT_OPTION = /Od
!endif
!if "$(COMPILER_NAME)" == "VS2003"
PRODUCT_OPT_OPTION = /O2
FASTDEBUG_OPT_OPTION = /O2
PRODUCT_OPT_OPTION = /O2 /Oy-
FASTDEBUG_OPT_OPTION = /O2 /Oy-
DEBUG_OPT_OPTION = /Od
!endif
!if "$(COMPILER_NAME)" == "VS2005"
PRODUCT_OPT_OPTION = /O2
FASTDEBUG_OPT_OPTION = /O2
PRODUCT_OPT_OPTION = /O2 /Oy-
FASTDEBUG_OPT_OPTION = /O2 /Oy-
DEBUG_OPT_OPTION = /Od
GX_OPTION = /EHsc
# This VS2005 compiler has /GS as a default and requires bufferoverflowU.lib
@ -165,8 +169,8 @@ CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_DEPRECATE
# Compile for space above time.
!if "$(Variant)" == "kernel"
PRODUCT_OPT_OPTION = /O1
FASTDEBUG_OPT_OPTION = /O1
PRODUCT_OPT_OPTION = /O1 /Oy-
FASTDEBUG_OPT_OPTION = /O1 /Oy-
DEBUG_OPT_OPTION = /Od
!endif

View File

@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2007
HS_MAJOR_VER=12
HS_MINOR_VER=0
HS_BUILD_NUMBER=01
HS_BUILD_NUMBER=03
JDK_MAJOR_VER=1
JDK_MINOR_VER=7

View File

@ -2037,7 +2037,7 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr
int LIR_Assembler::shift_amount(BasicType t) {
int elem_size = type2aelembytes[t];
int elem_size = type2aelembytes(t);
switch (elem_size) {
case 1 : return 0;
case 2 : return 1;
@ -2360,7 +2360,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
op->tmp2()->as_register(),
op->tmp3()->as_register(),
arrayOopDesc::header_size(op->type()),
type2aelembytes[op->type()],
type2aelembytes(op->type()),
op->klass()->as_register(),
*op->stub()->entry());
}

View File

@ -179,7 +179,7 @@ LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index,
LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_opr,
BasicType type, bool needs_card_mark) {
int elem_size = type2aelembytes[type];
int elem_size = type2aelembytes(type);
int shift = exact_log2(elem_size);
LIR_Opr base_opr;

View File

@ -6023,7 +6023,7 @@ instruct cmovII_imm(cmpOp cmp, flagsReg icc, iRegI dst, immI11 src) %{
ins_pipe(ialu_imm);
%}
instruct cmovII_U_reg(cmpOp cmp, flagsRegU icc, iRegI dst, iRegI src) %{
instruct cmovII_U_reg(cmpOpU cmp, flagsRegU icc, iRegI dst, iRegI src) %{
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
ins_cost(150);
size(4);
@ -6032,7 +6032,7 @@ instruct cmovII_U_reg(cmpOp cmp, flagsRegU icc, iRegI dst, iRegI src) %{
ins_pipe(ialu_reg);
%}
instruct cmovII_U_imm(cmpOp cmp, flagsRegU icc, iRegI dst, immI11 src) %{
instruct cmovII_U_imm(cmpOpU cmp, flagsRegU icc, iRegI dst, immI11 src) %{
match(Set dst (CMoveI (Binary cmp icc) (Binary dst src)));
ins_cost(140);
size(4);

View File

@ -2911,6 +2911,7 @@ class StubGenerator: public StubCodeGenerator {
// These entry points require SharedInfo::stack0 to be set up in non-core builds
StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError), false);
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false);
StubRoutines::_throw_ArithmeticException_entry = generate_throw_exception("ArithmeticException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_ArithmeticException), true);
StubRoutines::_throw_NullPointerException_entry = generate_throw_exception("NullPointerException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException), true);
StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false);

View File

@ -28,6 +28,12 @@
int VM_Version::_features = VM_Version::unknown_m;
const char* VM_Version::_features_str = "";
bool VM_Version::is_niagara1_plus() {
// This is a placeholder until the real test is determined.
return is_niagara1() &&
(os::processor_count() > maximum_niagara1_processor_count());
}
void VM_Version::initialize() {
_features = determine_features();
PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes();
@ -160,3 +166,13 @@ void VM_Version::allow_all() {
void VM_Version::revert() {
_features = saved_features;
}
unsigned int VM_Version::calc_parallel_worker_threads() {
unsigned int result;
if (is_niagara1_plus()) {
result = nof_parallel_worker_threads(5, 16, 8);
} else {
result = nof_parallel_worker_threads(5, 8, 8);
}
return result;
}

View File

@ -64,6 +64,11 @@ protected:
static bool is_niagara1(int features) { return (features & niagara1_m) == niagara1_m; }
static int maximum_niagara1_processor_count() { return 32; }
// Returns true if the platform is in the niagara line and
// newer than the niagara1.
static bool is_niagara1_plus();
public:
// Initialization
static void initialize();
@ -129,4 +134,7 @@ public:
// Override the Abstract_VM_Version implementation.
static uint page_size_count() { return is_sun4v() ? 4 : 2; }
// Calculates the number of parallel threads
static unsigned int calc_parallel_worker_threads();
};

View File

@ -175,17 +175,12 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
// %%%% Could load both offset and interface in one ldx, if they were
// in the opposite order. This would save a load.
__ ld_ptr(L0, base + itableOffsetEntry::interface_offset_in_bytes(), L1);
#ifdef ASSERT
Label ok;
// Check that entry is non-null and an Oop
__ bpr(Assembler::rc_nz, false, Assembler::pt, L1, ok);
__ delayed()->nop();
__ stop("null entry point found in itable's offset table");
__ bind(ok);
__ verify_oop(L1);
#endif // ASSERT
__ cmp(G5_interface, L1);
// If the entry is NULL then we've reached the end of the table
// without finding the expected interface, so throw an exception
Label throw_icce;
__ bpr(Assembler::rc_z, false, Assembler::pn, L1, throw_icce);
__ delayed()->cmp(G5_interface, L1);
__ brx(Assembler::notEqual, true, Assembler::pn, search);
__ delayed()->add(L0, itableOffsetEntry::size() * wordSize, L0);
@ -223,24 +218,30 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
__ JMP(G3_scratch, 0);
__ delayed()->nop();
__ bind(throw_icce);
Address icce(G3_scratch, StubRoutines::throw_IncompatibleClassChangeError_entry());
__ jump_to(icce, 0);
__ delayed()->restore();
masm->flush();
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
s->set_exception_points(npe_addr, ame_addr);
return s;
}
int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) return 999;
if (TraceJumps || DebugVtables || CountCompiledCalls || VerifyOops) return 1000;
else {
const int slop = 2*BytesPerInstWord; // sethi;add (needed for long offsets)
if (is_vtable_stub) {
const int basic = 5*BytesPerInstWord; // ld;ld;ld,jmp,nop
return basic + slop;
} else {
#ifdef ASSERT
return 999;
#endif // ASSERT
const int basic = 17*BytesPerInstWord; // save, ld, ld, sll, and, add, add, ld, cmp, br, add, ld, add, ld, ld, jmp, restore
// save, ld, ld, sll, and, add, add, ld, cmp, br, add, ld, add, ld, ld, jmp, restore, sethi, jmpl, restore
const int basic = (20 LP64_ONLY(+ 6)) * BytesPerInstWord;
return (basic + slop);
}
}
@ -252,29 +253,3 @@ int VtableStub::pd_code_alignment() {
const unsigned int icache_line_size = 32;
return icache_line_size;
}
//Reconciliation History
// 1.2 97/12/09 17:13:31 vtableStubs_i486.cpp
// 1.4 98/01/21 19:18:37 vtableStubs_i486.cpp
// 1.5 98/02/13 16:33:55 vtableStubs_i486.cpp
// 1.7 98/03/05 17:17:28 vtableStubs_i486.cpp
// 1.9 98/05/18 09:26:17 vtableStubs_i486.cpp
// 1.10 98/05/26 16:28:13 vtableStubs_i486.cpp
// 1.11 98/05/27 08:51:35 vtableStubs_i486.cpp
// 1.12 98/06/15 15:04:12 vtableStubs_i486.cpp
// 1.13 98/07/28 18:44:22 vtableStubs_i486.cpp
// 1.15 98/08/28 11:31:19 vtableStubs_i486.cpp
// 1.16 98/09/02 12:58:31 vtableStubs_i486.cpp
// 1.17 98/09/04 12:15:52 vtableStubs_i486.cpp
// 1.18 98/11/19 11:55:24 vtableStubs_i486.cpp
// 1.19 99/01/12 14:57:56 vtableStubs_i486.cpp
// 1.20 99/01/19 17:42:52 vtableStubs_i486.cpp
// 1.22 99/01/21 10:29:25 vtableStubs_i486.cpp
// 1.30 99/06/02 15:27:39 vtableStubs_i486.cpp
// 1.26 99/06/24 14:25:07 vtableStubs_i486.cpp
// 1.23 99/02/22 14:37:52 vtableStubs_i486.cpp
// 1.28 99/06/29 18:06:17 vtableStubs_i486.cpp
// 1.29 99/07/22 17:03:44 vtableStubs_i486.cpp
// 1.30 99/08/11 09:33:27 vtableStubs_i486.cpp
//End

View File

@ -2672,6 +2672,22 @@ void Assembler::movlpd(XMMRegister dst, Address src) {
emit_sse_operand(dst, src);
}
void Assembler::cvtdq2pd(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_sse2(), "");
emit_byte(0xF3);
emit_byte(0x0F);
emit_byte(0xE6);
emit_sse_operand(dst, src);
}
void Assembler::cvtdq2ps(XMMRegister dst, XMMRegister src) {
assert(VM_Version::supports_sse2(), "");
emit_byte(0x0F);
emit_byte(0x5B);
emit_sse_operand(dst, src);
}
emit_sse_instruction(andps, sse, 0, 0x54, XMMRegister, XMMRegister);
emit_sse_instruction(andpd, sse2, 0x66, 0x54, XMMRegister, XMMRegister);

View File

@ -901,6 +901,8 @@ class Assembler : public AbstractAssembler {
void cvtss2sd(XMMRegister dst, XMMRegister src);
void cvtsd2ss(XMMRegister dst, Address src); // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value
void cvtsd2ss(XMMRegister dst, XMMRegister src);
void cvtdq2pd(XMMRegister dst, XMMRegister src);
void cvtdq2ps(XMMRegister dst, XMMRegister src);
void cvtsi2ss(XMMRegister dst, Address src); // Convert Doubleword Integer to Scalar Single-Precision Floating-Point Value
void cvtsi2ss(XMMRegister dst, Register src);

View File

@ -1304,7 +1304,7 @@ void Assembler::movl(Address dst, Register src) {
emit_operand(src, dst);
}
void Assembler::mov64(Register dst, int64_t imm64) {
void Assembler::mov64(Register dst, intptr_t imm64) {
InstructionMark im(this);
int encode = prefixq_and_encode(dst->encoding());
emit_byte(0xB8 | encode);
@ -1331,7 +1331,7 @@ void Assembler::movq(Register dst, Address src) {
emit_operand(dst, src);
}
void Assembler::mov64(Address dst, int64_t imm32) {
void Assembler::mov64(Address dst, intptr_t imm32) {
assert(is_simm32(imm32), "lost bits");
InstructionMark im(this);
prefixq(dst);
@ -3372,6 +3372,21 @@ void Assembler::cvtss2sd(XMMRegister dst, XMMRegister src) {
emit_byte(0xC0 | encode);
}
void Assembler::cvtdq2pd(XMMRegister dst, XMMRegister src) {
emit_byte(0xF3);
int encode = prefix_and_encode(dst->encoding(), src->encoding());
emit_byte(0x0F);
emit_byte(0xE6);
emit_byte(0xC0 | encode);
}
void Assembler::cvtdq2ps(XMMRegister dst, XMMRegister src) {
int encode = prefix_and_encode(dst->encoding(), src->encoding());
emit_byte(0x0F);
emit_byte(0x5B);
emit_byte(0xC0 | encode);
}
void Assembler::cvtsd2ss(XMMRegister dst, XMMRegister src) {
emit_byte(0xF2);
int encode = prefix_and_encode(dst->encoding(), src->encoding());

View File

@ -922,6 +922,8 @@ class Assembler : public AbstractAssembler {
void cvttsd2siq(Register dst, XMMRegister src); // truncates
void cvtss2sd(XMMRegister dst, XMMRegister src);
void cvtsd2ss(XMMRegister dst, XMMRegister src);
void cvtdq2pd(XMMRegister dst, XMMRegister src);
void cvtdq2ps(XMMRegister dst, XMMRegister src);
void pxor(XMMRegister dst, Address src); // Xor Packed Byte Integer Values
void pxor(XMMRegister dst, XMMRegister src); // Xor Packed Byte Integer Values

View File

@ -546,8 +546,8 @@ void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst,
// set rsi.edi to the end of the arrays (arrays have same length)
// negate the index
__ leal(rsi, Address(rsi, rax, Address::times_2, type2aelembytes[T_CHAR]));
__ leal(rdi, Address(rdi, rax, Address::times_2, type2aelembytes[T_CHAR]));
__ leal(rsi, Address(rsi, rax, Address::times_2, type2aelembytes(T_CHAR)));
__ leal(rdi, Address(rdi, rax, Address::times_2, type2aelembytes(T_CHAR)));
__ negl(rax);
// compare the strings in a loop
@ -1232,7 +1232,7 @@ void LIR_Assembler::prefetchw(LIR_Opr src) {
NEEDS_CLEANUP; // This could be static?
Address::ScaleFactor LIR_Assembler::array_element_size(BasicType type) const {
int elem_size = type2aelembytes[type];
int elem_size = type2aelembytes(type);
switch (elem_size) {
case 1: return Address::times_1;
case 2: return Address::times_2;
@ -2739,7 +2739,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
assert(default_type != NULL && default_type->is_array_klass() && default_type->is_loaded(), "must be true at this point");
int elem_size = type2aelembytes[basic_type];
int elem_size = type2aelembytes(basic_type);
int shift_amount;
Address::ScaleFactor scale;

View File

@ -151,7 +151,7 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o
LIR_Address* addr;
if (index_opr->is_constant()) {
int elem_size = type2aelembytes[type];
int elem_size = type2aelembytes(type);
addr = new LIR_Address(array_opr,
offset_in_bytes + index_opr->as_jint() * elem_size, type);
} else {

View File

@ -1416,8 +1416,8 @@ class StubGenerator: public StubCodeGenerator {
// ======== end loop ========
// It was a real error; we must depend on the caller to finish the job.
// Register rdx = -1 * number of *remaining* oops, r14 = *total* oops.
// Emit GC store barriers for the oops we have copied (r14 + rdx),
// Register "count" = -1 * number of *remaining* oops, length_arg = *total* oops.
// Emit GC store barriers for the oops we have copied (length_arg + count),
// and report their number to the caller.
__ addl(count, length_arg); // transfers = (length - remaining)
__ movl(rax, count); // save the value
@ -1430,6 +1430,7 @@ class StubGenerator: public StubCodeGenerator {
// Come here on success only.
__ BIND(L_do_card_marks);
__ movl(count, length_arg);
__ movl(to, to_arg); // reload
gen_write_ref_array_post_barrier(to, count);
__ xorl(rax, rax); // return 0 on success
@ -2151,6 +2152,7 @@ class StubGenerator: public StubCodeGenerator {
// These entry points require SharedInfo::stack0 to be set up in non-core builds
// and need to be relocatable, so they each fabricate a RuntimeStub internally.
StubRoutines::_throw_AbstractMethodError_entry = generate_throw_exception("AbstractMethodError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_AbstractMethodError), false);
StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false);
StubRoutines::_throw_ArithmeticException_entry = generate_throw_exception("ArithmeticException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_ArithmeticException), true);
StubRoutines::_throw_NullPointerException_entry = generate_throw_exception("NullPointerException throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException), true);
StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false);

View File

@ -2832,6 +2832,13 @@ class StubGenerator: public StubCodeGenerator {
throw_AbstractMethodError),
false);
StubRoutines::_throw_IncompatibleClassChangeError_entry =
generate_throw_exception("IncompatibleClassChangeError throw_exception",
CAST_FROM_FN_PTR(address,
SharedRuntime::
throw_IncompatibleClassChangeError),
false);
StubRoutines::_throw_ArithmeticException_entry =
generate_throw_exception("ArithmeticException throw_exception",
CAST_FROM_FN_PTR(address,

View File

@ -321,6 +321,20 @@ void VM_Version::get_processor_features() {
UseXmmRegToRegMoveAll = false;
}
}
if( FLAG_IS_DEFAULT(UseXmmI2F) ) {
if( supports_sse4a() ) {
UseXmmI2F = true;
} else {
UseXmmI2F = false;
}
}
if( FLAG_IS_DEFAULT(UseXmmI2D) ) {
if( supports_sse4a() ) {
UseXmmI2D = true;
} else {
UseXmmI2D = false;
}
}
}
if( is_intel() ) { // Intel cpus specific settings

View File

@ -265,6 +265,20 @@ void VM_Version::get_processor_features() {
UseXmmRegToRegMoveAll = false;
}
}
if( FLAG_IS_DEFAULT(UseXmmI2F) ) {
if( supports_sse4a() ) {
UseXmmI2F = true;
} else {
UseXmmI2F = false;
}
}
if( FLAG_IS_DEFAULT(UseXmmI2D) ) {
if( supports_sse4a() ) {
UseXmmI2D = true;
} else {
UseXmmI2D = false;
}
}
}
if( is_intel() ) { // Intel cpus specific settings

View File

@ -138,29 +138,21 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
__ round_to(rbx, BytesPerLong);
}
Label hit, next, entry;
Label hit, next, entry, throw_icce;
__ jmp(entry);
__ jmpb(entry);
__ bind(next);
__ addl(rbx, itableOffsetEntry::size() * wordSize);
__ bind(entry);
#ifdef ASSERT
// Check that the entry is non-null
if (DebugVtables) {
Label L;
__ pushl(rbx);
__ movl(rbx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
__ testl(rbx, rbx);
__ jcc(Assembler::notZero, L);
__ stop("null entry point found in itable's offset table");
__ bind(L);
__ popl(rbx);
}
#endif
__ cmpl(rax, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
// If the entry is NULL then we've reached the end of the table
// without finding the expected interface, so throw an exception
__ movl(rdx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
__ testl(rdx, rdx);
__ jcc(Assembler::zero, throw_icce);
__ cmpl(rax, rdx);
__ jcc(Assembler::notEqual, next);
// We found a hit, move offset into rbx,
@ -194,7 +186,15 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
address ame_addr = __ pc();
__ jmp(Address(method, methodOopDesc::from_compiled_offset()));
__ bind(throw_icce);
// Restore saved register
__ popl(rdx);
__ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
masm->flush();
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
s->set_exception_points(npe_addr, ame_addr);
return s;
}
@ -207,7 +207,7 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0);
} else {
// Itable stub size
return (DebugVtables ? 140 : 55) + (CountCompiledCalls ? 6 : 0);
return (DebugVtables ? 144 : 64) + (CountCompiledCalls ? 6 : 0);
}
}

View File

@ -153,7 +153,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
// Round up to align_object_offset boundary
__ round_to_q(rbx, BytesPerLong);
}
Label hit, next, entry;
Label hit, next, entry, throw_icce;
__ jmpb(entry);
@ -162,22 +162,13 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
__ bind(entry);
#ifdef ASSERT
// Check that the entry is non-null
if (DebugVtables) {
Label L;
__ pushq(rbx);
__ movq(rbx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
__ testq(rbx, rbx);
__ jcc(Assembler::notZero, L);
__ stop("null entry point found in itable's offset table");
__ bind(L);
__ popq(rbx);
}
#endif
__ cmpq(rax, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
__ jcc(Assembler::notEqual, next);
// If the entry is NULL then we've reached the end of the table
// without finding the expected interface, so throw an exception
__ movq(j_rarg1, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
__ testq(j_rarg1, j_rarg1);
__ jcc(Assembler::zero, throw_icce);
__ cmpq(rax, j_rarg1);
__ jccb(Assembler::notEqual, next);
// We found a hit, move offset into j_rarg1
__ movl(j_rarg1, Address(rbx, itableOffsetEntry::offset_offset_in_bytes()));
@ -203,23 +194,31 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
#ifdef ASSERT
if (DebugVtables) {
Label L2;
__ cmpq(method, (int)NULL);
__ jcc(Assembler::equal, L2);
__ cmpq(Address(method, methodOopDesc::from_compiled_offset()), (int)NULL_WORD);
__ jcc(Assembler::notZero, L2);
__ stop("compiler entrypoint is null");
__ bind(L2);
}
if (DebugVtables) {
Label L2;
__ cmpq(method, (int)NULL);
__ jcc(Assembler::equal, L2);
__ cmpq(Address(method, methodOopDesc::from_compiled_offset()), (int)NULL_WORD);
__ jcc(Assembler::notZero, L2);
__ stop("compiler entrypoint is null");
__ bind(L2);
}
#endif // ASSERT
// rbx: methodOop
// j_rarg0: receiver
address ame_addr = __ pc();
__ jmp(Address(method, methodOopDesc::from_compiled_offset()));
// rbx: methodOop
// j_rarg0: receiver
address ame_addr = __ pc();
__ jmp(Address(method, methodOopDesc::from_compiled_offset()));
__ bind(throw_icce);
// Restore saved register
__ popq(j_rarg1);
__ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
__ flush();
guarantee(__ pc() <= s->code_end(), "overflowed buffer");
s->set_exception_points(npe_addr, ame_addr);
return s;
}
@ -230,7 +229,7 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
return (DebugVtables ? 512 : 24) + (CountCompiledCalls ? 13 : 0);
} else {
// Itable stub size
return (DebugVtables ? 636 : 64) + (CountCompiledCalls ? 13 : 0);
return (DebugVtables ? 636 : 72) + (CountCompiledCalls ? 13 : 0);
}
}

View File

@ -10970,7 +10970,7 @@ instruct convI2D_reg(regD dst, stackSlotI src) %{
%}
instruct convI2XD_reg(regXD dst, eRegI src) %{
predicate( UseSSE>=2 );
predicate( UseSSE>=2 && !UseXmmI2D );
match(Set dst (ConvI2D src));
format %{ "CVTSI2SD $dst,$src" %}
opcode(0xF2, 0x0F, 0x2A);
@ -10987,6 +10987,20 @@ instruct convI2XD_mem(regXD dst, memory mem) %{
ins_pipe( pipe_slow );
%}
instruct convXI2XD_reg(regXD dst, eRegI src)
%{
predicate( UseSSE>=2 && UseXmmI2D );
match(Set dst (ConvI2D src));
format %{ "MOVD $dst,$src\n\t"
"CVTDQ2PD $dst,$dst\t# i2d" %}
ins_encode %{
__ movd($dst$$XMMRegister, $src$$Register);
__ cvtdq2pd($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe(pipe_slow); // XXX
%}
instruct convI2D_mem(regD dst, memory mem) %{
predicate( UseSSE<=1 && !Compile::current()->select_24_bit_instr());
match(Set dst (ConvI2D (LoadI mem)));
@ -11062,7 +11076,7 @@ instruct convI2F_mem(regF dst, memory mem) %{
// Convert an int to a float in xmm; no rounding step needed.
instruct convI2X_reg(regX dst, eRegI src) %{
predicate(UseSSE>=1);
predicate( UseSSE==1 || UseSSE>=2 && !UseXmmI2F );
match(Set dst (ConvI2F src));
format %{ "CVTSI2SS $dst, $src" %}
@ -11071,6 +11085,20 @@ instruct convI2X_reg(regX dst, eRegI src) %{
ins_pipe( pipe_slow );
%}
instruct convXI2X_reg(regX dst, eRegI src)
%{
predicate( UseSSE>=2 && UseXmmI2F );
match(Set dst (ConvI2F src));
format %{ "MOVD $dst,$src\n\t"
"CVTDQ2PS $dst,$dst\t# i2f" %}
ins_encode %{
__ movd($dst$$XMMRegister, $src$$Register);
__ cvtdq2ps($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe(pipe_slow); // XXX
%}
instruct convI2L_reg( eRegL dst, eRegI src, eFlagsReg cr) %{
match(Set dst (ConvI2L src));
effect(KILL cr);

View File

@ -10098,6 +10098,7 @@ instruct convD2L_reg_reg(rRegL dst, regD src, rFlagsReg cr)
instruct convI2F_reg_reg(regF dst, rRegI src)
%{
predicate(!UseXmmI2F);
match(Set dst (ConvI2F src));
format %{ "cvtsi2ssl $dst, $src\t# i2f" %}
@ -10118,6 +10119,7 @@ instruct convI2F_reg_mem(regF dst, memory src)
instruct convI2D_reg_reg(regD dst, rRegI src)
%{
predicate(!UseXmmI2D);
match(Set dst (ConvI2D src));
format %{ "cvtsi2sdl $dst, $src\t# i2d" %}
@ -10136,6 +10138,34 @@ instruct convI2D_reg_mem(regD dst, memory src)
ins_pipe(pipe_slow); // XXX
%}
instruct convXI2F_reg(regF dst, rRegI src)
%{
predicate(UseXmmI2F);
match(Set dst (ConvI2F src));
format %{ "movdl $dst, $src\n\t"
"cvtdq2psl $dst, $dst\t# i2f" %}
ins_encode %{
__ movdl($dst$$XMMRegister, $src$$Register);
__ cvtdq2ps($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe(pipe_slow); // XXX
%}
instruct convXI2D_reg(regD dst, rRegI src)
%{
predicate(UseXmmI2D);
match(Set dst (ConvI2D src));
format %{ "movdl $dst, $src\n\t"
"cvtdq2pdl $dst, $dst\t# i2d" %}
ins_encode %{
__ movdl($dst$$XMMRegister, $src$$Register);
__ cvtdq2pd($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe(pipe_slow); // XXX
%}
instruct convL2F_reg_reg(regF dst, rRegL src)
%{
match(Set dst (ConvL2F src));

View File

@ -232,7 +232,7 @@ LinuxAttachOperation* LinuxAttachListener::read_request(int s) {
// where <ver> is the protocol version (1), <cmd> is the command
// name ("load", "datadump", ...), and <arg> is an argument
int expected_str_count = 2 + AttachOperation::arg_count_max;
int max_len = (strlen(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
const int max_len = (sizeof(ver_str) + 1) + (AttachOperation::name_length_max + 1) +
AttachOperation::arg_count_max*(AttachOperation::arg_length_max + 1);
char buf[max_len];

View File

@ -116,6 +116,20 @@ julong os::physical_memory() {
return Linux::physical_memory();
}
julong os::allocatable_physical_memory(julong size) {
#ifdef _LP64
return size;
#else
julong result = MIN2(size, (julong)3800*M);
if (!is_allocatable(result)) {
// See comments under solaris for alignment considerations
julong reasonable_size = (julong)2*G - 2 * os::vm_page_size();
result = MIN2(size, reasonable_size);
}
return result;
#endif // _LP64
}
////////////////////////////////////////////////////////////////////////////////
// environment support
@ -1247,19 +1261,13 @@ jlong os::elapsed_frequency() {
return (1000 * 1000);
}
jlong os::timeofday() {
jlong os::javaTimeMillis() {
timeval time;
int status = gettimeofday(&time, NULL);
assert(status != -1, "linux error");
return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);
}
// Must return millis since Jan 1 1970 for JVM_CurrentTimeMillis
// _use_global_time is only set if CacheTimeMillis is true
jlong os::javaTimeMillis() {
return (_use_global_time ? read_global_time() : timeofday());
}
#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC (1)
#endif
@ -2472,6 +2480,10 @@ bool os::can_commit_large_page_memory() {
return false;
}
bool os::can_execute_large_page_memory() {
return false;
}
// Reserve memory at an arbitrary address, only if that area is
// available (and not reserved for something else).

View File

@ -1691,19 +1691,14 @@ jlong getTimeMillis() {
return (jlong)(nanotime / NANOSECS_PER_MILLISECS);
}
jlong os::timeofday() {
// Must return millis since Jan 1 1970 for JVM_CurrentTimeMillis
jlong os::javaTimeMillis() {
timeval t;
if (gettimeofday( &t, NULL) == -1)
fatal1("timeofday: gettimeofday (%s)", strerror(errno));
fatal1("os::javaTimeMillis: gettimeofday (%s)", strerror(errno));
return jlong(t.tv_sec) * 1000 + jlong(t.tv_usec) / 1000;
}
// Must return millis since Jan 1 1970 for JVM_CurrentTimeMillis
// _use_global_time is only set if CacheTimeMillis is true
jlong os::javaTimeMillis() {
return (_use_global_time ? read_global_time() : timeofday());
}
jlong os::javaTimeNanos() {
return (jlong)getTimeNanos();
}
@ -2785,16 +2780,15 @@ char* os::Solaris::mmap_chunk(char *addr, size_t size, int flags, int prot) {
return b;
}
char*
os::reserve_memory(size_t bytes, char* requested_addr, size_t alignment_hint) {
char* addr = NULL;
int flags;
char* os::Solaris::anon_mmap(char* requested_addr, size_t bytes, size_t alignment_hint, bool fixed) {
char* addr = requested_addr;
int flags = MAP_PRIVATE | MAP_NORESERVE;
flags = MAP_PRIVATE | MAP_NORESERVE;
if (requested_addr != NULL) {
flags |= MAP_FIXED;
addr = requested_addr;
} else if (has_map_align && alignment_hint > (size_t) vm_page_size()) {
assert(!(fixed && (alignment_hint > 0)), "alignment hint meaningless with fixed mmap");
if (fixed) {
flags |= MAP_FIXED;
} else if (has_map_align && (alignment_hint > (size_t) vm_page_size())) {
flags |= MAP_ALIGN;
addr = (char*) alignment_hint;
}
@ -2802,11 +2796,14 @@ os::reserve_memory(size_t bytes, char* requested_addr, size_t alignment_hint) {
// Map uncommitted pages PROT_NONE so we fail early if we touch an
// uncommitted page. Otherwise, the read/write might succeed if we
// have enough swap space to back the physical page.
addr = Solaris::mmap_chunk(addr, bytes, flags, PROT_NONE);
return mmap_chunk(addr, bytes, flags, PROT_NONE);
}
char* os::reserve_memory(size_t bytes, char* requested_addr, size_t alignment_hint) {
char* addr = Solaris::anon_mmap(requested_addr, bytes, alignment_hint, (requested_addr != NULL));
guarantee(requested_addr == NULL || requested_addr == addr,
"OS failed to return requested mmap address.");
return addr;
}
@ -2832,6 +2829,31 @@ char* os::attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
// in one of the methods further up the call chain. See bug 5044738.
assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block");
// Since snv_84, Solaris attempts to honor the address hint - see 5003415.
// Give it a try, if the kernel honors the hint we can return immediately.
char* addr = Solaris::anon_mmap(requested_addr, bytes, 0, false);
volatile int err = errno;
if (addr == requested_addr) {
return addr;
} else if (addr != NULL) {
unmap_memory(addr, bytes);
}
if (PrintMiscellaneous && Verbose) {
char buf[256];
buf[0] = '\0';
if (addr == NULL) {
jio_snprintf(buf, sizeof(buf), ": %s", strerror(err));
}
warning("attempt_reserve_memory_at: couldn't reserve %d bytes at "
PTR_FORMAT ": reserve_memory_helper returned " PTR_FORMAT
"%s", bytes, requested_addr, addr, buf);
}
// Address hint method didn't work. Fall back to the old method.
// In theory, once SNV becomes our oldest supported platform, this
// code will no longer be needed.
//
// Repeatedly allocate blocks until the block is allocated at the
// right spot. Give up after max_tries.
int i;
@ -3067,6 +3089,8 @@ bool os::large_page_init() {
if (UseISM) {
// ISM disables MPSS to be compatible with old JDK behavior
UseMPSS = false;
_page_sizes[0] = _large_page_size;
_page_sizes[1] = vm_page_size();
}
UseMPSS = UseMPSS &&
@ -3156,6 +3180,10 @@ bool os::can_commit_large_page_memory() {
return UseISM ? false : true;
}
bool os::can_execute_large_page_memory() {
return UseISM ? false : true;
}
static int os_sleep(jlong millis, bool interruptible) {
const jlong limit = INT_MAX;
jlong prevtime;

View File

@ -156,6 +156,7 @@ class Solaris {
static int get_dev_zero_fd() { return _dev_zero_fd; }
static void set_dev_zero_fd(int fd) { _dev_zero_fd = fd; }
static char* mmap_chunk(char *addr, size_t size, int flags, int prot);
static char* anon_mmap(char* requested_addr, size_t bytes, size_t alignment_hint, bool fixed);
static bool mpss_sanity_check(bool warn, size_t * page_size);
static bool ism_sanity_check (bool warn, size_t * page_size);

View File

@ -621,7 +621,12 @@ julong os::physical_memory() {
}
julong os::allocatable_physical_memory(julong size) {
#ifdef _LP64
return size;
#else
// Limit to 1400m because of the 2gb address space wall
return MIN2(size, (julong)1400*M);
#endif
}
// VC6 lacks DWORD_PTR
@ -732,20 +737,13 @@ FILETIME java_to_windows_time(jlong l) {
return result;
}
jlong os::timeofday() {
FILETIME wt;
GetSystemTimeAsFileTime(&wt);
return windows_to_java_time(wt);
}
// Must return millis since Jan 1 1970 for JVM_CurrentTimeMillis
// _use_global_time is only set if CacheTimeMillis is true
jlong os::javaTimeMillis() {
if (UseFakeTimers) {
return fake_time++;
} else {
return (_use_global_time ? read_global_time() : timeofday());
FILETIME wt;
GetSystemTimeAsFileTime(&wt);
return windows_to_java_time(wt);
}
}
@ -2518,9 +2516,13 @@ bool os::can_commit_large_page_memory() {
return false;
}
bool os::can_execute_large_page_memory() {
return true;
}
char* os::reserve_memory_special(size_t bytes) {
DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
char * res = (char *)VirtualAlloc(NULL, bytes, flag, PAGE_READWRITE);
char * res = (char *)VirtualAlloc(NULL, bytes, flag, PAGE_EXECUTE_READWRITE);
return res;
}

View File

@ -60,7 +60,18 @@ inline u4 Bytes::swap_u4(u4 x) {
#ifdef AMD64
inline u8 Bytes::swap_u8(u8 x) {
#ifdef SPARC_WORKS
// workaround for SunStudio12 CR6615391
__asm__ __volatile__ (
"bswapq %0"
:"=r" (x) // output : register 0 => x
:"0" (x) // input : x => register 0
:"0" // clobbered register
);
return x;
#else
return bswap_64(x);
#endif
}
#else
// Helper function for swap_u8

View File

@ -62,8 +62,14 @@
#endif // AMD64
address os::current_stack_pointer() {
#ifdef SPARC_WORKS
register void *esp;
__asm__("mov %%"SPELL_REG_SP", %0":"=r"(esp));
return (address) ((char*)esp + sizeof(long)*2);
#else
register void *esp __asm__ (SPELL_REG_SP);
return (address) esp;
#endif
}
char* os::non_memory_address_word() {
@ -139,7 +145,12 @@ frame os::get_sender_for_C_frame(frame* fr) {
}
intptr_t* _get_previous_fp() {
#ifdef SPARC_WORKS
register intptr_t **ebp;
__asm__("mov %%"SPELL_REG_FP", %0":"=r"(ebp));
#else
register intptr_t **ebp __asm__ (SPELL_REG_FP);
#endif
return (intptr_t*) *ebp; // we want what it points to.
}
@ -157,23 +168,8 @@ frame os::current_frame() {
}
}
// Utility functions
julong os::allocatable_physical_memory(julong size) {
#ifdef AMD64
return size;
#else
julong result = MIN2(size, (julong)3800*M);
if (!is_allocatable(result)) {
// See comments under solaris for alignment considerations
julong reasonable_size = (julong)2*G - 2 * os::vm_page_size();
result = MIN2(size, reasonable_size);
}
return result;
#endif // AMD64
}
// From IA32 System Programming Guide
enum {
trap_page_fault = 0xE
@ -575,7 +571,9 @@ bool os::Linux::supports_variable_stack_size() { return true; }
#else
size_t os::Linux::min_stack_allowed = (48 DEBUG_ONLY(+4))*K;
#ifdef __GNUC__
#define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;})
#endif
// Test if pthread library can support variable thread stack size. LinuxThreads
// in fixed stack mode allocates 2M fixed slot for each thread. LinuxThreads
@ -606,7 +604,11 @@ bool os::Linux::supports_variable_stack_size() {
// return true and skip _thread_safety_check(), so we may not be able to
// detect stack-heap collisions. But otherwise it's harmless.
//
#ifdef __GNUC__
return (GET_GS() != 0);
#else
return false;
#endif
}
}
#endif // AMD64

View File

@ -105,7 +105,7 @@ LIR_Opr LIR_OprFact::dummy_value_type(ValueType* type) {
LIR_Address::Scale LIR_Address::scale(BasicType type) {
int elem_size = type2aelembytes[type];
int elem_size = type2aelembytes(type);
switch (elem_size) {
case 1: return LIR_Address::times_1;
case 2: return LIR_Address::times_2;

View File

@ -104,7 +104,7 @@ public:
};
void BCEscapeAnalyzer::set_returned(ArgumentMap vars) {
for (int i = 0; i <= _arg_size; i++) {
for (int i = 0; i < _arg_size; i++) {
if (vars.contains(i))
_arg_returned.set_bit(i);
}
@ -112,10 +112,9 @@ void BCEscapeAnalyzer::set_returned(ArgumentMap vars) {
_return_allocated = _return_allocated && vars.contains_allocated() && !(vars.contains_unknown() || vars.contains_vars());
}
// return true if any element of vars is an argument
bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) {
for (int i = 0; i <= _arg_size; i++) {
for (int i = 0; i < _arg_size; i++) {
if (vars.contains(i))
return true;
}
@ -126,7 +125,7 @@ bool BCEscapeAnalyzer::is_argument(ArgumentMap vars) {
bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){
if (_conservative)
return true;
for (int i = 0; i <= _arg_size; i++) {
for (int i = 0; i < _arg_size; i++) {
if (vars.contains(i) && _arg_stack.at(i))
return true;
}
@ -134,12 +133,13 @@ bool BCEscapeAnalyzer::is_arg_stack(ArgumentMap vars){
}
void BCEscapeAnalyzer::clear_bits(ArgumentMap vars, BitMap &bm) {
for (int i = 0; i <= _arg_size; i++) {
for (int i = 0; i < _arg_size; i++) {
if (vars.contains(i)) {
bm.clear_bit(i);
}
}
}
void BCEscapeAnalyzer::set_method_escape(ArgumentMap vars) {
clear_bits(vars, _arg_local);
}
@ -155,6 +155,17 @@ void BCEscapeAnalyzer::set_dirty(ArgumentMap vars) {
clear_bits(vars, _dirty);
}
void BCEscapeAnalyzer::set_modified(ArgumentMap vars, int offs, int size) {
for (int i = 0; i < _arg_size; i++) {
if (vars.contains(i)) {
set_arg_modified(i, offs, size);
}
}
if (vars.contains_unknown())
_unknown_modified = true;
}
bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) {
for (BCEscapeAnalyzer* scope = this; scope != NULL; scope = scope->_parent) {
if (scope->method() == callee) {
@ -164,6 +175,40 @@ bool BCEscapeAnalyzer::is_recursive_call(ciMethod* callee) {
return false;
}
bool BCEscapeAnalyzer::is_arg_modified(int arg, int offset, int size_in_bytes) {
if (offset == OFFSET_ANY)
return _arg_modified[arg] != 0;
assert(arg >= 0 && arg < _arg_size, "must be an argument.");
bool modified = false;
int l = offset / HeapWordSize;
int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize;
if (l > ARG_OFFSET_MAX)
l = ARG_OFFSET_MAX;
if (h > ARG_OFFSET_MAX+1)
h = ARG_OFFSET_MAX + 1;
for (int i = l; i < h; i++) {
modified = modified || (_arg_modified[arg] & (1 << i)) != 0;
}
return modified;
}
void BCEscapeAnalyzer::set_arg_modified(int arg, int offset, int size_in_bytes) {
if (offset == OFFSET_ANY) {
_arg_modified[arg] = (uint) -1;
return;
}
assert(arg >= 0 && arg < _arg_size, "must be an argument.");
int l = offset / HeapWordSize;
int h = round_to(offset + size_in_bytes, HeapWordSize) / HeapWordSize;
if (l > ARG_OFFSET_MAX)
l = ARG_OFFSET_MAX;
if (h > ARG_OFFSET_MAX+1)
h = ARG_OFFSET_MAX + 1;
for (int i = l; i < h; i++) {
_arg_modified[arg] |= (1 << i);
}
}
void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod* target, ciKlass* holder) {
int i;
@ -197,6 +242,7 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod*
for (i = 0; i < arg_size; i++) {
set_method_escape(state.raw_pop());
}
_unknown_modified = true; // assume the worst since we don't analyze the called method
return;
}
@ -224,6 +270,11 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod*
ArgumentMap arg = state.raw_pop();
if (!is_argument(arg))
continue;
for (int j = 0; j < _arg_size; j++) {
if (arg.contains(j)) {
_arg_modified[j] |= analyzer._arg_modified[i];
}
}
if (!is_arg_stack(arg)) {
// arguments have already been recognized as escaping
} else if (analyzer.is_arg_stack(i) && !analyzer.is_arg_returned(i)) {
@ -233,6 +284,7 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod*
set_global_escape(arg);
}
}
_unknown_modified = _unknown_modified || analyzer.has_non_arg_side_affects();
// record dependencies if at least one parameter retained stack-allocatable
if (must_record_dependencies) {
@ -250,8 +302,10 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod*
ArgumentMap arg = state.raw_pop();
if (!is_argument(arg))
continue;
set_modified(arg, OFFSET_ANY, type2size[T_INT]*HeapWordSize);
set_global_escape(arg);
}
_unknown_modified = true; // assume the worst since we don't know the called method
}
}
@ -421,6 +475,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
state.spop();
ArgumentMap arr = state.apop();
set_method_escape(arr);
set_modified(arr, OFFSET_ANY, type2size[T_INT]*HeapWordSize);
break;
}
case Bytecodes::_lastore:
@ -430,6 +485,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
state.spop();
ArgumentMap arr = state.apop();
set_method_escape(arr);
set_modified(arr, OFFSET_ANY, type2size[T_LONG]*HeapWordSize);
break;
}
case Bytecodes::_aastore:
@ -437,6 +493,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
set_global_escape(state.apop());
state.spop();
ArgumentMap arr = state.apop();
set_modified(arr, OFFSET_ANY, type2size[T_OBJECT]*HeapWordSize);
break;
}
case Bytecodes::_pop:
@ -762,6 +819,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
if (s.cur_bc() != Bytecodes::_putstatic) {
ArgumentMap p = state.apop();
set_method_escape(p);
set_modified(p, will_link ? field->offset() : OFFSET_ANY, type2size[field_type]*HeapWordSize);
}
}
break;
@ -872,7 +930,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
}
void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state) {
StateInfo *d_state = blockstates+dest->index();
StateInfo *d_state = blockstates + dest->index();
int nlocals = _method->max_locals();
// exceptions may cause transfer of control to handlers in the middle of a
@ -916,6 +974,7 @@ void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest,
}
for (int i = 0; i < s_state->_stack_height; i++) {
ArgumentMap t;
//extra_vars |= !d_state->_vars[i] & s_state->_vars[i];
t.clear();
t = s_state->_stack[i];
t.set_difference(d_state->_stack[i]);
@ -933,7 +992,7 @@ void BCEscapeAnalyzer::iterate_blocks(Arena *arena) {
int datacount = (numblocks + 1) * (stkSize + numLocals);
int datasize = datacount * sizeof(ArgumentMap);
StateInfo *blockstates = (StateInfo *) arena->Amalloc(_methodBlocks->num_blocks() * sizeof(StateInfo));
StateInfo *blockstates = (StateInfo *) arena->Amalloc(numblocks * sizeof(StateInfo));
ArgumentMap *statedata = (ArgumentMap *) arena->Amalloc(datasize);
for (int i = 0; i < datacount; i++) ::new ((void*)&statedata[i]) ArgumentMap();
ArgumentMap *dp = statedata;
@ -961,33 +1020,35 @@ void BCEscapeAnalyzer::iterate_blocks(Arena *arena) {
ArgumentMap allVars; // all oop arguments to method
ciSignature* sig = method()->signature();
int j = 0;
ciBlock* first_blk = _methodBlocks->block_containing(0);
int fb_i = first_blk->index();
if (!method()->is_static()) {
// record information for "this"
blockstates[0]._vars[j].set(j);
blockstates[fb_i]._vars[j].set(j);
allVars.add(j);
j++;
}
for (int i = 0; i < sig->count(); i++) {
ciType* t = sig->type_at(i);
if (!t->is_primitive_type()) {
blockstates[0]._vars[j].set(j);
blockstates[fb_i]._vars[j].set(j);
allVars.add(j);
}
j += t->size();
}
blockstates[0]._initialized = true;
blockstates[fb_i]._initialized = true;
assert(j == _arg_size, "just checking");
ArgumentMap unknown_map;
unknown_map.add_unknown();
worklist.push(_methodBlocks->block_containing(0));
worklist.push(first_blk);
while(worklist.length() > 0) {
ciBlock *blk = worklist.pop();
StateInfo *blkState = blockstates+blk->index();
StateInfo *blkState = blockstates + blk->index();
if (blk->is_handler() || blk->is_ret_target()) {
// for an exception handler or a target of a ret instruction, we assume the worst case,
// that any variable or stack slot could contain any argument
// that any variable could contain any argument
for (int i = 0; i < numLocals; i++) {
state._vars[i] = allVars;
}
@ -997,6 +1058,7 @@ void BCEscapeAnalyzer::iterate_blocks(Arena *arena) {
state._stack_height = blkState->_stack_height;
}
for (int i = 0; i < state._stack_height; i++) {
// ??? should this be unknown_map ???
state._stack[i] = allVars;
}
} else {
@ -1053,6 +1115,7 @@ vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() {
vmIntrinsics::ID iid = method()->intrinsic_id();
if (iid == vmIntrinsics::_getClass ||
iid == vmIntrinsics::_fillInStackTrace ||
iid == vmIntrinsics::_hashCode)
return iid;
else
@ -1060,12 +1123,16 @@ vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() {
}
bool BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) {
ArgumentMap empty;
empty.clear();
ArgumentMap arg;
arg.clear();
switch (iid) {
case vmIntrinsics::_getClass:
_return_local = false;
break;
case vmIntrinsics::_fillInStackTrace:
arg.set(0); // 'this'
set_returned(arg);
break;
case vmIntrinsics::_hashCode:
// initialized state is correct
break;
@ -1109,15 +1176,21 @@ void BCEscapeAnalyzer::initialize() {
_return_allocated = true;
}
_allocated_escapes = false;
_unknown_modified = false;
}
void BCEscapeAnalyzer::clear_escape_info() {
ciSignature* sig = method()->signature();
int arg_count = sig->count();
ArgumentMap var;
if (!method()->is_static()) {
arg_count++; // allow for "this"
}
for (int i = 0; i < arg_count; i++) {
set_arg_modified(i, OFFSET_ANY, 4);
var.clear();
var.set(i);
set_modified(var, OFFSET_ANY, 4);
set_global_escape(var);
}
_arg_local.clear();
@ -1126,6 +1199,7 @@ void BCEscapeAnalyzer::clear_escape_info() {
_return_local = false;
_return_allocated = false;
_allocated_escapes = true;
_unknown_modified = true;
}
@ -1173,8 +1247,14 @@ void BCEscapeAnalyzer::compute_escape_info() {
initialize();
// do not scan method if it has no object parameters
if (_arg_local.is_empty()) {
// Do not scan method if it has no object parameters and
// does not returns an object (_return_allocated is set in initialize()).
if (_arg_local.is_empty() && !_return_allocated) {
// Clear all info since method's bytecode was not analysed and
// set pessimistic escape information.
clear_escape_info();
methodData()->set_eflag(methodDataOopDesc::allocated_escapes);
methodData()->set_eflag(methodDataOopDesc::unknown_modified);
methodData()->set_eflag(methodDataOopDesc::estimated);
return;
}
@ -1185,36 +1265,8 @@ void BCEscapeAnalyzer::compute_escape_info() {
success = do_analysis();
}
// dump result of bytecode analysis
#ifndef PRODUCT
if (BCEATraceLevel >= 3) {
tty->print("[EA] estimated escape information for");
if (iid != vmIntrinsics::_none)
tty->print(" intrinsic");
method()->print_short_name();
tty->print_cr(has_dependencies() ? " (not stored)" : "");
tty->print(" non-escaping args: ");
_arg_local.print_on(tty);
tty->print(" stack-allocatable args: ");
_arg_stack.print_on(tty);
if (_return_local) {
tty->print(" returned args: ");
_arg_returned.print_on(tty);
} else if (is_return_allocated()) {
tty->print_cr(" allocated return values");
} else {
tty->print_cr(" non-local return values");
}
tty->cr();
tty->print(" flags: ");
if (_return_allocated)
tty->print(" return_allocated");
tty->cr();
}
#endif
// don't store interprocedural escape information if it introduces dependencies
// or if method data is empty
// don't store interprocedural escape information if it introduces
// dependencies or if method data is empty
//
if (!has_dependencies() && !methodData()->is_empty()) {
for (i = 0; i < _arg_size; i++) {
@ -1228,10 +1280,20 @@ void BCEscapeAnalyzer::compute_escape_info() {
if (_arg_returned.at(i)) {
methodData()->set_arg_returned(i);
}
methodData()->set_arg_modified(i, _arg_modified[i]);
}
if (_return_local) {
methodData()->set_eflag(methodDataOopDesc::return_local);
}
if (_return_allocated) {
methodData()->set_eflag(methodDataOopDesc::return_allocated);
}
if (_allocated_escapes) {
methodData()->set_eflag(methodDataOopDesc::allocated_escapes);
}
if (_unknown_modified) {
methodData()->set_eflag(methodDataOopDesc::unknown_modified);
}
methodData()->set_eflag(methodDataOopDesc::estimated);
}
}
@ -1244,29 +1306,50 @@ void BCEscapeAnalyzer::read_escape_info() {
_arg_local.at_put(i, methodData()->is_arg_local(i));
_arg_stack.at_put(i, methodData()->is_arg_stack(i));
_arg_returned.at_put(i, methodData()->is_arg_returned(i));
_arg_modified[i] = methodData()->arg_modified(i);
}
_return_local = methodData()->eflag_set(methodDataOopDesc::return_local);
// dump result of loaded escape information
#ifndef PRODUCT
if (BCEATraceLevel >= 4) {
tty->print(" non-escaping args: ");
_arg_local.print_on(tty);
tty->print(" stack-allocatable args: ");
_arg_stack.print_on(tty);
if (_return_local) {
tty->print(" returned args: ");
_arg_returned.print_on(tty);
} else {
tty->print_cr(" non-local return values");
}
tty->print(" modified args: ");
tty->cr();
}
#endif
_return_allocated = methodData()->eflag_set(methodDataOopDesc::return_allocated);
_allocated_escapes = methodData()->eflag_set(methodDataOopDesc::allocated_escapes);
_unknown_modified = methodData()->eflag_set(methodDataOopDesc::unknown_modified);
}
#ifndef PRODUCT
void BCEscapeAnalyzer::dump() {
tty->print("[EA] estimated escape information for");
method()->print_short_name();
tty->print_cr(has_dependencies() ? " (not stored)" : "");
tty->print(" non-escaping args: ");
_arg_local.print_on(tty);
tty->print(" stack-allocatable args: ");
_arg_stack.print_on(tty);
if (_return_local) {
tty->print(" returned args: ");
_arg_returned.print_on(tty);
} else if (is_return_allocated()) {
tty->print_cr(" return allocated value");
} else {
tty->print_cr(" return non-local value");
}
tty->print(" modified args: ");
for (int i = 0; i < _arg_size; i++) {
if (_arg_modified[i] == 0)
tty->print(" 0");
else
tty->print(" 0x%x", _arg_modified[i]);
}
tty->cr();
tty->print(" flags: ");
if (_return_allocated)
tty->print(" return_allocated");
if (_allocated_escapes)
tty->print(" allocated_escapes");
if (_unknown_modified)
tty->print(" unknown_modified");
tty->cr();
}
#endif
BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
: _conservative(method == NULL || !EstimateArgEscape)
@ -1281,6 +1364,7 @@ BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
, _return_local(false)
, _return_allocated(false)
, _allocated_escapes(false)
, _unknown_modified(false)
, _dependencies()
, _parent(parent)
, _level(parent == NULL ? 0 : parent->level() + 1) {
@ -1290,6 +1374,8 @@ BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
_arg_returned.clear();
_dirty.clear();
Arena* arena = CURRENT_ENV->arena();
_arg_modified = (uint *) arena->Amalloc(_arg_size * sizeof(uint));
Copy::zero_to_bytes(_arg_modified, _arg_size * sizeof(uint));
if (methodData() == NULL)
return;
@ -1307,6 +1393,12 @@ BCEscapeAnalyzer::BCEscapeAnalyzer(ciMethod* method, BCEscapeAnalyzer* parent)
compute_escape_info();
methodData()->update_escape_info();
}
#ifndef PRODUCT
if (BCEATraceLevel >= 3) {
// dump escape information
dump();
}
#endif
}
}

View File

@ -46,10 +46,13 @@ class BCEscapeAnalyzer : public ResourceObj {
BitMap _arg_stack;
BitMap _arg_returned;
BitMap _dirty;
enum{ ARG_OFFSET_MAX = 31};
uint *_arg_modified;
bool _return_local;
bool _allocated_escapes;
bool _return_allocated;
bool _allocated_escapes;
bool _unknown_modified;
ciObjectList _dependencies;
@ -80,6 +83,7 @@ class BCEscapeAnalyzer : public ResourceObj {
void set_method_escape(ArgumentMap vars);
void set_global_escape(ArgumentMap vars);
void set_dirty(ArgumentMap vars);
void set_modified(ArgumentMap vars, int offs, int size);
bool is_recursive_call(ciMethod* callee);
void add_dependence(ciKlass *klass, ciMethod *meth);
@ -140,6 +144,18 @@ class BCEscapeAnalyzer : public ResourceObj {
return !_conservative && _return_allocated && !_allocated_escapes;
}
// Tracking of argument modification
enum {OFFSET_ANY = -1};
bool is_arg_modified(int arg, int offset, int size_in_bytes);
void set_arg_modified(int arg, int offset, int size_in_bytes);
bool has_non_arg_side_affects() { return _unknown_modified; }
// Copy dependencies from this analysis into "deps"
void copy_dependencies(Dependencies *deps);
#ifndef PRODUCT
// dump escape information
void dump();
#endif
};

View File

@ -102,7 +102,7 @@ public:
BasicType layout_type() { return type2field[(_type == NULL) ? T_OBJECT : _type->basic_type()]; }
// How big is this field in memory?
int size_in_bytes() { return type2aelembytes[layout_type()]; }
int size_in_bytes() { return type2aelembytes(layout_type()); }
// What is the offset of this field?
int offset() {

View File

@ -34,7 +34,9 @@
// ciInstanceKlass::ciInstanceKlass
//
// Loaded instance klass.
ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : ciKlass(h_k) {
ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) :
ciKlass(h_k), _non_static_fields(NULL)
{
assert(get_Klass()->oop_is_instance(), "wrong type");
instanceKlass* ik = get_instanceKlass();
@ -335,6 +337,37 @@ ciField* ciInstanceKlass::get_field_by_offset(int field_offset, bool is_static)
return field;
}
// ------------------------------------------------------------------
// ciInstanceKlass::non_static_fields.
class NonStaticFieldFiller: public FieldClosure {
GrowableArray<ciField*>* _arr;
ciEnv* _curEnv;
public:
NonStaticFieldFiller(ciEnv* curEnv, GrowableArray<ciField*>* arr) :
_curEnv(curEnv), _arr(arr)
{}
void do_field(fieldDescriptor* fd) {
ciField* field = new (_curEnv->arena()) ciField(fd);
_arr->append(field);
}
};
GrowableArray<ciField*>* ciInstanceKlass::non_static_fields() {
if (_non_static_fields == NULL) {
VM_ENTRY_MARK;
ciEnv* curEnv = ciEnv::current();
instanceKlass* ik = get_instanceKlass();
int max_n_fields = ik->fields()->length()/instanceKlass::next_offset;
_non_static_fields =
new (curEnv->arena()) GrowableArray<ciField*>(max_n_fields);
NonStaticFieldFiller filler(curEnv, _non_static_fields);
ik->do_nonstatic_fields(&filler);
}
return _non_static_fields;
}
static int sort_field_by_offset(ciField** a, ciField** b) {
return (*a)->offset_in_bytes() - (*b)->offset_in_bytes();
// (no worries about 32-bit overflow...)

View File

@ -46,6 +46,7 @@ private:
bool _has_subklass;
ciFlags _flags;
jint _nonstatic_field_size;
jint _nonstatic_oop_map_size;
// Lazy fields get filled in only upon request.
ciInstanceKlass* _super;
@ -58,6 +59,8 @@ private:
ciInstanceKlass* _implementors[implementors_limit];
jint _nof_implementors;
GrowableArray<ciField*>* _non_static_fields;
protected:
ciInstanceKlass(KlassHandle h_k);
ciInstanceKlass(ciSymbol* name, jobject loader, jobject protection_domain);
@ -129,6 +132,9 @@ public:
jint nonstatic_field_size() {
assert(is_loaded(), "must be loaded");
return _nonstatic_field_size; }
jint nonstatic_oop_map_size() {
assert(is_loaded(), "must be loaded");
return _nonstatic_oop_map_size; }
ciInstanceKlass* super();
jint nof_implementors() {
assert(is_loaded(), "must be loaded");
@ -138,6 +144,9 @@ public:
ciInstanceKlass* get_canonical_holder(int offset);
ciField* get_field_by_offset(int field_offset, bool is_static);
GrowableArray<ciField*>* non_static_fields();
// total number of nonstatic fields (including inherited):
int nof_nonstatic_fields() {
if (_nonstatic_fields == NULL)

View File

@ -146,7 +146,7 @@ void ciMethod::load_code() {
memcpy(_code, me->code_base(), code_size());
// Revert any breakpoint bytecodes in ci's copy
if (_is_compilable && me->number_of_breakpoints() > 0) {
if (me->number_of_breakpoints() > 0) {
BreakpointInfo* bp = instanceKlass::cast(me->method_holder())->breakpoints();
for (; bp != NULL; bp = bp->next()) {
if (bp->match(me)) {

View File

@ -67,6 +67,14 @@ ciBlock *ciMethodBlocks::split_block_at(int bci) {
break;
}
}
// Move an exception handler information if needed.
if (former_block->is_handler()) {
int ex_start = former_block->ex_start_bci();
int ex_end = former_block->ex_limit_bci();
new_block->set_exception_range(ex_start, ex_end);
// Clear information in former_block.
former_block->clear_exception_handler();
}
return former_block;
}
@ -102,7 +110,7 @@ void ciMethodBlocks::do_analysis() {
// one and end the old one.
assert(cur_block != NULL, "must always have a current block");
ciBlock *new_block = block_containing(bci);
if (new_block == NULL) {
if (new_block == NULL || new_block == cur_block) {
// We have not marked this bci as the start of a new block.
// Keep interpreting the current_range.
_bci_to_block[bci] = cur_block;
@ -254,9 +262,33 @@ ciMethodBlocks::ciMethodBlocks(Arena *arena, ciMethod *meth): _method(meth),
for(ciExceptionHandlerStream str(meth); !str.is_done(); str.next()) {
ciExceptionHandler* handler = str.handler();
ciBlock *eb = make_block_at(handler->handler_bci());
eb->set_handler();
//
// Several exception handlers can have the same handler_bci:
//
// try {
// if (a.foo(b) < 0) {
// return a.error();
// }
// return CoderResult.UNDERFLOW;
// } finally {
// a.position(b);
// }
//
// The try block above is divided into 2 exception blocks
// separated by 'areturn' bci.
//
int ex_start = handler->start();
int ex_end = handler->limit();
if (eb->is_handler()) {
// Extend old handler exception range to cover additional range.
int old_ex_start = eb->ex_start_bci();
int old_ex_end = eb->ex_limit_bci();
if (ex_start > old_ex_start)
ex_start = old_ex_start;
if (ex_end < old_ex_end)
ex_end = old_ex_end;
eb->clear_exception_handler(); // Reset exception information
}
eb->set_exception_range(ex_start, ex_end);
// ensure a block at the start of exception range and start of following code
(void) make_block_at(ex_start);
@ -312,9 +344,10 @@ ciBlock::ciBlock(ciMethod *method, int index, ciMethodBlocks *mb, int start_bci)
void ciBlock::set_exception_range(int start_bci, int limit_bci) {
assert(limit_bci >= start_bci, "valid range");
assert(is_handler(), "must be handler");
assert(!is_handler() && _ex_start_bci == -1 && _ex_limit_bci == -1, "must not be handler");
_ex_start_bci = start_bci;
_ex_limit_bci = limit_bci;
set_handler();
}
#ifndef PRODUCT

View File

@ -110,9 +110,10 @@ public:
void set_does_jsr() { _flags |= DoesJsr; }
void clear_does_jsr() { _flags &= ~DoesJsr; }
void set_does_ret() { _flags |= DoesRet; }
void clear_does_ret() { _flags |= DoesRet; }
void clear_does_ret() { _flags &= ~DoesRet; }
void set_is_ret_target() { _flags |= RetTarget; }
void set_has_handler() { _flags |= HasHandler; }
void clear_exception_handler() { _flags &= ~Handler; _ex_start_bci = -1; _ex_limit_bci = -1; }
#ifndef PRODUCT
ciMethod *method() const { return _method; }
void dump();

View File

@ -42,6 +42,8 @@ ciMethodData::ciMethodData(methodDataHandle h_md) : ciObject(h_md) {
// Set an initial hint. Don't use set_hint_di() because
// first_di() may be out of bounds if data_size is 0.
_hint_di = first_di();
// Initialize the escape information (to "don't know.");
_eflags = _arg_local = _arg_stack = _arg_returned = 0;
}
// ------------------------------------------------------------------
@ -59,6 +61,8 @@ ciMethodData::ciMethodData() : ciObject() {
// Set an initial hint. Don't use set_hint_di() because
// first_di() may be out of bounds if data_size is 0.
_hint_di = first_di();
// Initialize the escape information (to "don't know.");
_eflags = _arg_local = _arg_stack = _arg_returned = 0;
}
void ciMethodData::load_data() {
@ -142,6 +146,8 @@ ciProfileData* ciMethodData::data_at(int data_index) {
return new ciBranchData(data_layout);
case DataLayout::multi_branch_data_tag:
return new ciMultiBranchData(data_layout);
case DataLayout::arg_info_data_tag:
return new ciArgInfoData(data_layout);
};
}
@ -172,6 +178,9 @@ ciProfileData* ciMethodData::bci_to_data(int bci) {
_saw_free_extra_data = true; // observed an empty slot (common case)
return NULL;
}
if (dp->tag() == DataLayout::arg_info_data_tag) {
break; // ArgInfoData is at the end of extra data section.
}
if (dp->bci() == bci) {
assert(dp->tag() == DataLayout::bit_data_tag, "sane");
return new ciBitData(dp);
@ -217,8 +226,14 @@ int ciMethodData::trap_recompiled_at(ciProfileData* data) {
void ciMethodData::clear_escape_info() {
VM_ENTRY_MARK;
methodDataOop mdo = get_methodDataOop();
if (mdo != NULL)
if (mdo != NULL) {
mdo->clear_escape_info();
ArgInfoData *aid = arg_info();
int arg_count = (aid == NULL) ? 0 : aid->number_of_args();
for (int i = 0; i < arg_count; i++) {
set_arg_modified(i, 0);
}
}
_eflags = _arg_local = _arg_stack = _arg_returned = 0;
}
@ -231,6 +246,10 @@ void ciMethodData::update_escape_info() {
mdo->set_arg_local(_arg_local);
mdo->set_arg_stack(_arg_stack);
mdo->set_arg_returned(_arg_returned);
int arg_count = mdo->method()->size_of_parameters();
for (int i = 0; i < arg_count; i++) {
mdo->set_arg_modified(i, arg_modified(i));
}
}
}
@ -262,6 +281,14 @@ void ciMethodData::set_arg_returned(int i) {
set_nth_bit(_arg_returned, i);
}
void ciMethodData::set_arg_modified(int arg, uint val) {
ArgInfoData *aid = arg_info();
if (aid == NULL)
return;
assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number");
aid->set_arg_modified(arg, val);
}
bool ciMethodData::is_arg_local(int i) const {
return is_set_nth_bit(_arg_local, i);
}
@ -274,6 +301,14 @@ bool ciMethodData::is_arg_returned(int i) const {
return is_set_nth_bit(_arg_returned, i);
}
uint ciMethodData::arg_modified(int arg) const {
ArgInfoData *aid = arg_info();
if (aid == NULL)
return 0;
assert(arg >= 0 && arg < aid->number_of_args(), "valid argument number");
return aid->arg_modified(arg);
}
ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data) {
// Get offset within methodDataOop of the data array
ByteSize data_offset = methodDataOopDesc::data_offset();
@ -287,6 +322,18 @@ ByteSize ciMethodData::offset_of_slot(ciProfileData* data, ByteSize slot_offset_
return in_ByteSize(offset);
}
ciArgInfoData *ciMethodData::arg_info() const {
// Should be last, have to skip all traps.
DataLayout* dp = data_layout_at(data_size());
DataLayout* end = data_layout_at(data_size() + extra_data_size());
for (; dp < end; dp = methodDataOopDesc::next_extra(dp)) {
if (dp->tag() == DataLayout::arg_info_data_tag)
return new ciArgInfoData(dp);
}
return NULL;
}
// Implementation of the print method.
void ciMethodData::print_impl(outputStream* st) {
ciObject::print_impl(st);
@ -305,6 +352,22 @@ void ciMethodData::print_data_on(outputStream* st) {
st->fill_to(6);
data->print_data_on(st);
}
st->print_cr("--- Extra data:");
DataLayout* dp = data_layout_at(data_size());
DataLayout* end = data_layout_at(data_size() + extra_data_size());
for (; dp < end; dp = methodDataOopDesc::next_extra(dp)) {
if (dp->tag() == DataLayout::no_tag) continue;
if (dp->tag() == DataLayout::bit_data_tag) {
data = new BitData(dp);
} else {
assert(dp->tag() == DataLayout::arg_info_data_tag, "must be BitData or ArgInfo");
data = new ciArgInfoData(dp);
dp = end; // ArgInfoData is at the end of extra data section.
}
st->print("%d", dp_to_di(data->dp()));
st->fill_to(6);
data->print_data_on(st);
}
}
void ciReceiverTypeData::print_receiver_data_on(outputStream* st) {

View File

@ -30,6 +30,7 @@ class ciRetData;
class ciBranchData;
class ciArrayData;
class ciMultiBranchData;
class ciArgInfoData;
typedef ProfileData ciProfileData;
@ -121,6 +122,11 @@ public:
ciMultiBranchData(DataLayout* layout) : MultiBranchData(layout) {};
};
class ciArgInfoData : public ArgInfoData {
public:
ciArgInfoData(DataLayout* layout) : ArgInfoData(layout) {};
};
// ciMethodData
//
// This class represents a methodDataOop in the HotSpot virtual
@ -163,9 +169,9 @@ private:
ciMethodData();
// Accessors
int data_size() { return _data_size; }
int extra_data_size() { return _extra_data_size; }
intptr_t * data() { return _data; }
int data_size() const { return _data_size; }
int extra_data_size() const { return _extra_data_size; }
intptr_t * data() const { return _data; }
methodDataOop get_methodDataOop() const {
if (handle() == NULL) return NULL;
@ -178,7 +184,7 @@ private:
void print_impl(outputStream* st);
DataLayout* data_layout_at(int data_index) {
DataLayout* data_layout_at(int data_index) const {
assert(data_index % sizeof(intptr_t) == 0, "unaligned");
return (DataLayout*) (((address)_data) + data_index);
}
@ -207,6 +213,8 @@ private:
// What is the index of the first data entry?
int first_di() { return 0; }
ciArgInfoData *arg_info() const;
public:
bool is_method_data() { return true; }
bool is_empty() { return _state == empty_state; }
@ -270,10 +278,12 @@ public:
void set_arg_local(int i);
void set_arg_stack(int i);
void set_arg_returned(int i);
void set_arg_modified(int arg, uint val);
bool is_arg_local(int i) const;
bool is_arg_stack(int i) const;
bool is_arg_returned(int i) const;
uint arg_modified(int arg) const;
// Code generation helper
ByteSize offset_of_slot(ciProfileData* data, ByteSize slot_offset_in_data);

View File

@ -0,0 +1,43 @@
/*
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
#include "incls/_precompiled.incl"
#include "incls/_ciObjArray.cpp.incl"
// ciObjArray
//
// This class represents an objArrayOop in the HotSpot virtual
// machine.
ciObject* ciObjArray::obj_at(int index) {
VM_ENTRY_MARK;
objArrayOop array = get_objArrayOop();
if (index < 0 || index >= array->length()) return NULL;
oop o = array->obj_at(index);
if (o == NULL) {
return ciNullObject::make();
} else {
return CURRENT_ENV->get_object(o);
}
}

View File

@ -43,4 +43,6 @@ protected:
public:
// What kind of ciObject is this?
bool is_obj_array() { return true; }
ciObject* obj_at(int index);
};

View File

@ -155,8 +155,8 @@ bool Dictionary::do_unloading(BoolObjectClosure* is_alive) {
for (int i = ik->previous_versions()->length() - 1; i >= 0; i--) {
// check the previous versions array for GC'ed weak refs
PreviousVersionNode * pv_node = ik->previous_versions()->at(i);
jweak cp_ref = pv_node->prev_constant_pool();
assert(cp_ref != NULL, "weak cp ref was unexpectedly cleared");
jobject cp_ref = pv_node->prev_constant_pool();
assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
if (cp_ref == NULL) {
delete pv_node;
ik->previous_versions()->remove_at(i);

View File

@ -143,13 +143,43 @@ Handle java_lang_String::create_from_platform_dependent_str(const char* str, TRA
jstring js = NULL;
{ JavaThread* thread = (JavaThread*)THREAD;
assert(thread->is_Java_thread(), "must be java thread");
ThreadToNativeFromVM ttn(thread);
HandleMark hm(thread);
ThreadToNativeFromVM ttn(thread);
js = (_to_java_string_fn)(thread->jni_environment(), str);
}
return Handle(THREAD, JNIHandles::resolve(js));
}
// Converts a Java String to a native C string that can be used for
// native OS calls.
char* java_lang_String::as_platform_dependent_str(Handle java_string, TRAPS) {
typedef char* (*to_platform_string_fn_t)(JNIEnv*, jstring, bool*);
static to_platform_string_fn_t _to_platform_string_fn = NULL;
if (_to_platform_string_fn == NULL) {
void *lib_handle = os::native_java_library();
_to_platform_string_fn = CAST_TO_FN_PTR(to_platform_string_fn_t, hpi::dll_lookup(lib_handle, "GetStringPlatformChars"));
if (_to_platform_string_fn == NULL) {
fatal("GetStringPlatformChars missing");
}
}
char *native_platform_string;
{ JavaThread* thread = (JavaThread*)THREAD;
assert(thread->is_Java_thread(), "must be java thread");
JNIEnv *env = thread->jni_environment();
jstring js = (jstring) JNIHandles::make_local(env, java_string());
bool is_copy;
HandleMark hm(thread);
ThreadToNativeFromVM ttn(thread);
native_platform_string = (_to_platform_string_fn)(env, js, &is_copy);
assert(is_copy == JNI_TRUE, "is_copy value changed");
JNIHandles::destroy_local(js);
}
return native_platform_string;
}
Handle java_lang_String::char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS) {
oop obj = java_string();
// Typical usage is to convert all '/' to '.' in string.

View File

@ -96,6 +96,7 @@ class java_lang_String : AllStatic {
// String converters
static char* as_utf8_string(oop java_string);
static char* as_utf8_string(oop java_string, int start, int len);
static char* as_platform_dependent_str(Handle java_string, TRAPS);
static jchar* as_unicode_string(oop java_string, int& length);
static bool equals(oop java_string, jchar* chars, int len);

View File

@ -1242,7 +1242,9 @@ static instanceKlassHandle download_and_retry_class_load(
oop obj = (oop) result.get_jobject();
if (obj == NULL) { return nk; }
char* new_class_name = java_lang_String::as_utf8_string(obj);
Handle h_obj(THREAD, obj);
char* new_class_name = java_lang_String::as_platform_dependent_str(h_obj,
CHECK_(nk));
// lock the loader
// we use this lock because JVMTI does.

View File

@ -318,6 +318,11 @@ inline bool match_F_SN(jshort flags) {
const int neg = JVM_ACC_SYNCHRONIZED;
return (flags & (req | neg)) == req;
}
inline bool match_F_RNY(jshort flags) {
const int req = JVM_ACC_NATIVE | JVM_ACC_SYNCHRONIZED;
const int neg = JVM_ACC_STATIC;
return (flags & (req | neg)) == req;
}
// These are for forming case labels:
#define ID3(x, y, z) (( jint)(z) + \
@ -359,6 +364,7 @@ const char* vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID id, char* buf,
case F_RN: fname = "native "; break;
case F_SN: fname = "native static "; break;
case F_S: fname = "static "; break;
case F_RNY:fname = "native synchronized "; break;
}
const char* kptr = strrchr(kname, '/');
if (kptr != NULL) kname = kptr + 1;
@ -485,7 +491,7 @@ void vmIntrinsics::verify_method(ID actual_id, methodOop m) {
if (PrintMiscellaneous && (WizardMode || Verbose)) {
tty->print_cr("*** misidentified method; %s(%d) should be %s(%d):",
declared_name, declared_id, actual_name, actual_id);
m->print_short_name(tty);
mh()->print_short_name(tty);
tty->cr();
}
}

View File

@ -58,12 +58,17 @@
template(java_lang_ThreadDeath, "java/lang/ThreadDeath") \
template(java_lang_Boolean, "java/lang/Boolean") \
template(java_lang_Character, "java/lang/Character") \
template(java_lang_Character_CharacterCache, "java/lang/Character$CharacterCache") \
template(java_lang_Float, "java/lang/Float") \
template(java_lang_Double, "java/lang/Double") \
template(java_lang_Byte, "java/lang/Byte") \
template(java_lang_Byte_Cache, "java/lang/Byte$ByteCache") \
template(java_lang_Short, "java/lang/Short") \
template(java_lang_Short_ShortCache, "java/lang/Short$ShortCache") \
template(java_lang_Integer, "java/lang/Integer") \
template(java_lang_Integer_IntegerCache, "java/lang/Integer$IntegerCache") \
template(java_lang_Long, "java/lang/Long") \
template(java_lang_Long_LongCache, "java/lang/Long$LongCache") \
template(java_lang_Shutdown, "java/lang/Shutdown") \
template(java_lang_ref_Reference, "java/lang/ref/Reference") \
template(java_lang_ref_SoftReference, "java/lang/ref/SoftReference") \
@ -91,10 +96,11 @@
template(java_util_Vector, "java/util/Vector") \
template(java_util_AbstractList, "java/util/AbstractList") \
template(java_util_Hashtable, "java/util/Hashtable") \
template(java_util_HashMap, "java/util/HashMap") \
template(java_lang_Compiler, "java/lang/Compiler") \
template(sun_misc_Signal, "sun/misc/Signal") \
template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \
template(sun_jkernel_DownloadManager, "sun/jkernel/DownloadManager") \
template(sun_jkernel_DownloadManager, "sun/jkernel/DownloadManager") \
template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \
\
/* class file format tags */ \
@ -274,7 +280,9 @@
template(exclusive_owner_thread_name, "exclusiveOwnerThread") \
template(park_blocker_name, "parkBlocker") \
template(park_event_name, "nativeParkEventPointer") \
template(cache_field_name, "cache") \
template(value_name, "value") \
template(frontCacheEnabled_name, "frontCacheEnabled") \
\
/* non-intrinsic name/signature pairs: */ \
template(register_method_name, "register") \
@ -576,6 +584,8 @@
do_name( attemptUpdate_name, "attemptUpdate") \
do_signature(attemptUpdate_signature, "(JJ)Z") \
\
do_intrinsic(_fillInStackTrace, java_lang_Throwable, fillInStackTrace_name, void_throwable_signature, F_RNY) \
\
/* support for sun.misc.Unsafe */ \
do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \
\
@ -863,7 +873,8 @@ class vmIntrinsics: AllStatic {
F_R, // !static !synchronized (R="regular")
F_S, // static !synchronized
F_RN, // !static native !synchronized
F_SN // static native !synchronized
F_SN, // static native !synchronized
F_RNY // !static native synchronized
};
public:

View File

@ -47,7 +47,8 @@ ScopeValue* DebugInfoReadStream::read_object_value() {
}
#endif
ObjectValue* result = new ObjectValue(id);
_obj_pool->append(result);
// Cache the object since an object field could reference it.
_obj_pool->push(result);
result->read_object(this);
return result;
}
@ -56,9 +57,9 @@ ScopeValue* DebugInfoReadStream::get_cached_object() {
int id = read_int();
assert(_obj_pool != NULL, "object pool does not exist");
for (int i = _obj_pool->length() - 1; i >= 0; i--) {
ObjectValue* sv = (ObjectValue*) _obj_pool->at(i);
if (sv->id() == id) {
return sv;
ObjectValue* ov = (ObjectValue*) _obj_pool->at(i);
if (ov->id() == id) {
return ov;
}
}
ShouldNotReachHere();

View File

@ -882,6 +882,14 @@ klassOop ClassHierarchyWalker::find_witness_in(DepChange& changes,
// Must not move the class hierarchy during this check:
assert_locked_or_safepoint(Compile_lock);
int nof_impls = instanceKlass::cast(context_type)->nof_implementors();
if (nof_impls > 1) {
// Avoid this case: *I.m > { A.m, C }; B.m > C
// %%% Until this is fixed more systematically, bail out.
// See corresponding comment in find_witness_anywhere.
return context_type;
}
assert(!is_participant(new_type), "only old classes are participants");
if (participants_hide_witnesses) {
// If the new type is a subtype of a participant, we are done.
@ -1491,9 +1499,12 @@ bool DepChange::ContextStream::next() {
// fall through:
_change_type = Change_new_sub;
case Change_new_sub:
_klass = instanceKlass::cast(_klass)->super();
if (_klass != NULL) {
return true;
// 6598190: brackets workaround Sun Studio C++ compiler bug 6629277
{
_klass = instanceKlass::cast(_klass)->super();
if (_klass != NULL) {
return true;
}
}
// else set up _ti_limit and fall through:
_ti_limit = (_ti_base == NULL) ? 0 : _ti_base->length();

View File

@ -1971,7 +1971,7 @@ void nmethod::print_dependencies() {
if (ctxk != NULL) {
Klass* k = Klass::cast(ctxk);
if (k->oop_is_instance() && ((instanceKlass*)k)->is_dependent_nmethod(this)) {
tty->print(" [nmethod<=klass]%s", k->external_name());
tty->print_cr(" [nmethod<=klass]%s", k->external_name());
}
}
deps.log_dependency(); // put it into the xml log also

View File

@ -91,7 +91,9 @@ GrowableArray<ScopeValue*>* ScopeDesc::decode_object_values(int decode_offset) {
DebugInfoReadStream* stream = new DebugInfoReadStream(_code, decode_offset, result);
int length = stream->read_int();
for (int index = 0; index < length; index++) {
result->push(ScopeValue::read_from(stream));
// Objects values are pushed to 'result' array during read so that
// object's fields could reference it (OBJECT_ID_CODE).
(void)ScopeValue::read_from(stream);
}
assert(result->length() == length, "inconsistent debug information");
return result;

View File

@ -36,16 +36,16 @@ const int VMRegImpl::register_count = ConcreteRegisterImpl::number_of_registers;
// Register names
const char *VMRegImpl::regName[ConcreteRegisterImpl::number_of_registers];
void VMRegImpl::print() {
#ifndef PRODUCT
void VMRegImpl::print_on(outputStream* st) const {
if( is_reg() ) {
assert( VMRegImpl::regName[value()], "" );
tty->print("%s",VMRegImpl::regName[value()]);
st->print("%s",VMRegImpl::regName[value()]);
} else if (is_stack()) {
int stk = value() - stack0->value();
tty->print("[%d]", stk*4);
st->print("[%d]", stk*4);
} else {
tty->print("BAD!");
st->print("BAD!");
}
#endif // PRODUCT
}
#endif // PRODUCT

View File

@ -66,9 +66,9 @@ public:
}
}
static VMReg Bad() { return (VMReg) (intptr_t) BAD; }
bool is_valid() { return ((intptr_t) this) != BAD; }
bool is_stack() { return (intptr_t) this >= (intptr_t) stack0; }
bool is_reg() { return is_valid() && !is_stack(); }
bool is_valid() const { return ((intptr_t) this) != BAD; }
bool is_stack() const { return (intptr_t) this >= (intptr_t) stack0; }
bool is_reg() const { return is_valid() && !is_stack(); }
// A concrete register is a value that returns true for is_reg() and is
// also a register you could use in the assembler. On machines with
@ -96,7 +96,8 @@ public:
intptr_t value() const {return (intptr_t) this; }
void print();
void print_on(outputStream* st) const PRODUCT_RETURN;
void print() const { print_on(tty); }
// bias a stack slot.
// Typically used to adjust a virtual frame slots by amounts that are offset by

View File

@ -506,27 +506,27 @@ bool OopMap::has_derived_pointer() const {
}
void print_register_type(OopMapValue::oop_types x, VMReg optional) {
static void print_register_type(OopMapValue::oop_types x, VMReg optional, outputStream* st) {
switch( x ) {
case OopMapValue::oop_value:
tty->print("Oop");
st->print("Oop");
break;
case OopMapValue::value_value:
tty->print("Value" );
st->print("Value" );
break;
case OopMapValue::dead_value:
tty->print("Dead" );
st->print("Dead" );
break;
case OopMapValue::callee_saved_value:
tty->print("Callers_" );
optional->print();
st->print("Callers_" );
optional->print_on(st);
break;
case OopMapValue::derived_oop_value:
tty->print("Derived_oop_" );
optional->print();
st->print("Derived_oop_" );
optional->print_on(st);
break;
case OopMapValue::stack_obj:
tty->print("Stack");
st->print("Stack");
break;
default:
ShouldNotReachHere();
@ -534,11 +534,11 @@ void print_register_type(OopMapValue::oop_types x, VMReg optional) {
}
void OopMapValue::print() const {
reg()->print();
tty->print("=");
print_register_type(type(),content_reg());
tty->print(" ");
void OopMapValue::print_on(outputStream* st) const {
reg()->print_on(st);
st->print("=");
print_register_type(type(),content_reg(),st);
st->print(" ");
}

View File

@ -129,7 +129,8 @@ public:
return reg()->reg2stack();
}
void print( ) const PRODUCT_RETURN;
void print_on(outputStream* st) const PRODUCT_RETURN;
void print() const { print_on(tty); }
};

View File

@ -1071,85 +1071,56 @@ void BinaryTreeDictionary::reportStatistics() const {
// for each list in the tree. Also print some summary
// information.
class printTreeCensusClosure : public AscendTreeCensusClosure {
int _print_line;
size_t _totalFree;
AllocationStats _totals;
size_t _count;
FreeList _total;
public:
printTreeCensusClosure() {
_print_line = 0;
_totalFree = 0;
_count = 0;
_totals.initialize();
}
AllocationStats* totals() { return &_totals; }
size_t count() { return _count; }
void increment_count_by(size_t v) { _count += v; }
FreeList* total() { return &_total; }
size_t totalFree() { return _totalFree; }
void increment_totalFree_by(size_t v) { _totalFree += v; }
void do_list(FreeList* fl) {
bool nl = false; // "maybe this is not needed" isNearLargestChunk(fl->head());
gclog_or_tty->print("%c %4d\t\t" "%7d\t" "%7d\t"
"%7d\t" "%7d\t" "%7d\t" "%7d\t"
"%7d\t" "%7d\t" "%7d\t"
"%7d\t" "\n",
" n"[nl], fl->size(), fl->bfrSurp(), fl->surplus(),
fl->desired(), fl->prevSweep(), fl->beforeSweep(), fl->count(),
fl->coalBirths(), fl->coalDeaths(), fl->splitBirths(),
fl->splitDeaths());
increment_totalFree_by(fl->count() * fl->size());
increment_count_by(fl->count());
totals()->set_bfrSurp(totals()->bfrSurp() + fl->bfrSurp());
totals()->set_surplus(totals()->splitDeaths() + fl->surplus());
totals()->set_prevSweep(totals()->prevSweep() + fl->prevSweep());
totals()->set_beforeSweep(totals()->beforeSweep() + fl->beforeSweep());
totals()->set_coalBirths(totals()->coalBirths() + fl->coalBirths());
totals()->set_coalDeaths(totals()->coalDeaths() + fl->coalDeaths());
totals()->set_splitBirths(totals()->splitBirths() + fl->splitBirths());
totals()->set_splitDeaths(totals()->splitDeaths() + fl->splitDeaths());
if (++_print_line >= 40) {
FreeList::print_labels_on(gclog_or_tty, "size");
_print_line = 0;
}
fl->print_on(gclog_or_tty);
_totalFree += fl->count() * fl->size() ;
total()->set_count( total()->count() + fl->count() );
total()->set_bfrSurp( total()->bfrSurp() + fl->bfrSurp() );
total()->set_surplus( total()->splitDeaths() + fl->surplus() );
total()->set_desired( total()->desired() + fl->desired() );
total()->set_prevSweep( total()->prevSweep() + fl->prevSweep() );
total()->set_beforeSweep(total()->beforeSweep() + fl->beforeSweep());
total()->set_coalBirths( total()->coalBirths() + fl->coalBirths() );
total()->set_coalDeaths( total()->coalDeaths() + fl->coalDeaths() );
total()->set_splitBirths(total()->splitBirths() + fl->splitBirths());
total()->set_splitDeaths(total()->splitDeaths() + fl->splitDeaths());
}
};
void BinaryTreeDictionary::printDictCensus(void) const {
gclog_or_tty->print("\nBinaryTree\n");
gclog_or_tty->print(
"%4s\t\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t"
"%7s\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t" "\n",
"size", "bfrsurp", "surplus", "desired", "prvSwep", "bfrSwep",
"count", "cBirths", "cDeaths", "sBirths", "sDeaths");
FreeList::print_labels_on(gclog_or_tty, "size");
printTreeCensusClosure ptc;
ptc.do_tree(root());
FreeList* total = ptc.total();
FreeList::print_labels_on(gclog_or_tty, " ");
total->print_on(gclog_or_tty, "TOTAL\t");
gclog_or_tty->print(
"\t\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t"
"%7s\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t" "\n",
"bfrsurp", "surplus", "prvSwep", "bfrSwep",
"count", "cBirths", "cDeaths", "sBirths", "sDeaths");
gclog_or_tty->print(
"%s\t\t" "%7d\t" "%7d\t" "%7d\t" "%7d\t"
"%7d\t" "%7d\t" "%7d\t" "%7d\t" "%7d\t" "\n",
"totl",
ptc.totals()->bfrSurp(),
ptc.totals()->surplus(),
ptc.totals()->prevSweep(),
ptc.totals()->beforeSweep(),
ptc.count(),
ptc.totals()->coalBirths(),
ptc.totals()->coalDeaths(),
ptc.totals()->splitBirths(),
ptc.totals()->splitDeaths());
gclog_or_tty->print("totalFree(words): %7d growth: %8.5f deficit: %8.5f\n",
"totalFree(words): " SIZE_FORMAT_W(16)
" growth: %8.5f deficit: %8.5f\n",
ptc.totalFree(),
(double)(ptc.totals()->splitBirths()+ptc.totals()->coalBirths()
-ptc.totals()->splitDeaths()-ptc.totals()->coalDeaths())
/(ptc.totals()->prevSweep() != 0 ?
(double)ptc.totals()->prevSweep() : 1.0),
(double)(ptc.totals()->desired() - ptc.count())
/(ptc.totals()->desired() != 0 ?
(double)ptc.totals()->desired() : 1.0));
(double)(total->splitBirths() + total->coalBirths()
- total->splitDeaths() - total->coalDeaths())
/(total->prevSweep() != 0 ? (double)total->prevSweep() : 1.0),
(double)(total->desired() - total->count())
/(total->desired() != 0 ? (double)total->desired() : 1.0));
}
// Verify the following tree invariants:

View File

@ -1835,7 +1835,7 @@ void CompactibleFreeListSpace::object_iterate_since_last_GC(ObjectClosure* cl) {
guarantee(false, "NYI");
}
bool CompactibleFreeListSpace::linearAllocationWouldFail() {
bool CompactibleFreeListSpace::linearAllocationWouldFail() const {
return _smallLinearAllocBlock._word_size == 0;
}
@ -1906,6 +1906,13 @@ CompactibleFreeListSpace::refillLinearAllocBlock(LinearAllocBlock* blk) {
}
}
// Support for concurrent collection policy decisions.
bool CompactibleFreeListSpace::should_concurrent_collect() const {
// In the future we might want to add in frgamentation stats --
// including erosion of the "mountain" into this decision as well.
return !adaptive_freelists() && linearAllocationWouldFail();
}
// Support for compaction
void CompactibleFreeListSpace::prepare_for_compaction(CompactPoint* cp) {
@ -2013,11 +2020,11 @@ void CompactibleFreeListSpace::clearFLCensus() {
}
}
void CompactibleFreeListSpace::endSweepFLCensus(int sweepCt) {
void CompactibleFreeListSpace::endSweepFLCensus(size_t sweep_count) {
setFLSurplus();
setFLHints();
if (PrintGC && PrintFLSCensus > 0) {
printFLCensus(sweepCt);
printFLCensus(sweep_count);
}
clearFLCensus();
assert_locked();
@ -2293,59 +2300,37 @@ void CompactibleFreeListSpace::checkFreeListConsistency() const {
}
#endif
void CompactibleFreeListSpace::printFLCensus(int sweepCt) const {
void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const {
assert_lock_strong(&_freelistLock);
ssize_t bfrSurp = 0;
ssize_t surplus = 0;
ssize_t desired = 0;
ssize_t prevSweep = 0;
ssize_t beforeSweep = 0;
ssize_t count = 0;
ssize_t coalBirths = 0;
ssize_t coalDeaths = 0;
ssize_t splitBirths = 0;
ssize_t splitDeaths = 0;
gclog_or_tty->print("end sweep# %d\n", sweepCt);
gclog_or_tty->print("%4s\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t"
"%7s\t" "%7s\t" "%7s\t" "%7s\t" "%7s\t"
"%7s\t" "\n",
"size", "bfrsurp", "surplus", "desired", "prvSwep",
"bfrSwep", "count", "cBirths", "cDeaths", "sBirths",
"sDeaths");
FreeList total;
gclog_or_tty->print("end sweep# " SIZE_FORMAT "\n", sweep_count);
FreeList::print_labels_on(gclog_or_tty, "size");
size_t totalFree = 0;
for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
const FreeList *fl = &_indexedFreeList[i];
totalFree += fl->count() * fl->size();
gclog_or_tty->print("%4d\t" "%7d\t" "%7d\t" "%7d\t"
"%7d\t" "%7d\t" "%7d\t" "%7d\t"
"%7d\t" "%7d\t" "%7d\t" "\n",
fl->size(), fl->bfrSurp(), fl->surplus(), fl->desired(),
fl->prevSweep(), fl->beforeSweep(), fl->count(), fl->coalBirths(),
fl->coalDeaths(), fl->splitBirths(), fl->splitDeaths());
bfrSurp += fl->bfrSurp();
surplus += fl->surplus();
desired += fl->desired();
prevSweep += fl->prevSweep();
beforeSweep += fl->beforeSweep();
count += fl->count();
coalBirths += fl->coalBirths();
coalDeaths += fl->coalDeaths();
splitBirths += fl->splitBirths();
splitDeaths += fl->splitDeaths();
totalFree += fl->count() * fl->size();
if (i % (40*IndexSetStride) == 0) {
FreeList::print_labels_on(gclog_or_tty, "size");
}
fl->print_on(gclog_or_tty);
total.set_bfrSurp( total.bfrSurp() + fl->bfrSurp() );
total.set_surplus( total.surplus() + fl->surplus() );
total.set_desired( total.desired() + fl->desired() );
total.set_prevSweep( total.prevSweep() + fl->prevSweep() );
total.set_beforeSweep(total.beforeSweep() + fl->beforeSweep());
total.set_count( total.count() + fl->count() );
total.set_coalBirths( total.coalBirths() + fl->coalBirths() );
total.set_coalDeaths( total.coalDeaths() + fl->coalDeaths() );
total.set_splitBirths(total.splitBirths() + fl->splitBirths());
total.set_splitDeaths(total.splitDeaths() + fl->splitDeaths());
}
gclog_or_tty->print("%4s\t"
"%7d\t" "%7d\t" "%7d\t" "%7d\t" "%7d\t"
"%7d\t" "%7d\t" "%7d\t" "%7d\t" "%7d\t" "\n",
"totl",
bfrSurp, surplus, desired, prevSweep, beforeSweep,
count, coalBirths, coalDeaths, splitBirths, splitDeaths);
gclog_or_tty->print_cr("Total free in indexed lists %d words", totalFree);
total.print_on(gclog_or_tty, "TOTAL");
gclog_or_tty->print_cr("Total free in indexed lists "
SIZE_FORMAT " words", totalFree);
gclog_or_tty->print("growth: %8.5f deficit: %8.5f\n",
(double)(splitBirths+coalBirths-splitDeaths-coalDeaths)/
(prevSweep != 0 ? (double)prevSweep : 1.0),
(double)(desired - count)/(desired != 0 ? (double)desired : 1.0));
(double)(total.splitBirths()+total.coalBirths()-total.splitDeaths()-total.coalDeaths())/
(total.prevSweep() != 0 ? (double)total.prevSweep() : 1.0),
(double)(total.desired() - total.count())/(total.desired() != 0 ? (double)total.desired() : 1.0));
_dictionary->printDictCensus();
}

View File

@ -418,7 +418,7 @@ class CompactibleFreeListSpace: public CompactibleSpace {
// chunk exists, return NULL.
FreeChunk* find_chunk_at_end();
bool adaptive_freelists() { return _adaptive_freelists; }
bool adaptive_freelists() const { return _adaptive_freelists; }
void set_collector(CMSCollector* collector) { _collector = collector; }
@ -566,7 +566,7 @@ class CompactibleFreeListSpace: public CompactibleSpace {
FreeChunk* allocateScratch(size_t size);
// returns true if either the small or large linear allocation buffer is empty.
bool linearAllocationWouldFail();
bool linearAllocationWouldFail() const;
// Adjust the chunk for the minimum size. This version is called in
// most cases in CompactibleFreeListSpace methods.
@ -585,6 +585,9 @@ class CompactibleFreeListSpace: public CompactibleSpace {
void addChunkAndRepairOffsetTable(HeapWord* chunk, size_t size,
bool coalesced);
// Support for decisions regarding concurrent collection policy
bool should_concurrent_collect() const;
// Support for compaction
void prepare_for_compaction(CompactPoint* cp);
void adjust_pointers();
@ -622,7 +625,7 @@ class CompactibleFreeListSpace: public CompactibleSpace {
// coalescing of chunks during the sweep of garbage.
// Print the statistics for the free lists.
void printFLCensus(int sweepCt) const;
void printFLCensus(size_t sweep_count) const;
// Statistics functions
// Initialize census for lists before the sweep.
@ -635,12 +638,11 @@ class CompactibleFreeListSpace: public CompactibleSpace {
// Clear the census for each of the free lists.
void clearFLCensus();
// Perform functions for the census after the end of the sweep.
void endSweepFLCensus(int sweepCt);
void endSweepFLCensus(size_t sweep_count);
// Return true if the count of free chunks is greater
// than the desired number of free chunks.
bool coalOverPopulated(size_t size);
// Record (for each size):
//
// split-births = #chunks added due to splits in (prev-sweep-end,

View File

@ -3121,12 +3121,7 @@ ConcurrentMarkSweepGeneration::expand_and_allocate(size_t word_size,
if (GCExpandToAllocateDelayMillis > 0) {
os::sleep(Thread::current(), GCExpandToAllocateDelayMillis, false);
}
size_t adj_word_sz = CompactibleFreeListSpace::adjustObjectSize(word_size);
if (parallel) {
return cmsSpace()->par_allocate(adj_word_sz);
} else {
return cmsSpace()->allocate(adj_word_sz);
}
return have_lock_and_allocate(word_size, tlab);
}
// YSR: All of this generation expansion/shrinking stuff is an exact copy of
@ -5732,13 +5727,19 @@ void CMSCollector::sweep(bool asynch) {
// in the perm_gen_verify_bit_map. In order to do that we traverse
// all blocks in perm gen and mark all dead objects.
if (verifying() && !cms_should_unload_classes()) {
CMSTokenSyncWithLocks ts(true, _permGen->freelistLock(),
bitMapLock());
assert(perm_gen_verify_bit_map()->sizeInBits() != 0,
"Should have already been allocated");
MarkDeadObjectsClosure mdo(this, _permGen->cmsSpace(),
markBitMap(), perm_gen_verify_bit_map());
_permGen->cmsSpace()->blk_iterate(&mdo);
if (asynch) {
CMSTokenSyncWithLocks ts(true, _permGen->freelistLock(),
bitMapLock());
_permGen->cmsSpace()->blk_iterate(&mdo);
} else {
// In the case of synchronous sweep, we already have
// the requisite locks/tokens.
_permGen->cmsSpace()->blk_iterate(&mdo);
}
}
if (asynch) {

View File

@ -302,3 +302,29 @@ void FreeList::assert_proper_lock_protection_work() const {
#endif
}
#endif
// Print the "label line" for free list stats.
void FreeList::print_labels_on(outputStream* st, const char* c) {
st->print("%16s\t", c);
st->print("%14s\t" "%14s\t" "%14s\t" "%14s\t" "%14s\t"
"%14s\t" "%14s\t" "%14s\t" "%14s\t" "%14s\t" "\n",
"bfrsurp", "surplus", "desired", "prvSwep", "bfrSwep",
"count", "cBirths", "cDeaths", "sBirths", "sDeaths");
}
// Print the AllocationStats for the given free list. If the second argument
// to the call is a non-null string, it is printed in the first column;
// otherwise, if the argument is null (the default), then the size of the
// (free list) block is printed in the first column.
void FreeList::print_on(outputStream* st, const char* c) const {
if (c != NULL) {
st->print("%16s", c);
} else {
st->print(SIZE_FORMAT_W(16), size());
}
st->print("\t"
SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t"
SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\t" SSIZE_FORMAT_W(14) "\n",
bfrSurp(), surplus(), desired(), prevSweep(), beforeSweep(),
count(), coalBirths(), coalDeaths(), splitBirths(), splitDeaths());
}

View File

@ -38,6 +38,7 @@ class Mutex;
class FreeList VALUE_OBJ_CLASS_SPEC {
friend class CompactibleFreeListSpace;
friend class printTreeCensusClosure;
FreeChunk* _head; // List of free chunks
FreeChunk* _tail; // Tail of list of free chunks
size_t _size; // Size in Heap words of each chunks
@ -63,10 +64,11 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
protected:
void init_statistics();
void set_count(ssize_t v) { _count = v;}
void increment_count() { _count++; }
void increment_count() { _count++; }
void decrement_count() {
_count--;
assert(_count >= 0, "Count should not be negative"); }
assert(_count >= 0, "Count should not be negative");
}
public:
// Constructor
@ -159,6 +161,10 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
ssize_t desired() const {
return _allocation_stats.desired();
}
void set_desired(ssize_t v) {
assert_proper_lock_protection();
_allocation_stats.set_desired(v);
}
void compute_desired(float inter_sweep_current,
float inter_sweep_estimate) {
assert_proper_lock_protection();
@ -298,4 +304,8 @@ class FreeList VALUE_OBJ_CLASS_SPEC {
// Verify that the chunk is in the list.
// found. Return NULL if "fc" is not found.
bool verifyChunkInFreeLists(FreeChunk* fc) const;
// Printing support
static void print_labels_on(outputStream* st, const char* c);
void print_on(outputStream* st, const char* c = NULL) const;
};

View File

@ -19,15 +19,22 @@
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// have any questions.
//
//
//
// NOTE: DO NOT CHANGE THIS COPYRIGHT TO NEW STYLE - IT WILL BREAK makeDeps!
gcAdaptivePolicyCounters.hpp adaptiveSizePolicy.hpp
gcAdaptivePolicyCounters.hpp gcPolicyCounters.hpp
allocationStats.cpp allocationStats.hpp
allocationStats.cpp ostream.hpp
gcAdaptivePolicyCounters.cpp resourceArea.hpp
allocationStats.hpp allocation.hpp
allocationStats.hpp gcUtil.hpp
allocationStats.hpp globalDefinitions.hpp
gcAdaptivePolicyCounters.hpp adaptiveSizePolicy.hpp
gcAdaptivePolicyCounters.hpp gcPolicyCounters.hpp
gcAdaptivePolicyCounters.cpp resourceArea.hpp
gcAdaptivePolicyCounters.cpp gcAdaptivePolicyCounters.hpp
gSpaceCounters.cpp generation.hpp
@ -44,7 +51,7 @@ immutableSpace.cpp universe.hpp
isGCActiveMark.hpp parallelScavengeHeap.hpp
markSweep.inline.hpp psParallelCompact.hpp
markSweep.inline.hpp psParallelCompact.hpp
mutableNUMASpace.cpp mutableNUMASpace.hpp
mutableNUMASpace.cpp sharedHeap.hpp

View File

@ -74,8 +74,8 @@ size_t ASParNewGeneration::available_to_live() const {
#ifdef SHRINKS_AT_END_OF_EDEN
size_t delta_in_survivor = 0;
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
const size_t space_alignment = heap->intra_generation_alignment();
const size_t gen_alignment = heap->generation_alignment();
const size_t space_alignment = heap->intra_heap_alignment();
const size_t gen_alignment = heap->object_heap_alignment();
MutableSpace* space_shrinking = NULL;
if (from_space()->end() > to_space()->end()) {

View File

@ -785,6 +785,9 @@ void ParNewGeneration::collect(bool full,
swap_spaces(); // Make life simpler for CMS || rescan; see 6483690.
from()->set_next_compaction_space(to());
gch->set_incremental_collection_will_fail();
// Reset the PromotionFailureALot counters.
NOT_PRODUCT(Universe::heap()->reset_promotion_should_fail();)
}
// set new iteration safe limit for the survivor spaces
from()->set_concurrent_iteration_safe_limit(from()->top());

View File

@ -86,7 +86,7 @@ size_t ASPSYoungGen::available_for_contraction() {
if (eden_space()->is_empty()) {
// Respect the minimum size for eden and for the young gen as a whole.
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
const size_t eden_alignment = heap->intra_generation_alignment();
const size_t eden_alignment = heap->intra_heap_alignment();
const size_t gen_alignment = heap->young_gen_alignment();
assert(eden_space()->capacity_in_bytes() >= eden_alignment,
@ -124,7 +124,7 @@ size_t ASPSYoungGen::available_for_contraction() {
// to_space can be.
size_t ASPSYoungGen::available_to_live() {
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
const size_t alignment = heap->intra_generation_alignment();
const size_t alignment = heap->intra_heap_alignment();
// Include any space that is committed but is not in eden.
size_t available = pointer_delta(eden_space()->bottom(),
@ -275,7 +275,7 @@ void ASPSYoungGen::resize_spaces(size_t requested_eden_size,
assert(eden_start < from_start, "Cannot push into from_space");
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
const size_t alignment = heap->intra_generation_alignment();
const size_t alignment = heap->intra_heap_alignment();
// Check whether from space is below to space
if (from_start < to_start) {

View File

@ -39,10 +39,10 @@ class GenerationSizer : public TwoGenerationCollectorPolicy {
// If the user hasn't explicitly set the number of worker
// threads, set the count.
if (ParallelGCThreads == 0) {
assert(UseParallelGC, "Setting ParallelGCThreads without UseParallelGC");
ParallelGCThreads = os::active_processor_count();
}
assert(UseSerialGC ||
!FLAG_IS_DEFAULT(ParallelGCThreads) ||
(ParallelGCThreads > 0),
"ParallelGCThreads should be set before flag initialization");
// The survivor ratio's are calculated "raw", unlike the
// default gc, which adds 2 to the ratio value. We need to

View File

@ -41,7 +41,7 @@ ParMarkBitMap::initialize(MemRegion covered_region)
const size_t rs_align = page_sz == (size_t) os::vm_page_size() ? 0 :
MAX2(page_sz, granularity);
ReservedSpace rs(bytes, rs_align, false);
ReservedSpace rs(bytes, rs_align, rs_align > 0);
os::trace_page_sizes("par bitmap", raw_bytes, raw_bytes, page_sz,
rs.base(), rs.size());
_virtual_space = new PSVirtualSpace(rs, page_sz);

View File

@ -173,7 +173,7 @@ jint ParallelScavengeHeap::initialize() {
new PSAdaptiveSizePolicy(eden_capacity,
initial_promo_size,
young_gen()->to_space()->capacity_in_bytes(),
intra_generation_alignment(),
intra_heap_alignment(),
max_gc_pause_sec,
max_gc_minor_pause_sec,
GCTimeRatio

View File

@ -58,9 +58,9 @@ class ParallelScavengeHeap : public CollectedHeap {
public:
ParallelScavengeHeap() : CollectedHeap() {
set_alignment(_perm_gen_alignment, intra_generation_alignment());
set_alignment(_young_gen_alignment, intra_generation_alignment());
set_alignment(_old_gen_alignment, intra_generation_alignment());
set_alignment(_perm_gen_alignment, intra_heap_alignment());
set_alignment(_young_gen_alignment, intra_heap_alignment());
set_alignment(_old_gen_alignment, intra_heap_alignment());
}
// For use by VM operations
@ -92,14 +92,14 @@ class ParallelScavengeHeap : public CollectedHeap {
void post_initialize();
void update_counters();
// The alignment used for the various generations.
size_t perm_gen_alignment() const { return _perm_gen_alignment; }
size_t young_gen_alignment() const { return _young_gen_alignment; }
size_t old_gen_alignment() const { return _old_gen_alignment; }
// The alignment used for eden and survivors within the young gen.
size_t intra_generation_alignment() const { return 64 * K; }
// The alignment used for eden and survivors within the young gen
// and for boundary between young gen and old gen.
size_t intra_heap_alignment() const { return 64 * K; }
size_t capacity() const;
size_t used() const;
@ -217,6 +217,6 @@ class ParallelScavengeHeap : public CollectedHeap {
inline size_t ParallelScavengeHeap::set_alignment(size_t& var, size_t val)
{
assert(is_power_of_2((intptr_t)val), "must be a power of 2");
var = round_to(val, intra_generation_alignment());
var = round_to(val, intra_heap_alignment());
return var;
}

View File

@ -413,7 +413,7 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size)
const size_t rs_align = page_sz == (size_t) os::vm_page_size() ? 0 :
MAX2(page_sz, granularity);
ReservedSpace rs(bytes, rs_align, false);
ReservedSpace rs(bytes, rs_align, rs_align > 0);
os::trace_page_sizes("par compact", raw_bytes, raw_bytes, page_sz, rs.base(),
rs.size());
PSVirtualSpace* vspace = new PSVirtualSpace(rs, page_sz);

View File

@ -88,7 +88,7 @@ void PSYoungGen::initialize_work() {
// Compute maximum space sizes for performance counters
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
size_t alignment = heap->intra_generation_alignment();
size_t alignment = heap->intra_heap_alignment();
size_t size = _virtual_space->reserved_size();
size_t max_survivor_size;
@ -141,7 +141,7 @@ void PSYoungGen::compute_initial_space_boundaries() {
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
// Compute sizes
size_t alignment = heap->intra_generation_alignment();
size_t alignment = heap->intra_heap_alignment();
size_t size = _virtual_space->committed_size();
size_t survivor_size = size / InitialSurvivorRatio;
@ -192,7 +192,7 @@ void PSYoungGen::set_space_boundaries(size_t eden_size, size_t survivor_size) {
#ifndef PRODUCT
void PSYoungGen::space_invariants() {
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
const size_t alignment = heap->intra_generation_alignment();
const size_t alignment = heap->intra_heap_alignment();
// Currently, our eden size cannot shrink to zero
guarantee(eden_space()->capacity_in_bytes() >= alignment, "eden too small");
@ -392,7 +392,7 @@ void PSYoungGen::resize_spaces(size_t requested_eden_size,
char* to_end = (char*)to_space()->end();
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
const size_t alignment = heap->intra_generation_alignment();
const size_t alignment = heap->intra_heap_alignment();
const bool maintain_minimum =
(requested_eden_size + 2 * requested_survivor_size) <= min_gen_size();
@ -708,7 +708,7 @@ size_t PSYoungGen::available_to_min_gen() {
size_t PSYoungGen::available_to_live() {
size_t delta_in_survivor = 0;
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
const size_t space_alignment = heap->intra_generation_alignment();
const size_t space_alignment = heap->intra_heap_alignment();
const size_t gen_alignment = heap->young_gen_alignment();
MutableSpace* space_shrinking = NULL;

View File

@ -98,6 +98,8 @@ class AllocationStats VALUE_OBJ_CLASS_SPEC {
}
ssize_t desired() const { return _desired; }
void set_desired(ssize_t v) { _desired = v; }
ssize_t coalDesired() const { return _coalDesired; }
void set_coalDesired(ssize_t v) { _coalDesired = v; }

View File

@ -19,7 +19,7 @@
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// have any questions.
//
//
//
ad_<arch_model>.cpp adGlobals_<arch_model>.hpp
@ -164,6 +164,7 @@ callGenerator.hpp deoptimization.hpp
callGenerator.hpp type.hpp
callnode.cpp callnode.hpp
callnode.cpp bcEscapeAnalyzer.hpp
callnode.cpp escape.hpp
callnode.cpp locknode.hpp
callnode.cpp machnode.hpp
@ -176,7 +177,6 @@ callnode.cpp rootnode.hpp
callnode.cpp runtime.hpp
callnode.hpp connode.hpp
callnode.hpp escape.hpp
callnode.hpp mulnode.hpp
callnode.hpp multnode.hpp
callnode.hpp opcodes.hpp
@ -347,7 +347,6 @@ connode.cpp addnode.hpp
connode.cpp allocation.inline.hpp
connode.cpp compile.hpp
connode.cpp connode.hpp
connode.cpp escape.hpp
connode.cpp machnode.hpp
connode.cpp matcher.hpp
connode.cpp memnode.hpp
@ -410,6 +409,7 @@ domgraph.cpp vectset.hpp
escape.cpp allocation.hpp
escape.cpp bcEscapeAnalyzer.hpp
escape.cpp c2compiler.hpp
escape.cpp callnode.hpp
escape.cpp cfgnode.hpp
escape.cpp compile.hpp
@ -843,7 +843,6 @@ phaseX.cpp block.hpp
phaseX.cpp callnode.hpp
phaseX.cpp cfgnode.hpp
phaseX.cpp connode.hpp
phaseX.cpp escape.hpp
phaseX.cpp loopnode.hpp
phaseX.cpp machnode.hpp
phaseX.cpp opcodes.hpp
@ -990,6 +989,7 @@ stubRoutines.cpp runtime.hpp
subnode.cpp addnode.hpp
subnode.cpp allocation.inline.hpp
subnode.cpp callnode.hpp
subnode.cpp cfgnode.hpp
subnode.cpp compileLog.hpp
subnode.cpp connode.hpp
@ -1086,7 +1086,7 @@ idealGraphPrinter.hpp growableArray.hpp
idealGraphPrinter.hpp ostream.hpp
idealGraphPrinter.cpp idealGraphPrinter.hpp
idealGraphPrinter.cpp chaitin.hpp
idealGraphPrinter.cpp chaitin.hpp
idealGraphPrinter.cpp machnode.hpp
idealGraphPrinter.cpp parse.hpp
idealGraphPrinter.cpp threadCritical.hpp
@ -1098,4 +1098,4 @@ parse2.cpp idealGraphPrinter.hpp
parse1.cpp idealGraphPrinter.hpp
matcher.cpp idealGraphPrinter.hpp
loopnode.cpp idealGraphPrinter.hpp
chaitin.cpp idealGraphPrinter.hpp
chaitin.cpp idealGraphPrinter.hpp

View File

@ -19,7 +19,7 @@
// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
// CA 95054 USA or visit www.sun.com if you need additional information or
// have any questions.
//
//
//
// NOTE: DO NOT CHANGE THIS COPYRIGHT TO NEW STYLE - IT WILL BREAK makeDeps!
@ -46,13 +46,13 @@
// as dependencies. Header files named H.inline.hpp generally contain
// bodies for inline functions declared in H.hpp.
//
// NOTE: Files that use the token "generate_platform_dependent_include"
// NOTE: Files that use the token "generate_platform_dependent_include"
// are expected to contain macro references like <os>, <arch_model>, ... and
// makedeps has a dependency on these platform files looking like:
// foo_<macro>.trailing_string
// foo_<macro>.trailing_string
// (where "trailing_string" can be any legal filename strings but typically
// is "hpp" or "inline.hpp").
//
//
// The dependency in makedeps (and enforced) is that an underscore
// will precedure the macro invocation. Note that this restriction
// is only enforced on filenames that have the dependency token
@ -148,12 +148,6 @@ allocation.hpp globals.hpp
allocation.inline.hpp os.hpp
allocationStats.cpp allocationStats.hpp
allocationStats.hpp allocation.hpp
allocationStats.hpp gcUtil.hpp
allocationStats.hpp globalDefinitions.hpp
aprofiler.cpp aprofiler.hpp
aprofiler.cpp collectedHeap.inline.hpp
aprofiler.cpp oop.inline.hpp
@ -720,6 +714,11 @@ ciObjArray.hpp ciArray.hpp
ciObjArray.hpp ciClassList.hpp
ciObjArray.hpp objArrayOop.hpp
ciObjArray.cpp ciObjArray.hpp
ciObjArray.cpp ciNullObject.hpp
ciObjArray.cpp ciUtilities.hpp
ciObjArray.cpp objArrayOop.hpp
ciObjArrayKlass.cpp ciInstanceKlass.hpp
ciObjArrayKlass.cpp ciObjArrayKlass.hpp
ciObjArrayKlass.cpp ciObjArrayKlassKlass.hpp
@ -1935,7 +1934,7 @@ icache_<arch>.hpp generate_platform_dependent_include
init.cpp bytecodes.hpp
init.cpp collectedHeap.hpp
init.cpp handles.inline.hpp
init.cpp handles.inline.hpp
init.cpp icBuffer.hpp
init.cpp icache.hpp
init.cpp init.hpp
@ -3068,6 +3067,7 @@ oopMap.hpp vmreg.hpp
oopMapCache.cpp allocation.inline.hpp
oopMapCache.cpp handles.inline.hpp
oopMapCache.cpp jvmtiRedefineClassesTrace.hpp
oopMapCache.cpp oop.inline.hpp
oopMapCache.cpp oopMapCache.hpp
oopMapCache.cpp resourceArea.hpp

View File

@ -532,6 +532,10 @@ void OopMapCache::flush_obsolete_entries() {
if (!_array[i].is_empty() && _array[i].method()->is_old()) {
// Cache entry is occupied by an old redefined method and we don't want
// to pin it down so flush the entry.
RC_TRACE(0x08000000, ("flush: %s(%s): cached entry @%d",
_array[i].method()->name()->as_C_string(),
_array[i].method()->signature()->as_C_string(), i));
_array[i].flush();
}
}
@ -577,6 +581,15 @@ void OopMapCache::lookup(methodHandle method,
// Entry is not in hashtable.
// Compute entry and return it
if (method->should_not_be_cached()) {
// It is either not safe or not a good idea to cache this methodOop
// at this time. We give the caller of lookup() a copy of the
// interesting info via parameter entry_for, but we don't add it to
// the cache. See the gory details in methodOop.cpp.
compute_one_oop_map(method, bci, entry_for);
return;
}
// First search for an empty slot
for(i = 0; i < _probe_depth; i++) {
entry = entry_at(probe + i);
@ -584,12 +597,6 @@ void OopMapCache::lookup(methodHandle method,
entry->fill(method, bci);
entry_for->resource_copy(entry);
assert(!entry_for->is_empty(), "A non-empty oop map should be returned");
if (method->is_old()) {
// The caller of lookup() will receive a copy of the interesting
// info via entry_for, but we don't keep an old redefined method in
// the cache to avoid pinning down the method.
entry->flush();
}
return;
}
}
@ -623,13 +630,6 @@ void OopMapCache::lookup(methodHandle method,
}
assert(!entry_for->is_empty(), "A non-empty oop map should be returned");
if (method->is_old()) {
// The caller of lookup() will receive a copy of the interesting
// info via entry_for, but we don't keep an old redefined method in
// the cache to avoid pinning down the method.
entry->flush();
}
return;
}

View File

@ -51,7 +51,7 @@ CardTableModRefBS::CardTableModRefBS(MemRegion whole_heap,
_whole_heap(whole_heap),
_guard_index(cards_required(whole_heap.word_size()) - 1),
_last_valid_index(_guard_index - 1),
_page_size(os::page_size_for_region(_guard_index + 1, _guard_index + 1, 1)),
_page_size(os::vm_page_size()),
_byte_map_size(compute_byte_map_size())
{
_kind = BarrierSet::CardTableModRef;
@ -196,8 +196,8 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) {
assert(_whole_heap.contains(new_region),
"attempt to cover area not in reserved area");
debug_only(verify_guard();)
int ind = find_covering_region_by_base(new_region.start());
MemRegion old_region = _covered[ind];
int const ind = find_covering_region_by_base(new_region.start());
MemRegion const old_region = _covered[ind];
assert(old_region.start() == new_region.start(), "just checking");
if (new_region.word_size() != old_region.word_size()) {
// Commit new or uncommit old pages, if necessary.
@ -205,21 +205,21 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) {
// Extend the end of this _commited region
// to cover the end of any lower _committed regions.
// This forms overlapping regions, but never interior regions.
HeapWord* max_prev_end = largest_prev_committed_end(ind);
HeapWord* const max_prev_end = largest_prev_committed_end(ind);
if (max_prev_end > cur_committed.end()) {
cur_committed.set_end(max_prev_end);
}
// Align the end up to a page size (starts are already aligned).
jbyte* new_end = byte_after(new_region.last());
HeapWord* new_end_aligned =
(HeapWord*)align_size_up((uintptr_t)new_end, _page_size);
jbyte* const new_end = byte_after(new_region.last());
HeapWord* const new_end_aligned =
(HeapWord*) align_size_up((uintptr_t)new_end, _page_size);
assert(new_end_aligned >= (HeapWord*) new_end,
"align up, but less");
// The guard page is always committed and should not be committed over.
HeapWord* new_end_for_commit = MIN2(new_end_aligned, _guard_region.start());
HeapWord* const new_end_for_commit = MIN2(new_end_aligned, _guard_region.start());
if (new_end_for_commit > cur_committed.end()) {
// Must commit new pages.
MemRegion new_committed =
MemRegion const new_committed =
MemRegion(cur_committed.end(), new_end_for_commit);
assert(!new_committed.is_empty(), "Region should not be empty here");
@ -233,7 +233,7 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) {
// the cur_committed region may include the guard region.
} else if (new_end_aligned < cur_committed.end()) {
// Must uncommit pages.
MemRegion uncommit_region =
MemRegion const uncommit_region =
committed_unique_to_self(ind, MemRegion(new_end_aligned,
cur_committed.end()));
if (!uncommit_region.is_empty()) {
@ -257,7 +257,7 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) {
}
assert(index_for(new_region.last()) < (int) _guard_index,
"The guard card will be overwritten");
jbyte* end = byte_after(new_region.last());
jbyte* const end = byte_after(new_region.last());
// do nothing if we resized downward.
if (entry < end) {
memset(entry, clean_card, pointer_delta(end, entry, sizeof(jbyte)));

View File

@ -556,10 +556,16 @@ void CardTableRS::verify() {
}
void CardTableRS::verify_empty(MemRegion mr) {
void CardTableRS::verify_aligned_region_empty(MemRegion mr) {
if (!mr.is_empty()) {
jbyte* cur_entry = byte_for(mr.start());
jbyte* limit = byte_after(mr.last());
// The region mr may not start on a card boundary so
// the first card may reflect a write to the space
// just prior to mr.
if (!is_aligned(mr.start())) {
cur_entry++;
}
for (;cur_entry < limit; cur_entry++) {
guarantee(*cur_entry == CardTableModRefBS::clean_card,
"Unexpected dirty card found");

View File

@ -126,7 +126,7 @@ public:
}
void verify();
void verify_empty(MemRegion mr);
void verify_aligned_region_empty(MemRegion mr);
void clear(MemRegion mr) { _ct_bs.clear(mr); }
void clear_into_younger(Generation* gen, bool clear_perm);

View File

@ -57,45 +57,51 @@ void CollectorPolicy::initialize_size_info() {
// User inputs from -mx and ms are aligned
_initial_heap_byte_size = align_size_up(Arguments::initial_heap_size(),
min_alignment());
_min_heap_byte_size = align_size_up(Arguments::min_heap_size(),
min_alignment());
_max_heap_byte_size = align_size_up(MaxHeapSize, max_alignment());
set_min_heap_byte_size(align_size_up(Arguments::min_heap_size(),
min_alignment()));
set_max_heap_byte_size(align_size_up(MaxHeapSize, max_alignment()));
// Check validity of heap parameters from launcher
if (_initial_heap_byte_size == 0) {
_initial_heap_byte_size = NewSize + OldSize;
if (initial_heap_byte_size() == 0) {
set_initial_heap_byte_size(NewSize + OldSize);
} else {
Universe::check_alignment(_initial_heap_byte_size, min_alignment(),
Universe::check_alignment(initial_heap_byte_size(), min_alignment(),
"initial heap");
}
if (_min_heap_byte_size == 0) {
_min_heap_byte_size = NewSize + OldSize;
if (min_heap_byte_size() == 0) {
set_min_heap_byte_size(NewSize + OldSize);
} else {
Universe::check_alignment(_min_heap_byte_size, min_alignment(),
Universe::check_alignment(min_heap_byte_size(), min_alignment(),
"initial heap");
}
// Check heap parameter properties
if (_initial_heap_byte_size < M) {
if (initial_heap_byte_size() < M) {
vm_exit_during_initialization("Too small initial heap");
}
// Check heap parameter properties
if (_min_heap_byte_size < M) {
if (min_heap_byte_size() < M) {
vm_exit_during_initialization("Too small minimum heap");
}
if (_initial_heap_byte_size <= NewSize) {
if (initial_heap_byte_size() <= NewSize) {
// make sure there is at least some room in old space
vm_exit_during_initialization("Too small initial heap for new size specified");
}
if (_max_heap_byte_size < _min_heap_byte_size) {
if (max_heap_byte_size() < min_heap_byte_size()) {
vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
}
if (_initial_heap_byte_size < _min_heap_byte_size) {
if (initial_heap_byte_size() < min_heap_byte_size()) {
vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified");
}
if (_max_heap_byte_size < _initial_heap_byte_size) {
if (max_heap_byte_size() < initial_heap_byte_size()) {
vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
}
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap "
SIZE_FORMAT " Maximum heap " SIZE_FORMAT,
min_heap_byte_size(), initial_heap_byte_size(), max_heap_byte_size());
}
}
void CollectorPolicy::initialize_perm_generation(PermGen::Name pgnm) {
@ -128,10 +134,26 @@ GenRemSet* CollectorPolicy::create_rem_set(MemRegion whole_heap,
// GenCollectorPolicy methods.
size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) {
size_t x = base_size / (NewRatio+1);
size_t new_gen_size = x > min_alignment() ?
align_size_down(x, min_alignment()) :
min_alignment();
return new_gen_size;
}
size_t GenCollectorPolicy::bound_minus_alignment(size_t desired_size,
size_t maximum_size) {
size_t alignment = min_alignment();
size_t max_minus = maximum_size - alignment;
return desired_size < max_minus ? desired_size : max_minus;
}
void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size,
size_t init_promo_size,
size_t init_survivor_size) {
double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;
const double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;
_size_policy = new AdaptiveSizePolicy(init_eden_size,
init_promo_size,
init_survivor_size,
@ -210,74 +232,260 @@ void TwoGenerationCollectorPolicy::initialize_flags() {
assert(MaxHeapSize % max_alignment() == 0, "maximum heap alignment");
}
// Values set on the command line win over any ergonomically
// set command line parameters.
// Ergonomic choice of parameters are done before this
// method is called. Values for command line parameters such as NewSize
// and MaxNewSize feed those ergonomic choices into this method.
// This method makes the final generation sizings consistent with
// themselves and with overall heap sizings.
// In the absence of explicitly set command line flags, policies
// such as the use of NewRatio are used to size the generation.
void GenCollectorPolicy::initialize_size_info() {
CollectorPolicy::initialize_size_info();
// Minimum sizes of the generations may be different than
// the initial sizes.
if (!FLAG_IS_DEFAULT(NewSize)) {
_min_gen0_size = NewSize;
} else {
_min_gen0_size = align_size_down(_min_heap_byte_size / (NewRatio+1),
// min_alignment() is used for alignment within a generation.
// There is additional alignment done down stream for some
// collectors that sometimes causes unwanted rounding up of
// generations sizes.
// Determine maximum size of gen0
size_t max_new_size = 0;
if (FLAG_IS_CMDLINE(MaxNewSize)) {
if (MaxNewSize < min_alignment()) {
max_new_size = min_alignment();
} else if (MaxNewSize >= max_heap_byte_size()) {
max_new_size = align_size_down(max_heap_byte_size() - min_alignment(),
min_alignment());
// We bound the minimum size by NewSize below (since it historically
warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or "
"greater than the entire heap (" SIZE_FORMAT "k). A "
"new generation size of " SIZE_FORMAT "k will be used.",
MaxNewSize/K, max_heap_byte_size()/K, max_new_size/K);
} else {
max_new_size = align_size_down(MaxNewSize, min_alignment());
}
// The case for FLAG_IS_ERGO(MaxNewSize) could be treated
// specially at this point to just use an ergonomically set
// MaxNewSize to set max_new_size. For cases with small
// heaps such a policy often did not work because the MaxNewSize
// was larger than the entire heap. The interpretation given
// to ergonomically set flags is that the flags are set
// by different collectors for their own special needs but
// are not allowed to badly shape the heap. This allows the
// different collectors to decide what's best for themselves
// without having to factor in the overall heap shape. It
// can be the case in the future that the collectors would
// only make "wise" ergonomics choices and this policy could
// just accept those choices. The choices currently made are
// not always "wise".
} else {
max_new_size = scale_by_NewRatio_aligned(max_heap_byte_size());
// Bound the maximum size by NewSize below (since it historically
// would have been NewSize and because the NewRatio calculation could
// yield a size that is too small) and bound it by MaxNewSize above.
// This is not always best. The NewSize calculated by CMS (which has
// a fixed minimum of 16m) can sometimes be "too" large. Consider
// the case where -Xmx32m. The CMS calculated NewSize would be about
// half the entire heap which seems too large. But the counter
// example is seen when the client defaults for NewRatio are used.
// An initial young generation size of 640k was observed
// with -Xmx128m -XX:MaxNewSize=32m when NewSize was not used
// as a lower bound as with
// _min_gen0_size = MIN2(_min_gen0_size, MaxNewSize);
// and 640k seemed too small a young generation.
_min_gen0_size = MIN2(MAX2(_min_gen0_size, NewSize), MaxNewSize);
// Ergonomics plays here by previously calculating the desired
// NewSize and MaxNewSize.
max_new_size = MIN2(MAX2(max_new_size, NewSize), MaxNewSize);
}
assert(max_new_size > 0, "All paths should set max_new_size");
// Given the maximum gen0 size, determine the initial and
// minimum sizes.
if (max_heap_byte_size() == min_heap_byte_size()) {
// The maximum and minimum heap sizes are the same so
// the generations minimum and initial must be the
// same as its maximum.
set_min_gen0_size(max_new_size);
set_initial_gen0_size(max_new_size);
set_max_gen0_size(max_new_size);
} else {
size_t desired_new_size = 0;
if (!FLAG_IS_DEFAULT(NewSize)) {
// If NewSize is set ergonomically (for example by cms), it
// would make sense to use it. If it is used, also use it
// to set the initial size. Although there is no reason
// the minimum size and the initial size have to be the same,
// the current implementation gets into trouble during the calculation
// of the tenured generation sizes if they are different.
// Note that this makes the initial size and the minimum size
// generally small compared to the NewRatio calculation.
_min_gen0_size = NewSize;
desired_new_size = NewSize;
max_new_size = MAX2(max_new_size, NewSize);
} else {
// For the case where NewSize is the default, use NewRatio
// to size the minimum and initial generation sizes.
// Use the default NewSize as the floor for these values. If
// NewRatio is overly large, the resulting sizes can be too
// small.
_min_gen0_size = MAX2(scale_by_NewRatio_aligned(min_heap_byte_size()),
NewSize);
desired_new_size =
MAX2(scale_by_NewRatio_aligned(initial_heap_byte_size()),
NewSize);
}
assert(_min_gen0_size > 0, "Sanity check");
set_initial_gen0_size(desired_new_size);
set_max_gen0_size(max_new_size);
// At this point the desirable initial and minimum sizes have been
// determined without regard to the maximum sizes.
// Bound the sizes by the corresponding overall heap sizes.
set_min_gen0_size(
bound_minus_alignment(_min_gen0_size, min_heap_byte_size()));
set_initial_gen0_size(
bound_minus_alignment(_initial_gen0_size, initial_heap_byte_size()));
set_max_gen0_size(
bound_minus_alignment(_max_gen0_size, max_heap_byte_size()));
// At this point all three sizes have been checked against the
// maximum sizes but have not been checked for consistency
// amoung the three.
// Final check min <= initial <= max
set_min_gen0_size(MIN2(_min_gen0_size, _max_gen0_size));
set_initial_gen0_size(
MAX2(MIN2(_initial_gen0_size, _max_gen0_size), _min_gen0_size));
set_min_gen0_size(MIN2(_min_gen0_size, _initial_gen0_size));
}
// Parameters are valid, compute area sizes.
size_t max_new_size = align_size_down(_max_heap_byte_size / (NewRatio+1),
min_alignment());
max_new_size = MIN2(MAX2(max_new_size, _min_gen0_size), MaxNewSize);
// desired_new_size is used to set the initial size. The
// initial size must be greater than the minimum size.
size_t desired_new_size =
align_size_down(_initial_heap_byte_size / (NewRatio+1),
min_alignment());
size_t new_size = MIN2(MAX2(desired_new_size, _min_gen0_size), max_new_size);
_initial_gen0_size = new_size;
_max_gen0_size = max_new_size;
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT " Initial gen0 "
SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT,
min_gen0_size(), initial_gen0_size(), max_gen0_size());
}
}
// Call this method during the sizing of the gen1 to make
// adjustments to gen0 because of gen1 sizing policy. gen0 initially has
// the most freedom in sizing because it is done before the
// policy for gen1 is applied. Once gen1 policies have been applied,
// there may be conflicts in the shape of the heap and this method
// is used to make the needed adjustments. The application of the
// policies could be more sophisticated (iterative for example) but
// keeping it simple also seems a worthwhile goal.
bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr,
size_t* gen1_size_ptr,
size_t heap_size,
size_t min_gen0_size) {
bool result = false;
if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) {
if (((*gen0_size_ptr + OldSize) > heap_size) &&
(heap_size - min_gen0_size) >= min_alignment()) {
// Adjust gen0 down to accomodate OldSize
*gen0_size_ptr = heap_size - min_gen0_size;
*gen0_size_ptr =
MAX2((uintx)align_size_down(*gen0_size_ptr, min_alignment()),
min_alignment());
assert(*gen0_size_ptr > 0, "Min gen0 is too large");
result = true;
} else {
*gen1_size_ptr = heap_size - *gen0_size_ptr;
*gen1_size_ptr =
MAX2((uintx)align_size_down(*gen1_size_ptr, min_alignment()),
min_alignment());
}
}
return result;
}
// Minimum sizes of the generations may be different than
// the initial sizes. An inconsistently is permitted here
// in the total size that can be specified explicitly by
// command line specification of OldSize and NewSize and
// also a command line specification of -Xms. Issue a warning
// but allow the values to pass.
void TwoGenerationCollectorPolicy::initialize_size_info() {
GenCollectorPolicy::initialize_size_info();
// Minimum sizes of the generations may be different than
// the initial sizes. An inconsistently is permitted here
// in the total size that can be specified explicitly by
// command line specification of OldSize and NewSize and
// also a command line specification of -Xms. Issue a warning
// but allow the values to pass.
if (!FLAG_IS_DEFAULT(OldSize)) {
_min_gen1_size = OldSize;
// At this point the minimum, initial and maximum sizes
// of the overall heap and of gen0 have been determined.
// The maximum gen1 size can be determined from the maximum gen0
// and maximum heap size since not explicit flags exits
// for setting the gen1 maximum.
_max_gen1_size = max_heap_byte_size() - _max_gen0_size;
_max_gen1_size =
MAX2((uintx)align_size_down(_max_gen1_size, min_alignment()),
min_alignment());
// If no explicit command line flag has been set for the
// gen1 size, use what is left for gen1.
if (FLAG_IS_DEFAULT(OldSize) || FLAG_IS_ERGO(OldSize)) {
// The user has not specified any value or ergonomics
// has chosen a value (which may or may not be consistent
// with the overall heap size). In either case make
// the minimum, maximum and initial sizes consistent
// with the gen0 sizes and the overall heap sizes.
assert(min_heap_byte_size() > _min_gen0_size,
"gen0 has an unexpected minimum size");
set_min_gen1_size(min_heap_byte_size() - min_gen0_size());
set_min_gen1_size(
MAX2((uintx)align_size_down(_min_gen1_size, min_alignment()),
min_alignment()));
set_initial_gen1_size(initial_heap_byte_size() - initial_gen0_size());
set_initial_gen1_size(
MAX2((uintx)align_size_down(_initial_gen1_size, min_alignment()),
min_alignment()));
} else {
// It's been explicitly set on the command line. Use the
// OldSize and then determine the consequences.
set_min_gen1_size(OldSize);
set_initial_gen1_size(OldSize);
// If the user has explicitly set an OldSize that is inconsistent
// with other command line flags, issue a warning.
// The generation minimums and the overall heap mimimum should
// be within one heap alignment.
if ((_min_gen1_size + _min_gen0_size + max_alignment()) <
_min_heap_byte_size) {
if ((_min_gen1_size + _min_gen0_size + min_alignment()) <
min_heap_byte_size()) {
warning("Inconsistency between minimum heap size and minimum "
"generation sizes: using min heap = " SIZE_FORMAT,
_min_heap_byte_size);
"generation sizes: using minimum heap = " SIZE_FORMAT,
min_heap_byte_size());
}
} else {
_min_gen1_size = _min_heap_byte_size - _min_gen0_size;
if ((OldSize > _max_gen1_size)) {
warning("Inconsistency between maximum heap size and maximum "
"generation sizes: using maximum heap = " SIZE_FORMAT
" -XX:OldSize flag is being ignored",
max_heap_byte_size());
}
// If there is an inconsistency between the OldSize and the minimum and/or
// initial size of gen0, since OldSize was explicitly set, OldSize wins.
if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size,
min_heap_byte_size(), OldSize)) {
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT " Initial gen0 "
SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT,
min_gen0_size(), initial_gen0_size(), max_gen0_size());
}
}
// Initial size
if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size,
initial_heap_byte_size(), OldSize)) {
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT " Initial gen0 "
SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT,
min_gen0_size(), initial_gen0_size(), max_gen0_size());
}
}
}
// Enforce the maximum gen1 size.
set_min_gen1_size(MIN2(_min_gen1_size, _max_gen1_size));
_initial_gen1_size = _initial_heap_byte_size - _initial_gen0_size;
_max_gen1_size = _max_heap_byte_size - _max_gen0_size;
// Check that min gen1 <= initial gen1 <= max gen1
set_initial_gen1_size(MAX2(_initial_gen1_size, _min_gen1_size));
set_initial_gen1_size(MIN2(_initial_gen1_size, _max_gen1_size));
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("Minimum gen1 " SIZE_FORMAT " Initial gen1 "
SIZE_FORMAT " Maximum gen1 " SIZE_FORMAT,
min_gen1_size(), initial_gen1_size(), max_gen1_size());
}
}
HeapWord* GenCollectorPolicy::mem_allocate_work(size_t size,

View File

@ -82,8 +82,11 @@ class CollectorPolicy : public CHeapObj {
size_t max_alignment() { return _max_alignment; }
size_t initial_heap_byte_size() { return _initial_heap_byte_size; }
void set_initial_heap_byte_size(size_t v) { _initial_heap_byte_size = v; }
size_t max_heap_byte_size() { return _max_heap_byte_size; }
void set_max_heap_byte_size(size_t v) { _max_heap_byte_size = v; }
size_t min_heap_byte_size() { return _min_heap_byte_size; }
void set_min_heap_byte_size(size_t v) { _min_heap_byte_size = v; }
enum Name {
CollectorPolicyKind,
@ -182,8 +185,24 @@ class GenCollectorPolicy : public CollectorPolicy {
// compute max heap alignment
size_t compute_max_alignment();
// Scale the base_size by NewRation according to
// result = base_size / (NewRatio + 1)
// and align by min_alignment()
size_t scale_by_NewRatio_aligned(size_t base_size);
// Bound the value by the given maximum minus the
// min_alignment.
size_t bound_minus_alignment(size_t desired_size, size_t maximum_size);
public:
// Accessors
size_t min_gen0_size() { return _min_gen0_size; }
void set_min_gen0_size(size_t v) { _min_gen0_size = v; }
size_t initial_gen0_size() { return _initial_gen0_size; }
void set_initial_gen0_size(size_t v) { _initial_gen0_size = v; }
size_t max_gen0_size() { return _max_gen0_size; }
void set_max_gen0_size(size_t v) { _max_gen0_size = v; }
virtual int number_of_generations() = 0;
virtual GenerationSpec **generations() {
@ -236,6 +255,14 @@ class TwoGenerationCollectorPolicy : public GenCollectorPolicy {
void initialize_generations() { ShouldNotReachHere(); }
public:
// Accessors
size_t min_gen1_size() { return _min_gen1_size; }
void set_min_gen1_size(size_t v) { _min_gen1_size = v; }
size_t initial_gen1_size() { return _initial_gen1_size; }
void set_initial_gen1_size(size_t v) { _initial_gen1_size = v; }
size_t max_gen1_size() { return _max_gen1_size; }
void set_max_gen1_size(size_t v) { _max_gen1_size = v; }
// Inherited methods
TwoGenerationCollectorPolicy* as_two_generation_policy() { return this; }
@ -246,6 +273,10 @@ class TwoGenerationCollectorPolicy : public GenCollectorPolicy {
virtual CollectorPolicy::Name kind() {
return CollectorPolicy::TwoGenerationCollectorPolicyKind;
}
// Returns true is gen0 sizes were adjusted
bool adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr,
size_t heap_size, size_t min_gen1_size);
};
class MarkSweepPolicy : public TwoGenerationCollectorPolicy {

View File

@ -26,9 +26,27 @@
#include "incls/_compactingPermGenGen.cpp.incl"
// Recursively adjust all pointers in an object and all objects by
// referenced it. Clear marks on objects in order to prevent visiting
// any object twice.
// An ObjectClosure helper: Recursively adjust all pointers in an object
// and all objects by referenced it. Clear marks on objects in order to
// prevent visiting any object twice. This helper is used when the
// RedefineClasses() API has been called.
class AdjustSharedObjectClosure : public ObjectClosure {
public:
void do_object(oop obj) {
if (obj->is_shared_readwrite()) {
if (obj->mark()->is_marked()) {
obj->init_mark(); // Don't revisit this object.
obj->adjust_pointers(); // Adjust this object's references.
}
}
}
};
// An OopClosure helper: Recursively adjust all pointers in an object
// and all objects by referenced it. Clear marks on objects in order
// to prevent visiting any object twice.
class RecursiveAdjustSharedObjectClosure : public OopClosure {
public:
@ -274,15 +292,34 @@ CompactingPermGenGen::CompactingPermGenGen(ReservedSpace rs,
// objects in the space will page in more objects than we need.
// Instead, use the system dictionary as strong roots into the read
// write space.
//
// If a RedefineClasses() call has been made, then we have to iterate
// over the entire shared read-write space in order to find all the
// objects that need to be forwarded. For example, it is possible for
// an nmethod to be found and marked in GC phase-1 only for the nmethod
// to be freed by the time we reach GC phase-3. The underlying method
// is still marked, but we can't (easily) find it in GC phase-3 so we
// blow up in GC phase-4. With RedefineClasses() we want replaced code
// (EMCP or obsolete) to go away (i.e., be collectible) once it is no
// longer being executed by any thread so we keep minimal attachments
// to the replaced code. However, we can't guarantee when those EMCP
// or obsolete methods will be collected so they may still be out there
// even after we've severed our minimal attachments.
void CompactingPermGenGen::pre_adjust_pointers() {
if (spec()->enable_shared_spaces()) {
RecursiveAdjustSharedObjectClosure blk;
Universe::oops_do(&blk);
StringTable::oops_do(&blk);
SystemDictionary::always_strong_classes_do(&blk);
TraversePlaceholdersClosure tpc;
SystemDictionary::placeholders_do(&tpc);
if (JvmtiExport::has_redefined_a_class()) {
// RedefineClasses() requires a brute force approach
AdjustSharedObjectClosure blk;
rw_space()->object_iterate(&blk);
} else {
RecursiveAdjustSharedObjectClosure blk;
Universe::oops_do(&blk);
StringTable::oops_do(&blk);
SystemDictionary::always_strong_classes_do(&blk);
TraversePlaceholdersClosure tpc;
SystemDictionary::placeholders_do(&tpc);
}
}
}

View File

@ -91,8 +91,15 @@ public:
virtual void verify() = 0;
// Verify that the remembered set has no entries for
// the heap interval denoted by mr.
virtual void verify_empty(MemRegion mr) = 0;
// the heap interval denoted by mr. If there are any
// alignment constraints on the remembered set, only the
// part of the region that is aligned is checked.
//
// alignment boundaries
// +--------+-------+--------+-------+
// [ region mr )
// [ part checked )
virtual void verify_aligned_region_empty(MemRegion mr) = 0;
// If appropriate, print some information about the remset on "tty".
virtual void print() {}

View File

@ -102,8 +102,9 @@ bool CodeHeap::reserve(size_t reserved_size, size_t committed_size,
_log2_segment_size = exact_log2(segment_size);
// Reserve and initialize space for _memory.
const size_t page_size = os::page_size_for_region(committed_size,
reserved_size, 8);
const size_t page_size = os::can_execute_large_page_memory() ?
os::page_size_for_region(committed_size, reserved_size, 8) :
os::vm_page_size();
const size_t granularity = os::vm_allocation_granularity();
const size_t r_align = MAX2(page_size, granularity);
const size_t r_size = align_size_up(reserved_size, r_align);
@ -111,7 +112,7 @@ bool CodeHeap::reserve(size_t reserved_size, size_t committed_size,
const size_t rs_align = page_size == (size_t) os::vm_page_size() ? 0 :
MAX2(page_size, granularity);
ReservedSpace rs(r_size, rs_align, false);
ReservedSpace rs(r_size, rs_align, rs_align > 0);
os::trace_page_sizes("code heap", committed_size, reserved_size, page_size,
rs.base(), rs.size());
if (!_memory.initialize(rs, c_size)) {

View File

@ -65,7 +65,7 @@ void KlassInfoEntry::print_on(outputStream* st) const {
name = "<no name>";
}
// simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit
st->print_cr("%13" FORMAT64_MODIFIER "d %13" FORMAT64_MODIFIER "u %s",
st->print_cr(INT64_FORMAT_W(13) " " UINT64_FORMAT_W(13) " %s",
(jlong) _instance_count,
(julong) _instance_words * HeapWordSize,
name);
@ -80,7 +80,10 @@ KlassInfoEntry* KlassInfoBucket::lookup(const klassOop k) {
elt = elt->next();
}
elt = new KlassInfoEntry(k, list());
set_list(elt);
// We may be out of space to allocate the new entry.
if (elt != NULL) {
set_list(elt);
}
return elt;
}
@ -103,21 +106,25 @@ void KlassInfoBucket::empty() {
}
KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) {
_size = size;
_size = 0;
_ref = ref;
_buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, _size);
for (int index = 0; index < _size; index++) {
_buckets[index].initialize();
_buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size);
if (_buckets != NULL) {
_size = size;
for (int index = 0; index < _size; index++) {
_buckets[index].initialize();
}
}
}
KlassInfoTable::~KlassInfoTable() {
for (int index = 0; index < _size; index++) {
_buckets[index].empty();
if (_buckets != NULL) {
for (int index = 0; index < _size; index++) {
_buckets[index].empty();
}
FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets);
_size = 0;
}
FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets);
_size = 0;
}
uint KlassInfoTable::hash(klassOop p) {
@ -127,19 +134,32 @@ uint KlassInfoTable::hash(klassOop p) {
KlassInfoEntry* KlassInfoTable::lookup(const klassOop k) {
uint idx = hash(k) % _size;
assert(_buckets != NULL, "Allocation failure should have been caught");
KlassInfoEntry* e = _buckets[idx].lookup(k);
assert(k == e->klass(), "must be equal");
// Lookup may fail if this is a new klass for which we
// could not allocate space for an new entry.
assert(e == NULL || k == e->klass(), "must be equal");
return e;
}
void KlassInfoTable::record_instance(const oop obj) {
// Return false if the entry could not be recorded on account
// of running out of space required to create a new entry.
bool KlassInfoTable::record_instance(const oop obj) {
klassOop k = obj->klass();
KlassInfoEntry* elt = lookup(k);
elt->set_count(elt->count() + 1);
elt->set_words(elt->words() + obj->size());
// elt may be NULL if it's a new klass for which we
// could not allocate space for a new entry in the hashtable.
if (elt != NULL) {
elt->set_count(elt->count() + 1);
elt->set_words(elt->words() + obj->size());
return true;
} else {
return false;
}
}
void KlassInfoTable::iterate(KlassInfoClosure* cic) {
assert(_size == 0 || _buckets != NULL, "Allocation failure should have been caught");
for (int index = 0; index < _size; index++) {
_buckets[index].iterate(cic);
}
@ -176,7 +196,7 @@ void KlassInfoHisto::print_elements(outputStream* st) const {
total += elements()->at(i)->count();
totalw += elements()->at(i)->words();
}
st->print_cr("Total %13" FORMAT64_MODIFIER "d %13" FORMAT64_MODIFIER "u",
st->print_cr("Total " INT64_FORMAT_W(13) " " UINT64_FORMAT_W(13),
total, totalw * HeapWordSize);
}
@ -199,12 +219,18 @@ class HistoClosure : public KlassInfoClosure {
class RecordInstanceClosure : public ObjectClosure {
private:
KlassInfoTable* _cit;
size_t _missed_count;
public:
RecordInstanceClosure(KlassInfoTable* cit) : _cit(cit) {}
RecordInstanceClosure(KlassInfoTable* cit) :
_cit(cit), _missed_count(0) {}
void do_object(oop obj) {
_cit->record_instance(obj);
if (!_cit->record_instance(obj)) {
_missed_count++;
}
}
size_t missed_count() { return _missed_count; }
};
void HeapInspection::heap_inspection(outputStream* st) {
@ -230,21 +256,32 @@ void HeapInspection::heap_inspection(outputStream* st) {
ShouldNotReachHere(); // Unexpected heap kind for this op
}
// Collect klass instance info
// Iterate over objects in the heap
KlassInfoTable cit(KlassInfoTable::cit_size, ref);
RecordInstanceClosure ric(&cit);
Universe::heap()->object_iterate(&ric);
if (!cit.allocation_failed()) {
// Iterate over objects in the heap
RecordInstanceClosure ric(&cit);
Universe::heap()->object_iterate(&ric);
// Sort and print klass instance info
KlassInfoHisto histo("\n"
" num #instances #bytes class name\n"
"----------------------------------------------",
KlassInfoHisto::histo_initial_size);
HistoClosure hc(&histo);
cit.iterate(&hc);
histo.sort();
histo.print_on(st);
// Report if certain classes are not counted because of
// running out of C-heap for the histogram.
size_t missed_count = ric.missed_count();
if (missed_count != 0) {
st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT
" total instances in data below",
missed_count);
}
// Sort and print klass instance info
KlassInfoHisto histo("\n"
" num #instances #bytes class name\n"
"----------------------------------------------",
KlassInfoHisto::histo_initial_size);
HistoClosure hc(&histo);
cit.iterate(&hc);
histo.sort();
histo.print_on(st);
} else {
st->print_cr("WARNING: Ran out of C-heap; histogram not generated");
}
st->flush();
if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap) {

View File

@ -98,8 +98,9 @@ class KlassInfoTable: public StackObj {
};
KlassInfoTable(int size, HeapWord* ref);
~KlassInfoTable();
void record_instance(const oop obj);
bool record_instance(const oop obj);
void iterate(KlassInfoClosure* cic);
bool allocation_failed() { return _buckets == NULL; }
};
class KlassInfoHisto : public StackObj {

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