Merge
This commit is contained in:
commit
47ab693590
2
.hgtags
2
.hgtags
@ -33,3 +33,5 @@ c8b275d62d6b0a980c510e839b70292245863e85 jdk7-b55
|
||||
a8134c4ee2cf451cf9b5e1609f39d83ecd53acc5 jdk7-b56
|
||||
b44f05654c26fcd1f995e712992f9b07ffd7c0c6 jdk7-b57
|
||||
d60a9ce3c3eabf28f5d50ae839d18be04a551bc2 jdk7-b58
|
||||
c33e7d38c9210741dbc285507403a4b20bd802a0 jdk7-b59
|
||||
5a10e4d0b14d7beac53a7b2213ae6864afe1fd3e jdk7-b60
|
||||
|
@ -34,3 +34,4 @@ ba12117a5e6c918578d6b2a8c693232a33289024 jdk7-b56
|
||||
ffd09e767dfa6d21466183a400f72cf62d53297f jdk7-b57
|
||||
59b497130f82ec809c245ffb5e521e3a5fabf8af jdk7-b58
|
||||
030142474602b4a067662fffc0c8e541de5a78df jdk7-b59
|
||||
39565502682c7085369bd09e51640919dc741097 jdk7-b60
|
||||
|
@ -33,3 +33,5 @@ bec82237d694f9802b820fa11bbb4f7fa9bf8e77 jdk7-b52
|
||||
553a664b807bb3a3c93f3b5a3c20ff0a90e08371 jdk7-b56
|
||||
972c6157fae57850694675da82fd58a17930db0a jdk7-b57
|
||||
2e3b8edab3ef55406494d3dd562e06882e6fc15e jdk7-b58
|
||||
7e6b2b55c00cc523b468272353ada3979adbbf16 jdk7-b59
|
||||
f1e1cccbd13aa96d2d8bd872782ff764010bc22c jdk7-b60
|
||||
|
@ -1,14 +0,0 @@
|
||||
README:
|
||||
This file should be located at the top of the corba Mercurial repository.
|
||||
|
||||
See http://openjdk.java.net/ for more information about the OpenJDK.
|
||||
|
||||
See ../README-builds.html for complete details on build machine requirements.
|
||||
|
||||
Simple Build Instructions:
|
||||
|
||||
cd make && gnumake
|
||||
|
||||
The files that will be imported into the jdk build will be in the "dist"
|
||||
directory.
|
||||
|
@ -73,23 +73,18 @@ ifeq ($(PLATFORM), linux)
|
||||
ifneq ("$(findstring sparc,$(ARCH))", "")
|
||||
# sparc or sparcv9
|
||||
REQUIRED_CC_VER = 4.0
|
||||
REQUIRED_GCC_VER = 4.0.*
|
||||
else
|
||||
ifeq ($(ARCH_DATA_MODEL), 32)
|
||||
# i586
|
||||
REQUIRED_CC_VER = 3.2
|
||||
REQUIRED_GCC_VER = 3.2.1*
|
||||
REQUIRED_GCC_VER_INT = 3.2.1-7a
|
||||
else
|
||||
ifeq ($(ARCH), amd64)
|
||||
# amd64
|
||||
REQUIRED_CC_VER = 3.2
|
||||
REQUIRED_GCC_VER = 3.2.*
|
||||
endif
|
||||
ifeq ($(ARCH), ia64)
|
||||
# ia64
|
||||
REQUIRED_CC_VER = 3.2
|
||||
REQUIRED_GCC_VER = 2.9[56789].*
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
@ -109,13 +104,6 @@ ifeq ($(PLATFORM), solaris)
|
||||
|
||||
# Option used to create a shared library
|
||||
SHARED_LIBRARY_FLAG = -G
|
||||
# But gcc is still needed no matter what on 32bit
|
||||
ifeq ($(ARCH_DATA_MODEL), 32)
|
||||
REQUIRED_GCC_VER = 2.95
|
||||
GCC =$(GCC_COMPILER_PATH)gcc
|
||||
_GCC_VER :=$(shell $(GCC) -dumpversion 2>&1 )
|
||||
GCC_VER :=$(call GetVersion,"$(_GCC_VER)")
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
|
@ -39,13 +39,6 @@ ifeq ($(PLATFORM), solaris)
|
||||
LINT = $(COMPILER_PATH)lint
|
||||
# Option used to create a shared library
|
||||
SHARED_LIBRARY_FLAG = -G
|
||||
# But gcc is still needed no matter what on 32bit
|
||||
ifeq ($(ARCH_DATA_MODEL), 32)
|
||||
REQUIRED_GCC_VER = 2.95
|
||||
GCC =$(GCC_COMPILER_PATH)gcc
|
||||
_GCC_VER :=$(shell $(GCC) -dumpversion 2>&1 )
|
||||
GCC_VER :=$(call GetVersion,"$(_GCC_VER)")
|
||||
endif
|
||||
endif
|
||||
|
||||
# Sun Studio Compiler settings specific to Linux
|
||||
|
@ -288,11 +288,22 @@ ifeq ($(PLATFORM), windows)
|
||||
TEMP_DISK=C:/temp
|
||||
# GNU Make or MKS overrides $(PROCESSOR_ARCHITECTURE) to always
|
||||
# return "x86". Use the first word of $(PROCESSOR_IDENTIFIER) instead.
|
||||
PROC_ARCH:=$(word 1, $(PROCESSOR_IDENTIFIER))
|
||||
PROC_ARCH:=$(subst x86,X86,$(PROC_ARCH))
|
||||
PROC_ARCH:=$(subst x64,X64,$(PROC_ARCH))
|
||||
PROC_ARCH:=$(subst intel64,X64,$(PROC_ARCH))
|
||||
PROC_ARCH:=$(subst Intel64,X64,$(PROC_ARCH))
|
||||
PROC_ARCH:=$(subst INTEL64,X64,$(PROC_ARCH))
|
||||
PROC_ARCH:=$(subst em64t,X64,$(PROC_ARCH))
|
||||
PROC_ARCH:=$(subst EM64T,X64,$(PROC_ARCH))
|
||||
PROC_ARCH:=$(subst amd64,X64,$(PROC_ARCH))
|
||||
PROC_ARCH:=$(subst AMD64,X64,$(PROC_ARCH))
|
||||
PROC_ARCH:=$(subst ia64,IA64,$(PROC_ARCH))
|
||||
ifndef ARCH_DATA_MODEL
|
||||
ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),ia64)
|
||||
ifeq ($(PROC_ARCH),IA64)
|
||||
ARCH_DATA_MODEL=64
|
||||
else
|
||||
ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),AMD64)
|
||||
ifeq ($(PROC_ARCH),X64)
|
||||
ARCH_DATA_MODEL=64
|
||||
else
|
||||
ARCH_DATA_MODEL=32
|
||||
@ -313,10 +324,12 @@ ifeq ($(PLATFORM), windows)
|
||||
# + set ARCH to ia64 or amd64, or
|
||||
REQUIRED_WINDOWS_NAME=Windows Server 2003
|
||||
REQUIRED_WINDOWS_VERSION=5 2 Service Pack 1
|
||||
ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)), AMD64)
|
||||
ifeq ($(PROC_ARCH),X64)
|
||||
ARCH=amd64
|
||||
else
|
||||
ARCH=ia64
|
||||
ifeq ($(PROC_ARCH),IA64)
|
||||
ARCH=ia64
|
||||
endif
|
||||
endif
|
||||
LIBARCH=$(ARCH)
|
||||
# Value of Java os.arch property
|
||||
|
@ -33,3 +33,5 @@ f8e839c086152da70d6ec5913ba6f9f509282e8d jdk7-b55
|
||||
a3fd9e40ff2e854f6169eb6d09d491a28634d04f jdk7-b56
|
||||
f4cbf78110c726919f46b59a3b054c54c7e889b4 jdk7-b57
|
||||
53d9bf689e80fcc76b221bbe6c5d58e08b80cbc6 jdk7-b58
|
||||
c55be0c7bd32c016c52218eb4c8b5da8a75450b5 jdk7-b59
|
||||
a77eddcd510c3972717c025cfcef9a60bfa4ecac jdk7-b60
|
||||
|
@ -317,11 +317,11 @@ public class JavaThread extends Thread {
|
||||
}
|
||||
|
||||
public Address getStackBase() {
|
||||
return stackBaseField.getValue();
|
||||
return stackBaseField.getValue(addr);
|
||||
}
|
||||
|
||||
public long getStackSize() {
|
||||
return stackSizeField.getValue();
|
||||
return stackSizeField.getValue(addr);
|
||||
}
|
||||
|
||||
/** Gets the Java-side thread object for this JavaThread */
|
||||
|
@ -1,14 +0,0 @@
|
||||
README:
|
||||
This file should be located at the top of the hotspot Mercurial repository.
|
||||
|
||||
See http://openjdk.java.net/ for more information about the OpenJDK.
|
||||
|
||||
See ../README-builds.html for complete details on build machine requirements.
|
||||
|
||||
Simple Build Instructions:
|
||||
|
||||
cd make && gnumake
|
||||
|
||||
The files that will be imported into the jdk build will be in the "build"
|
||||
directory.
|
||||
|
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2009
|
||||
|
||||
HS_MAJOR_VER=16
|
||||
HS_MINOR_VER=0
|
||||
HS_BUILD_NUMBER=03
|
||||
HS_BUILD_NUMBER=04
|
||||
|
||||
JDK_MAJOR_VER=1
|
||||
JDK_MINOR_VER=7
|
||||
|
@ -335,7 +335,19 @@ jprt.test.targets = \
|
||||
|
||||
# The default test/Makefile targets that should be run
|
||||
|
||||
# Example:
|
||||
# jprt.make.rule.test.targets=*-*-*-packtest
|
||||
#jprt.make.rule.test.targets=*-product-*-packtest
|
||||
|
||||
jprt.make.rule.test.targets = \
|
||||
${jprt.my.solaris.sparc}-*-c1-clienttest, \
|
||||
${jprt.my.solaris.i586}-*-c1-clienttest, \
|
||||
${jprt.my.linux.i586}-*-c1-clienttest, \
|
||||
${jprt.my.windows.i586}-*-c1-clienttest, \
|
||||
${jprt.my.solaris.sparc}-*-c2-servertest, \
|
||||
${jprt.my.solaris.sparcv9}-*-c2-servertest, \
|
||||
${jprt.my.solaris.i586}-*-c2-servertest, \
|
||||
${jprt.my.solaris.x64}-*-c2-servertest, \
|
||||
${jprt.my.linux.i586}-*-c2-servertest, \
|
||||
${jprt.my.linux.x64}-*-c2-servertest, \
|
||||
${jprt.my.windows.i586}-*-c2-servertest, \
|
||||
${jprt.my.windows.x64}-*-c2-servertest
|
||||
|
||||
|
@ -171,3 +171,9 @@ DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH))
|
||||
ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),)
|
||||
DEBUG_CFLAGS += -gstabs
|
||||
endif
|
||||
|
||||
# DEBUG_BINARIES overrides everything, use full -g debug information
|
||||
ifeq ($(DEBUG_BINARIES), true)
|
||||
DEBUG_CFLAGS = -g
|
||||
CFLAGS += $(DEBUG_CFLAGS)
|
||||
endif
|
||||
|
@ -41,10 +41,15 @@ LIBJSIG_MAPFILE = $(MAKEFILES_DIR)/mapfile-vers-jsig
|
||||
|
||||
LFLAGS_JSIG += -D_GNU_SOURCE -D_REENTRANT $(LDFLAGS_HASH_STYLE)
|
||||
|
||||
# DEBUG_BINARIES overrides everything, use full -g debug information
|
||||
ifeq ($(DEBUG_BINARIES), true)
|
||||
JSIG_DEBUG_CFLAGS = -g
|
||||
endif
|
||||
|
||||
$(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE)
|
||||
@echo Making signal interposition lib...
|
||||
$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
|
||||
$(LFLAGS_JSIG) -o $@ $< -ldl
|
||||
$(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $@ $< -ldl
|
||||
|
||||
install_jsig: $(LIBJSIG)
|
||||
@echo "Copying $(LIBJSIG) to $(DEST_JSIG)"
|
||||
|
@ -43,6 +43,11 @@ SAMAPFILE = $(SASRCDIR)/mapfile
|
||||
|
||||
DEST_SAPROC = $(JDK_LIBDIR)/$(LIBSAPROC)
|
||||
|
||||
# DEBUG_BINARIES overrides everything, use full -g debug information
|
||||
ifeq ($(DEBUG_BINARIES), true)
|
||||
SA_DEBUG_CFLAGS = -g
|
||||
endif
|
||||
|
||||
# if $(AGENT_DIR) does not exist, we don't build SA
|
||||
# also, we don't build SA on Itanium.
|
||||
|
||||
@ -67,6 +72,7 @@ $(LIBSAPROC): $(SASRCFILES) $(SAMAPFILE)
|
||||
-I$(BOOT_JAVA_HOME)/include/$(Platform_os_family) \
|
||||
$(SASRCFILES) \
|
||||
$(SA_LFLAGS) \
|
||||
$(SA_DEBUG_CFLAGS) \
|
||||
-o $@ \
|
||||
-lthread_db
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -4454,43 +4454,26 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val
|
||||
delayed()->nop();
|
||||
}
|
||||
|
||||
// Now we decide how to generate the card table write. If we're
|
||||
// enqueueing, we call out to a generated function. Otherwise, we do it
|
||||
// inline here.
|
||||
|
||||
if (G1RSBarrierUseQueue) {
|
||||
// If the "store_addr" register is an "in" or "local" register, move it to
|
||||
// a scratch reg so we can pass it as an argument.
|
||||
bool use_scr = !(store_addr->is_global() || store_addr->is_out());
|
||||
// Pick a scratch register different from "tmp".
|
||||
Register scr = (tmp == G1_scratch ? G3_scratch : G1_scratch);
|
||||
// Make sure we use up the delay slot!
|
||||
if (use_scr) {
|
||||
post_filter_masm->mov(store_addr, scr);
|
||||
} else {
|
||||
post_filter_masm->nop();
|
||||
}
|
||||
generate_dirty_card_log_enqueue_if_necessary(bs->byte_map_base);
|
||||
save_frame(0);
|
||||
call(dirty_card_log_enqueue);
|
||||
if (use_scr) {
|
||||
delayed()->mov(scr, O0);
|
||||
} else {
|
||||
delayed()->mov(store_addr->after_save(), O0);
|
||||
}
|
||||
restore();
|
||||
|
||||
// If the "store_addr" register is an "in" or "local" register, move it to
|
||||
// a scratch reg so we can pass it as an argument.
|
||||
bool use_scr = !(store_addr->is_global() || store_addr->is_out());
|
||||
// Pick a scratch register different from "tmp".
|
||||
Register scr = (tmp == G1_scratch ? G3_scratch : G1_scratch);
|
||||
// Make sure we use up the delay slot!
|
||||
if (use_scr) {
|
||||
post_filter_masm->mov(store_addr, scr);
|
||||
} else {
|
||||
|
||||
#ifdef _LP64
|
||||
post_filter_masm->srlx(store_addr, CardTableModRefBS::card_shift, store_addr);
|
||||
#else
|
||||
post_filter_masm->srl(store_addr, CardTableModRefBS::card_shift, store_addr);
|
||||
#endif
|
||||
assert(tmp != store_addr, "need separate temp reg");
|
||||
set(bs->byte_map_base, tmp);
|
||||
stb(G0, tmp, store_addr);
|
||||
post_filter_masm->nop();
|
||||
}
|
||||
generate_dirty_card_log_enqueue_if_necessary(bs->byte_map_base);
|
||||
save_frame(0);
|
||||
call(dirty_card_log_enqueue);
|
||||
if (use_scr) {
|
||||
delayed()->mov(scr, O0);
|
||||
} else {
|
||||
delayed()->mov(store_addr->after_save(), O0);
|
||||
}
|
||||
restore();
|
||||
|
||||
bind(filtered);
|
||||
|
||||
|
@ -378,7 +378,7 @@ void LIR_Assembler::emit_exception_handler() {
|
||||
compilation()->offsets()->set_value(CodeOffsets::Exceptions, code_offset());
|
||||
|
||||
|
||||
if (compilation()->has_exception_handlers() || JvmtiExport::can_post_exceptions()) {
|
||||
if (compilation()->has_exception_handlers() || compilation()->env()->jvmti_can_post_exceptions()) {
|
||||
__ call(Runtime1::entry_for(Runtime1::handle_exception_id), relocInfo::runtime_call_type);
|
||||
__ delayed()->nop();
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ void C1_MacroAssembler::initialize_object(
|
||||
initialize_body(base, index);
|
||||
}
|
||||
|
||||
if (DTraceAllocProbes) {
|
||||
if (CURRENT_ENV->dtrace_alloc_probes()) {
|
||||
assert(obj == O0, "must be");
|
||||
call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)),
|
||||
relocInfo::runtime_call_type);
|
||||
@ -355,7 +355,7 @@ void C1_MacroAssembler::allocate_array(
|
||||
sub(arr_size, hdr_size * wordSize, index); // compute index = number of words to clear
|
||||
initialize_body(base, index);
|
||||
|
||||
if (DTraceAllocProbes) {
|
||||
if (CURRENT_ENV->dtrace_alloc_probes()) {
|
||||
assert(obj == O0, "must be");
|
||||
call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)),
|
||||
relocInfo::runtime_call_type);
|
||||
|
@ -59,7 +59,7 @@ inline bool frame::is_younger(intptr_t* id) const { assert(this->id() != NULL &&
|
||||
inline bool frame::is_older(intptr_t* id) const { assert(this->id() != NULL && id != NULL, "NULL frame id");
|
||||
return this->id() > id ; }
|
||||
|
||||
inline int frame::frame_size() const { return sender_sp() - sp(); }
|
||||
inline int frame::frame_size(RegisterMap* map) const { return sender_sp() - sp(); }
|
||||
|
||||
inline intptr_t* frame::link() const { return (intptr_t *)(fp()[FP->sp_offset_in_saved_window()] + STACK_BIAS); }
|
||||
|
||||
|
@ -1712,6 +1712,23 @@ static FloatRegister reg_to_DoubleFloatRegister_object(int register_encoding) {
|
||||
return as_DoubleFloatRegister(register_encoding);
|
||||
}
|
||||
|
||||
const bool Matcher::match_rule_supported(int opcode) {
|
||||
if (!has_match_rule(opcode))
|
||||
return false;
|
||||
|
||||
switch (opcode) {
|
||||
case Op_CountLeadingZerosI:
|
||||
case Op_CountLeadingZerosL:
|
||||
case Op_CountTrailingZerosI:
|
||||
case Op_CountTrailingZerosL:
|
||||
if (!UsePopCountInstruction)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return true; // Per default match rules are supported.
|
||||
}
|
||||
|
||||
int Matcher::regnum_to_fpu_offset(int regnum) {
|
||||
return regnum - 32; // The FP registers are in the second chunk
|
||||
}
|
||||
@ -1874,15 +1891,17 @@ RegMask Matcher::modL_proj_mask() {
|
||||
// The intptr_t operand types, defined by textual substitution.
|
||||
// (Cf. opto/type.hpp. This lets us avoid many, many other ifdefs.)
|
||||
#ifdef _LP64
|
||||
#define immX immL
|
||||
#define immX13 immL13
|
||||
#define iRegX iRegL
|
||||
#define g1RegX g1RegL
|
||||
#define immX immL
|
||||
#define immX13 immL13
|
||||
#define immX13m7 immL13m7
|
||||
#define iRegX iRegL
|
||||
#define g1RegX g1RegL
|
||||
#else
|
||||
#define immX immI
|
||||
#define immX13 immI13
|
||||
#define iRegX iRegI
|
||||
#define g1RegX g1RegI
|
||||
#define immX immI
|
||||
#define immX13 immI13
|
||||
#define immX13m7 immI13m7
|
||||
#define iRegX iRegI
|
||||
#define g1RegX g1RegI
|
||||
#endif
|
||||
|
||||
//----------ENCODING BLOCK-----------------------------------------------------
|
||||
@ -3437,6 +3456,16 @@ operand immI13() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: 13-bit minus 7
|
||||
operand immI13m7() %{
|
||||
predicate((-4096 < n->get_int()) && ((n->get_int() + 7) <= 4095));
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Unsigned (positive) Integer Immediate: 13-bit
|
||||
operand immU13() %{
|
||||
predicate((0 <= n->get_int()) && Assembler::is_simm13(n->get_int()));
|
||||
@ -3515,6 +3544,28 @@ operand immI_32_63() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Immediates for special shifts (sign extend)
|
||||
|
||||
// Integer Immediate: the value 16
|
||||
operand immI_16() %{
|
||||
predicate(n->get_int() == 16);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the value 24
|
||||
operand immI_24() %{
|
||||
predicate(n->get_int() == 24);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the value 255
|
||||
operand immI_255() %{
|
||||
predicate( n->get_int() == 255 );
|
||||
@ -3525,6 +3576,16 @@ operand immI_255() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Integer Immediate: the value 65535
|
||||
operand immI_65535() %{
|
||||
predicate(n->get_int() == 65535);
|
||||
match(ConI);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Long Immediate: the value FF
|
||||
operand immL_FF() %{
|
||||
predicate( n->get_long() == 0xFFL );
|
||||
@ -3630,6 +3691,16 @@ operand immL13() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Long Immediate: 13-bit minus 7
|
||||
operand immL13m7() %{
|
||||
predicate((-4096L < n->get_long()) && ((n->get_long() + 7L) <= 4095L));
|
||||
match(ConL);
|
||||
op_cost(0);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Long Immediate: low 32-bit mask
|
||||
operand immL_32bits() %{
|
||||
predicate(n->get_long() == 0xFFFFFFFFL);
|
||||
@ -4067,7 +4138,7 @@ operand indirect(sp_ptr_RegP reg) %{
|
||||
%}
|
||||
%}
|
||||
|
||||
// Indirect with Offset
|
||||
// Indirect with simm13 Offset
|
||||
operand indOffset13(sp_ptr_RegP reg, immX13 offset) %{
|
||||
constraint(ALLOC_IN_RC(sp_ptr_reg));
|
||||
match(AddP reg offset);
|
||||
@ -4082,6 +4153,21 @@ operand indOffset13(sp_ptr_RegP reg, immX13 offset) %{
|
||||
%}
|
||||
%}
|
||||
|
||||
// Indirect with simm13 Offset minus 7
|
||||
operand indOffset13m7(sp_ptr_RegP reg, immX13m7 offset) %{
|
||||
constraint(ALLOC_IN_RC(sp_ptr_reg));
|
||||
match(AddP reg offset);
|
||||
|
||||
op_cost(100);
|
||||
format %{ "[$reg + $offset]" %}
|
||||
interface(MEMORY_INTER) %{
|
||||
base($reg);
|
||||
index(0x0);
|
||||
scale(0x0);
|
||||
disp($offset);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Note: Intel has a swapped version also, like this:
|
||||
//operand indOffsetX(iRegI reg, immP offset) %{
|
||||
// constraint(ALLOC_IN_RC(int_reg));
|
||||
@ -5487,6 +5573,20 @@ instruct loadS(iRegI dst, memory mem) %{
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Short (16 bit signed) to Byte (8 bit signed)
|
||||
instruct loadS2B(iRegI dst, indOffset13m7 mem, immI_24 twentyfour) %{
|
||||
match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
|
||||
format %{ "LDSB $mem+1,$dst\t! short -> byte" %}
|
||||
ins_encode %{
|
||||
__ ldsb($mem$$Address, $dst$$Register, 1);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Short (16bit signed) into a Long Register
|
||||
instruct loadS2L(iRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadS mem)));
|
||||
@ -5513,6 +5613,19 @@ instruct loadUS(iRegI dst, memory mem) %{
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed)
|
||||
instruct loadUS2B(iRegI dst, indOffset13m7 mem, immI_24 twentyfour) %{
|
||||
match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
format %{ "LDSB $mem+1,$dst\t! ushort -> byte" %}
|
||||
ins_encode %{
|
||||
__ ldsb($mem$$Address, $dst$$Register, 1);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16bit UNsigned) into a Long Register
|
||||
instruct loadUS2L(iRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadUS mem)));
|
||||
@ -5539,6 +5652,62 @@ instruct loadI(iRegI dst, memory mem) %{
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
// Load Integer to Byte (8 bit signed)
|
||||
instruct loadI2B(iRegI dst, indOffset13m7 mem, immI_24 twentyfour) %{
|
||||
match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
|
||||
format %{ "LDSB $mem+3,$dst\t! int -> byte" %}
|
||||
ins_encode %{
|
||||
__ ldsb($mem$$Address, $dst$$Register, 3);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Integer to Unsigned Byte (8 bit UNsigned)
|
||||
instruct loadI2UB(iRegI dst, indOffset13m7 mem, immI_255 mask) %{
|
||||
match(Set dst (AndI (LoadI mem) mask));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
|
||||
format %{ "LDUB $mem+3,$dst\t! int -> ubyte" %}
|
||||
ins_encode %{
|
||||
__ ldub($mem$$Address, $dst$$Register, 3);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Integer to Short (16 bit signed)
|
||||
instruct loadI2S(iRegI dst, indOffset13m7 mem, immI_16 sixteen) %{
|
||||
match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
|
||||
format %{ "LDSH $mem+2,$dst\t! int -> short" %}
|
||||
ins_encode %{
|
||||
__ ldsh($mem$$Address, $dst$$Register, 2);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Integer to Unsigned Short (16 bit UNsigned)
|
||||
instruct loadI2US(iRegI dst, indOffset13m7 mem, immI_65535 mask) %{
|
||||
match(Set dst (AndI (LoadI mem) mask));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
|
||||
format %{ "LDUH $mem+2,$dst\t! int -> ushort/char" %}
|
||||
ins_encode %{
|
||||
__ lduh($mem$$Address, $dst$$Register, 2);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
// Load Integer into a Long Register
|
||||
instruct loadI2L(iRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadI mem)));
|
||||
@ -9188,6 +9357,145 @@ instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp
|
||||
ins_pipe(long_memory_op);
|
||||
%}
|
||||
|
||||
|
||||
//---------- Zeros Count Instructions ------------------------------------------
|
||||
|
||||
instruct countLeadingZerosI(iRegI dst, iRegI src, iRegI tmp, flagsReg cr) %{
|
||||
predicate(UsePopCountInstruction); // See Matcher::match_rule_supported
|
||||
match(Set dst (CountLeadingZerosI src));
|
||||
effect(TEMP dst, TEMP tmp, KILL cr);
|
||||
|
||||
// x |= (x >> 1);
|
||||
// x |= (x >> 2);
|
||||
// x |= (x >> 4);
|
||||
// x |= (x >> 8);
|
||||
// x |= (x >> 16);
|
||||
// return (WORDBITS - popc(x));
|
||||
format %{ "SRL $src,1,$dst\t! count leading zeros (int)\n\t"
|
||||
"OR $src,$tmp,$dst\n\t"
|
||||
"SRL $dst,2,$tmp\n\t"
|
||||
"OR $dst,$tmp,$dst\n\t"
|
||||
"SRL $dst,4,$tmp\n\t"
|
||||
"OR $dst,$tmp,$dst\n\t"
|
||||
"SRL $dst,8,$tmp\n\t"
|
||||
"OR $dst,$tmp,$dst\n\t"
|
||||
"SRL $dst,16,$tmp\n\t"
|
||||
"OR $dst,$tmp,$dst\n\t"
|
||||
"POPC $dst,$dst\n\t"
|
||||
"MOV 32,$tmp\n\t"
|
||||
"SUB $tmp,$dst,$dst" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Register Rsrc = $src$$Register;
|
||||
Register Rtmp = $tmp$$Register;
|
||||
__ srl(Rsrc, 1, Rtmp);
|
||||
__ or3(Rsrc, Rtmp, Rdst);
|
||||
__ srl(Rdst, 2, Rtmp);
|
||||
__ or3(Rdst, Rtmp, Rdst);
|
||||
__ srl(Rdst, 4, Rtmp);
|
||||
__ or3(Rdst, Rtmp, Rdst);
|
||||
__ srl(Rdst, 8, Rtmp);
|
||||
__ or3(Rdst, Rtmp, Rdst);
|
||||
__ srl(Rdst, 16, Rtmp);
|
||||
__ or3(Rdst, Rtmp, Rdst);
|
||||
__ popc(Rdst, Rdst);
|
||||
__ mov(BitsPerInt, Rtmp);
|
||||
__ sub(Rtmp, Rdst, Rdst);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct countLeadingZerosL(iRegI dst, iRegL src, iRegL tmp, flagsReg cr) %{
|
||||
predicate(UsePopCountInstruction); // See Matcher::match_rule_supported
|
||||
match(Set dst (CountLeadingZerosL src));
|
||||
effect(TEMP dst, TEMP tmp, KILL cr);
|
||||
|
||||
// x |= (x >> 1);
|
||||
// x |= (x >> 2);
|
||||
// x |= (x >> 4);
|
||||
// x |= (x >> 8);
|
||||
// x |= (x >> 16);
|
||||
// x |= (x >> 32);
|
||||
// return (WORDBITS - popc(x));
|
||||
format %{ "SRLX $src,1,$dst\t! count leading zeros (long)\n\t"
|
||||
"OR $src,$tmp,$dst\n\t"
|
||||
"SRLX $dst,2,$tmp\n\t"
|
||||
"OR $dst,$tmp,$dst\n\t"
|
||||
"SRLX $dst,4,$tmp\n\t"
|
||||
"OR $dst,$tmp,$dst\n\t"
|
||||
"SRLX $dst,8,$tmp\n\t"
|
||||
"OR $dst,$tmp,$dst\n\t"
|
||||
"SRLX $dst,16,$tmp\n\t"
|
||||
"OR $dst,$tmp,$dst\n\t"
|
||||
"SRLX $dst,32,$tmp\n\t"
|
||||
"OR $dst,$tmp,$dst\n\t"
|
||||
"POPC $dst,$dst\n\t"
|
||||
"MOV 64,$tmp\n\t"
|
||||
"SUB $tmp,$dst,$dst" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Register Rsrc = $src$$Register;
|
||||
Register Rtmp = $tmp$$Register;
|
||||
__ srlx(Rsrc, 1, Rtmp);
|
||||
__ or3(Rsrc, Rtmp, Rdst);
|
||||
__ srlx(Rdst, 2, Rtmp);
|
||||
__ or3(Rdst, Rtmp, Rdst);
|
||||
__ srlx(Rdst, 4, Rtmp);
|
||||
__ or3(Rdst, Rtmp, Rdst);
|
||||
__ srlx(Rdst, 8, Rtmp);
|
||||
__ or3(Rdst, Rtmp, Rdst);
|
||||
__ srlx(Rdst, 16, Rtmp);
|
||||
__ or3(Rdst, Rtmp, Rdst);
|
||||
__ srlx(Rdst, 32, Rtmp);
|
||||
__ or3(Rdst, Rtmp, Rdst);
|
||||
__ popc(Rdst, Rdst);
|
||||
__ mov(BitsPerLong, Rtmp);
|
||||
__ sub(Rtmp, Rdst, Rdst);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct countTrailingZerosI(iRegI dst, iRegI src, flagsReg cr) %{
|
||||
predicate(UsePopCountInstruction); // See Matcher::match_rule_supported
|
||||
match(Set dst (CountTrailingZerosI src));
|
||||
effect(TEMP dst, KILL cr);
|
||||
|
||||
// return popc(~x & (x - 1));
|
||||
format %{ "SUB $src,1,$dst\t! count trailing zeros (int)\n\t"
|
||||
"ANDN $dst,$src,$dst\n\t"
|
||||
"SRL $dst,R_G0,$dst\n\t"
|
||||
"POPC $dst,$dst" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Register Rsrc = $src$$Register;
|
||||
__ sub(Rsrc, 1, Rdst);
|
||||
__ andn(Rdst, Rsrc, Rdst);
|
||||
__ srl(Rdst, G0, Rdst);
|
||||
__ popc(Rdst, Rdst);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct countTrailingZerosL(iRegI dst, iRegL src, flagsReg cr) %{
|
||||
predicate(UsePopCountInstruction); // See Matcher::match_rule_supported
|
||||
match(Set dst (CountTrailingZerosL src));
|
||||
effect(TEMP dst, KILL cr);
|
||||
|
||||
// return popc(~x & (x - 1));
|
||||
format %{ "SUB $src,1,$dst\t! count trailing zeros (long)\n\t"
|
||||
"ANDN $dst,$src,$dst\n\t"
|
||||
"POPC $dst,$dst" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Register Rsrc = $src$$Register;
|
||||
__ sub(Rsrc, 1, Rdst);
|
||||
__ andn(Rdst, Rsrc, Rdst);
|
||||
__ popc(Rdst, Rdst);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
|
||||
//---------- Population Count Instructions -------------------------------------
|
||||
|
||||
instruct popCountI(iRegI dst, iRegI src) %{
|
||||
|
@ -952,6 +952,21 @@ void Assembler::andpd(XMMRegister dst, Address src) {
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
void Assembler::bsfl(Register dst, Register src) {
|
||||
int encode = prefix_and_encode(dst->encoding(), src->encoding());
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xBC);
|
||||
emit_byte(0xC0 | encode);
|
||||
}
|
||||
|
||||
void Assembler::bsrl(Register dst, Register src) {
|
||||
assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT");
|
||||
int encode = prefix_and_encode(dst->encoding(), src->encoding());
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xBD);
|
||||
emit_byte(0xC0 | encode);
|
||||
}
|
||||
|
||||
void Assembler::bswapl(Register reg) { // bswap
|
||||
int encode = prefix_and_encode(reg->encoding());
|
||||
emit_byte(0x0F);
|
||||
@ -1438,6 +1453,15 @@ void Assembler::lock() {
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::lzcntl(Register dst, Register src) {
|
||||
assert(VM_Version::supports_lzcnt(), "encoding is treated as BSR");
|
||||
emit_byte(0xF3);
|
||||
int encode = prefix_and_encode(dst->encoding(), src->encoding());
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xBD);
|
||||
emit_byte(0xC0 | encode);
|
||||
}
|
||||
|
||||
// Emit mfence instruction
|
||||
void Assembler::mfence() {
|
||||
NOT_LP64(assert(VM_Version::supports_sse2(), "unsupported");)
|
||||
@ -3688,6 +3712,21 @@ void Assembler::andq(Register dst, Register src) {
|
||||
emit_arith(0x23, 0xC0, dst, src);
|
||||
}
|
||||
|
||||
void Assembler::bsfq(Register dst, Register src) {
|
||||
int encode = prefixq_and_encode(dst->encoding(), src->encoding());
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xBC);
|
||||
emit_byte(0xC0 | encode);
|
||||
}
|
||||
|
||||
void Assembler::bsrq(Register dst, Register src) {
|
||||
assert(!VM_Version::supports_lzcnt(), "encoding is treated as LZCNT");
|
||||
int encode = prefixq_and_encode(dst->encoding(), src->encoding());
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xBD);
|
||||
emit_byte(0xC0 | encode);
|
||||
}
|
||||
|
||||
void Assembler::bswapq(Register reg) {
|
||||
int encode = prefixq_and_encode(reg->encoding());
|
||||
emit_byte(0x0F);
|
||||
@ -3941,6 +3980,15 @@ void Assembler::cmp_narrow_oop(Address src1, int32_t imm32, RelocationHolder con
|
||||
emit_data((int)imm32, rspec, narrow_oop_operand);
|
||||
}
|
||||
|
||||
void Assembler::lzcntq(Register dst, Register src) {
|
||||
assert(VM_Version::supports_lzcnt(), "encoding is treated as BSR");
|
||||
emit_byte(0xF3);
|
||||
int encode = prefixq_and_encode(dst->encoding(), src->encoding());
|
||||
emit_byte(0x0F);
|
||||
emit_byte(0xBD);
|
||||
emit_byte(0xC0 | encode);
|
||||
}
|
||||
|
||||
void Assembler::movdq(XMMRegister dst, Register src) {
|
||||
// table D-1 says MMX/SSE2
|
||||
NOT_LP64(assert(VM_Version::supports_sse2() || VM_Version::supports_mmx(), ""));
|
||||
|
@ -757,6 +757,14 @@ private:
|
||||
void andpd(XMMRegister dst, Address src);
|
||||
void andpd(XMMRegister dst, XMMRegister src);
|
||||
|
||||
void bsfl(Register dst, Register src);
|
||||
void bsrl(Register dst, Register src);
|
||||
|
||||
#ifdef _LP64
|
||||
void bsfq(Register dst, Register src);
|
||||
void bsrq(Register dst, Register src);
|
||||
#endif
|
||||
|
||||
void bswapl(Register reg);
|
||||
|
||||
void bswapq(Register reg);
|
||||
@ -1061,6 +1069,12 @@ private:
|
||||
|
||||
void lock();
|
||||
|
||||
void lzcntl(Register dst, Register src);
|
||||
|
||||
#ifdef _LP64
|
||||
void lzcntq(Register dst, Register src);
|
||||
#endif
|
||||
|
||||
enum Membar_mask_bits {
|
||||
StoreStore = 1 << 3,
|
||||
LoadStore = 1 << 2,
|
||||
|
@ -439,7 +439,7 @@ void LIR_Assembler::emit_exception_handler() {
|
||||
|
||||
// if the method does not have an exception handler, then there is
|
||||
// no reason to search for one
|
||||
if (compilation()->has_exception_handlers() || JvmtiExport::can_post_exceptions()) {
|
||||
if (compilation()->has_exception_handlers() || compilation()->env()->jvmti_can_post_exceptions()) {
|
||||
// the exception oop and pc are in rax, and rdx
|
||||
// no other registers need to be preserved, so invalidate them
|
||||
__ invalidate_registers(false, true, true, false, true, true);
|
||||
|
@ -258,7 +258,7 @@ void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register
|
||||
}
|
||||
}
|
||||
|
||||
if (DTraceAllocProbes) {
|
||||
if (CURRENT_ENV->dtrace_alloc_probes()) {
|
||||
assert(obj == rax, "must be");
|
||||
call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)));
|
||||
}
|
||||
@ -291,7 +291,7 @@ void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1,
|
||||
const Register len_zero = len;
|
||||
initialize_body(obj, arr_size, header_size * BytesPerWord, len_zero);
|
||||
|
||||
if (DTraceAllocProbes) {
|
||||
if (CURRENT_ENV->dtrace_alloc_probes()) {
|
||||
assert(obj == rax, "must be");
|
||||
call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)));
|
||||
}
|
||||
|
@ -237,9 +237,8 @@ bool frame::is_interpreted_frame() const {
|
||||
return Interpreter::contains(pc());
|
||||
}
|
||||
|
||||
int frame::frame_size() const {
|
||||
RegisterMap map(JavaThread::current(), false);
|
||||
frame sender = this->sender(&map);
|
||||
int frame::frame_size(RegisterMap* map) const {
|
||||
frame sender = this->sender(map);
|
||||
return sender.sp() - sp();
|
||||
}
|
||||
|
||||
|
@ -284,7 +284,7 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
|
||||
char buf[256];
|
||||
jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
cores_per_cpu(), threads_per_core(),
|
||||
cpu_family(), _model, _stepping,
|
||||
(supports_cmov() ? ", cmov" : ""),
|
||||
@ -301,6 +301,7 @@ void VM_Version::get_processor_features() {
|
||||
(supports_mmx_ext() ? ", mmxext" : ""),
|
||||
(supports_3dnow() ? ", 3dnow" : ""),
|
||||
(supports_3dnow2() ? ", 3dnowext" : ""),
|
||||
(supports_lzcnt() ? ", lzcnt": ""),
|
||||
(supports_sse4a() ? ", sse4a": ""),
|
||||
(supports_ht() ? ", ht": ""));
|
||||
_features_str = strdup(buf);
|
||||
@ -364,6 +365,13 @@ void VM_Version::get_processor_features() {
|
||||
UseXmmI2D = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Use count leading zeros count instruction if available.
|
||||
if (supports_lzcnt()) {
|
||||
if (FLAG_IS_DEFAULT(UseCountLeadingZerosInstruction)) {
|
||||
UseCountLeadingZerosInstruction = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( is_intel() ) { // Intel cpus specific settings
|
||||
|
@ -120,7 +120,7 @@ public:
|
||||
uint32_t LahfSahf : 1,
|
||||
CmpLegacy : 1,
|
||||
: 4,
|
||||
abm : 1,
|
||||
lzcnt : 1,
|
||||
sse4a : 1,
|
||||
misalignsse : 1,
|
||||
prefetchw : 1,
|
||||
@ -182,7 +182,8 @@ protected:
|
||||
CPU_SSE4A = (1 << 10),
|
||||
CPU_SSE4_1 = (1 << 11),
|
||||
CPU_SSE4_2 = (1 << 12),
|
||||
CPU_POPCNT = (1 << 13)
|
||||
CPU_POPCNT = (1 << 13),
|
||||
CPU_LZCNT = (1 << 14)
|
||||
} cpuFeatureFlags;
|
||||
|
||||
// cpuid information block. All info derived from executing cpuid with
|
||||
@ -277,8 +278,6 @@ protected:
|
||||
if (_cpuid_info.std_cpuid1_edx.bits.mmx != 0 || is_amd() &&
|
||||
_cpuid_info.ext_cpuid1_edx.bits.mmx != 0)
|
||||
result |= CPU_MMX;
|
||||
if (is_amd() && _cpuid_info.ext_cpuid1_edx.bits.tdnow != 0)
|
||||
result |= CPU_3DNOW;
|
||||
if (_cpuid_info.std_cpuid1_edx.bits.sse != 0)
|
||||
result |= CPU_SSE;
|
||||
if (_cpuid_info.std_cpuid1_edx.bits.sse2 != 0)
|
||||
@ -287,14 +286,23 @@ protected:
|
||||
result |= CPU_SSE3;
|
||||
if (_cpuid_info.std_cpuid1_ecx.bits.ssse3 != 0)
|
||||
result |= CPU_SSSE3;
|
||||
if (is_amd() && _cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0)
|
||||
result |= CPU_SSE4A;
|
||||
if (_cpuid_info.std_cpuid1_ecx.bits.sse4_1 != 0)
|
||||
result |= CPU_SSE4_1;
|
||||
if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0)
|
||||
result |= CPU_SSE4_2;
|
||||
if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0)
|
||||
result |= CPU_POPCNT;
|
||||
|
||||
// AMD features.
|
||||
if (is_amd()) {
|
||||
if (_cpuid_info.ext_cpuid1_edx.bits.tdnow != 0)
|
||||
result |= CPU_3DNOW;
|
||||
if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0)
|
||||
result |= CPU_LZCNT;
|
||||
if (_cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0)
|
||||
result |= CPU_SSE4A;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -391,6 +399,7 @@ public:
|
||||
static bool supports_3dnow() { return (_cpuFeatures & CPU_3DNOW) != 0; }
|
||||
static bool supports_mmx_ext() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; }
|
||||
static bool supports_3dnow2() { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.tdnow2 != 0; }
|
||||
static bool supports_lzcnt() { return (_cpuFeatures & CPU_LZCNT) != 0; }
|
||||
static bool supports_sse4a() { return (_cpuFeatures & CPU_SSE4A) != 0; }
|
||||
|
||||
static bool supports_compare_and_exchange() { return true; }
|
||||
|
@ -1281,6 +1281,13 @@ static void emit_float_constant(CodeBuffer& cbuf, float x) {
|
||||
}
|
||||
|
||||
|
||||
const bool Matcher::match_rule_supported(int opcode) {
|
||||
if (!has_match_rule(opcode))
|
||||
return false;
|
||||
|
||||
return true; // Per default match rules are supported.
|
||||
}
|
||||
|
||||
int Matcher::regnum_to_fpu_offset(int regnum) {
|
||||
return regnum - 32; // The FP registers are in the second chunk
|
||||
}
|
||||
@ -5233,6 +5240,15 @@ operand immI_255() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Constant for short-wide masking
|
||||
operand immI_65535() %{
|
||||
predicate(n->get_int() == 65535);
|
||||
match(ConI);
|
||||
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Register Operands
|
||||
// Integer Register
|
||||
operand eRegI() %{
|
||||
@ -6644,6 +6660,153 @@ instruct bytes_reverse_long(eRegL dst) %{
|
||||
%}
|
||||
|
||||
|
||||
//---------- Zeros Count Instructions ------------------------------------------
|
||||
|
||||
instruct countLeadingZerosI(eRegI dst, eRegI src, eFlagsReg cr) %{
|
||||
predicate(UseCountLeadingZerosInstruction);
|
||||
match(Set dst (CountLeadingZerosI src));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "LZCNT $dst, $src\t# count leading zeros (int)" %}
|
||||
ins_encode %{
|
||||
__ lzcntl($dst$$Register, $src$$Register);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct countLeadingZerosI_bsr(eRegI dst, eRegI src, eFlagsReg cr) %{
|
||||
predicate(!UseCountLeadingZerosInstruction);
|
||||
match(Set dst (CountLeadingZerosI src));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "BSR $dst, $src\t# count leading zeros (int)\n\t"
|
||||
"JNZ skip\n\t"
|
||||
"MOV $dst, -1\n"
|
||||
"skip:\n\t"
|
||||
"NEG $dst\n\t"
|
||||
"ADD $dst, 31" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Register Rsrc = $src$$Register;
|
||||
Label skip;
|
||||
__ bsrl(Rdst, Rsrc);
|
||||
__ jccb(Assembler::notZero, skip);
|
||||
__ movl(Rdst, -1);
|
||||
__ bind(skip);
|
||||
__ negl(Rdst);
|
||||
__ addl(Rdst, BitsPerInt - 1);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct countLeadingZerosL(eRegI dst, eRegL src, eFlagsReg cr) %{
|
||||
predicate(UseCountLeadingZerosInstruction);
|
||||
match(Set dst (CountLeadingZerosL src));
|
||||
effect(TEMP dst, KILL cr);
|
||||
|
||||
format %{ "LZCNT $dst, $src.hi\t# count leading zeros (long)\n\t"
|
||||
"JNC done\n\t"
|
||||
"LZCNT $dst, $src.lo\n\t"
|
||||
"ADD $dst, 32\n"
|
||||
"done:" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Register Rsrc = $src$$Register;
|
||||
Label done;
|
||||
__ lzcntl(Rdst, HIGH_FROM_LOW(Rsrc));
|
||||
__ jccb(Assembler::carryClear, done);
|
||||
__ lzcntl(Rdst, Rsrc);
|
||||
__ addl(Rdst, BitsPerInt);
|
||||
__ bind(done);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct countLeadingZerosL_bsr(eRegI dst, eRegL src, eFlagsReg cr) %{
|
||||
predicate(!UseCountLeadingZerosInstruction);
|
||||
match(Set dst (CountLeadingZerosL src));
|
||||
effect(TEMP dst, KILL cr);
|
||||
|
||||
format %{ "BSR $dst, $src.hi\t# count leading zeros (long)\n\t"
|
||||
"JZ msw_is_zero\n\t"
|
||||
"ADD $dst, 32\n\t"
|
||||
"JMP not_zero\n"
|
||||
"msw_is_zero:\n\t"
|
||||
"BSR $dst, $src.lo\n\t"
|
||||
"JNZ not_zero\n\t"
|
||||
"MOV $dst, -1\n"
|
||||
"not_zero:\n\t"
|
||||
"NEG $dst\n\t"
|
||||
"ADD $dst, 63\n" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Register Rsrc = $src$$Register;
|
||||
Label msw_is_zero;
|
||||
Label not_zero;
|
||||
__ bsrl(Rdst, HIGH_FROM_LOW(Rsrc));
|
||||
__ jccb(Assembler::zero, msw_is_zero);
|
||||
__ addl(Rdst, BitsPerInt);
|
||||
__ jmpb(not_zero);
|
||||
__ bind(msw_is_zero);
|
||||
__ bsrl(Rdst, Rsrc);
|
||||
__ jccb(Assembler::notZero, not_zero);
|
||||
__ movl(Rdst, -1);
|
||||
__ bind(not_zero);
|
||||
__ negl(Rdst);
|
||||
__ addl(Rdst, BitsPerLong - 1);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct countTrailingZerosI(eRegI dst, eRegI src, eFlagsReg cr) %{
|
||||
match(Set dst (CountTrailingZerosI src));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "BSF $dst, $src\t# count trailing zeros (int)\n\t"
|
||||
"JNZ done\n\t"
|
||||
"MOV $dst, 32\n"
|
||||
"done:" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Label done;
|
||||
__ bsfl(Rdst, $src$$Register);
|
||||
__ jccb(Assembler::notZero, done);
|
||||
__ movl(Rdst, BitsPerInt);
|
||||
__ bind(done);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct countTrailingZerosL(eRegI dst, eRegL src, eFlagsReg cr) %{
|
||||
match(Set dst (CountTrailingZerosL src));
|
||||
effect(TEMP dst, KILL cr);
|
||||
|
||||
format %{ "BSF $dst, $src.lo\t# count trailing zeros (long)\n\t"
|
||||
"JNZ done\n\t"
|
||||
"BSF $dst, $src.hi\n\t"
|
||||
"JNZ msw_not_zero\n\t"
|
||||
"MOV $dst, 32\n"
|
||||
"msw_not_zero:\n\t"
|
||||
"ADD $dst, 32\n"
|
||||
"done:" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Register Rsrc = $src$$Register;
|
||||
Label msw_not_zero;
|
||||
Label done;
|
||||
__ bsfl(Rdst, Rsrc);
|
||||
__ jccb(Assembler::notZero, done);
|
||||
__ bsfl(Rdst, HIGH_FROM_LOW(Rsrc));
|
||||
__ jccb(Assembler::notZero, msw_not_zero);
|
||||
__ movl(Rdst, BitsPerInt);
|
||||
__ bind(msw_not_zero);
|
||||
__ addl(Rdst, BitsPerInt);
|
||||
__ bind(done);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
|
||||
//---------- Population Count Instructions -------------------------------------
|
||||
|
||||
instruct popCountI(eRegI dst, eRegI src) %{
|
||||
@ -6784,6 +6947,18 @@ instruct loadS(eRegI dst, memory mem) %{
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Short (16 bit signed) to Byte (8 bit signed)
|
||||
instruct loadS2B(eRegI dst, memory mem, immI_24 twentyfour) %{
|
||||
match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "MOVSX $dst, $mem\t# short -> byte" %}
|
||||
ins_encode %{
|
||||
__ movsbl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Short (16bit signed) into Long Register
|
||||
instruct loadS2L(eRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadS mem)));
|
||||
@ -6816,9 +6991,20 @@ instruct loadUS(eRegI dst, memory mem) %{
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed)
|
||||
instruct loadUS2B(eRegI dst, memory mem, immI_24 twentyfour) %{
|
||||
match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "MOVSX $dst, $mem\t# ushort -> byte" %}
|
||||
ins_encode %{
|
||||
__ movsbl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) into Long Register
|
||||
instruct loadUS2L(eRegL dst, memory mem)
|
||||
%{
|
||||
instruct loadUS2L(eRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadUS mem)));
|
||||
|
||||
ins_cost(250);
|
||||
@ -6847,6 +7033,54 @@ instruct loadI(eRegI dst, memory mem) %{
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer (32 bit signed) to Byte (8 bit signed)
|
||||
instruct loadI2B(eRegI dst, memory mem, immI_24 twentyfour) %{
|
||||
match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "MOVSX $dst, $mem\t# int -> byte" %}
|
||||
ins_encode %{
|
||||
__ movsbl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer (32 bit signed) to Unsigned Byte (8 bit UNsigned)
|
||||
instruct loadI2UB(eRegI dst, memory mem, immI_255 mask) %{
|
||||
match(Set dst (AndI (LoadI mem) mask));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "MOVZX $dst, $mem\t# int -> ubyte" %}
|
||||
ins_encode %{
|
||||
__ movzbl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer (32 bit signed) to Short (16 bit signed)
|
||||
instruct loadI2S(eRegI dst, memory mem, immI_16 sixteen) %{
|
||||
match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "MOVSX $dst, $mem\t# int -> short" %}
|
||||
ins_encode %{
|
||||
__ movswl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer (32 bit signed) to Unsigned Short/Char (16 bit UNsigned)
|
||||
instruct loadI2US(eRegI dst, memory mem, immI_65535 mask) %{
|
||||
match(Set dst (AndI (LoadI mem) mask));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "MOVZX $dst, $mem\t# int -> ushort/char" %}
|
||||
ins_encode %{
|
||||
__ movzwl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer into Long Register
|
||||
instruct loadI2L(eRegL dst, memory mem) %{
|
||||
match(Set dst (ConvI2L (LoadI mem)));
|
||||
@ -8880,28 +9114,28 @@ instruct shrI_eReg_imm(eRegI dst, immI8 shift, eFlagsReg cr) %{
|
||||
|
||||
// Logical Shift Right by 24, followed by Arithmetic Shift Left by 24.
|
||||
// This idiom is used by the compiler for the i2b bytecode.
|
||||
instruct i2b(eRegI dst, xRegI src, immI_24 twentyfour, eFlagsReg cr) %{
|
||||
instruct i2b(eRegI dst, xRegI src, immI_24 twentyfour) %{
|
||||
match(Set dst (RShiftI (LShiftI src twentyfour) twentyfour));
|
||||
effect(KILL cr);
|
||||
|
||||
size(3);
|
||||
format %{ "MOVSX $dst,$src :8" %}
|
||||
opcode(0xBE, 0x0F);
|
||||
ins_encode( OpcS, OpcP, RegReg( dst, src));
|
||||
ins_pipe( ialu_reg_reg );
|
||||
ins_encode %{
|
||||
__ movsbl($dst$$Register, $src$$Register);
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
|
||||
// Logical Shift Right by 16, followed by Arithmetic Shift Left by 16.
|
||||
// This idiom is used by the compiler the i2s bytecode.
|
||||
instruct i2s(eRegI dst, xRegI src, immI_16 sixteen, eFlagsReg cr) %{
|
||||
instruct i2s(eRegI dst, xRegI src, immI_16 sixteen) %{
|
||||
match(Set dst (RShiftI (LShiftI src sixteen) sixteen));
|
||||
effect(KILL cr);
|
||||
|
||||
size(3);
|
||||
format %{ "MOVSX $dst,$src :16" %}
|
||||
opcode(0xBF, 0x0F);
|
||||
ins_encode( OpcS, OpcP, RegReg( dst, src));
|
||||
ins_pipe( ialu_reg_reg );
|
||||
ins_encode %{
|
||||
__ movswl($dst$$Register, $src$$Register);
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
|
||||
|
||||
|
@ -1980,6 +1980,13 @@ static void emit_float_constant(CodeBuffer& cbuf, float x) {
|
||||
}
|
||||
|
||||
|
||||
const bool Matcher::match_rule_supported(int opcode) {
|
||||
if (!has_match_rule(opcode))
|
||||
return false;
|
||||
|
||||
return true; // Per default match rules are supported.
|
||||
}
|
||||
|
||||
int Matcher::regnum_to_fpu_offset(int regnum)
|
||||
{
|
||||
return regnum - 32; // The FP registers are in the second chunk
|
||||
@ -6452,6 +6459,18 @@ instruct loadS(rRegI dst, memory mem)
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Short (16 bit signed) to Byte (8 bit signed)
|
||||
instruct loadS2B(rRegI dst, memory mem, immI_24 twentyfour) %{
|
||||
match(Set dst (RShiftI (LShiftI (LoadS mem) twentyfour) twentyfour));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "movsbl $dst, $mem\t# short -> byte" %}
|
||||
ins_encode %{
|
||||
__ movsbl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Short (16 bit signed) into Long Register
|
||||
instruct loadS2L(rRegL dst, memory mem)
|
||||
%{
|
||||
@ -6482,6 +6501,18 @@ instruct loadUS(rRegI dst, memory mem)
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) to Byte (8 bit signed)
|
||||
instruct loadUS2B(rRegI dst, memory mem, immI_24 twentyfour) %{
|
||||
match(Set dst (RShiftI (LShiftI (LoadUS mem) twentyfour) twentyfour));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "movsbl $dst, $mem\t# ushort -> byte" %}
|
||||
ins_encode %{
|
||||
__ movsbl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Unsigned Short/Char (16 bit UNsigned) into Long Register
|
||||
instruct loadUS2L(rRegL dst, memory mem)
|
||||
%{
|
||||
@ -6512,6 +6543,54 @@ instruct loadI(rRegI dst, memory mem)
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer (32 bit signed) to Byte (8 bit signed)
|
||||
instruct loadI2B(rRegI dst, memory mem, immI_24 twentyfour) %{
|
||||
match(Set dst (RShiftI (LShiftI (LoadI mem) twentyfour) twentyfour));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "movsbl $dst, $mem\t# int -> byte" %}
|
||||
ins_encode %{
|
||||
__ movsbl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer (32 bit signed) to Unsigned Byte (8 bit UNsigned)
|
||||
instruct loadI2UB(rRegI dst, memory mem, immI_255 mask) %{
|
||||
match(Set dst (AndI (LoadI mem) mask));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "movzbl $dst, $mem\t# int -> ubyte" %}
|
||||
ins_encode %{
|
||||
__ movzbl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer (32 bit signed) to Short (16 bit signed)
|
||||
instruct loadI2S(rRegI dst, memory mem, immI_16 sixteen) %{
|
||||
match(Set dst (RShiftI (LShiftI (LoadI mem) sixteen) sixteen));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "movswl $dst, $mem\t# int -> short" %}
|
||||
ins_encode %{
|
||||
__ movswl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer (32 bit signed) to Unsigned Short/Char (16 bit UNsigned)
|
||||
instruct loadI2US(rRegI dst, memory mem, immI_65535 mask) %{
|
||||
match(Set dst (AndI (LoadI mem) mask));
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "movzwl $dst, $mem\t# int -> ushort/char" %}
|
||||
ins_encode %{
|
||||
__ movzwl($dst$$Register, $mem$$Address);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Load Integer into Long Register
|
||||
instruct loadI2L(rRegL dst, memory mem)
|
||||
%{
|
||||
@ -7656,6 +7735,121 @@ instruct storeL_reversed(memory dst, rRegL src) %{
|
||||
%}
|
||||
|
||||
|
||||
//---------- Zeros Count Instructions ------------------------------------------
|
||||
|
||||
instruct countLeadingZerosI(rRegI dst, rRegI src, rFlagsReg cr) %{
|
||||
predicate(UseCountLeadingZerosInstruction);
|
||||
match(Set dst (CountLeadingZerosI src));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "lzcntl $dst, $src\t# count leading zeros (int)" %}
|
||||
ins_encode %{
|
||||
__ lzcntl($dst$$Register, $src$$Register);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct countLeadingZerosI_bsr(rRegI dst, rRegI src, rFlagsReg cr) %{
|
||||
predicate(!UseCountLeadingZerosInstruction);
|
||||
match(Set dst (CountLeadingZerosI src));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "bsrl $dst, $src\t# count leading zeros (int)\n\t"
|
||||
"jnz skip\n\t"
|
||||
"movl $dst, -1\n"
|
||||
"skip:\n\t"
|
||||
"negl $dst\n\t"
|
||||
"addl $dst, 31" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Register Rsrc = $src$$Register;
|
||||
Label skip;
|
||||
__ bsrl(Rdst, Rsrc);
|
||||
__ jccb(Assembler::notZero, skip);
|
||||
__ movl(Rdst, -1);
|
||||
__ bind(skip);
|
||||
__ negl(Rdst);
|
||||
__ addl(Rdst, BitsPerInt - 1);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct countLeadingZerosL(rRegI dst, rRegL src, rFlagsReg cr) %{
|
||||
predicate(UseCountLeadingZerosInstruction);
|
||||
match(Set dst (CountLeadingZerosL src));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "lzcntq $dst, $src\t# count leading zeros (long)" %}
|
||||
ins_encode %{
|
||||
__ lzcntq($dst$$Register, $src$$Register);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct countLeadingZerosL_bsr(rRegI dst, rRegL src, rFlagsReg cr) %{
|
||||
predicate(!UseCountLeadingZerosInstruction);
|
||||
match(Set dst (CountLeadingZerosL src));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "bsrq $dst, $src\t# count leading zeros (long)\n\t"
|
||||
"jnz skip\n\t"
|
||||
"movl $dst, -1\n"
|
||||
"skip:\n\t"
|
||||
"negl $dst\n\t"
|
||||
"addl $dst, 63" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Register Rsrc = $src$$Register;
|
||||
Label skip;
|
||||
__ bsrq(Rdst, Rsrc);
|
||||
__ jccb(Assembler::notZero, skip);
|
||||
__ movl(Rdst, -1);
|
||||
__ bind(skip);
|
||||
__ negl(Rdst);
|
||||
__ addl(Rdst, BitsPerLong - 1);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct countTrailingZerosI(rRegI dst, rRegI src, rFlagsReg cr) %{
|
||||
match(Set dst (CountTrailingZerosI src));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "bsfl $dst, $src\t# count trailing zeros (int)\n\t"
|
||||
"jnz done\n\t"
|
||||
"movl $dst, 32\n"
|
||||
"done:" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Label done;
|
||||
__ bsfl(Rdst, $src$$Register);
|
||||
__ jccb(Assembler::notZero, done);
|
||||
__ movl(Rdst, BitsPerInt);
|
||||
__ bind(done);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
instruct countTrailingZerosL(rRegI dst, rRegL src, rFlagsReg cr) %{
|
||||
match(Set dst (CountTrailingZerosL src));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "bsfq $dst, $src\t# count trailing zeros (long)\n\t"
|
||||
"jnz done\n\t"
|
||||
"movl $dst, 64\n"
|
||||
"done:" %}
|
||||
ins_encode %{
|
||||
Register Rdst = $dst$$Register;
|
||||
Label done;
|
||||
__ bsfq(Rdst, $src$$Register);
|
||||
__ jccb(Assembler::notZero, done);
|
||||
__ movl(Rdst, BitsPerLong);
|
||||
__ bind(done);
|
||||
%}
|
||||
ins_pipe(ialu_reg);
|
||||
%}
|
||||
|
||||
|
||||
//---------- Population Count Instructions -------------------------------------
|
||||
|
||||
instruct popCountI(rRegI dst, rRegI src) %{
|
||||
|
@ -73,7 +73,7 @@ class FileBuff {
|
||||
|
||||
// This converts a pointer into the buffer to a file offset. It only works
|
||||
// when the pointer is valid (i.e. just obtained from getline()).
|
||||
long getoff(const char* s) { return _bufoff + (s - _buf); }
|
||||
long getoff(const char* s) { return _bufoff + (long)(s - _buf); }
|
||||
};
|
||||
|
||||
//------------------------------FileBuffRegion---------------------------------
|
||||
|
@ -1745,6 +1745,7 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
|
||||
fprintf(fp," del_req(i);\n");
|
||||
fprintf(fp," }\n");
|
||||
fprintf(fp," _num_opnds = %d;\n", new_num_opnds);
|
||||
assert(new_num_opnds == node->num_unique_opnds(), "what?");
|
||||
}
|
||||
}
|
||||
|
||||
@ -3761,6 +3762,12 @@ bool InstructForm::define_cisc_version(ArchDesc &AD, FILE *fp_cpp) {
|
||||
if ( this->captures_bottom_type() ) {
|
||||
fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n");
|
||||
}
|
||||
|
||||
uint cur_num_opnds = num_opnds();
|
||||
if (cur_num_opnds > 1 && cur_num_opnds != num_unique_opnds()) {
|
||||
fprintf(fp_cpp," node->_num_opnds = %d;\n", num_unique_opnds());
|
||||
}
|
||||
|
||||
fprintf(fp_cpp, "\n");
|
||||
fprintf(fp_cpp, " // Copy _idx, inputs and operands to new node\n");
|
||||
fprintf(fp_cpp, " fill_new_machnode(node, C);\n");
|
||||
|
@ -319,7 +319,7 @@ void Compilation::compile_method() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
|
||||
if (_env->jvmti_can_hotswap_or_post_breakpoint()) {
|
||||
// We can assert evol_method because method->can_be_compiled is true.
|
||||
dependency_recorder()->assert_evol_method(method());
|
||||
}
|
||||
@ -435,7 +435,7 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho
|
||||
assert(_arena == NULL, "shouldn't only one instance of Compilation in existence at a time");
|
||||
_arena = Thread::current()->resource_area();
|
||||
_compilation = this;
|
||||
_needs_debug_information = JvmtiExport::can_examine_or_deopt_anywhere() ||
|
||||
_needs_debug_information = _env->jvmti_can_examine_or_deopt_anywhere() ||
|
||||
JavaMonitorsInStackTrace || AlwaysEmitDebugInfo || DeoptimizeALot;
|
||||
_exception_info_list = new ExceptionInfoList();
|
||||
_implicit_exception_table.set_size(0);
|
||||
|
@ -1662,7 +1662,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
|
||||
// Register dependence if JVMTI has either breakpoint
|
||||
// setting or hotswapping of methods capabilities since they may
|
||||
// cause deoptimization.
|
||||
if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
|
||||
if (compilation()->env()->jvmti_can_hotswap_or_post_breakpoint()) {
|
||||
dependency_recorder()->assert_evol_method(inline_target);
|
||||
}
|
||||
return;
|
||||
@ -2863,7 +2863,7 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
|
||||
start_block->merge(_initial_state);
|
||||
|
||||
BlockBegin* sync_handler = NULL;
|
||||
if (method()->is_synchronized() || DTraceMethodProbes) {
|
||||
if (method()->is_synchronized() || _compilation->env()->dtrace_method_probes()) {
|
||||
// setup an exception handler to do the unlocking and/or notification
|
||||
sync_handler = new BlockBegin(-1);
|
||||
sync_handler->set(BlockBegin::exception_entry_flag);
|
||||
|
@ -1064,7 +1064,7 @@ void LIRGenerator::do_IfInstanceOf(IfInstanceOf* x) {
|
||||
|
||||
|
||||
void LIRGenerator::do_Return(Return* x) {
|
||||
if (DTraceMethodProbes) {
|
||||
if (compilation()->env()->dtrace_method_probes()) {
|
||||
BasicTypeList signature;
|
||||
signature.append(T_INT); // thread
|
||||
signature.append(T_OBJECT); // methodOop
|
||||
@ -1769,7 +1769,7 @@ void LIRGenerator::do_Throw(Throw* x) {
|
||||
__ null_check(exception_opr, new CodeEmitInfo(info, true));
|
||||
}
|
||||
|
||||
if (JvmtiExport::can_post_exceptions() &&
|
||||
if (compilation()->env()->jvmti_can_post_exceptions() &&
|
||||
!block()->is_set(BlockBegin::default_exception_handler_flag)) {
|
||||
// we need to go through the exception lookup path to get JVMTI
|
||||
// notification done
|
||||
@ -1779,7 +1779,7 @@ void LIRGenerator::do_Throw(Throw* x) {
|
||||
assert(!block()->is_set(BlockBegin::default_exception_handler_flag) || unwind,
|
||||
"should be no more handlers to dispatch to");
|
||||
|
||||
if (DTraceMethodProbes &&
|
||||
if (compilation()->env()->dtrace_method_probes() &&
|
||||
block()->is_set(BlockBegin::default_exception_handler_flag)) {
|
||||
// notify that this frame is unwinding
|
||||
BasicTypeList signature;
|
||||
@ -2204,7 +2204,7 @@ void LIRGenerator::do_Base(Base* x) {
|
||||
java_index += type2size[t];
|
||||
}
|
||||
|
||||
if (DTraceMethodProbes) {
|
||||
if (compilation()->env()->dtrace_method_probes()) {
|
||||
BasicTypeList signature;
|
||||
signature.append(T_INT); // thread
|
||||
signature.append(T_OBJECT); // methodOop
|
||||
|
@ -170,6 +170,34 @@ ciEnv::~ciEnv() {
|
||||
current_thread->set_env(NULL);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Cache Jvmti state
|
||||
void ciEnv::cache_jvmti_state() {
|
||||
VM_ENTRY_MARK;
|
||||
// Get Jvmti capabilities under lock to get consistant values.
|
||||
MutexLocker mu(JvmtiThreadState_lock);
|
||||
_jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint();
|
||||
_jvmti_can_examine_or_deopt_anywhere = JvmtiExport::can_examine_or_deopt_anywhere();
|
||||
_jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables();
|
||||
_jvmti_can_post_exceptions = JvmtiExport::can_post_exceptions();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Cache DTrace flags
|
||||
void ciEnv::cache_dtrace_flags() {
|
||||
// Need lock?
|
||||
_dtrace_extended_probes = ExtendedDTraceProbes;
|
||||
if (_dtrace_extended_probes) {
|
||||
_dtrace_monitor_probes = true;
|
||||
_dtrace_method_probes = true;
|
||||
_dtrace_alloc_probes = true;
|
||||
} else {
|
||||
_dtrace_monitor_probes = DTraceMonitorProbes;
|
||||
_dtrace_method_probes = DTraceMethodProbes;
|
||||
_dtrace_alloc_probes = DTraceAllocProbes;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// helper for lazy exception creation
|
||||
ciInstance* ciEnv::get_or_create_exception(jobject& handle, symbolHandle name) {
|
||||
@ -810,16 +838,39 @@ void ciEnv::register_method(ciMethod* target,
|
||||
// and invalidating our dependencies until we install this method.
|
||||
MutexLocker ml(Compile_lock);
|
||||
|
||||
if (log() != NULL) {
|
||||
// Log the dependencies which this compilation declares.
|
||||
dependencies()->log_all_dependencies();
|
||||
// Change in Jvmti state may invalidate compilation.
|
||||
if (!failing() &&
|
||||
( (!jvmti_can_hotswap_or_post_breakpoint() &&
|
||||
JvmtiExport::can_hotswap_or_post_breakpoint()) ||
|
||||
(!jvmti_can_examine_or_deopt_anywhere() &&
|
||||
JvmtiExport::can_examine_or_deopt_anywhere()) ||
|
||||
(!jvmti_can_access_local_variables() &&
|
||||
JvmtiExport::can_access_local_variables()) ||
|
||||
(!jvmti_can_post_exceptions() &&
|
||||
JvmtiExport::can_post_exceptions()) )) {
|
||||
record_failure("Jvmti state change invalidated dependencies");
|
||||
}
|
||||
|
||||
// Encode the dependencies now, so we can check them right away.
|
||||
dependencies()->encode_content_bytes();
|
||||
// Change in DTrace flags may invalidate compilation.
|
||||
if (!failing() &&
|
||||
( (!dtrace_extended_probes() && ExtendedDTraceProbes) ||
|
||||
(!dtrace_method_probes() && DTraceMethodProbes) ||
|
||||
(!dtrace_alloc_probes() && DTraceAllocProbes) )) {
|
||||
record_failure("DTrace flags change invalidated dependencies");
|
||||
}
|
||||
|
||||
// Check for {class loads, evolution, breakpoints} during compilation
|
||||
check_for_system_dictionary_modification(target);
|
||||
if (!failing()) {
|
||||
if (log() != NULL) {
|
||||
// Log the dependencies which this compilation declares.
|
||||
dependencies()->log_all_dependencies();
|
||||
}
|
||||
|
||||
// Encode the dependencies now, so we can check them right away.
|
||||
dependencies()->encode_content_bytes();
|
||||
|
||||
// Check for {class loads, evolution, breakpoints} during compilation
|
||||
check_for_system_dictionary_modification(target);
|
||||
}
|
||||
|
||||
methodHandle method(THREAD, target->get_methodOop());
|
||||
|
||||
|
@ -53,6 +53,18 @@ private:
|
||||
char* _name_buffer;
|
||||
int _name_buffer_len;
|
||||
|
||||
// Cache Jvmti state
|
||||
bool _jvmti_can_hotswap_or_post_breakpoint;
|
||||
bool _jvmti_can_examine_or_deopt_anywhere;
|
||||
bool _jvmti_can_access_local_variables;
|
||||
bool _jvmti_can_post_exceptions;
|
||||
|
||||
// Cache DTrace flags
|
||||
bool _dtrace_extended_probes;
|
||||
bool _dtrace_monitor_probes;
|
||||
bool _dtrace_method_probes;
|
||||
bool _dtrace_alloc_probes;
|
||||
|
||||
// Distinguished instances of certain ciObjects..
|
||||
static ciObject* _null_object_instance;
|
||||
static ciMethodKlass* _method_klass_instance;
|
||||
@ -236,6 +248,20 @@ public:
|
||||
bool break_at_compile() { return _break_at_compile; }
|
||||
void set_break_at_compile(bool z) { _break_at_compile = z; }
|
||||
|
||||
// Cache Jvmti state
|
||||
void cache_jvmti_state();
|
||||
bool jvmti_can_hotswap_or_post_breakpoint() const { return _jvmti_can_hotswap_or_post_breakpoint; }
|
||||
bool jvmti_can_examine_or_deopt_anywhere() const { return _jvmti_can_examine_or_deopt_anywhere; }
|
||||
bool jvmti_can_access_local_variables() const { return _jvmti_can_access_local_variables; }
|
||||
bool jvmti_can_post_exceptions() const { return _jvmti_can_post_exceptions; }
|
||||
|
||||
// Cache DTrace flags
|
||||
void cache_dtrace_flags();
|
||||
bool dtrace_extended_probes() const { return _dtrace_extended_probes; }
|
||||
bool dtrace_monitor_probes() const { return _dtrace_monitor_probes; }
|
||||
bool dtrace_method_probes() const { return _dtrace_method_probes; }
|
||||
bool dtrace_alloc_probes() const { return _dtrace_alloc_probes; }
|
||||
|
||||
// The compiler task which has created this env.
|
||||
// May be useful to find out compile_id, comp_level, etc.
|
||||
CompileTask* task() { return _task; }
|
||||
|
@ -60,7 +60,8 @@ ciMethod::ciMethod(methodHandle h_m) : ciObject(h_m) {
|
||||
_flow = NULL;
|
||||
#endif // COMPILER2
|
||||
|
||||
if (JvmtiExport::can_hotswap_or_post_breakpoint() && _is_compilable) {
|
||||
ciEnv *env = CURRENT_ENV;
|
||||
if (env->jvmti_can_hotswap_or_post_breakpoint() && _is_compilable) {
|
||||
// 6328518 check hotswap conditions under the right lock.
|
||||
MutexLocker locker(Compile_lock);
|
||||
if (Dependencies::check_evol_method(h_m()) != NULL) {
|
||||
@ -84,7 +85,6 @@ ciMethod::ciMethod(methodHandle h_m) : ciObject(h_m) {
|
||||
if (_can_be_statically_bound && h_m()->is_abstract())
|
||||
_can_be_statically_bound = false;
|
||||
|
||||
ciEnv *env = CURRENT_ENV;
|
||||
// generating _signature may allow GC and therefore move m.
|
||||
// These fields are always filled in.
|
||||
_name = env->get_object(h_m()->name())->as_symbol();
|
||||
@ -337,7 +337,7 @@ MethodLivenessResult ciMethod::liveness_at_bci(int bci) {
|
||||
_liveness->compute_liveness();
|
||||
}
|
||||
MethodLivenessResult result = _liveness->get_liveness_at(bci);
|
||||
if (JvmtiExport::can_access_local_variables() || DeoptimizeALot || CompileTheWorld) {
|
||||
if (CURRENT_ENV->jvmti_can_access_local_variables() || DeoptimizeALot || CompileTheWorld) {
|
||||
// Keep all locals live for the user's edification and amusement.
|
||||
result.at_put_range(0, result.size(), true);
|
||||
}
|
||||
|
@ -313,6 +313,8 @@
|
||||
template(value_name, "value") \
|
||||
template(frontCacheEnabled_name, "frontCacheEnabled") \
|
||||
template(stringCacheEnabled_name, "stringCacheEnabled") \
|
||||
template(numberOfLeadingZeros_name, "numberOfLeadingZeros") \
|
||||
template(numberOfTrailingZeros_name, "numberOfTrailingZeros") \
|
||||
template(bitCount_name, "bitCount") \
|
||||
template(profile_name, "profile") \
|
||||
template(equals_name, "equals") \
|
||||
@ -559,6 +561,12 @@
|
||||
do_intrinsic(_longBitsToDouble, java_lang_Double, longBitsToDouble_name, long_double_signature, F_S) \
|
||||
do_name( longBitsToDouble_name, "longBitsToDouble") \
|
||||
\
|
||||
do_intrinsic(_numberOfLeadingZeros_i, java_lang_Integer, numberOfLeadingZeros_name,int_int_signature, F_S) \
|
||||
do_intrinsic(_numberOfLeadingZeros_l, java_lang_Long, numberOfLeadingZeros_name,long_int_signature, F_S) \
|
||||
\
|
||||
do_intrinsic(_numberOfTrailingZeros_i, java_lang_Integer, numberOfTrailingZeros_name,int_int_signature, F_S) \
|
||||
do_intrinsic(_numberOfTrailingZeros_l, java_lang_Long, numberOfTrailingZeros_name,long_int_signature, F_S) \
|
||||
\
|
||||
do_intrinsic(_bitCount_i, java_lang_Integer, bitCount_name, int_int_signature, F_S) \
|
||||
do_intrinsic(_bitCount_l, java_lang_Long, bitCount_name, long_int_signature, F_S) \
|
||||
\
|
||||
|
@ -1530,6 +1530,12 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
||||
assert(thread->env() == &ci_env, "set by ci_env");
|
||||
// The thread-env() field is cleared in ~CompileTaskWrapper.
|
||||
|
||||
// Cache Jvmti state
|
||||
ci_env.cache_jvmti_state();
|
||||
|
||||
// Cache DTrace flags
|
||||
ci_env.cache_dtrace_flags();
|
||||
|
||||
ciMethod* target = ci_env.get_method_from_handle(target_handle);
|
||||
|
||||
TraceTime t1("compilation", &time);
|
||||
|
@ -555,6 +555,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
|
||||
_collector_policy(cp),
|
||||
_should_unload_classes(false),
|
||||
_concurrent_cycles_since_last_unload(0),
|
||||
_roots_scanning_options(0),
|
||||
_sweep_estimate(CMS_SweepWeight, CMS_SweepPadding)
|
||||
{
|
||||
if (ExplicitGCInvokesConcurrentAndUnloadsClasses) {
|
||||
|
@ -545,6 +545,11 @@ class CMSCollector: public CHeapObj {
|
||||
bool unloaded_classes_last_cycle() const {
|
||||
return concurrent_cycles_since_last_unload() == 0;
|
||||
}
|
||||
// Root scanning options for perm gen
|
||||
int _roots_scanning_options;
|
||||
int roots_scanning_options() const { return _roots_scanning_options; }
|
||||
void add_root_scanning_option(int o) { _roots_scanning_options |= o; }
|
||||
void remove_root_scanning_option(int o) { _roots_scanning_options &= ~o; }
|
||||
|
||||
// Verification support
|
||||
CMSBitMap _verification_mark_bm;
|
||||
@ -719,11 +724,6 @@ class CMSCollector: public CHeapObj {
|
||||
NOT_PRODUCT(bool simulate_overflow();) // sequential
|
||||
NOT_PRODUCT(bool par_simulate_overflow();) // MT version
|
||||
|
||||
int _roots_scanning_options;
|
||||
int roots_scanning_options() const { return _roots_scanning_options; }
|
||||
void add_root_scanning_option(int o) { _roots_scanning_options |= o; }
|
||||
void remove_root_scanning_option(int o) { _roots_scanning_options &= ~o; }
|
||||
|
||||
// CMS work methods
|
||||
void checkpointRootsInitialWork(bool asynch); // initial checkpoint work
|
||||
|
||||
|
@ -25,26 +25,37 @@
|
||||
#include "incls/_precompiled.incl"
|
||||
#include "incls/_concurrentG1Refine.cpp.incl"
|
||||
|
||||
bool ConcurrentG1Refine::_enabled = false;
|
||||
|
||||
ConcurrentG1Refine::ConcurrentG1Refine() :
|
||||
_pya(PYA_continue), _last_pya(PYA_continue),
|
||||
_last_cards_during(), _first_traversal(false),
|
||||
_card_counts(NULL), _cur_card_count_histo(NULL), _cum_card_count_histo(NULL),
|
||||
_hot_cache(NULL),
|
||||
_def_use_cache(false), _use_cache(false),
|
||||
_n_periods(0), _total_cards(0), _total_travs(0)
|
||||
_n_periods(0), _total_cards(0), _total_travs(0),
|
||||
_threads(NULL), _n_threads(0)
|
||||
{
|
||||
if (G1ConcRefine) {
|
||||
_cg1rThread = new ConcurrentG1RefineThread(this);
|
||||
assert(cg1rThread() != NULL, "Conc refine should have been created");
|
||||
assert(cg1rThread()->cg1r() == this,
|
||||
"Conc refine thread should refer to this");
|
||||
} else {
|
||||
_cg1rThread = NULL;
|
||||
_n_threads = (int)thread_num();
|
||||
if (_n_threads > 0) {
|
||||
_threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads);
|
||||
int worker_id_offset = (int)DirtyCardQueueSet::num_par_ids();
|
||||
ConcurrentG1RefineThread *next = NULL;
|
||||
for (int i = _n_threads - 1; i >= 0; i--) {
|
||||
ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i);
|
||||
assert(t != NULL, "Conc refine should have been created");
|
||||
assert(t->cg1r() == this, "Conc refine thread should refer to this");
|
||||
_threads[i] = t;
|
||||
next = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t ConcurrentG1Refine::thread_num() {
|
||||
if (G1ConcRefine) {
|
||||
return (G1ParallelRSetThreads > 0) ? G1ParallelRSetThreads : ParallelGCThreads;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ConcurrentG1Refine::init() {
|
||||
if (G1ConcRSLogCacheSize > 0 || G1ConcRSCountTraversals) {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
@ -75,6 +86,14 @@ void ConcurrentG1Refine::init() {
|
||||
}
|
||||
}
|
||||
|
||||
void ConcurrentG1Refine::stop() {
|
||||
if (_threads != NULL) {
|
||||
for (int i = 0; i < _n_threads; i++) {
|
||||
_threads[i]->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConcurrentG1Refine::~ConcurrentG1Refine() {
|
||||
if (G1ConcRSLogCacheSize > 0 || G1ConcRSCountTraversals) {
|
||||
assert(_card_counts != NULL, "Logic");
|
||||
@ -88,104 +107,22 @@ ConcurrentG1Refine::~ConcurrentG1Refine() {
|
||||
assert(_hot_cache != NULL, "Logic");
|
||||
FREE_C_HEAP_ARRAY(jbyte*, _hot_cache);
|
||||
}
|
||||
}
|
||||
|
||||
bool ConcurrentG1Refine::refine() {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
unsigned cards_before = g1h->g1_rem_set()->conc_refine_cards();
|
||||
clear_hot_cache(); // Any previous values in this are now invalid.
|
||||
g1h->g1_rem_set()->concurrentRefinementPass(this);
|
||||
_traversals++;
|
||||
unsigned cards_after = g1h->g1_rem_set()->conc_refine_cards();
|
||||
unsigned cards_during = cards_after-cards_before;
|
||||
// If this is the first traversal in the current enabling
|
||||
// and we did some cards, or if the number of cards found is decreasing
|
||||
// sufficiently quickly, then keep going. Otherwise, sleep a while.
|
||||
bool res =
|
||||
(_first_traversal && cards_during > 0)
|
||||
||
|
||||
(!_first_traversal && cards_during * 3 < _last_cards_during * 2);
|
||||
_last_cards_during = cards_during;
|
||||
_first_traversal = false;
|
||||
return res;
|
||||
}
|
||||
|
||||
void ConcurrentG1Refine::enable() {
|
||||
MutexLocker x(G1ConcRefine_mon);
|
||||
if (!_enabled) {
|
||||
_enabled = true;
|
||||
_first_traversal = true; _last_cards_during = 0;
|
||||
G1ConcRefine_mon->notify_all();
|
||||
if (_threads != NULL) {
|
||||
for (int i = 0; i < _n_threads; i++) {
|
||||
delete _threads[i];
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _threads);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned ConcurrentG1Refine::disable() {
|
||||
MutexLocker x(G1ConcRefine_mon);
|
||||
if (_enabled) {
|
||||
_enabled = false;
|
||||
return _traversals;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ConcurrentG1Refine::wait_for_ConcurrentG1Refine_enabled() {
|
||||
G1ConcRefine_mon->lock();
|
||||
while (!_enabled) {
|
||||
G1ConcRefine_mon->wait(Mutex::_no_safepoint_check_flag);
|
||||
}
|
||||
G1ConcRefine_mon->unlock();
|
||||
_traversals = 0;
|
||||
};
|
||||
|
||||
void ConcurrentG1Refine::set_pya_restart() {
|
||||
// If we're using the log-based RS barrier, the above will cause
|
||||
// in-progress traversals of completed log buffers to quit early; we will
|
||||
// also abandon all other buffers.
|
||||
if (G1RSBarrierUseQueue) {
|
||||
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
|
||||
dcqs.abandon_logs();
|
||||
// Reset the post-yield actions.
|
||||
_pya = PYA_continue;
|
||||
_last_pya = PYA_continue;
|
||||
} else {
|
||||
_pya = PYA_restart;
|
||||
}
|
||||
}
|
||||
|
||||
void ConcurrentG1Refine::set_pya_cancel() {
|
||||
_pya = PYA_cancel;
|
||||
}
|
||||
|
||||
PostYieldAction ConcurrentG1Refine::get_pya() {
|
||||
if (_pya != PYA_continue) {
|
||||
jint val = _pya;
|
||||
while (true) {
|
||||
jint val_read = Atomic::cmpxchg(PYA_continue, &_pya, val);
|
||||
if (val_read == val) {
|
||||
PostYieldAction res = (PostYieldAction)val;
|
||||
assert(res != PYA_continue, "Only the refine thread should reset.");
|
||||
_last_pya = res;
|
||||
return res;
|
||||
} else {
|
||||
val = val_read;
|
||||
}
|
||||
void ConcurrentG1Refine::threads_do(ThreadClosure *tc) {
|
||||
if (_threads != NULL) {
|
||||
for (int i = 0; i < _n_threads; i++) {
|
||||
tc->do_thread(_threads[i]);
|
||||
}
|
||||
}
|
||||
// QQQ WELL WHAT DO WE RETURN HERE???
|
||||
// make up something!
|
||||
return PYA_continue;
|
||||
}
|
||||
|
||||
PostYieldAction ConcurrentG1Refine::get_last_pya() {
|
||||
PostYieldAction res = _last_pya;
|
||||
_last_pya = PYA_continue;
|
||||
return res;
|
||||
}
|
||||
|
||||
bool ConcurrentG1Refine::do_traversal() {
|
||||
return _cg1rThread->do_traversal();
|
||||
}
|
||||
|
||||
int ConcurrentG1Refine::add_card_count(jbyte* card_ptr) {
|
||||
size_t card_num = (card_ptr - _ct_bot);
|
||||
|
@ -26,26 +26,9 @@
|
||||
class ConcurrentG1RefineThread;
|
||||
class G1RemSet;
|
||||
|
||||
// What to do after a yield:
|
||||
enum PostYieldAction {
|
||||
PYA_continue, // Continue the traversal
|
||||
PYA_restart, // Restart
|
||||
PYA_cancel // It's been completed by somebody else: cancel.
|
||||
};
|
||||
|
||||
class ConcurrentG1Refine: public CHeapObj {
|
||||
ConcurrentG1RefineThread* _cg1rThread;
|
||||
|
||||
volatile jint _pya;
|
||||
PostYieldAction _last_pya;
|
||||
|
||||
static bool _enabled; // Protected by G1ConcRefine_mon.
|
||||
unsigned _traversals;
|
||||
|
||||
// Number of cards processed during last refinement traversal.
|
||||
unsigned _first_traversal;
|
||||
unsigned _last_cards_during;
|
||||
|
||||
ConcurrentG1RefineThread** _threads;
|
||||
int _n_threads;
|
||||
// The cache for card refinement.
|
||||
bool _use_cache;
|
||||
bool _def_use_cache;
|
||||
@ -74,37 +57,10 @@ class ConcurrentG1Refine: public CHeapObj {
|
||||
~ConcurrentG1Refine();
|
||||
|
||||
void init(); // Accomplish some initialization that has to wait.
|
||||
void stop();
|
||||
|
||||
// Enabled Conc refinement, waking up thread if necessary.
|
||||
void enable();
|
||||
|
||||
// Returns the number of traversals performed since this refiner was enabled.
|
||||
unsigned disable();
|
||||
|
||||
// Requires G1ConcRefine_mon to be held.
|
||||
bool enabled() { return _enabled; }
|
||||
|
||||
// Returns only when G1 concurrent refinement has been enabled.
|
||||
void wait_for_ConcurrentG1Refine_enabled();
|
||||
|
||||
// Do one concurrent refinement pass over the card table. Returns "true"
|
||||
// if heuristics determine that another pass should be done immediately.
|
||||
bool refine();
|
||||
|
||||
// Indicate that an in-progress refinement pass should start over.
|
||||
void set_pya_restart();
|
||||
// Indicate that an in-progress refinement pass should quit.
|
||||
void set_pya_cancel();
|
||||
|
||||
// Get the appropriate post-yield action. Also sets last_pya.
|
||||
PostYieldAction get_pya();
|
||||
|
||||
// The last PYA read by "get_pya".
|
||||
PostYieldAction get_last_pya();
|
||||
|
||||
bool do_traversal();
|
||||
|
||||
ConcurrentG1RefineThread* cg1rThread() { return _cg1rThread; }
|
||||
// Iterate over the conc refine threads
|
||||
void threads_do(ThreadClosure *tc);
|
||||
|
||||
// If this is the first entry for the slot, writes into the cache and
|
||||
// returns NULL. If it causes an eviction, returns the evicted pointer.
|
||||
@ -129,4 +85,6 @@ class ConcurrentG1Refine: public CHeapObj {
|
||||
|
||||
void clear_and_record_card_counts();
|
||||
void print_final_card_counts();
|
||||
|
||||
static size_t thread_num();
|
||||
};
|
||||
|
@ -30,12 +30,14 @@
|
||||
// The CM thread is created when the G1 garbage collector is used
|
||||
|
||||
ConcurrentG1RefineThread::
|
||||
ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r) :
|
||||
ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next,
|
||||
int worker_id_offset, int worker_id) :
|
||||
ConcurrentGCThread(),
|
||||
_worker_id_offset(worker_id_offset),
|
||||
_worker_id(worker_id),
|
||||
_active(false),
|
||||
_next(next),
|
||||
_cg1r(cg1r),
|
||||
_started(false),
|
||||
_in_progress(false),
|
||||
_do_traversal(false),
|
||||
_vtime_accum(0.0),
|
||||
_co_tracker(G1CRGroup),
|
||||
_interval_ms(5.0)
|
||||
@ -43,112 +45,6 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r) :
|
||||
create_and_start();
|
||||
}
|
||||
|
||||
const long timeout = 200; // ms.
|
||||
|
||||
void ConcurrentG1RefineThread::traversalBasedRefinement() {
|
||||
_cg1r->wait_for_ConcurrentG1Refine_enabled();
|
||||
MutexLocker x(G1ConcRefine_mon);
|
||||
while (_cg1r->enabled()) {
|
||||
MutexUnlocker ux(G1ConcRefine_mon);
|
||||
ResourceMark rm;
|
||||
HandleMark hm;
|
||||
|
||||
if (G1TraceConcurrentRefinement) {
|
||||
gclog_or_tty->print_cr("G1-Refine starting pass");
|
||||
}
|
||||
_sts.join();
|
||||
bool no_sleep = _cg1r->refine();
|
||||
_sts.leave();
|
||||
if (!no_sleep) {
|
||||
MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
|
||||
// We do this only for the timeout; we don't expect this to be signalled.
|
||||
CGC_lock->wait(Mutex::_no_safepoint_check_flag, timeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConcurrentG1RefineThread::queueBasedRefinement() {
|
||||
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
|
||||
// Wait for completed log buffers to exist.
|
||||
{
|
||||
MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
|
||||
while (!_do_traversal && !dcqs.process_completed_buffers() &&
|
||||
!_should_terminate) {
|
||||
DirtyCardQ_CBL_mon->wait(Mutex::_no_safepoint_check_flag);
|
||||
}
|
||||
}
|
||||
|
||||
if (_should_terminate) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Now we take them off (this doesn't hold locks while it applies
|
||||
// closures.) (If we did a full collection, then we'll do a full
|
||||
// traversal.
|
||||
_sts.join();
|
||||
if (_do_traversal) {
|
||||
(void)_cg1r->refine();
|
||||
switch (_cg1r->get_last_pya()) {
|
||||
case PYA_cancel: case PYA_continue:
|
||||
// Continue was caught and handled inside "refine". If it's still
|
||||
// "continue" when we get here, we're done.
|
||||
_do_traversal = false;
|
||||
break;
|
||||
case PYA_restart:
|
||||
assert(_do_traversal, "Because of Full GC.");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
int n_logs = 0;
|
||||
int lower_limit = 0;
|
||||
double start_vtime_sec; // only used when G1SmoothConcRefine is on
|
||||
int prev_buffer_num; // only used when G1SmoothConcRefine is on
|
||||
|
||||
if (G1SmoothConcRefine) {
|
||||
lower_limit = 0;
|
||||
start_vtime_sec = os::elapsedVTime();
|
||||
prev_buffer_num = (int) dcqs.completed_buffers_num();
|
||||
} else {
|
||||
lower_limit = DCQBarrierProcessCompletedThreshold / 4; // For now.
|
||||
}
|
||||
while (dcqs.apply_closure_to_completed_buffer(0, lower_limit)) {
|
||||
double end_vtime_sec;
|
||||
double elapsed_vtime_sec;
|
||||
int elapsed_vtime_ms;
|
||||
int curr_buffer_num;
|
||||
|
||||
if (G1SmoothConcRefine) {
|
||||
end_vtime_sec = os::elapsedVTime();
|
||||
elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
|
||||
elapsed_vtime_ms = (int) (elapsed_vtime_sec * 1000.0);
|
||||
curr_buffer_num = (int) dcqs.completed_buffers_num();
|
||||
|
||||
if (curr_buffer_num > prev_buffer_num ||
|
||||
curr_buffer_num > DCQBarrierProcessCompletedThreshold) {
|
||||
decreaseInterval(elapsed_vtime_ms);
|
||||
} else if (curr_buffer_num < prev_buffer_num) {
|
||||
increaseInterval(elapsed_vtime_ms);
|
||||
}
|
||||
}
|
||||
|
||||
sample_young_list_rs_lengths();
|
||||
_co_tracker.update(false);
|
||||
|
||||
if (G1SmoothConcRefine) {
|
||||
prev_buffer_num = curr_buffer_num;
|
||||
_sts.leave();
|
||||
os::sleep(Thread::current(), (jlong) _interval_ms, false);
|
||||
_sts.join();
|
||||
start_vtime_sec = os::elapsedVTime();
|
||||
}
|
||||
n_logs++;
|
||||
}
|
||||
// Make sure we harvest the PYA, if any.
|
||||
(void)_cg1r->get_pya();
|
||||
}
|
||||
_sts.leave();
|
||||
}
|
||||
|
||||
void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
G1CollectorPolicy* g1p = g1h->g1_policy();
|
||||
@ -184,15 +80,97 @@ void ConcurrentG1RefineThread::run() {
|
||||
_co_tracker.start();
|
||||
|
||||
while (!_should_terminate) {
|
||||
// wait until started is set.
|
||||
if (G1RSBarrierUseQueue) {
|
||||
queueBasedRefinement();
|
||||
} else {
|
||||
traversalBasedRefinement();
|
||||
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
|
||||
// Wait for completed log buffers to exist.
|
||||
{
|
||||
MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
|
||||
while (((_worker_id == 0 && !dcqs.process_completed_buffers()) ||
|
||||
(_worker_id > 0 && !is_active())) &&
|
||||
!_should_terminate) {
|
||||
DirtyCardQ_CBL_mon->wait(Mutex::_no_safepoint_check_flag);
|
||||
}
|
||||
}
|
||||
|
||||
if (_should_terminate) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Now we take them off (this doesn't hold locks while it applies
|
||||
// closures.) (If we did a full collection, then we'll do a full
|
||||
// traversal.
|
||||
_sts.join();
|
||||
_co_tracker.update();
|
||||
int n_logs = 0;
|
||||
int lower_limit = 0;
|
||||
double start_vtime_sec; // only used when G1SmoothConcRefine is on
|
||||
int prev_buffer_num; // only used when G1SmoothConcRefine is on
|
||||
// This thread activation threshold
|
||||
int threshold = DCQBarrierProcessCompletedThreshold * _worker_id;
|
||||
// Next thread activation threshold
|
||||
int next_threshold = threshold + DCQBarrierProcessCompletedThreshold;
|
||||
int deactivation_threshold = MAX2<int>(threshold - DCQBarrierProcessCompletedThreshold / 2, 0);
|
||||
|
||||
if (G1SmoothConcRefine) {
|
||||
lower_limit = 0;
|
||||
start_vtime_sec = os::elapsedVTime();
|
||||
prev_buffer_num = (int) dcqs.completed_buffers_num();
|
||||
} else {
|
||||
lower_limit = DCQBarrierProcessCompletedThreshold / 4; // For now.
|
||||
}
|
||||
while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, lower_limit)) {
|
||||
double end_vtime_sec;
|
||||
double elapsed_vtime_sec;
|
||||
int elapsed_vtime_ms;
|
||||
int curr_buffer_num = (int) dcqs.completed_buffers_num();
|
||||
|
||||
if (G1SmoothConcRefine) {
|
||||
end_vtime_sec = os::elapsedVTime();
|
||||
elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
|
||||
elapsed_vtime_ms = (int) (elapsed_vtime_sec * 1000.0);
|
||||
|
||||
if (curr_buffer_num > prev_buffer_num ||
|
||||
curr_buffer_num > next_threshold) {
|
||||
decreaseInterval(elapsed_vtime_ms);
|
||||
} else if (curr_buffer_num < prev_buffer_num) {
|
||||
increaseInterval(elapsed_vtime_ms);
|
||||
}
|
||||
}
|
||||
if (_worker_id == 0) {
|
||||
sample_young_list_rs_lengths();
|
||||
} else if (curr_buffer_num < deactivation_threshold) {
|
||||
// If the number of the buffer has fallen below our threshold
|
||||
// we should deactivate. The predecessor will reactivate this
|
||||
// thread should the number of the buffers cross the threshold again.
|
||||
MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
|
||||
deactivate();
|
||||
if (G1TraceConcurrentRefinement) {
|
||||
gclog_or_tty->print_cr("G1-Refine-deactivated worker %d", _worker_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
_co_tracker.update(false);
|
||||
|
||||
// Check if we need to activate the next thread.
|
||||
if (curr_buffer_num > next_threshold && _next != NULL && !_next->is_active()) {
|
||||
MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
|
||||
_next->activate();
|
||||
DirtyCardQ_CBL_mon->notify_all();
|
||||
if (G1TraceConcurrentRefinement) {
|
||||
gclog_or_tty->print_cr("G1-Refine-activated worker %d", _next->_worker_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (G1SmoothConcRefine) {
|
||||
prev_buffer_num = curr_buffer_num;
|
||||
_sts.leave();
|
||||
os::sleep(Thread::current(), (jlong) _interval_ms, false);
|
||||
_sts.join();
|
||||
start_vtime_sec = os::elapsedVTime();
|
||||
}
|
||||
n_logs++;
|
||||
}
|
||||
_co_tracker.update(false);
|
||||
_sts.leave();
|
||||
|
||||
if (os::supports_vtime()) {
|
||||
_vtime_accum = (os::elapsedVTime() - _vtime_start);
|
||||
} else {
|
||||
@ -240,7 +218,3 @@ void ConcurrentG1RefineThread::print() {
|
||||
Thread::print();
|
||||
gclog_or_tty->cr();
|
||||
}
|
||||
|
||||
void ConcurrentG1RefineThread::set_do_traversal(bool b) {
|
||||
_do_traversal = b;
|
||||
}
|
||||
|
@ -33,21 +33,27 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread {
|
||||
|
||||
double _vtime_start; // Initial virtual time.
|
||||
double _vtime_accum; // Initial virtual time.
|
||||
int _worker_id;
|
||||
int _worker_id_offset;
|
||||
|
||||
// The refinement threads collection is linked list. A predecessor can activate a successor
|
||||
// when the number of the rset update buffer crosses a certain threshold. A successor
|
||||
// would self-deactivate when the number of the buffers falls below the threshold.
|
||||
bool _active;
|
||||
ConcurrentG1RefineThread * _next;
|
||||
public:
|
||||
virtual void run();
|
||||
|
||||
bool is_active() { return _active; }
|
||||
void activate() { _active = true; }
|
||||
void deactivate() { _active = false; }
|
||||
|
||||
private:
|
||||
ConcurrentG1Refine* _cg1r;
|
||||
bool _started;
|
||||
bool _in_progress;
|
||||
volatile bool _restart;
|
||||
|
||||
COTracker _co_tracker;
|
||||
double _interval_ms;
|
||||
|
||||
bool _do_traversal;
|
||||
|
||||
void decreaseInterval(int processing_time_ms) {
|
||||
double min_interval_ms = (double) processing_time_ms;
|
||||
_interval_ms = 0.8 * _interval_ms;
|
||||
@ -63,16 +69,13 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread {
|
||||
|
||||
void sleepBeforeNextCycle();
|
||||
|
||||
void traversalBasedRefinement();
|
||||
|
||||
void queueBasedRefinement();
|
||||
|
||||
// For use by G1CollectedHeap, which is a friend.
|
||||
static SuspendibleThreadSet* sts() { return &_sts; }
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r);
|
||||
ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next,
|
||||
int worker_id_offset, int worker_id);
|
||||
|
||||
// Printing
|
||||
void print();
|
||||
@ -82,23 +85,11 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread {
|
||||
|
||||
ConcurrentG1Refine* cg1r() { return _cg1r; }
|
||||
|
||||
|
||||
void set_started() { _started = true; }
|
||||
void clear_started() { _started = false; }
|
||||
bool started() { return _started; }
|
||||
|
||||
void set_in_progress() { _in_progress = true; }
|
||||
void clear_in_progress() { _in_progress = false; }
|
||||
bool in_progress() { return _in_progress; }
|
||||
|
||||
void set_do_traversal(bool b);
|
||||
bool do_traversal() { return _do_traversal; }
|
||||
|
||||
void sample_young_list_rs_lengths();
|
||||
|
||||
// Yield for GC
|
||||
void yield();
|
||||
|
||||
// shutdown
|
||||
static void stop();
|
||||
void stop();
|
||||
};
|
||||
|
@ -80,5 +80,5 @@ class ConcurrentMarkThread: public ConcurrentGCThread {
|
||||
void yield();
|
||||
|
||||
// shutdown
|
||||
static void stop();
|
||||
void stop();
|
||||
};
|
||||
|
@ -73,7 +73,7 @@ class ConcurrentZFThread: public ConcurrentGCThread {
|
||||
// while holding the ZF_needed_mon lock.
|
||||
|
||||
// shutdown
|
||||
static void stop();
|
||||
void stop();
|
||||
|
||||
// Stats
|
||||
static void note_region_alloc() {_region_allocs++; }
|
||||
|
@ -71,11 +71,11 @@ DirtyCardQueueSet::DirtyCardQueueSet() :
|
||||
_all_active = true;
|
||||
}
|
||||
|
||||
// Determines how many mutator threads can process the buffers in parallel.
|
||||
size_t DirtyCardQueueSet::num_par_ids() {
|
||||
return MAX2(ParallelGCThreads, (size_t)2);
|
||||
return os::processor_count();
|
||||
}
|
||||
|
||||
|
||||
void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock,
|
||||
int max_completed_queue,
|
||||
Mutex* lock, PtrQueueSet* fl_owner) {
|
||||
@ -85,8 +85,6 @@ void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock,
|
||||
|
||||
_shared_dirty_card_queue.set_lock(lock);
|
||||
_free_ids = new FreeIdSet((int) num_par_ids(), _cbl_mon);
|
||||
bool b = _free_ids->claim_perm_id(0);
|
||||
guarantee(b, "Must reserve id zero for concurrent refinement thread.");
|
||||
}
|
||||
|
||||
void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) {
|
||||
@ -234,7 +232,7 @@ bool DirtyCardQueueSet::apply_closure_to_completed_buffer(int worker_i,
|
||||
nd = get_completed_buffer_lock(stop_at);
|
||||
}
|
||||
bool res = apply_closure_to_completed_buffer_helper(worker_i, nd);
|
||||
if (res) _processed_buffers_rs_thread++;
|
||||
if (res) Atomic::inc(&_processed_buffers_rs_thread);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -446,8 +446,61 @@ void YoungList::print() {
|
||||
gclog_or_tty->print_cr("");
|
||||
}
|
||||
|
||||
void G1CollectedHeap::push_dirty_cards_region(HeapRegion* hr)
|
||||
{
|
||||
// Claim the right to put the region on the dirty cards region list
|
||||
// by installing a self pointer.
|
||||
HeapRegion* next = hr->get_next_dirty_cards_region();
|
||||
if (next == NULL) {
|
||||
HeapRegion* res = (HeapRegion*)
|
||||
Atomic::cmpxchg_ptr(hr, hr->next_dirty_cards_region_addr(),
|
||||
NULL);
|
||||
if (res == NULL) {
|
||||
HeapRegion* head;
|
||||
do {
|
||||
// Put the region to the dirty cards region list.
|
||||
head = _dirty_cards_region_list;
|
||||
next = (HeapRegion*)
|
||||
Atomic::cmpxchg_ptr(hr, &_dirty_cards_region_list, head);
|
||||
if (next == head) {
|
||||
assert(hr->get_next_dirty_cards_region() == hr,
|
||||
"hr->get_next_dirty_cards_region() != hr");
|
||||
if (next == NULL) {
|
||||
// The last region in the list points to itself.
|
||||
hr->set_next_dirty_cards_region(hr);
|
||||
} else {
|
||||
hr->set_next_dirty_cards_region(next);
|
||||
}
|
||||
}
|
||||
} while (next != head);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HeapRegion* G1CollectedHeap::pop_dirty_cards_region()
|
||||
{
|
||||
HeapRegion* head;
|
||||
HeapRegion* hr;
|
||||
do {
|
||||
head = _dirty_cards_region_list;
|
||||
if (head == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
HeapRegion* new_head = head->get_next_dirty_cards_region();
|
||||
if (head == new_head) {
|
||||
// The last region.
|
||||
new_head = NULL;
|
||||
}
|
||||
hr = (HeapRegion*)Atomic::cmpxchg_ptr(new_head, &_dirty_cards_region_list,
|
||||
head);
|
||||
} while (hr != head);
|
||||
assert(hr != NULL, "invariant");
|
||||
hr->set_next_dirty_cards_region(NULL);
|
||||
return hr;
|
||||
}
|
||||
|
||||
void G1CollectedHeap::stop_conc_gc_threads() {
|
||||
_cg1r->cg1rThread()->stop();
|
||||
_cg1r->stop();
|
||||
_czft->stop();
|
||||
_cmThread->stop();
|
||||
}
|
||||
@ -1001,12 +1054,8 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs,
|
||||
|
||||
gc_epilogue(true);
|
||||
|
||||
// Abandon concurrent refinement. This must happen last: in the
|
||||
// dirty-card logging system, some cards may be dirty by weak-ref
|
||||
// processing, and may be enqueued. But the whole card table is
|
||||
// dirtied, so this should abandon those logs, and set "do_traversal"
|
||||
// to true.
|
||||
concurrent_g1_refine()->set_pya_restart();
|
||||
// Discard all rset updates
|
||||
JavaThread::dirty_card_queue_set().abandon_logs();
|
||||
assert(!G1DeferredRSUpdate
|
||||
|| (G1DeferredRSUpdate && (dirty_card_queue_set().completed_buffers_num() == 0)), "Should not be any");
|
||||
assert(regions_accounted_for(), "Region leakage!");
|
||||
@ -1333,7 +1382,8 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) :
|
||||
_gc_time_stamp(0),
|
||||
_surviving_young_words(NULL),
|
||||
_in_cset_fast_test(NULL),
|
||||
_in_cset_fast_test_base(NULL) {
|
||||
_in_cset_fast_test_base(NULL),
|
||||
_dirty_cards_region_list(NULL) {
|
||||
_g1h = this; // To catch bugs.
|
||||
if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) {
|
||||
vm_exit_during_initialization("Failed necessary allocation.");
|
||||
@ -1521,12 +1571,12 @@ jint G1CollectedHeap::initialize() {
|
||||
SATB_Q_FL_lock,
|
||||
0,
|
||||
Shared_SATB_Q_lock);
|
||||
if (G1RSBarrierUseQueue) {
|
||||
JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
|
||||
DirtyCardQ_FL_lock,
|
||||
G1DirtyCardQueueMax,
|
||||
Shared_DirtyCardQ_lock);
|
||||
}
|
||||
|
||||
JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
|
||||
DirtyCardQ_FL_lock,
|
||||
G1DirtyCardQueueMax,
|
||||
Shared_DirtyCardQ_lock);
|
||||
|
||||
if (G1DeferredRSUpdate) {
|
||||
dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
|
||||
DirtyCardQ_FL_lock,
|
||||
@ -2249,6 +2299,15 @@ void G1CollectedHeap::print_on(outputStream* st) const {
|
||||
_hrs->iterate(&blk);
|
||||
}
|
||||
|
||||
class PrintOnThreadsClosure : public ThreadClosure {
|
||||
outputStream* _st;
|
||||
public:
|
||||
PrintOnThreadsClosure(outputStream* st) : _st(st) { }
|
||||
virtual void do_thread(Thread *t) {
|
||||
t->print_on(_st);
|
||||
}
|
||||
};
|
||||
|
||||
void G1CollectedHeap::print_gc_threads_on(outputStream* st) const {
|
||||
if (ParallelGCThreads > 0) {
|
||||
workers()->print_worker_threads();
|
||||
@ -2256,8 +2315,9 @@ void G1CollectedHeap::print_gc_threads_on(outputStream* st) const {
|
||||
st->print("\"G1 concurrent mark GC Thread\" ");
|
||||
_cmThread->print();
|
||||
st->cr();
|
||||
st->print("\"G1 concurrent refinement GC Thread\" ");
|
||||
_cg1r->cg1rThread()->print_on(st);
|
||||
st->print("\"G1 concurrent refinement GC Threads\" ");
|
||||
PrintOnThreadsClosure p(st);
|
||||
_cg1r->threads_do(&p);
|
||||
st->cr();
|
||||
st->print("\"G1 zero-fill GC Thread\" ");
|
||||
_czft->print_on(st);
|
||||
@ -2269,7 +2329,7 @@ void G1CollectedHeap::gc_threads_do(ThreadClosure* tc) const {
|
||||
workers()->threads_do(tc);
|
||||
}
|
||||
tc->do_thread(_cmThread);
|
||||
tc->do_thread(_cg1r->cg1rThread());
|
||||
_cg1r->threads_do(tc);
|
||||
tc->do_thread(_czft);
|
||||
}
|
||||
|
||||
@ -4685,15 +4745,58 @@ void G1CollectedHeap::dirtyCardsForYoungRegions(CardTableModRefBS* ct_bs, HeapRe
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class G1ParCleanupCTTask : public AbstractGangTask {
|
||||
CardTableModRefBS* _ct_bs;
|
||||
G1CollectedHeap* _g1h;
|
||||
public:
|
||||
G1ParCleanupCTTask(CardTableModRefBS* ct_bs,
|
||||
G1CollectedHeap* g1h) :
|
||||
AbstractGangTask("G1 Par Cleanup CT Task"),
|
||||
_ct_bs(ct_bs),
|
||||
_g1h(g1h)
|
||||
{ }
|
||||
|
||||
void work(int i) {
|
||||
HeapRegion* r;
|
||||
while (r = _g1h->pop_dirty_cards_region()) {
|
||||
clear_cards(r);
|
||||
}
|
||||
}
|
||||
void clear_cards(HeapRegion* r) {
|
||||
// Cards for Survivor and Scan-Only regions will be dirtied later.
|
||||
if (!r->is_scan_only() && !r->is_survivor()) {
|
||||
_ct_bs->clear(MemRegion(r->bottom(), r->end()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void G1CollectedHeap::cleanUpCardTable() {
|
||||
CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set());
|
||||
double start = os::elapsedTime();
|
||||
|
||||
ct_bs->clear(_g1_committed);
|
||||
|
||||
// Iterate over the dirty cards region list.
|
||||
G1ParCleanupCTTask cleanup_task(ct_bs, this);
|
||||
if (ParallelGCThreads > 0) {
|
||||
set_par_threads(workers()->total_workers());
|
||||
workers()->run_task(&cleanup_task);
|
||||
set_par_threads(0);
|
||||
} else {
|
||||
while (_dirty_cards_region_list) {
|
||||
HeapRegion* r = _dirty_cards_region_list;
|
||||
cleanup_task.clear_cards(r);
|
||||
_dirty_cards_region_list = r->get_next_dirty_cards_region();
|
||||
if (_dirty_cards_region_list == r) {
|
||||
// The last region.
|
||||
_dirty_cards_region_list = NULL;
|
||||
}
|
||||
r->set_next_dirty_cards_region(NULL);
|
||||
}
|
||||
}
|
||||
// now, redirty the cards of the scan-only and survivor regions
|
||||
// (it seemed faster to do it this way, instead of iterating over
|
||||
// all regions and then clearing / dirtying as approprite)
|
||||
// all regions and then clearing / dirtying as appropriate)
|
||||
dirtyCardsForYoungRegions(ct_bs, _young_list->first_scan_only_region());
|
||||
dirtyCardsForYoungRegions(ct_bs, _young_list->first_survivor_region());
|
||||
|
||||
|
@ -158,6 +158,7 @@ class G1CollectedHeap : public SharedHeap {
|
||||
friend class RegionSorter;
|
||||
friend class CountRCClosure;
|
||||
friend class EvacPopObjClosure;
|
||||
friend class G1ParCleanupCTTask;
|
||||
|
||||
// Other related classes.
|
||||
friend class G1MarkSweep;
|
||||
@ -1191,6 +1192,16 @@ public:
|
||||
ConcurrentMark* concurrent_mark() const { return _cm; }
|
||||
ConcurrentG1Refine* concurrent_g1_refine() const { return _cg1r; }
|
||||
|
||||
// The dirty cards region list is used to record a subset of regions
|
||||
// whose cards need clearing. The list if populated during the
|
||||
// remembered set scanning and drained during the card table
|
||||
// cleanup. Although the methods are reentrant, population/draining
|
||||
// phases must not overlap. For synchronization purposes the last
|
||||
// element on the list points to itself.
|
||||
HeapRegion* _dirty_cards_region_list;
|
||||
void push_dirty_cards_region(HeapRegion* hr);
|
||||
HeapRegion* pop_dirty_cards_region();
|
||||
|
||||
public:
|
||||
void stop_conc_gc_threads();
|
||||
|
||||
|
@ -167,11 +167,6 @@ G1CollectorPolicy::G1CollectorPolicy() :
|
||||
|
||||
_all_full_gc_times_ms(new NumberSeq()),
|
||||
|
||||
_conc_refine_enabled(0),
|
||||
_conc_refine_zero_traversals(0),
|
||||
_conc_refine_max_traversals(0),
|
||||
_conc_refine_current_delta(G1ConcRefineInitialDelta),
|
||||
|
||||
// G1PausesBtwnConcMark defaults to -1
|
||||
// so the hack is to do the cast QQQ FIXME
|
||||
_pauses_btwn_concurrent_mark((size_t)G1PausesBtwnConcMark),
|
||||
@ -1634,9 +1629,8 @@ void G1CollectorPolicy::record_collection_pause_end(bool abandoned) {
|
||||
print_stats(1, "Parallel Time", _cur_collection_par_time_ms);
|
||||
print_par_stats(2, "Update RS (Start)", _par_last_update_rs_start_times_ms, false);
|
||||
print_par_stats(2, "Update RS", _par_last_update_rs_times_ms);
|
||||
if (G1RSBarrierUseQueue)
|
||||
print_par_buffers(3, "Processed Buffers",
|
||||
_par_last_update_rs_processed_buffers, true);
|
||||
print_par_buffers(3, "Processed Buffers",
|
||||
_par_last_update_rs_processed_buffers, true);
|
||||
print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms);
|
||||
print_par_stats(2, "Mark Stack Scanning", _par_last_mark_stack_scan_times_ms);
|
||||
print_par_stats(2, "Scan-Only Scanning", _par_last_scan_only_times_ms);
|
||||
@ -1649,9 +1643,8 @@ void G1CollectorPolicy::record_collection_pause_end(bool abandoned) {
|
||||
print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
|
||||
} else {
|
||||
print_stats(1, "Update RS", update_rs_time);
|
||||
if (G1RSBarrierUseQueue)
|
||||
print_stats(2, "Processed Buffers",
|
||||
(int)update_rs_processed_buffers);
|
||||
print_stats(2, "Processed Buffers",
|
||||
(int)update_rs_processed_buffers);
|
||||
print_stats(1, "Ext Root Scanning", ext_root_scan_time);
|
||||
print_stats(1, "Mark Stack Scanning", mark_stack_scan_time);
|
||||
print_stats(1, "Scan-Only Scanning", scan_only_time);
|
||||
@ -2467,18 +2460,6 @@ void G1CollectorPolicy::print_tracing_info() const {
|
||||
(double) _region_num_young / (double) all_region_num * 100.0,
|
||||
_region_num_tenured,
|
||||
(double) _region_num_tenured / (double) all_region_num * 100.0);
|
||||
|
||||
if (!G1RSBarrierUseQueue) {
|
||||
gclog_or_tty->print_cr("Of %d times conc refinement was enabled, %d (%7.2f%%) "
|
||||
"did zero traversals.",
|
||||
_conc_refine_enabled, _conc_refine_zero_traversals,
|
||||
_conc_refine_enabled > 0 ?
|
||||
100.0 * (float)_conc_refine_zero_traversals/
|
||||
(float)_conc_refine_enabled : 0.0);
|
||||
gclog_or_tty->print_cr(" Max # of traversals = %d.",
|
||||
_conc_refine_max_traversals);
|
||||
gclog_or_tty->print_cr("");
|
||||
}
|
||||
}
|
||||
if (TraceGen1Time) {
|
||||
if (_all_full_gc_times_ms->num() > 0) {
|
||||
@ -2500,38 +2481,6 @@ void G1CollectorPolicy::print_yg_surv_rate_info() const {
|
||||
#endif // PRODUCT
|
||||
}
|
||||
|
||||
void G1CollectorPolicy::update_conc_refine_data() {
|
||||
unsigned traversals = _g1->concurrent_g1_refine()->disable();
|
||||
if (traversals == 0) _conc_refine_zero_traversals++;
|
||||
_conc_refine_max_traversals = MAX2(_conc_refine_max_traversals,
|
||||
(size_t)traversals);
|
||||
|
||||
if (G1PolicyVerbose > 1)
|
||||
gclog_or_tty->print_cr("Did a CR traversal series: %d traversals.", traversals);
|
||||
double multiplier = 1.0;
|
||||
if (traversals == 0) {
|
||||
multiplier = 4.0;
|
||||
} else if (traversals > (size_t)G1ConcRefineTargTraversals) {
|
||||
multiplier = 1.0/1.5;
|
||||
} else if (traversals < (size_t)G1ConcRefineTargTraversals) {
|
||||
multiplier = 1.5;
|
||||
}
|
||||
if (G1PolicyVerbose > 1) {
|
||||
gclog_or_tty->print_cr(" Multiplier = %7.2f.", multiplier);
|
||||
gclog_or_tty->print(" Delta went from %d regions to ",
|
||||
_conc_refine_current_delta);
|
||||
}
|
||||
_conc_refine_current_delta =
|
||||
MIN2(_g1->n_regions(),
|
||||
(size_t)(_conc_refine_current_delta * multiplier));
|
||||
_conc_refine_current_delta =
|
||||
MAX2(_conc_refine_current_delta, (size_t)1);
|
||||
if (G1PolicyVerbose > 1) {
|
||||
gclog_or_tty->print_cr("%d regions.", _conc_refine_current_delta);
|
||||
}
|
||||
_conc_refine_enabled++;
|
||||
}
|
||||
|
||||
bool
|
||||
G1CollectorPolicy::should_add_next_region_to_young_list() {
|
||||
assert(in_young_gc_mode(), "should be in young GC mode");
|
||||
|
@ -637,18 +637,6 @@ protected:
|
||||
// The number of collection pauses at the end of the last mark.
|
||||
size_t _n_pauses_at_mark_end;
|
||||
|
||||
// ==== This section is for stats related to starting Conc Refinement on time.
|
||||
size_t _conc_refine_enabled;
|
||||
size_t _conc_refine_zero_traversals;
|
||||
size_t _conc_refine_max_traversals;
|
||||
// In # of heap regions.
|
||||
size_t _conc_refine_current_delta;
|
||||
|
||||
// At the beginning of a collection pause, update the variables above,
|
||||
// especially the "delta".
|
||||
void update_conc_refine_data();
|
||||
// ====
|
||||
|
||||
// Stash a pointer to the g1 heap.
|
||||
G1CollectedHeap* _g1;
|
||||
|
||||
|
@ -105,28 +105,6 @@ StupidG1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
|
||||
_g1->heap_region_iterate(&rc);
|
||||
}
|
||||
|
||||
class UpdateRSOutOfRegionClosure: public HeapRegionClosure {
|
||||
G1CollectedHeap* _g1h;
|
||||
ModRefBarrierSet* _mr_bs;
|
||||
UpdateRSOopClosure _cl;
|
||||
int _worker_i;
|
||||
public:
|
||||
UpdateRSOutOfRegionClosure(G1CollectedHeap* g1, int worker_i = 0) :
|
||||
_cl(g1->g1_rem_set()->as_HRInto_G1RemSet(), worker_i),
|
||||
_mr_bs(g1->mr_bs()),
|
||||
_worker_i(worker_i),
|
||||
_g1h(g1)
|
||||
{}
|
||||
bool doHeapRegion(HeapRegion* r) {
|
||||
if (!r->in_collection_set() && !r->continuesHumongous()) {
|
||||
_cl.set_from(r);
|
||||
r->set_next_filter_kind(HeapRegionDCTOC::OutOfRegionFilterKind);
|
||||
_mr_bs->mod_oop_in_space_iterate(r, &_cl, true, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class VerifyRSCleanCardOopClosure: public OopClosure {
|
||||
G1CollectedHeap* _g1;
|
||||
public:
|
||||
@ -241,6 +219,7 @@ public:
|
||||
HeapRegionRemSet* hrrs = r->rem_set();
|
||||
if (hrrs->iter_is_complete()) return false; // All done.
|
||||
if (!_try_claimed && !hrrs->claim_iter()) return false;
|
||||
_g1h->push_dirty_cards_region(r);
|
||||
// If we didn't return above, then
|
||||
// _try_claimed || r->claim_iter()
|
||||
// is true: either we're supposed to work on claimed-but-not-complete
|
||||
@ -264,6 +243,10 @@ public:
|
||||
assert(card_region != NULL, "Yielding cards not in the heap?");
|
||||
_cards++;
|
||||
|
||||
if (!card_region->is_on_dirty_cards_region_list()) {
|
||||
_g1h->push_dirty_cards_region(card_region);
|
||||
}
|
||||
|
||||
// If the card is dirty, then we will scan it during updateRS.
|
||||
if (!card_region->in_collection_set() && !_ct_bs->is_card_dirty(card_index)) {
|
||||
if (!_ct_bs->is_card_claimed(card_index) && _ct_bs->claim_card(card_index)) {
|
||||
@ -350,30 +333,17 @@ void HRInto_G1RemSet::updateRS(int worker_i) {
|
||||
double start = os::elapsedTime();
|
||||
_g1p->record_update_rs_start_time(worker_i, start * 1000.0);
|
||||
|
||||
if (G1RSBarrierUseQueue && !cg1r->do_traversal()) {
|
||||
// Apply the appropriate closure to all remaining log entries.
|
||||
_g1->iterate_dirty_card_closure(false, worker_i);
|
||||
// Now there should be no dirty cards.
|
||||
if (G1RSLogCheckCardTable) {
|
||||
CountNonCleanMemRegionClosure cl(_g1);
|
||||
_ct_bs->mod_card_iterate(&cl);
|
||||
// XXX This isn't true any more: keeping cards of young regions
|
||||
// marked dirty broke it. Need some reasonable fix.
|
||||
guarantee(cl.n() == 0, "Card table should be clean.");
|
||||
}
|
||||
} else {
|
||||
UpdateRSOutOfRegionClosure update_rs(_g1, worker_i);
|
||||
_g1->heap_region_iterate(&update_rs);
|
||||
// We did a traversal; no further one is necessary.
|
||||
if (G1RSBarrierUseQueue) {
|
||||
assert(cg1r->do_traversal(), "Or we shouldn't have gotten here.");
|
||||
cg1r->set_pya_cancel();
|
||||
}
|
||||
if (_cg1r->use_cache()) {
|
||||
_cg1r->clear_and_record_card_counts();
|
||||
_cg1r->clear_hot_cache();
|
||||
}
|
||||
// Apply the appropriate closure to all remaining log entries.
|
||||
_g1->iterate_dirty_card_closure(false, worker_i);
|
||||
// Now there should be no dirty cards.
|
||||
if (G1RSLogCheckCardTable) {
|
||||
CountNonCleanMemRegionClosure cl(_g1);
|
||||
_ct_bs->mod_card_iterate(&cl);
|
||||
// XXX This isn't true any more: keeping cards of young regions
|
||||
// marked dirty broke it. Need some reasonable fix.
|
||||
guarantee(cl.n() == 0, "Card table should be clean.");
|
||||
}
|
||||
|
||||
_g1p->record_update_rs_time(worker_i, (os::elapsedTime() - start) * 1000.0);
|
||||
}
|
||||
|
||||
@ -486,11 +456,6 @@ HRInto_G1RemSet::scanNewRefsRS(OopsInHeapRegionClosure* oc,
|
||||
* 1000.0);
|
||||
}
|
||||
|
||||
void HRInto_G1RemSet::set_par_traversal(bool b) {
|
||||
_par_traversal_in_progress = b;
|
||||
HeapRegionRemSet::set_par_traversal(b);
|
||||
}
|
||||
|
||||
void HRInto_G1RemSet::cleanupHRRS() {
|
||||
HeapRegionRemSet::cleanup();
|
||||
}
|
||||
@ -527,7 +492,7 @@ HRInto_G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
|
||||
updateRS(worker_i);
|
||||
scanNewRefsRS(oc, worker_i);
|
||||
} else {
|
||||
_g1p->record_update_rs_start_time(worker_i, os::elapsedTime());
|
||||
_g1p->record_update_rs_start_time(worker_i, os::elapsedTime() * 1000.0);
|
||||
_g1p->record_update_rs_processed_buffers(worker_i, 0.0);
|
||||
_g1p->record_update_rs_time(worker_i, 0.0);
|
||||
_g1p->record_scan_new_refs_time(worker_i, 0.0);
|
||||
@ -535,7 +500,7 @@ HRInto_G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc,
|
||||
if (G1ParallelRSetScanningEnabled || (worker_i == 0)) {
|
||||
scanRS(oc, worker_i);
|
||||
} else {
|
||||
_g1p->record_scan_rs_start_time(worker_i, os::elapsedTime());
|
||||
_g1p->record_scan_rs_start_time(worker_i, os::elapsedTime() * 1000.0);
|
||||
_g1p->record_scan_rs_time(worker_i, 0.0);
|
||||
}
|
||||
} else {
|
||||
@ -562,11 +527,6 @@ prepare_for_oops_into_collection_set_do() {
|
||||
if (ParallelGCThreads > 0) {
|
||||
set_par_traversal(true);
|
||||
_seq_task->set_par_threads((int)n_workers());
|
||||
if (cg1r->do_traversal()) {
|
||||
updateRS(0);
|
||||
// Have to do this again after updaters
|
||||
cleanupHRRS();
|
||||
}
|
||||
}
|
||||
guarantee( _cards_scanned == NULL, "invariant" );
|
||||
_cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers());
|
||||
@ -647,11 +607,8 @@ void HRInto_G1RemSet::cleanup_after_oops_into_collection_set_do() {
|
||||
_g1->collection_set_iterate(&iterClosure);
|
||||
// Set all cards back to clean.
|
||||
_g1->cleanUpCardTable();
|
||||
|
||||
if (ParallelGCThreads > 0) {
|
||||
ConcurrentG1Refine* cg1r = _g1->concurrent_g1_refine();
|
||||
if (cg1r->do_traversal()) {
|
||||
cg1r->cg1rThread()->set_do_traversal(false);
|
||||
}
|
||||
set_par_traversal(false);
|
||||
}
|
||||
|
||||
@ -721,139 +678,8 @@ void HRInto_G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm,
|
||||
}
|
||||
|
||||
|
||||
class ConcRefineRegionClosure: public HeapRegionClosure {
|
||||
G1CollectedHeap* _g1h;
|
||||
CardTableModRefBS* _ctbs;
|
||||
ConcurrentGCThread* _cgc_thrd;
|
||||
ConcurrentG1Refine* _cg1r;
|
||||
unsigned _cards_processed;
|
||||
UpdateRSOopClosure _update_rs_oop_cl;
|
||||
public:
|
||||
ConcRefineRegionClosure(CardTableModRefBS* ctbs,
|
||||
ConcurrentG1Refine* cg1r,
|
||||
HRInto_G1RemSet* g1rs) :
|
||||
_ctbs(ctbs), _cg1r(cg1r), _cgc_thrd(cg1r->cg1rThread()),
|
||||
_update_rs_oop_cl(g1rs), _cards_processed(0),
|
||||
_g1h(G1CollectedHeap::heap())
|
||||
{}
|
||||
|
||||
bool doHeapRegion(HeapRegion* r) {
|
||||
if (!r->in_collection_set() &&
|
||||
!r->continuesHumongous() &&
|
||||
!r->is_young()) {
|
||||
_update_rs_oop_cl.set_from(r);
|
||||
UpdateRSObjectClosure update_rs_obj_cl(&_update_rs_oop_cl);
|
||||
|
||||
// For each run of dirty card in the region:
|
||||
// 1) Clear the cards.
|
||||
// 2) Process the range corresponding to the run, adding any
|
||||
// necessary RS entries.
|
||||
// 1 must precede 2, so that a concurrent modification redirties the
|
||||
// card. If a processing attempt does not succeed, because it runs
|
||||
// into an unparseable region, we will do binary search to find the
|
||||
// beginning of the next parseable region.
|
||||
HeapWord* startAddr = r->bottom();
|
||||
HeapWord* endAddr = r->used_region().end();
|
||||
HeapWord* lastAddr;
|
||||
HeapWord* nextAddr;
|
||||
|
||||
for (nextAddr = lastAddr = startAddr;
|
||||
nextAddr < endAddr;
|
||||
nextAddr = lastAddr) {
|
||||
MemRegion dirtyRegion;
|
||||
|
||||
// Get and clear dirty region from card table
|
||||
MemRegion next_mr(nextAddr, endAddr);
|
||||
dirtyRegion =
|
||||
_ctbs->dirty_card_range_after_reset(
|
||||
next_mr,
|
||||
true, CardTableModRefBS::clean_card_val());
|
||||
assert(dirtyRegion.start() >= nextAddr,
|
||||
"returned region inconsistent?");
|
||||
|
||||
if (!dirtyRegion.is_empty()) {
|
||||
HeapWord* stop_point =
|
||||
r->object_iterate_mem_careful(dirtyRegion,
|
||||
&update_rs_obj_cl);
|
||||
if (stop_point == NULL) {
|
||||
lastAddr = dirtyRegion.end();
|
||||
_cards_processed +=
|
||||
(int) (dirtyRegion.word_size() / CardTableModRefBS::card_size_in_words);
|
||||
} else {
|
||||
// We're going to skip one or more cards that we can't parse.
|
||||
HeapWord* next_parseable_card =
|
||||
r->next_block_start_careful(stop_point);
|
||||
// Round this up to a card boundary.
|
||||
next_parseable_card =
|
||||
_ctbs->addr_for(_ctbs->byte_after_const(next_parseable_card));
|
||||
// Now we invalidate the intervening cards so we'll see them
|
||||
// again.
|
||||
MemRegion remaining_dirty =
|
||||
MemRegion(stop_point, dirtyRegion.end());
|
||||
MemRegion skipped =
|
||||
MemRegion(stop_point, next_parseable_card);
|
||||
_ctbs->invalidate(skipped.intersection(remaining_dirty));
|
||||
|
||||
// Now start up again where we can parse.
|
||||
lastAddr = next_parseable_card;
|
||||
|
||||
// Count how many we did completely.
|
||||
_cards_processed +=
|
||||
(stop_point - dirtyRegion.start()) /
|
||||
CardTableModRefBS::card_size_in_words;
|
||||
}
|
||||
// Allow interruption at regular intervals.
|
||||
// (Might need to make them more regular, if we get big
|
||||
// dirty regions.)
|
||||
if (_cgc_thrd != NULL) {
|
||||
if (_cgc_thrd->should_yield()) {
|
||||
_cgc_thrd->yield();
|
||||
switch (_cg1r->get_pya()) {
|
||||
case PYA_continue:
|
||||
// This may have changed: re-read.
|
||||
endAddr = r->used_region().end();
|
||||
continue;
|
||||
case PYA_restart: case PYA_cancel:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// A good yield opportunity.
|
||||
if (_cgc_thrd != NULL) {
|
||||
if (_cgc_thrd->should_yield()) {
|
||||
_cgc_thrd->yield();
|
||||
switch (_cg1r->get_pya()) {
|
||||
case PYA_restart: case PYA_cancel:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned cards_processed() { return _cards_processed; }
|
||||
};
|
||||
|
||||
|
||||
void HRInto_G1RemSet::concurrentRefinementPass(ConcurrentG1Refine* cg1r) {
|
||||
ConcRefineRegionClosure cr_cl(ct_bs(), cg1r, this);
|
||||
_g1->heap_region_iterate(&cr_cl);
|
||||
_conc_refine_traversals++;
|
||||
_conc_refine_cards += cr_cl.cards_processed();
|
||||
}
|
||||
|
||||
static IntHistogram out_of_histo(50, 50);
|
||||
|
||||
|
||||
|
||||
void HRInto_G1RemSet::concurrentRefineOneCard(jbyte* card_ptr, int worker_i) {
|
||||
// If the card is no longer dirty, nothing to do.
|
||||
if (*card_ptr != CardTableModRefBS::dirty_card_val()) return;
|
||||
@ -983,10 +809,16 @@ public:
|
||||
HeapRegion* max_mem_sz_region() { return _max_mem_sz_region; }
|
||||
};
|
||||
|
||||
class PrintRSThreadVTimeClosure : public ThreadClosure {
|
||||
public:
|
||||
virtual void do_thread(Thread *t) {
|
||||
ConcurrentG1RefineThread* crt = (ConcurrentG1RefineThread*) t;
|
||||
gclog_or_tty->print(" %5.2f", crt->vtime_accum());
|
||||
}
|
||||
};
|
||||
|
||||
void HRInto_G1RemSet::print_summary_info() {
|
||||
G1CollectedHeap* g1 = G1CollectedHeap::heap();
|
||||
ConcurrentG1RefineThread* cg1r_thrd =
|
||||
g1->concurrent_g1_refine()->cg1rThread();
|
||||
|
||||
#if CARD_REPEAT_HISTO
|
||||
gclog_or_tty->print_cr("\nG1 card_repeat count histogram: ");
|
||||
@ -999,15 +831,13 @@ void HRInto_G1RemSet::print_summary_info() {
|
||||
gclog_or_tty->print_cr(" # of CS ptrs --> # of cards with that number.");
|
||||
out_of_histo.print_on(gclog_or_tty);
|
||||
}
|
||||
gclog_or_tty->print_cr("\n Concurrent RS processed %d cards in "
|
||||
"%5.2fs.",
|
||||
_conc_refine_cards, cg1r_thrd->vtime_accum());
|
||||
|
||||
gclog_or_tty->print_cr("\n Concurrent RS processed %d cards",
|
||||
_conc_refine_cards);
|
||||
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
|
||||
jint tot_processed_buffers =
|
||||
dcqs.processed_buffers_mut() + dcqs.processed_buffers_rs_thread();
|
||||
gclog_or_tty->print_cr(" Of %d completed buffers:", tot_processed_buffers);
|
||||
gclog_or_tty->print_cr(" %8d (%5.1f%%) by conc RS thread.",
|
||||
gclog_or_tty->print_cr(" %8d (%5.1f%%) by conc RS threads.",
|
||||
dcqs.processed_buffers_rs_thread(),
|
||||
100.0*(float)dcqs.processed_buffers_rs_thread()/
|
||||
(float)tot_processed_buffers);
|
||||
@ -1015,15 +845,12 @@ void HRInto_G1RemSet::print_summary_info() {
|
||||
dcqs.processed_buffers_mut(),
|
||||
100.0*(float)dcqs.processed_buffers_mut()/
|
||||
(float)tot_processed_buffers);
|
||||
gclog_or_tty->print_cr(" Did %d concurrent refinement traversals.",
|
||||
_conc_refine_traversals);
|
||||
if (!G1RSBarrierUseQueue) {
|
||||
gclog_or_tty->print_cr(" Scanned %8.2f cards/traversal.",
|
||||
_conc_refine_traversals > 0 ?
|
||||
(float)_conc_refine_cards/(float)_conc_refine_traversals :
|
||||
0);
|
||||
}
|
||||
gclog_or_tty->print_cr(" Conc RS threads times(s)");
|
||||
PrintRSThreadVTimeClosure p;
|
||||
gclog_or_tty->print(" ");
|
||||
g1->concurrent_g1_refine()->threads_do(&p);
|
||||
gclog_or_tty->print_cr("");
|
||||
|
||||
if (G1UseHRIntoRS) {
|
||||
HRRSStatsIter blk;
|
||||
g1->heap_region_iterate(&blk);
|
||||
|
@ -33,15 +33,12 @@ class ConcurrentG1Refine;
|
||||
class G1RemSet: public CHeapObj {
|
||||
protected:
|
||||
G1CollectedHeap* _g1;
|
||||
|
||||
unsigned _conc_refine_traversals;
|
||||
unsigned _conc_refine_cards;
|
||||
|
||||
size_t n_workers();
|
||||
|
||||
public:
|
||||
G1RemSet(G1CollectedHeap* g1) :
|
||||
_g1(g1), _conc_refine_traversals(0), _conc_refine_cards(0)
|
||||
_g1(g1), _conc_refine_cards(0)
|
||||
{}
|
||||
|
||||
// Invoke "blk->do_oop" on all pointers into the CS in object in regions
|
||||
@ -81,19 +78,11 @@ public:
|
||||
virtual void scrub_par(BitMap* region_bm, BitMap* card_bm,
|
||||
int worker_num, int claim_val) = 0;
|
||||
|
||||
// Do any "refinement" activity that might be appropriate to the given
|
||||
// G1RemSet. If "refinement" has iterateive "passes", do one pass.
|
||||
// If "t" is non-NULL, it is the thread performing the refinement.
|
||||
// Default implementation does nothing.
|
||||
virtual void concurrentRefinementPass(ConcurrentG1Refine* cg1r) {}
|
||||
|
||||
// Refine the card corresponding to "card_ptr". If "sts" is non-NULL,
|
||||
// join and leave around parts that must be atomic wrt GC. (NULL means
|
||||
// being done at a safepoint.)
|
||||
virtual void concurrentRefineOneCard(jbyte* card_ptr, int worker_i) {}
|
||||
|
||||
unsigned conc_refine_cards() { return _conc_refine_cards; }
|
||||
|
||||
// Print any relevant summary info.
|
||||
virtual void print_summary_info() {}
|
||||
|
||||
@ -153,7 +142,7 @@ protected:
|
||||
// progress. If so, then cards added to remembered sets should also have
|
||||
// their references into the collection summarized in "_new_refs".
|
||||
bool _par_traversal_in_progress;
|
||||
void set_par_traversal(bool b);
|
||||
void set_par_traversal(bool b) { _par_traversal_in_progress = b; }
|
||||
GrowableArray<oop*>** _new_refs;
|
||||
void new_refs_iterate(OopClosure* cl);
|
||||
|
||||
@ -194,7 +183,6 @@ public:
|
||||
void scrub_par(BitMap* region_bm, BitMap* card_bm,
|
||||
int worker_num, int claim_val);
|
||||
|
||||
virtual void concurrentRefinementPass(ConcurrentG1Refine* t);
|
||||
virtual void concurrentRefineOneCard(jbyte* card_ptr, int worker_i);
|
||||
|
||||
virtual void print_summary_info();
|
||||
|
@ -147,9 +147,6 @@
|
||||
develop(bool, G1PrintCTFilterStats, false, \
|
||||
"If true, print stats on RS filtering effectiveness") \
|
||||
\
|
||||
develop(bool, G1RSBarrierUseQueue, true, \
|
||||
"If true, use queueing RS barrier") \
|
||||
\
|
||||
develop(bool, G1DeferredRSUpdate, true, \
|
||||
"If true, use deferred RS updates") \
|
||||
\
|
||||
@ -253,6 +250,10 @@
|
||||
\
|
||||
experimental(bool, G1ParallelRSetScanningEnabled, false, \
|
||||
"Enables the parallelization of remembered set scanning " \
|
||||
"during evacuation pauses")
|
||||
"during evacuation pauses") \
|
||||
\
|
||||
product(uintx, G1ParallelRSetThreads, 0, \
|
||||
"If non-0 is the number of parallel rem set update threads, " \
|
||||
"otherwise the value is determined ergonomically.")
|
||||
|
||||
G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG)
|
||||
|
@ -351,6 +351,7 @@ HeapRegion(G1BlockOffsetSharedArray* sharedOffsetArray,
|
||||
_claimed(InitialClaimValue), _evacuation_failed(false),
|
||||
_prev_marked_bytes(0), _next_marked_bytes(0), _sort_index(-1),
|
||||
_young_type(NotYoung), _next_young_region(NULL),
|
||||
_next_dirty_cards_region(NULL),
|
||||
_young_index_in_cset(-1), _surv_rate_group(NULL), _age_index(-1),
|
||||
_rem_set(NULL), _zfs(NotZeroFilled)
|
||||
{
|
||||
|
@ -227,6 +227,9 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
||||
// next region in the young "generation" region set
|
||||
HeapRegion* _next_young_region;
|
||||
|
||||
// Next region whose cards need cleaning
|
||||
HeapRegion* _next_dirty_cards_region;
|
||||
|
||||
// For parallel heapRegion traversal.
|
||||
jint _claimed;
|
||||
|
||||
@ -468,6 +471,11 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
||||
_next_young_region = hr;
|
||||
}
|
||||
|
||||
HeapRegion* get_next_dirty_cards_region() const { return _next_dirty_cards_region; }
|
||||
HeapRegion** next_dirty_cards_region_addr() { return &_next_dirty_cards_region; }
|
||||
void set_next_dirty_cards_region(HeapRegion* hr) { _next_dirty_cards_region = hr; }
|
||||
bool is_on_dirty_cards_region_list() const { return get_next_dirty_cards_region() != NULL; }
|
||||
|
||||
// Allows logical separation between objects allocated before and after.
|
||||
void save_marks();
|
||||
|
||||
|
@ -1052,18 +1052,11 @@ bool OtherRegionsTable::contains_reference_locked(oop* from) const {
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool HeapRegionRemSet::_par_traversal = false;
|
||||
|
||||
void HeapRegionRemSet::set_par_traversal(bool b) {
|
||||
assert(_par_traversal != b, "Proper alternation...");
|
||||
_par_traversal = b;
|
||||
}
|
||||
|
||||
// Determines how many threads can add records to an rset in parallel.
|
||||
// This can be done by either mutator threads together with the
|
||||
// concurrent refinement threads or GC threads.
|
||||
int HeapRegionRemSet::num_par_rem_sets() {
|
||||
// We always have at least two, so that a mutator thread can claim an
|
||||
// id and add to a rem set.
|
||||
return (int) MAX2(ParallelGCThreads, (size_t)2);
|
||||
return (int)MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads);
|
||||
}
|
||||
|
||||
HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa,
|
||||
|
@ -177,8 +177,6 @@ private:
|
||||
G1BlockOffsetSharedArray* _bosa;
|
||||
G1BlockOffsetSharedArray* bosa() const { return _bosa; }
|
||||
|
||||
static bool _par_traversal;
|
||||
|
||||
OtherRegionsTable _other_regions;
|
||||
|
||||
// One set bit for every region that has an entry for this one.
|
||||
@ -211,8 +209,6 @@ public:
|
||||
HeapRegion* hr);
|
||||
|
||||
static int num_par_rem_sets();
|
||||
static bool par_traversal() { return _par_traversal; }
|
||||
static void set_par_traversal(bool b);
|
||||
|
||||
HeapRegion* hr() const {
|
||||
return _other_regions.hr();
|
||||
|
@ -172,7 +172,7 @@ void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index, bool ignore_
|
||||
_n_completed_buffers++;
|
||||
|
||||
if (!_process_completed &&
|
||||
_n_completed_buffers == _process_completed_threshold) {
|
||||
_n_completed_buffers >= _process_completed_threshold) {
|
||||
_process_completed = true;
|
||||
if (_notify_when_complete)
|
||||
_cbl_mon->notify_all();
|
||||
|
@ -49,6 +49,8 @@ concurrentG1Refine.cpp space.inline.hpp
|
||||
|
||||
concurrentG1Refine.hpp globalDefinitions.hpp
|
||||
concurrentG1Refine.hpp allocation.hpp
|
||||
concurrentG1Refine.hpp thread.hpp
|
||||
|
||||
|
||||
concurrentG1RefineThread.cpp concurrentG1Refine.hpp
|
||||
concurrentG1RefineThread.cpp concurrentG1RefineThread.hpp
|
||||
@ -280,6 +282,7 @@ heapRegionRemSet.hpp sparsePRT.hpp
|
||||
|
||||
heapRegionRemSet.cpp allocation.hpp
|
||||
heapRegionRemSet.cpp bitMap.inline.hpp
|
||||
heapRegionRemSet.cpp concurrentG1Refine.hpp
|
||||
heapRegionRemSet.cpp g1BlockOffsetTable.inline.hpp
|
||||
heapRegionRemSet.cpp g1CollectedHeap.inline.hpp
|
||||
heapRegionRemSet.cpp heapRegionRemSet.hpp
|
||||
|
@ -27,13 +27,12 @@
|
||||
# include "incls/_precompiled.incl"
|
||||
# include "incls/_concurrentGCThread.cpp.incl"
|
||||
|
||||
bool ConcurrentGCThread::_should_terminate = false;
|
||||
bool ConcurrentGCThread::_has_terminated = false;
|
||||
int ConcurrentGCThread::_CGC_flag = CGC_nil;
|
||||
|
||||
SuspendibleThreadSet ConcurrentGCThread::_sts;
|
||||
|
||||
ConcurrentGCThread::ConcurrentGCThread() {
|
||||
ConcurrentGCThread::ConcurrentGCThread() :
|
||||
_should_terminate(false), _has_terminated(false) {
|
||||
_sts.initialize();
|
||||
};
|
||||
|
||||
|
@ -72,8 +72,8 @@ class ConcurrentGCThread: public NamedThread {
|
||||
friend class VMStructs;
|
||||
|
||||
protected:
|
||||
static bool _should_terminate;
|
||||
static bool _has_terminated;
|
||||
bool _should_terminate;
|
||||
bool _has_terminated;
|
||||
|
||||
enum CGC_flag_type {
|
||||
CGC_nil = 0x0,
|
||||
|
@ -33,12 +33,8 @@ CardTableRS::CardTableRS(MemRegion whole_heap,
|
||||
{
|
||||
#ifndef SERIALGC
|
||||
if (UseG1GC) {
|
||||
if (G1RSBarrierUseQueue) {
|
||||
_ct_bs = new G1SATBCardTableLoggingModRefBS(whole_heap,
|
||||
max_covered_regions);
|
||||
} else {
|
||||
_ct_bs = new G1SATBCardTableModRefBS(whole_heap, max_covered_regions);
|
||||
}
|
||||
} else {
|
||||
_ct_bs = new CardTableModRefBSForCTRS(whole_heap, max_covered_regions);
|
||||
}
|
||||
|
@ -1181,7 +1181,28 @@ int constantPoolOopDesc::copy_cpool_bytes(int cpool_size,
|
||||
unsigned int hash;
|
||||
char *str = string_at_noresolve(idx);
|
||||
symbolOop sym = SymbolTable::lookup_only(str, (int) strlen(str), hash);
|
||||
idx1 = tbl->symbol_to_value(sym);
|
||||
if (sym == NULL) {
|
||||
// sym can be NULL if string refers to incorrectly encoded JVM_CONSTANT_Utf8
|
||||
// this can happen with JVM TI; see CR 6839599 for more details
|
||||
oop string = *(obj_at_addr(idx));
|
||||
assert(java_lang_String::is_instance(string),"Not a String");
|
||||
DBG(printf("Error #%03hd tag=%03hd\n", idx, tag));
|
||||
idx1 = 0;
|
||||
for (int j = 0; j < tbl->table_size() && idx1 == 0; j++) {
|
||||
for (SymbolHashMapEntry* cur = tbl->bucket(j); cur != NULL; cur = cur->next()) {
|
||||
int length;
|
||||
sym = cur->symbol();
|
||||
jchar* chars = sym->as_unicode(length);
|
||||
if (java_lang_String::equals(string, chars, length)) {
|
||||
idx1 = cur->value();
|
||||
DBG(printf("Index found: %d\n",idx1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
idx1 = tbl->symbol_to_value(sym);
|
||||
}
|
||||
assert(idx1 != 0, "Have not found a hashtable entry");
|
||||
Bytes::put_Java_u2((address) (bytes+1), idx1);
|
||||
DBG(printf("JVM_CONSTANT_String: idx=#%03hd, %s", idx1, str));
|
||||
|
@ -104,6 +104,10 @@ macro(ConvL2I)
|
||||
macro(CosD)
|
||||
macro(CountedLoop)
|
||||
macro(CountedLoopEnd)
|
||||
macro(CountLeadingZerosI)
|
||||
macro(CountLeadingZerosL)
|
||||
macro(CountTrailingZerosI)
|
||||
macro(CountTrailingZerosL)
|
||||
macro(CreateEx)
|
||||
macro(DecodeN)
|
||||
macro(DivD)
|
||||
|
@ -1255,3 +1255,93 @@ const Type *MoveD2LNode::Value( PhaseTransform *phase ) const {
|
||||
v.set_jdouble(td->getd());
|
||||
return TypeLong::make( v.get_jlong() );
|
||||
}
|
||||
|
||||
//------------------------------Value------------------------------------------
|
||||
const Type* CountLeadingZerosINode::Value(PhaseTransform* phase) const {
|
||||
const Type* t = phase->type(in(1));
|
||||
if (t == Type::TOP) return Type::TOP;
|
||||
const TypeInt* ti = t->isa_int();
|
||||
if (ti && ti->is_con()) {
|
||||
jint i = ti->get_con();
|
||||
// HD, Figure 5-6
|
||||
if (i == 0)
|
||||
return TypeInt::make(BitsPerInt);
|
||||
int n = 1;
|
||||
unsigned int x = i;
|
||||
if (x >> 16 == 0) { n += 16; x <<= 16; }
|
||||
if (x >> 24 == 0) { n += 8; x <<= 8; }
|
||||
if (x >> 28 == 0) { n += 4; x <<= 4; }
|
||||
if (x >> 30 == 0) { n += 2; x <<= 2; }
|
||||
n -= x >> 31;
|
||||
return TypeInt::make(n);
|
||||
}
|
||||
return TypeInt::INT;
|
||||
}
|
||||
|
||||
//------------------------------Value------------------------------------------
|
||||
const Type* CountLeadingZerosLNode::Value(PhaseTransform* phase) const {
|
||||
const Type* t = phase->type(in(1));
|
||||
if (t == Type::TOP) return Type::TOP;
|
||||
const TypeLong* tl = t->isa_long();
|
||||
if (tl && tl->is_con()) {
|
||||
jlong l = tl->get_con();
|
||||
// HD, Figure 5-6
|
||||
if (l == 0)
|
||||
return TypeInt::make(BitsPerLong);
|
||||
int n = 1;
|
||||
unsigned int x = (((julong) l) >> 32);
|
||||
if (x == 0) { n += 32; x = (int) l; }
|
||||
if (x >> 16 == 0) { n += 16; x <<= 16; }
|
||||
if (x >> 24 == 0) { n += 8; x <<= 8; }
|
||||
if (x >> 28 == 0) { n += 4; x <<= 4; }
|
||||
if (x >> 30 == 0) { n += 2; x <<= 2; }
|
||||
n -= x >> 31;
|
||||
return TypeInt::make(n);
|
||||
}
|
||||
return TypeInt::INT;
|
||||
}
|
||||
|
||||
//------------------------------Value------------------------------------------
|
||||
const Type* CountTrailingZerosINode::Value(PhaseTransform* phase) const {
|
||||
const Type* t = phase->type(in(1));
|
||||
if (t == Type::TOP) return Type::TOP;
|
||||
const TypeInt* ti = t->isa_int();
|
||||
if (ti && ti->is_con()) {
|
||||
jint i = ti->get_con();
|
||||
// HD, Figure 5-14
|
||||
int y;
|
||||
if (i == 0)
|
||||
return TypeInt::make(BitsPerInt);
|
||||
int n = 31;
|
||||
y = i << 16; if (y != 0) { n = n - 16; i = y; }
|
||||
y = i << 8; if (y != 0) { n = n - 8; i = y; }
|
||||
y = i << 4; if (y != 0) { n = n - 4; i = y; }
|
||||
y = i << 2; if (y != 0) { n = n - 2; i = y; }
|
||||
y = i << 1; if (y != 0) { n = n - 1; }
|
||||
return TypeInt::make(n);
|
||||
}
|
||||
return TypeInt::INT;
|
||||
}
|
||||
|
||||
//------------------------------Value------------------------------------------
|
||||
const Type* CountTrailingZerosLNode::Value(PhaseTransform* phase) const {
|
||||
const Type* t = phase->type(in(1));
|
||||
if (t == Type::TOP) return Type::TOP;
|
||||
const TypeLong* tl = t->isa_long();
|
||||
if (tl && tl->is_con()) {
|
||||
jlong l = tl->get_con();
|
||||
// HD, Figure 5-14
|
||||
int x, y;
|
||||
if (l == 0)
|
||||
return TypeInt::make(BitsPerLong);
|
||||
int n = 63;
|
||||
y = (int) l; if (y != 0) { n = n - 32; x = y; } else x = (((julong) l) >> 32);
|
||||
y = x << 16; if (y != 0) { n = n - 16; x = y; }
|
||||
y = x << 8; if (y != 0) { n = n - 8; x = y; }
|
||||
y = x << 4; if (y != 0) { n = n - 4; x = y; }
|
||||
y = x << 2; if (y != 0) { n = n - 2; x = y; }
|
||||
y = x << 1; if (y != 0) { n = n - 1; }
|
||||
return TypeInt::make(n);
|
||||
}
|
||||
return TypeInt::INT;
|
||||
}
|
||||
|
@ -636,22 +636,62 @@ class MoveD2LNode : public Node {
|
||||
virtual const Type* Value( PhaseTransform *phase ) const;
|
||||
};
|
||||
|
||||
//---------- PopCountINode -----------------------------------------------------
|
||||
// Population count (bit count) of an integer.
|
||||
class PopCountINode : public Node {
|
||||
//---------- CountBitsNode -----------------------------------------------------
|
||||
class CountBitsNode : public Node {
|
||||
public:
|
||||
PopCountINode(Node* in1) : Node(0, in1) {}
|
||||
virtual int Opcode() const;
|
||||
CountBitsNode(Node* in1) : Node(0, in1) {}
|
||||
const Type* bottom_type() const { return TypeInt::INT; }
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
};
|
||||
|
||||
//---------- CountLeadingZerosINode --------------------------------------------
|
||||
// Count leading zeros (0-bit count starting from MSB) of an integer.
|
||||
class CountLeadingZerosINode : public CountBitsNode {
|
||||
public:
|
||||
CountLeadingZerosINode(Node* in1) : CountBitsNode(in1) {}
|
||||
virtual int Opcode() const;
|
||||
virtual const Type* Value(PhaseTransform* phase) const;
|
||||
};
|
||||
|
||||
//---------- CountLeadingZerosLNode --------------------------------------------
|
||||
// Count leading zeros (0-bit count starting from MSB) of a long.
|
||||
class CountLeadingZerosLNode : public CountBitsNode {
|
||||
public:
|
||||
CountLeadingZerosLNode(Node* in1) : CountBitsNode(in1) {}
|
||||
virtual int Opcode() const;
|
||||
virtual const Type* Value(PhaseTransform* phase) const;
|
||||
};
|
||||
|
||||
//---------- CountTrailingZerosINode -------------------------------------------
|
||||
// Count trailing zeros (0-bit count starting from LSB) of an integer.
|
||||
class CountTrailingZerosINode : public CountBitsNode {
|
||||
public:
|
||||
CountTrailingZerosINode(Node* in1) : CountBitsNode(in1) {}
|
||||
virtual int Opcode() const;
|
||||
virtual const Type* Value(PhaseTransform* phase) const;
|
||||
};
|
||||
|
||||
//---------- CountTrailingZerosLNode -------------------------------------------
|
||||
// Count trailing zeros (0-bit count starting from LSB) of a long.
|
||||
class CountTrailingZerosLNode : public CountBitsNode {
|
||||
public:
|
||||
CountTrailingZerosLNode(Node* in1) : CountBitsNode(in1) {}
|
||||
virtual int Opcode() const;
|
||||
virtual const Type* Value(PhaseTransform* phase) const;
|
||||
};
|
||||
|
||||
//---------- PopCountINode -----------------------------------------------------
|
||||
// Population count (bit count) of an integer.
|
||||
class PopCountINode : public CountBitsNode {
|
||||
public:
|
||||
PopCountINode(Node* in1) : CountBitsNode(in1) {}
|
||||
virtual int Opcode() const;
|
||||
};
|
||||
|
||||
//---------- PopCountLNode -----------------------------------------------------
|
||||
// Population count (bit count) of a long.
|
||||
class PopCountLNode : public Node {
|
||||
class PopCountLNode : public CountBitsNode {
|
||||
public:
|
||||
PopCountLNode(Node* in1) : Node(0, in1) {}
|
||||
PopCountLNode(Node* in1) : CountBitsNode(in1) {}
|
||||
virtual int Opcode() const;
|
||||
const Type* bottom_type() const { return TypeInt::INT; }
|
||||
virtual uint ideal_reg() const { return Op_RegI; }
|
||||
};
|
||||
|
@ -47,7 +47,7 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
|
||||
CallGenerator* cg;
|
||||
|
||||
// Dtrace currently doesn't work unless all calls are vanilla
|
||||
if (DTraceMethodProbes) {
|
||||
if (env()->dtrace_method_probes()) {
|
||||
allow_inline = false;
|
||||
}
|
||||
|
||||
|
@ -905,15 +905,22 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
|
||||
// see if it is unescaped.
|
||||
if (es != PointsToNode::NoEscape || !ptn->_scalar_replaceable)
|
||||
continue;
|
||||
if (alloc->is_Allocate()) {
|
||||
// Set the scalar_replaceable flag before the next check.
|
||||
alloc->as_Allocate()->_is_scalar_replaceable = true;
|
||||
}
|
||||
// find CheckCastPP of call return value
|
||||
|
||||
// Find CheckCastPP for the allocate or for the return value of a call
|
||||
n = alloc->result_cast();
|
||||
if (n == NULL || // No uses accept Initialize or
|
||||
!n->is_CheckCastPP()) // not unique CheckCastPP.
|
||||
if (n == NULL) { // No uses except Initialize node
|
||||
if (alloc->is_Allocate()) {
|
||||
// Set the scalar_replaceable flag for allocation
|
||||
// so it could be eliminated if it has no uses.
|
||||
alloc->as_Allocate()->_is_scalar_replaceable = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!n->is_CheckCastPP()) { // not unique CheckCastPP.
|
||||
assert(!alloc->is_Allocate(), "allocation should have unique type");
|
||||
continue;
|
||||
}
|
||||
|
||||
// The inline code for Object.clone() casts the allocation result to
|
||||
// java.lang.Object and then to the actual type of the allocated
|
||||
// object. Detect this case and use the second cast.
|
||||
@ -934,9 +941,17 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
|
||||
if (cast2 != NULL) {
|
||||
n = cast2;
|
||||
} else {
|
||||
// Non-scalar replaceable if the allocation type is unknown statically
|
||||
// (reflection allocation), the object can't be restored during
|
||||
// deoptimization without precise type.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (alloc->is_Allocate()) {
|
||||
// Set the scalar_replaceable flag for allocation
|
||||
// so it could be eliminated.
|
||||
alloc->as_Allocate()->_is_scalar_replaceable = true;
|
||||
}
|
||||
set_escape_state(n->_idx, es);
|
||||
// in order for an object to be scalar-replaceable, it must be:
|
||||
// - a direct allocation (not a call returning an object)
|
||||
|
@ -617,6 +617,9 @@ Block* PhaseCFG::insert_anti_dependences(Block* LCA, Node* load, bool verify) {
|
||||
assert(!LCA_orig->dominates(pred_block) ||
|
||||
early->dominates(pred_block), "early is high enough");
|
||||
must_raise_LCA = true;
|
||||
} else {
|
||||
// anti-dependent upon PHI pinned below 'early', no edge needed
|
||||
LCA = early; // but can not schedule below 'early'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -459,7 +459,7 @@ Bytecodes::Code GraphKit::java_bc() const {
|
||||
void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) {
|
||||
bool must_throw = true;
|
||||
|
||||
if (JvmtiExport::can_post_exceptions()) {
|
||||
if (env()->jvmti_can_post_exceptions()) {
|
||||
// Do not try anything fancy if we're notifying the VM on every throw.
|
||||
// Cf. case Bytecodes::_athrow in parse2.cpp.
|
||||
uncommon_trap(reason, Deoptimization::Action_none,
|
||||
@ -769,7 +769,7 @@ void GraphKit::add_safepoint_edges(SafePointNode* call, bool must_throw) {
|
||||
}
|
||||
}
|
||||
|
||||
if (JvmtiExport::can_examine_or_deopt_anywhere()) {
|
||||
if (env()->jvmti_can_examine_or_deopt_anywhere()) {
|
||||
// At any safepoint, this method can get breakpointed, which would
|
||||
// then require an immediate deoptimization.
|
||||
full_info = true;
|
||||
|
@ -222,6 +222,8 @@ class LibraryCallKit : public GraphKit {
|
||||
bool inline_unsafe_CAS(BasicType type);
|
||||
bool inline_unsafe_ordered_store(BasicType type);
|
||||
bool inline_fp_conversions(vmIntrinsics::ID id);
|
||||
bool inline_numberOfLeadingZeros(vmIntrinsics::ID id);
|
||||
bool inline_numberOfTrailingZeros(vmIntrinsics::ID id);
|
||||
bool inline_bitCount(vmIntrinsics::ID id);
|
||||
bool inline_reverseBytes(vmIntrinsics::ID id);
|
||||
};
|
||||
@ -630,6 +632,14 @@ bool LibraryCallKit::try_to_inline() {
|
||||
case vmIntrinsics::_longBitsToDouble:
|
||||
return inline_fp_conversions(intrinsic_id());
|
||||
|
||||
case vmIntrinsics::_numberOfLeadingZeros_i:
|
||||
case vmIntrinsics::_numberOfLeadingZeros_l:
|
||||
return inline_numberOfLeadingZeros(intrinsic_id());
|
||||
|
||||
case vmIntrinsics::_numberOfTrailingZeros_i:
|
||||
case vmIntrinsics::_numberOfTrailingZeros_l:
|
||||
return inline_numberOfTrailingZeros(intrinsic_id());
|
||||
|
||||
case vmIntrinsics::_bitCount_i:
|
||||
case vmIntrinsics::_bitCount_l:
|
||||
return inline_bitCount(intrinsic_id());
|
||||
@ -1844,6 +1854,48 @@ inline Node* LibraryCallKit::make_unsafe_address(Node* base, Node* offset) {
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------inline_numberOfLeadingZeros_int/long-----------------------
|
||||
// inline int Integer.numberOfLeadingZeros(int)
|
||||
// inline int Long.numberOfLeadingZeros(long)
|
||||
bool LibraryCallKit::inline_numberOfLeadingZeros(vmIntrinsics::ID id) {
|
||||
assert(id == vmIntrinsics::_numberOfLeadingZeros_i || id == vmIntrinsics::_numberOfLeadingZeros_l, "not numberOfLeadingZeros");
|
||||
if (id == vmIntrinsics::_numberOfLeadingZeros_i && !Matcher::match_rule_supported(Op_CountLeadingZerosI)) return false;
|
||||
if (id == vmIntrinsics::_numberOfLeadingZeros_l && !Matcher::match_rule_supported(Op_CountLeadingZerosL)) return false;
|
||||
_sp += arg_size(); // restore stack pointer
|
||||
switch (id) {
|
||||
case vmIntrinsics::_numberOfLeadingZeros_i:
|
||||
push(_gvn.transform(new (C, 2) CountLeadingZerosINode(pop())));
|
||||
break;
|
||||
case vmIntrinsics::_numberOfLeadingZeros_l:
|
||||
push(_gvn.transform(new (C, 2) CountLeadingZerosLNode(pop_pair())));
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------inline_numberOfTrailingZeros_int/long----------------------
|
||||
// inline int Integer.numberOfTrailingZeros(int)
|
||||
// inline int Long.numberOfTrailingZeros(long)
|
||||
bool LibraryCallKit::inline_numberOfTrailingZeros(vmIntrinsics::ID id) {
|
||||
assert(id == vmIntrinsics::_numberOfTrailingZeros_i || id == vmIntrinsics::_numberOfTrailingZeros_l, "not numberOfTrailingZeros");
|
||||
if (id == vmIntrinsics::_numberOfTrailingZeros_i && !Matcher::match_rule_supported(Op_CountTrailingZerosI)) return false;
|
||||
if (id == vmIntrinsics::_numberOfTrailingZeros_l && !Matcher::match_rule_supported(Op_CountTrailingZerosL)) return false;
|
||||
_sp += arg_size(); // restore stack pointer
|
||||
switch (id) {
|
||||
case vmIntrinsics::_numberOfTrailingZeros_i:
|
||||
push(_gvn.transform(new (C, 2) CountTrailingZerosINode(pop())));
|
||||
break;
|
||||
case vmIntrinsics::_numberOfTrailingZeros_l:
|
||||
push(_gvn.transform(new (C, 2) CountTrailingZerosLNode(pop_pair())));
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------inline_bitCount_int/long-----------------------
|
||||
// inline int Integer.bitCount(int)
|
||||
// inline int Long.bitCount(long)
|
||||
@ -2541,7 +2593,8 @@ bool LibraryCallKit::inline_native_isInterrupted() {
|
||||
Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset()));
|
||||
Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS);
|
||||
p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::interrupted_offset()));
|
||||
Node* int_bit = make_load(NULL, p, TypeInt::BOOL, T_INT);
|
||||
// Set the control input on the field _interrupted read to prevent it floating up.
|
||||
Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT);
|
||||
Node* cmp_bit = _gvn.transform( new (C, 3) CmpINode(int_bit, intcon(0)) );
|
||||
Node* bol_bit = _gvn.transform( new (C, 2) BoolNode(cmp_bit, BoolTest::ne) );
|
||||
|
||||
|
@ -1630,6 +1630,10 @@ bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_
|
||||
// Before attempting fancy unrolling, RCE or alignment, see if we want
|
||||
// to completely unroll this loop or do loop unswitching.
|
||||
if( cl->is_normal_loop() ) {
|
||||
if (should_unswitch) {
|
||||
phase->do_unswitching(this, old_new);
|
||||
return true;
|
||||
}
|
||||
bool should_maximally_unroll = policy_maximally_unroll(phase);
|
||||
if( should_maximally_unroll ) {
|
||||
// Here we did some unrolling and peeling. Eventually we will
|
||||
@ -1637,10 +1641,6 @@ bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_
|
||||
phase->do_maximally_unroll(this,old_new);
|
||||
return true;
|
||||
}
|
||||
if (should_unswitch) {
|
||||
phase->do_unswitching(this, old_new);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -988,7 +988,7 @@ void PhaseMacroExpand::expand_allocate_common(
|
||||
initial_slow_test = BoolNode::make_predicate(initial_slow_test, &_igvn);
|
||||
}
|
||||
|
||||
if (DTraceAllocProbes ||
|
||||
if (C->env()->dtrace_alloc_probes() ||
|
||||
!UseTLAB && (!Universe::heap()->supports_inline_contig_alloc() ||
|
||||
(UseConcMarkSweepGC && CMSIncrementalMode))) {
|
||||
// Force slow-path allocation
|
||||
@ -1150,7 +1150,7 @@ void PhaseMacroExpand::expand_allocate_common(
|
||||
fast_oop_ctrl, fast_oop_rawmem, fast_oop,
|
||||
klass_node, length, size_in_bytes);
|
||||
|
||||
if (ExtendedDTraceProbes) {
|
||||
if (C->env()->dtrace_extended_probes()) {
|
||||
// Slow-path call
|
||||
int size = TypeFunc::Parms + 2;
|
||||
CallLeafNode *call = new (C, size) CallLeafNode(OptoRuntime::dtrace_object_alloc_Type(),
|
||||
|
@ -225,10 +225,16 @@ public:
|
||||
OptoRegPair *_parm_regs; // Array of machine registers per argument
|
||||
RegMask *_calling_convention_mask; // Array of RegMasks per argument
|
||||
|
||||
// Does matcher support this ideal node?
|
||||
// Does matcher have a match rule for this ideal node?
|
||||
static const bool has_match_rule(int opcode);
|
||||
static const bool _hasMatchRule[_last_opcode];
|
||||
|
||||
// Does matcher have a match rule for this ideal node and is the
|
||||
// predicate (if there is one) true?
|
||||
// NOTE: If this function is used more commonly in the future, ADLC
|
||||
// should generate this one.
|
||||
static const bool match_rule_supported(int opcode);
|
||||
|
||||
// Used to determine if we have fast l2f conversion
|
||||
// USII has it, USIII doesn't
|
||||
static const bool convL2FSupported(void);
|
||||
|
@ -439,7 +439,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
|
||||
// Always register dependence if JVMTI is enabled, because
|
||||
// either breakpoint setting or hotswapping of methods may
|
||||
// cause deoptimization.
|
||||
if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
|
||||
if (C->env()->jvmti_can_hotswap_or_post_breakpoint()) {
|
||||
C->dependencies()->assert_evol_method(method());
|
||||
}
|
||||
|
||||
@ -953,7 +953,7 @@ void Parse::do_exits() {
|
||||
bool do_synch = method()->is_synchronized() && GenerateSynchronizationCode;
|
||||
|
||||
// record exit from a method if compiled while Dtrace is turned on.
|
||||
if (do_synch || DTraceMethodProbes) {
|
||||
if (do_synch || C->env()->dtrace_method_probes()) {
|
||||
// First move the exception list out of _exits:
|
||||
GraphKit kit(_exits.transfer_exceptions_into_jvms());
|
||||
SafePointNode* normal_map = kit.map(); // keep this guy safe
|
||||
@ -975,7 +975,7 @@ void Parse::do_exits() {
|
||||
// Unlock!
|
||||
kit.shared_unlock(_synch_lock->box_node(), _synch_lock->obj_node());
|
||||
}
|
||||
if (DTraceMethodProbes) {
|
||||
if (C->env()->dtrace_method_probes()) {
|
||||
kit.make_dtrace_method_exit(method());
|
||||
}
|
||||
// Done with exception-path processing.
|
||||
@ -1074,7 +1074,7 @@ void Parse::do_method_entry() {
|
||||
|
||||
NOT_PRODUCT( count_compiled_calls(true/*at_method_entry*/, false/*is_inline*/); )
|
||||
|
||||
if (DTraceMethodProbes) {
|
||||
if (C->env()->dtrace_method_probes()) {
|
||||
make_dtrace_method_entry(method());
|
||||
}
|
||||
|
||||
@ -1960,7 +1960,7 @@ void Parse::return_current(Node* value) {
|
||||
if (method()->is_synchronized() && GenerateSynchronizationCode) {
|
||||
shared_unlock(_synch_lock->box_node(), _synch_lock->obj_node());
|
||||
}
|
||||
if (DTraceMethodProbes) {
|
||||
if (C->env()->dtrace_method_probes()) {
|
||||
make_dtrace_method_exit(method());
|
||||
}
|
||||
SafePointNode* exit_return = _exits.map();
|
||||
|
@ -2052,7 +2052,7 @@ void Parse::do_one_bytecode() {
|
||||
// null exception oop throws NULL pointer exception
|
||||
do_null_check(peek(), T_OBJECT);
|
||||
if (stopped()) return;
|
||||
if (JvmtiExport::can_post_exceptions()) {
|
||||
if (env()->jvmti_can_post_exceptions()) {
|
||||
// "Full-speed throwing" is not necessary here,
|
||||
// since we're notifying the VM on every throw.
|
||||
uncommon_trap(Deoptimization::Reason_unhandled,
|
||||
|
@ -640,7 +640,11 @@ const Type *CmpPNode::sub( const Type *t1, const Type *t2 ) const {
|
||||
if (klass0 && klass1 &&
|
||||
kps != 1 && // both or neither are klass pointers
|
||||
klass0->is_loaded() && !klass0->is_interface() && // do not trust interfaces
|
||||
klass1->is_loaded() && !klass1->is_interface()) {
|
||||
klass1->is_loaded() && !klass1->is_interface() &&
|
||||
(!klass0->is_obj_array_klass() ||
|
||||
!klass0->as_obj_array_klass()->base_element_klass()->is_interface()) &&
|
||||
(!klass1->is_obj_array_klass() ||
|
||||
!klass1->as_obj_array_klass()->base_element_klass()->is_interface())) {
|
||||
bool unrelated_classes = false;
|
||||
// See if neither subclasses the other, or if the class on top
|
||||
// is precise. In either of these cases, the compare is known
|
||||
|
@ -117,7 +117,7 @@ class frame VALUE_OBJ_CLASS_SPEC {
|
||||
bool can_be_deoptimized() const;
|
||||
|
||||
// returns the frame size in stack slots
|
||||
int frame_size() const;
|
||||
int frame_size(RegisterMap* map) const;
|
||||
|
||||
// returns the sending frame
|
||||
frame sender(RegisterMap* map) const;
|
||||
|
@ -2189,6 +2189,9 @@ class CommandLineFlags {
|
||||
diagnostic(bool, PrintIntrinsics, false, \
|
||||
"prints attempted and successful inlining of intrinsics") \
|
||||
\
|
||||
product(bool, UseCountLeadingZerosInstruction, false, \
|
||||
"Use count leading zeros instruction") \
|
||||
\
|
||||
product(bool, UsePopCountInstruction, false, \
|
||||
"Use population count instruction") \
|
||||
\
|
||||
|
@ -70,7 +70,6 @@ Monitor* FullGCCount_lock = NULL;
|
||||
Monitor* CMark_lock = NULL;
|
||||
Monitor* ZF_mon = NULL;
|
||||
Monitor* Cleanup_mon = NULL;
|
||||
Monitor* G1ConcRefine_mon = NULL;
|
||||
Mutex* SATB_Q_FL_lock = NULL;
|
||||
Monitor* SATB_Q_CBL_mon = NULL;
|
||||
Mutex* Shared_SATB_Q_lock = NULL;
|
||||
@ -168,7 +167,6 @@ void mutex_init() {
|
||||
def(CMark_lock , Monitor, nonleaf, true ); // coordinate concurrent mark thread
|
||||
def(ZF_mon , Monitor, leaf, true );
|
||||
def(Cleanup_mon , Monitor, nonleaf, true );
|
||||
def(G1ConcRefine_mon , Monitor, nonleaf, true );
|
||||
def(SATB_Q_FL_lock , Mutex , special, true );
|
||||
def(SATB_Q_CBL_mon , Monitor, nonleaf, true );
|
||||
def(Shared_SATB_Q_lock , Mutex, nonleaf, true );
|
||||
|
@ -63,9 +63,6 @@ extern Monitor* FullGCCount_lock; // in support of "concurrent" f
|
||||
extern Monitor* CMark_lock; // used for concurrent mark thread coordination
|
||||
extern Monitor* ZF_mon; // used for G1 conc zero-fill.
|
||||
extern Monitor* Cleanup_mon; // used for G1 conc cleanup.
|
||||
extern Monitor* G1ConcRefine_mon; // used for G1 conc-refine
|
||||
// coordination.
|
||||
|
||||
extern Mutex* SATB_Q_FL_lock; // Protects SATB Q
|
||||
// buffer free list.
|
||||
extern Monitor* SATB_Q_CBL_mon; // Protects SATB Q
|
||||
|
@ -559,7 +559,8 @@ void javaVFrame::print_value() const {
|
||||
}
|
||||
// Check frame size and print warning if it looks suspiciously large
|
||||
if (fr().sp() != NULL) {
|
||||
uint size = fr().frame_size();
|
||||
RegisterMap map = *register_map();
|
||||
uint size = fr().frame_size(&map);
|
||||
#ifdef _LP64
|
||||
if (size > 8*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size);
|
||||
#else
|
||||
|
@ -172,6 +172,33 @@ PHONY_LIST += jtreg_tests
|
||||
|
||||
################################################################
|
||||
|
||||
# clienttest (make sure various basic java client options work)
|
||||
|
||||
clienttest: prep $(PRODUCT_HOME)
|
||||
$(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -version
|
||||
$(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -help
|
||||
$(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -X
|
||||
$(RM) $(PRODUCT_HOME)/jre/lib/*/client/classes.jsa
|
||||
$(RM) $(PRODUCT_HOME)/jre/lib/*/client/classes_g.jsa
|
||||
$(RM) $(PRODUCT_HOME)/jre/bin/client/classes.jsa
|
||||
$(RM) $(PRODUCT_HOME)/jre/bin/client/classes_g.jsa
|
||||
$(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -Xshare:dump
|
||||
|
||||
PHONY_LIST += clienttest
|
||||
|
||||
################################################################
|
||||
|
||||
# servertest (make sure various basic java server options work)
|
||||
|
||||
servertest: prep $(PRODUCT_HOME)
|
||||
$(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -version
|
||||
$(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -help
|
||||
$(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -X
|
||||
|
||||
PHONY_LIST += servertest
|
||||
|
||||
################################################################
|
||||
|
||||
# packtest
|
||||
|
||||
# Expect JPRT to set JPRT_PACKTEST_HOME.
|
||||
|
@ -29,7 +29,7 @@
|
||||
* @run main/othervm -server -Xbatch -XX:CompileOnly=Test1.init Test1
|
||||
*/
|
||||
|
||||
class Test1 {
|
||||
public class Test1 {
|
||||
|
||||
public static void init(int src[], int [] dst, int[] ref) {
|
||||
// initialize the arrays
|
||||
|
@ -29,7 +29,7 @@
|
||||
* @run main/othervm -server -Xbatch -XX:CompileOnly=Test2.shift Test2
|
||||
*/
|
||||
|
||||
class Test2 {
|
||||
public class Test2 {
|
||||
|
||||
public static void init(int src[]) {
|
||||
// Initialize the array
|
||||
|
65
hotspot/test/compiler/6772683/InterruptedTest.java
Normal file
65
hotspot/test/compiler/6772683/InterruptedTest.java
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6772683
|
||||
* @summary Thread.isInterrupted() fails to return true on multiprocessor PC
|
||||
* @run main/othervm InterruptedTest
|
||||
*/
|
||||
|
||||
public class InterruptedTest {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Thread workerThread = new Thread("worker") {
|
||||
public void run() {
|
||||
System.out.println("Worker thread: running...");
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
}
|
||||
System.out.println("Worker thread: bye");
|
||||
}
|
||||
};
|
||||
System.out.println("Main thread: starts a worker thread...");
|
||||
workerThread.start();
|
||||
System.out.println("Main thread: waits at most 5s for the worker thread to die...");
|
||||
workerThread.join(5000); // Wait 5 sec to let run() method to be compiled
|
||||
int ntries = 0;
|
||||
while (workerThread.isAlive() && ntries < 5) {
|
||||
System.out.println("Main thread: interrupts the worker thread...");
|
||||
workerThread.interrupt();
|
||||
if (workerThread.isInterrupted()) {
|
||||
System.out.println("Main thread: worker thread is interrupted");
|
||||
}
|
||||
ntries++;
|
||||
System.out.println("Main thread: waits for the worker thread to die...");
|
||||
workerThread.join(1000); // Wait 1 sec and try again
|
||||
}
|
||||
if (ntries == 5) {
|
||||
System.out.println("Main thread: the worker thread dod not die");
|
||||
System.exit(97);
|
||||
}
|
||||
System.out.println("Main thread: bye");
|
||||
}
|
||||
|
||||
}
|
104
hotspot/test/compiler/6814842/Test6814842.java
Normal file
104
hotspot/test/compiler/6814842/Test6814842.java
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6814842
|
||||
* @summary Load shortening optimizations
|
||||
*
|
||||
* @run main/othervm -Xcomp -XX:CompileOnly=Test6814842.loadS2B,Test6814842.loadS2Bmask255,Test6814842.loadUS2B,Test6814842.loadUS2Bmask255,Test6814842.loadI2B,Test6814842.loadI2Bmask255,Test6814842.loadI2S,Test6814842.loadI2Smask255,Test6814842.loadI2Smask65535,Test6814842.loadI2US,Test6814842.loadI2USmask255,Test6814842.loadI2USmask65535 Test6814842
|
||||
*/
|
||||
|
||||
public class Test6814842 {
|
||||
static final short[] sa = new short[] { (short) 0xF1F2 };
|
||||
static final char[] ca = new char[] { (char) 0xF3F4 };
|
||||
static final int[] ia = new int[] { 0xF1F2F3F4 };
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
byte s2b = loadS2B(sa);
|
||||
if (s2b != (byte) 0xF2)
|
||||
throw new InternalError("loadS2B failed: " + s2b + " != " + (byte) 0xF2);
|
||||
|
||||
byte s2bmask255 = loadS2Bmask255(sa);
|
||||
if (s2bmask255 != (byte) 0xF2)
|
||||
throw new InternalError("loadS2Bmask255 failed: " + s2bmask255 + " != " + (byte) 0xF2);
|
||||
|
||||
byte us2b = loadUS2B(ca);
|
||||
if (us2b != (byte) 0xF4)
|
||||
throw new InternalError("loadUS2B failed: " + us2b + " != " + (byte) 0xF4);
|
||||
|
||||
byte us2bmask255 = loadUS2Bmask255(ca);
|
||||
if (us2bmask255 != (byte) 0xF4)
|
||||
throw new InternalError("loadUS2Bmask255 failed: " + us2bmask255 + " != " + (byte) 0xF4);
|
||||
|
||||
byte i2b = loadI2B(ia);
|
||||
if (i2b != (byte) 0xF4)
|
||||
throw new InternalError("loadI2B failed: " + i2b + " != " + (byte) 0xF4);
|
||||
|
||||
byte i2bmask255 = loadI2Bmask255(ia);
|
||||
if (i2bmask255 != (byte) 0xF4)
|
||||
throw new InternalError("loadI2Bmask255 failed: " + i2bmask255 + " != " + (byte) 0xF4);
|
||||
|
||||
short i2s = loadI2S(ia);
|
||||
if (i2s != (short) 0xF3F4)
|
||||
throw new InternalError("loadI2S failed: " + i2s + " != " + (short) 0xF3F4);
|
||||
|
||||
short i2smask255 = loadI2Smask255(ia);
|
||||
if (i2smask255 != (short) 0xF4)
|
||||
throw new InternalError("loadI2Smask255 failed: " + i2smask255 + " != " + (short) 0xF4);
|
||||
|
||||
short i2smask65535 = loadI2Smask65535(ia);
|
||||
if (i2smask65535 != (short) 0xF3F4)
|
||||
throw new InternalError("loadI2Smask65535 failed: " + i2smask65535 + " != " + (short) 0xF3F4);
|
||||
|
||||
char i2us = loadI2US(ia);
|
||||
if (i2us != (char) 0xF3F4)
|
||||
throw new InternalError("loadI2US failed: " + (int) i2us + " != " + (char) 0xF3F4);
|
||||
|
||||
char i2usmask255 = loadI2USmask255(ia);
|
||||
if (i2usmask255 != (char) 0xF4)
|
||||
throw new InternalError("loadI2USmask255 failed: " + (int) i2usmask255 + " != " + (char) 0xF4);
|
||||
|
||||
char i2usmask65535 = loadI2USmask65535(ia);
|
||||
if (i2usmask65535 != (char) 0xF3F4)
|
||||
throw new InternalError("loadI2USmask65535 failed: " + (int) i2usmask65535 + " != " + (char) 0xF3F4);
|
||||
}
|
||||
|
||||
static byte loadS2B (short[] sa) { return (byte) (sa[0] ); }
|
||||
static byte loadS2Bmask255 (short[] sa) { return (byte) (sa[0] & 0xFF ); }
|
||||
|
||||
static byte loadUS2B (char[] ca) { return (byte) (ca[0] ); }
|
||||
static byte loadUS2Bmask255 (char[] ca) { return (byte) (ca[0] & 0xFF ); }
|
||||
|
||||
static byte loadI2B (int[] ia) { return (byte) (ia[0] ); }
|
||||
static byte loadI2Bmask255 (int[] ia) { return (byte) (ia[0] & 0xFF ); }
|
||||
|
||||
static short loadI2S (int[] ia) { return (short) (ia[0] ); }
|
||||
static short loadI2Smask255 (int[] ia) { return (short) (ia[0] & 0xFF ); }
|
||||
static short loadI2Smask65535 (int[] ia) { return (short) (ia[0] & 0xFFFF); }
|
||||
|
||||
static char loadI2US (int[] ia) { return (char) (ia[0] ); }
|
||||
static char loadI2USmask255 (int[] ia) { return (char) (ia[0] & 0xFF ); }
|
||||
static char loadI2USmask65535(int[] ia) { return (char) (ia[0] & 0xFFFF); }
|
||||
}
|
266
hotspot/test/compiler/6823354/Test6823354.java
Normal file
266
hotspot/test/compiler/6823354/Test6823354.java
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6823354
|
||||
* @summary These methods can be instrinsified by using bit scan, bit test, and population count instructions.
|
||||
*
|
||||
* @run main/othervm -Xcomp -XX:CompileOnly=Test6823354.lzcomp,Test6823354.tzcomp,.dolzcomp,.dotzcomp Test6823354
|
||||
*/
|
||||
|
||||
import java.net.URLClassLoader;
|
||||
|
||||
public class Test6823354 {
|
||||
// Arrays of corner case values.
|
||||
static final int[] ia = new int[] { 0, 1, -1, Integer.MIN_VALUE, Integer.MAX_VALUE };
|
||||
static final long[] la = new long[] { 0L, 1L, -1L, Long.MIN_VALUE, Long.MAX_VALUE };
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Load the classes and the methods.
|
||||
Integer.numberOfLeadingZeros(0);
|
||||
Integer.numberOfTrailingZeros(0);
|
||||
Long.numberOfLeadingZeros(0);
|
||||
Long.numberOfTrailingZeros(0);
|
||||
|
||||
lz();
|
||||
tz();
|
||||
}
|
||||
|
||||
static void lz() throws Exception {
|
||||
// int
|
||||
|
||||
// Test corner cases.
|
||||
for (int i = 0; i < ia.length; i++) {
|
||||
int x = ia[i];
|
||||
check(x, lzcomp(x), lzint(x));
|
||||
}
|
||||
|
||||
// Test all possible return values.
|
||||
for (int i = 0; i < Integer.SIZE; i++) {
|
||||
int x = 1 << i;
|
||||
check(x, lzcomp(x), lzint(x));
|
||||
}
|
||||
|
||||
String classname = "Test6823354$lzconI";
|
||||
|
||||
// Test Ideal optimizations (constant values).
|
||||
for (int i = 0; i < ia.length; i++) {
|
||||
testclass(classname, ia[i]);
|
||||
}
|
||||
|
||||
// Test Ideal optimizations (constant values).
|
||||
for (int i = 0; i < Integer.SIZE; i++) {
|
||||
int x = 1 << i;
|
||||
testclass(classname, x);
|
||||
}
|
||||
|
||||
|
||||
// long
|
||||
|
||||
// Test corner cases.
|
||||
for (int i = 0; i < ia.length; i++) {
|
||||
long x = la[i];
|
||||
check(x, lzcomp(x), lzint(x));
|
||||
}
|
||||
|
||||
// Test all possible return values.
|
||||
for (int i = 0; i < Long.SIZE; i++) {
|
||||
long x = 1L << i;
|
||||
check(x, lzcomp(x), lzint(x));
|
||||
}
|
||||
|
||||
classname = "Test6823354$lzconL";
|
||||
|
||||
// Test Ideal optimizations (constant values).
|
||||
for (int i = 0; i < la.length; i++) {
|
||||
testclass(classname, la[i]);
|
||||
}
|
||||
|
||||
// Test Ideal optimizations (constant values).
|
||||
for (int i = 0; i < Long.SIZE; i++) {
|
||||
long x = 1L << i;
|
||||
testclass(classname, x);
|
||||
}
|
||||
}
|
||||
|
||||
static void tz() throws Exception {
|
||||
// int
|
||||
|
||||
// Test corner cases.
|
||||
for (int i = 0; i < ia.length; i++) {
|
||||
int x = ia[i];
|
||||
check(x, tzcomp(x), tzint(x));
|
||||
}
|
||||
|
||||
// Test all possible return values.
|
||||
for (int i = 0; i < Integer.SIZE; i++) {
|
||||
int x = 1 << i;
|
||||
check(x, tzcomp(x), tzint(x));
|
||||
}
|
||||
|
||||
String classname = "Test6823354$tzconI";
|
||||
|
||||
// Test Ideal optimizations (constant values).
|
||||
for (int i = 0; i < ia.length; i++) {
|
||||
testclass(classname, ia[i]);
|
||||
}
|
||||
|
||||
// Test Ideal optimizations (constant values).
|
||||
for (int i = 0; i < Integer.SIZE; i++) {
|
||||
int x = 1 << i;
|
||||
testclass(classname, x);
|
||||
}
|
||||
|
||||
|
||||
// long
|
||||
|
||||
// Test corner cases.
|
||||
for (int i = 0; i < la.length; i++) {
|
||||
long x = la[i];
|
||||
check(x, tzcomp(x), tzint(x));
|
||||
}
|
||||
|
||||
// Test all possible return values.
|
||||
for (int i = 0; i < Long.SIZE; i++) {
|
||||
long x = 1L << i;
|
||||
check(x, tzcomp(x), tzint(x));
|
||||
}
|
||||
|
||||
classname = "Test6823354$tzconL";
|
||||
|
||||
// Test Ideal optimizations (constant values).
|
||||
for (int i = 0; i < la.length; i++) {
|
||||
testclass(classname, la[i]);
|
||||
}
|
||||
|
||||
// Test Ideal optimizations (constant values).
|
||||
for (int i = 0; i < Long.SIZE; i++) {
|
||||
long x = 1L << i;
|
||||
testclass(classname, x);
|
||||
}
|
||||
}
|
||||
|
||||
static void check(int value, int result, int expected) {
|
||||
//System.out.println(value + ": " + result + ", " + expected);
|
||||
if (result != expected)
|
||||
throw new InternalError(value + " failed: " + result + " != " + expected);
|
||||
}
|
||||
|
||||
static void check(long value, long result, long expected) {
|
||||
//System.out.println(value + ": " + result + ", " + expected);
|
||||
if (result != expected)
|
||||
throw new InternalError(value + " failed: " + result + " != " + expected);
|
||||
}
|
||||
|
||||
static int lzint( int i) { return Integer.numberOfLeadingZeros(i); }
|
||||
static int lzcomp(int i) { return Integer.numberOfLeadingZeros(i); }
|
||||
|
||||
static int lzint( long l) { return Long.numberOfLeadingZeros(l); }
|
||||
static int lzcomp(long l) { return Long.numberOfLeadingZeros(l); }
|
||||
|
||||
static int tzint( int i) { return Integer.numberOfTrailingZeros(i); }
|
||||
static int tzcomp(int i) { return Integer.numberOfTrailingZeros(i); }
|
||||
|
||||
static int tzint( long l) { return Long.numberOfTrailingZeros(l); }
|
||||
static int tzcomp(long l) { return Long.numberOfTrailingZeros(l); }
|
||||
|
||||
static void testclass(String classname, int x) throws Exception {
|
||||
System.setProperty("value", "" + x);
|
||||
loadandrunclass(classname);
|
||||
}
|
||||
|
||||
static void testclass(String classname, long x) throws Exception {
|
||||
System.setProperty("value", "" + x);
|
||||
loadandrunclass(classname);
|
||||
}
|
||||
|
||||
static void loadandrunclass(String classname) throws Exception {
|
||||
Class cl = Class.forName(classname);
|
||||
URLClassLoader apploader = (URLClassLoader) cl.getClassLoader();
|
||||
ClassLoader loader = new URLClassLoader(apploader.getURLs(), apploader.getParent());
|
||||
Class c = loader.loadClass(classname);
|
||||
Runnable r = (Runnable) c.newInstance();
|
||||
r.run();
|
||||
}
|
||||
|
||||
public static class lzconI implements Runnable {
|
||||
static final int VALUE;
|
||||
|
||||
static {
|
||||
int value = 0;
|
||||
try {
|
||||
value = Integer.decode(System.getProperty("value"));
|
||||
} catch (Throwable e) {}
|
||||
VALUE = value;
|
||||
}
|
||||
|
||||
public void run() { check(VALUE, lzint(VALUE), dolzcomp()); }
|
||||
static int dolzcomp() { return lzcomp(VALUE); }
|
||||
}
|
||||
|
||||
public static class lzconL implements Runnable {
|
||||
static final long VALUE;
|
||||
|
||||
static {
|
||||
long value = 0;
|
||||
try {
|
||||
value = Long.decode(System.getProperty("value"));
|
||||
} catch (Throwable e) {}
|
||||
VALUE = value;
|
||||
}
|
||||
|
||||
public void run() { check(VALUE, lzint(VALUE), dolzcomp()); }
|
||||
static int dolzcomp() { return lzcomp(VALUE); }
|
||||
}
|
||||
|
||||
public static class tzconI implements Runnable {
|
||||
static final int VALUE;
|
||||
|
||||
static {
|
||||
int value = 0;
|
||||
try {
|
||||
value = Integer.decode(System.getProperty("value"));
|
||||
} catch (Throwable e) {}
|
||||
VALUE = value;
|
||||
}
|
||||
|
||||
public void run() { check(VALUE, tzint(VALUE), dotzcomp()); }
|
||||
static int dotzcomp() { return tzcomp(VALUE); }
|
||||
}
|
||||
|
||||
public static class tzconL implements Runnable {
|
||||
static final long VALUE;
|
||||
|
||||
static {
|
||||
long value = 0;
|
||||
try {
|
||||
value = Long.decode(System.getProperty("value"));
|
||||
} catch (Throwable e) {}
|
||||
VALUE = value;
|
||||
}
|
||||
|
||||
public void run() { check(VALUE, tzint(VALUE), dotzcomp()); }
|
||||
static int dotzcomp() { return tzcomp(VALUE); }
|
||||
}
|
||||
}
|
135
hotspot/test/compiler/6832293/Test.java
Normal file
135
hotspot/test/compiler/6832293/Test.java
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6832293
|
||||
* @summary JIT compiler got wrong result in type checking with -server
|
||||
* @run main/othervm -Xcomp -XX:CompileOnly=Test.run Test
|
||||
*/
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
interface SomeInterface {
|
||||
int SEVENS = 777;
|
||||
}
|
||||
|
||||
interface AnotherInterface {
|
||||
int THIRDS = 33;
|
||||
}
|
||||
|
||||
class SomeClass implements SomeInterface {
|
||||
int i;
|
||||
|
||||
SomeClass(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
||||
|
||||
class ImmediateSubclass extends SomeClass implements SomeInterface {
|
||||
float f;
|
||||
|
||||
ImmediateSubclass(int i, float f) {
|
||||
super(i);
|
||||
this.f = f;
|
||||
}
|
||||
}
|
||||
|
||||
final class FinalSubclass extends ImmediateSubclass implements AnotherInterface {
|
||||
double d;
|
||||
|
||||
FinalSubclass(int i, float f, double d) {
|
||||
super(i, f);
|
||||
this.d = d;
|
||||
}
|
||||
}
|
||||
|
||||
public class Test {
|
||||
|
||||
public static void main(String args[]) throws Exception{
|
||||
/* try to pre initialize */
|
||||
SomeClass[] a=new SomeClass[10];
|
||||
Class.forName("ImmediateSubclass");
|
||||
Class.forName("FinalSubclass");
|
||||
System.exit(run(args, System.out) + 95/*STATUS_TEMP*/);
|
||||
}
|
||||
|
||||
static int errorStatus = 0/*STATUS_PASSED*/;
|
||||
|
||||
static void errorAlert(PrintStream out, int errorLevel) {
|
||||
out.println("Test: failure #" + errorLevel);
|
||||
errorStatus = 2/*STATUS_FAILED*/;
|
||||
}
|
||||
|
||||
static SomeClass[] v2 = new FinalSubclass[4];
|
||||
|
||||
public static int run(String args[],PrintStream out) {
|
||||
int i [], j [];
|
||||
SomeInterface u [], v[] [];
|
||||
AnotherInterface w [];
|
||||
SomeClass x [] [];
|
||||
|
||||
i = new int [10];
|
||||
i[0] = 777;
|
||||
j = (int []) i;
|
||||
if (j != i)
|
||||
errorAlert(out, 2);
|
||||
else if (j.length != 10)
|
||||
errorAlert(out, 3);
|
||||
else if (j[0] != 777)
|
||||
errorAlert(out, 4);
|
||||
|
||||
v = new SomeClass [3] [];
|
||||
x = (SomeClass [] []) v;
|
||||
if (! (x instanceof SomeInterface [] []))
|
||||
errorAlert(out, 5);
|
||||
else if (! (x instanceof SomeClass [] []))
|
||||
errorAlert(out, 6);
|
||||
else if (x != v)
|
||||
errorAlert(out, 7);
|
||||
|
||||
x[0] = (SomeClass []) new ImmediateSubclass [4];
|
||||
if (! (x[0] instanceof ImmediateSubclass []))
|
||||
errorAlert(out, 8);
|
||||
else if (x[0].length != 4)
|
||||
errorAlert(out, 9);
|
||||
|
||||
x[1] = (SomeClass []) v2;
|
||||
if (! (x[1] instanceof FinalSubclass []))
|
||||
errorAlert(out, 10);
|
||||
else if (x[1].length != 4)
|
||||
errorAlert(out, 11);
|
||||
|
||||
w = (AnotherInterface []) x[1];
|
||||
if (! (w instanceof FinalSubclass []))
|
||||
errorAlert(out, 12);
|
||||
else if (w != x[1])
|
||||
errorAlert(out, 13);
|
||||
else if (w.length != 4)
|
||||
errorAlert(out, 14);
|
||||
|
||||
return errorStatus;
|
||||
}
|
||||
}
|
||||
|
119
hotspot/test/compiler/6843752/Test.java
Normal file
119
hotspot/test/compiler/6843752/Test.java
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6843752
|
||||
* @summary missing code for an anti-dependent Phi in GCM
|
||||
* @run main/othervm -Xbatch Test
|
||||
*/
|
||||
|
||||
public class Test {
|
||||
|
||||
Item list;
|
||||
|
||||
static class Item {
|
||||
public Item next;
|
||||
public Item prev;
|
||||
public boolean remove;
|
||||
|
||||
Item(boolean r) { remove = r; }
|
||||
}
|
||||
|
||||
private void linkIn(Item item) {
|
||||
Item head = list;
|
||||
if (head == null) {
|
||||
item.next = item;
|
||||
item.prev = item;
|
||||
list = item;
|
||||
} else {
|
||||
item.next = head;
|
||||
item.prev = head.prev;
|
||||
head.prev.next = item;
|
||||
head.prev = item;
|
||||
}
|
||||
}
|
||||
|
||||
private void linkOut(Item item) {
|
||||
Item head = list;
|
||||
if (item.next == item) {
|
||||
list = null;
|
||||
} else {
|
||||
item.prev.next = item.next;
|
||||
item.next.prev = item.prev;
|
||||
if (head == item) {
|
||||
list = item.next;
|
||||
}
|
||||
}
|
||||
item.next = null;
|
||||
item.prev = null; // this is the null pointer we are seeing
|
||||
}
|
||||
|
||||
private void removeItems(int numItems) {
|
||||
Item item = list;
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
Item last = item.prev;
|
||||
boolean done = false;
|
||||
while (!done && numItems > 1) {
|
||||
// the original code "done = (item == last);" triggered an infinite loop
|
||||
// and was changed slightly in order to produce an exception instead.
|
||||
done = (item.next == last.next);
|
||||
item = item.next;
|
||||
if (item.prev.remove) {
|
||||
linkOut(item.prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void perform(int numItems) {
|
||||
for (int i = 0; i < numItems; i++) {
|
||||
linkIn(new Item(i == 0));
|
||||
}
|
||||
removeItems(numItems);
|
||||
list = null;
|
||||
}
|
||||
|
||||
static public void main(String[] args) {
|
||||
int caseCnt = 0;
|
||||
Test bj = new Test();
|
||||
try {
|
||||
for (; caseCnt < 500000;) {
|
||||
int numItems = (++caseCnt % 2);
|
||||
if ((caseCnt % 64) == 0) {
|
||||
numItems = 5;
|
||||
}
|
||||
bj.perform(numItems);
|
||||
if ((caseCnt % 100000) == 0) {
|
||||
System.out.println("successfully performed " + caseCnt + " cases");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("ERROR: crashed during case " + caseCnt);
|
||||
e.printStackTrace(System.out);
|
||||
System.exit(97);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,3 +33,5 @@ e8837366d3fd72f7c7a47ebfdbd5106c16156f12 jdk7-b53
|
||||
c197c6801271c60f9c9f5d18fcc95b59e76dcd54 jdk7-b56
|
||||
e4851e9f7be26fc52a628be06ffa8aaea0919bd7 jdk7-b57
|
||||
13bf67d8c6341b841d268985cabaf747f2652bc8 jdk7-b58
|
||||
75113d7ce083048e7576b9d0d60a4e80db6b181f jdk7-b59
|
||||
259aef5045a155eb6a2f8dd0e2429c6dbe0f652f jdk7-b60
|
||||
|
@ -69,6 +69,10 @@ else
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG_CLASSFILES), true)
|
||||
ANT_OPTIONS += -Djavac.debug=true
|
||||
endif
|
||||
|
||||
# Note: jdk/make/common/Defs.gmk uses LANGUAGE_VERSION (-source NN)
|
||||
# and the somewhat misnamed CLASS_VERSION (-target NN)
|
||||
ifdef TARGET_CLASS_VERSION
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user