Merge
diff --git a/hotspot/make/aix/Makefile b/hotspot/make/aix/Makefile
index e015074..bbb92c9 100644
--- a/hotspot/make/aix/Makefile
+++ b/hotspot/make/aix/Makefile
@@ -246,8 +246,7 @@
XSLT_CHECK = $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory
# If not found then fail fast.
check_j2se_version:
- $(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
- if [ $$? -ne 0 ]; then \
+ $(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
$(REMOTE) $(RUN.JAVA) -version; \
echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
"to bootstrap this build" 1>&2; \
diff --git a/hotspot/make/bsd/Makefile b/hotspot/make/bsd/Makefile
index 3f0cfc3..4d45841 100644
--- a/hotspot/make/bsd/Makefile
+++ b/hotspot/make/bsd/Makefile
@@ -240,8 +240,7 @@
XSLT_CHECK = $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory
# If not found then fail fast.
check_j2se_version:
- $(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
- if [ $$? -ne 0 ]; then \
+ $(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
$(REMOTE) $(RUN.JAVA) -version; \
echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
"to bootstrap this build" 1>&2; \
diff --git a/hotspot/make/bsd/makefiles/dtrace.make b/hotspot/make/bsd/makefiles/dtrace.make
index dbb4116..80eb4d9 100644
--- a/hotspot/make/bsd/makefiles/dtrace.make
+++ b/hotspot/make/bsd/makefiles/dtrace.make
@@ -179,23 +179,23 @@
# $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs.
$(JVMOFFS).h: $(GENOFFS)
$(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -header > $@.tmp; touch $@; \
- if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
- then rm -f $@; mv $@.tmp $@; \
- else rm -f $@.tmp; \
+ if diff $@.tmp $@ > /dev/null 2>&1 ; \
+ then rm -f $@.tmp; \
+ else rm -f $@; mv $@.tmp $@; \
fi
$(JVMOFFS)Index.h: $(GENOFFS)
$(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -index > $@.tmp; touch $@; \
- if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
- then rm -f $@; mv $@.tmp $@; \
- else rm -f $@.tmp; \
+ if diff $@.tmp $@ > /dev/null 2>&1 ; \
+ then rm -f $@.tmp; \
+ else rm -f $@; mv $@.tmp $@; \
fi
$(JVMOFFS).cpp: $(GENOFFS) $(JVMOFFS).h $(JVMOFFS)Index.h
$(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -table > $@.tmp; touch $@; \
- if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
- then rm -f $@; mv $@.tmp $@; \
- else rm -f $@.tmp; \
+ if diff $@.tmp $@ > /dev/null 2>&1; \
+ then rm -f $@.tmp; \
+ else rm -f $@; mv $@.tmp $@; \
fi
$(JVMOFFS.o): $(JVMOFFS).h $(JVMOFFS).cpp
diff --git a/hotspot/make/bsd/makefiles/universal.gmk b/hotspot/make/bsd/makefiles/universal.gmk
index 12a34d7..40868ad 100644
--- a/hotspot/make/bsd/makefiles/universal.gmk
+++ b/hotspot/make/bsd/makefiles/universal.gmk
@@ -59,7 +59,7 @@
# Package built libraries in a universal binary
$(UNIVERSAL_LIPO_LIST):
- BUILT_LIPO_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) 2>/dev/null`"; \
+ BUILT_LIPO_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) 2>/dev/null`" || test $$? = "1"; \
if [ -n "$${BUILT_LIPO_FILES}" ]; then \
$(MKDIR) -p $(shell dirname $@); \
lipo -create -output $@ $${BUILT_LIPO_FILES}; \
@@ -70,7 +70,7 @@
# - copies directories; including empty dirs
# - copies files, symlinks, other non-directory files
$(UNIVERSAL_COPY_LIST):
- BUILT_COPY_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) -prune 2>/dev/null`"; \
+ BUILT_COPY_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) -prune 2>/dev/null`" || test $$? = "1"; \
if [ -n "$${BUILT_COPY_FILES}" ]; then \
for i in $${BUILT_COPY_FILES}; do \
$(MKDIR) -p $(shell dirname $@); \
diff --git a/hotspot/make/linux/Makefile b/hotspot/make/linux/Makefile
index c3ed19f..33ed65d 100644
--- a/hotspot/make/linux/Makefile
+++ b/hotspot/make/linux/Makefile
@@ -246,8 +246,7 @@
XSLT_CHECK = $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory
# If not found then fail fast.
check_j2se_version:
- $(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
- if [ $$? -ne 0 ]; then \
+ $(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
$(REMOTE) $(RUN.JAVA) -version; \
echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
"to bootstrap this build" 1>&2; \
diff --git a/hotspot/make/linux/makefiles/vm.make b/hotspot/make/linux/makefiles/vm.make
index a138a16..65b11f5 100644
--- a/hotspot/make/linux/makefiles/vm.make
+++ b/hotspot/make/linux/makefiles/vm.make
@@ -334,10 +334,8 @@
rm -f $@.1; ln -s $@ $@.1; \
if [ \"$(CROSS_COMPILE_ARCH)\" = \"\" ] ; then \
if [ -x /usr/sbin/selinuxenabled ] ; then \
- /usr/sbin/selinuxenabled; \
- if [ $$? = 0 ] ; then \
- /usr/bin/chcon -t textrel_shlib_t $@; \
- if [ $$? != 0 ]; then \
+ if /usr/sbin/selinuxenabled; then \
+ if ! /usr/bin/chcon -t textrel_shlib_t $@; then \
echo "ERROR: Cannot chcon $@"; \
fi \
fi \
diff --git a/hotspot/make/sa.files b/hotspot/make/sa.files
index fa807c3..dfe1e53 100644
--- a/hotspot/make/sa.files
+++ b/hotspot/make/sa.files
@@ -39,6 +39,7 @@
$(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/c1/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/ci/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/classfile/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/code/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/compiler/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/*.java \
@@ -49,8 +50,10 @@
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/basic/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/dummy/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/ia64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ia64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ppc64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/sparc/*.java \
@@ -71,6 +74,7 @@
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/win32/coff/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/ia64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windows/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windows/amd64/*.java \
@@ -101,6 +105,8 @@
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/solaris_x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/x86/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/win32_amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/win32_x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/ppc64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/tools/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/tools/jcore/*.java \
diff --git a/hotspot/make/solaris/Makefile b/hotspot/make/solaris/Makefile
index 869db69..f8fb06c 100644
--- a/hotspot/make/solaris/Makefile
+++ b/hotspot/make/solaris/Makefile
@@ -190,8 +190,7 @@
XSLT_CHECK = $(RUN.JAVAP) javax.xml.transform.TransformerFactory
# If not found then fail fast.
check_j2se_version:
- $(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
- if [ $$? -ne 0 ]; then \
+ $(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
$(RUN.JAVA) -version; \
echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
"to bootstrap this build" 1>&2; \
diff --git a/hotspot/make/solaris/makefiles/dtrace.make b/hotspot/make/solaris/makefiles/dtrace.make
index be6e71d..1b76dc7 100644
--- a/hotspot/make/solaris/makefiles/dtrace.make
+++ b/hotspot/make/solaris/makefiles/dtrace.make
@@ -171,11 +171,11 @@
./lib$(GENOFFS).so
CONDITIONALLY_UPDATE_JVMOFFS_TARGET = \
- cmp -s $@ $@.tmp; \
- case $$? in \
- 0) rm -f $@.tmp;; \
- *) rm -f $@ && mv $@.tmp $@ && echo Updated $@;; \
- esac
+ if cmp -s $@ $@.tmp; then \
+ rm -f $@.tmp; \
+ else \
+ rm -f $@ && mv $@.tmp $@ && echo Updated $@; \
+ fi
# $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs.
$(JVMOFFS).h: $(GENOFFS)
diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp
index 5c11898..4621678 100644
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp
@@ -567,16 +567,21 @@
inline void load_with_trap_null_check(Register d, int si16, Register s1);
// Load heap oop and decompress. Loaded oop may not be null.
- inline void load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1 = noreg);
+ // Specify tmp to save one cycle.
+ inline void load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1 = noreg,
+ Register tmp = noreg);
+ // Store heap oop and decompress. Decompressed oop may not be null.
+ // Specify tmp register if d should not be changed.
inline void store_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1,
- /*specify if d must stay uncompressed*/ Register tmp = noreg);
+ Register tmp = noreg);
// Null allowed.
inline void load_heap_oop(Register d, RegisterOrConstant offs, Register s1 = noreg);
// Encode/decode heap oop. Oop may not be null, else en/decoding goes wrong.
+ // src == d allowed.
inline Register encode_heap_oop_not_null(Register d, Register src = noreg);
- inline void decode_heap_oop_not_null(Register d);
+ inline Register decode_heap_oop_not_null(Register d, Register src = noreg);
// Null allowed.
inline void decode_heap_oop(Register d);
diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp
index 84485d4..f5d19df 100644
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp
@@ -311,11 +311,14 @@
ld(d, si16, s1);
}
-inline void MacroAssembler::load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1) {
+inline void MacroAssembler::load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1, Register tmp) {
if (UseCompressedOops) {
- lwz(d, offs, s1);
+ // In disjoint mode decoding can save a cycle if src != dst.
+ Register narrowOop = (tmp != noreg && Universe::narrow_oop_base_disjoint()) ? tmp : d;
+ lwz(narrowOop, offs, s1);
// Attention: no null check here!
- decode_heap_oop_not_null(d);
+ Register res = decode_heap_oop_not_null(d, narrowOop);
+ assert(res == d, "caller will not consume loaded value");
} else {
ld(d, offs, s1);
}
@@ -340,26 +343,36 @@
}
inline Register MacroAssembler::encode_heap_oop_not_null(Register d, Register src) {
- Register current = (src!=noreg) ? src : d; // Compressed oop is in d if no src provided.
- if (Universe::narrow_oop_base() != NULL) {
+ Register current = (src != noreg) ? src : d; // Oop to be compressed is in d if no src provided.
+ if (Universe::narrow_oop_base_overlaps()) {
sub(d, current, R30);
current = d;
}
if (Universe::narrow_oop_shift() != 0) {
- srdi(d, current, LogMinObjAlignmentInBytes);
+ rldicl(d, current, 64-Universe::narrow_oop_shift(), 32); // Clears the upper bits.
current = d;
}
return current; // Encoded oop is in this register.
}
-inline void MacroAssembler::decode_heap_oop_not_null(Register d) {
+inline Register MacroAssembler::decode_heap_oop_not_null(Register d, Register src) {
+ if (Universe::narrow_oop_base_disjoint() && src != noreg && src != d &&
+ Universe::narrow_oop_shift() != 0) {
+ mr(d, R30);
+ rldimi(d, src, Universe::narrow_oop_shift(), 32-Universe::narrow_oop_shift());
+ return d;
+ }
+
+ Register current = (src != noreg) ? src : d; // Compressed oop is in d if no src provided.
if (Universe::narrow_oop_shift() != 0) {
- assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
- sldi(d, d, LogMinObjAlignmentInBytes);
+ sldi(d, current, Universe::narrow_oop_shift());
+ current = d;
}
if (Universe::narrow_oop_base() != NULL) {
- add(d, d, R30);
+ add(d, current, R30);
+ current = d;
}
+ return current; // Decoded oop is in this register.
}
inline void MacroAssembler::decode_heap_oop(Register d) {
@@ -368,13 +381,7 @@
cmpwi(CCR0, d, 0);
beq(CCR0, isNull);
}
- if (Universe::narrow_oop_shift() != 0) {
- assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
- sldi(d, d, LogMinObjAlignmentInBytes);
- }
- if (Universe::narrow_oop_base() != NULL) {
- add(d, d, R30);
- }
+ decode_heap_oop_not_null(d);
bind(isNull);
}
diff --git a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp
index 89c0344..88e0dec 100644
--- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp
@@ -172,15 +172,15 @@
// Load the invoker, as MH -> MH.form -> LF.vmentry
__ verify_oop(recv);
- __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv);
+ __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv, temp2);
__ verify_oop(method_temp);
- __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp);
+ __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp, temp2);
__ verify_oop(method_temp);
- // the following assumes that a Method* is normally compressed in the vmtarget field:
+ // The following assumes that a Method* is normally compressed in the vmtarget field:
__ ld(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), method_temp);
if (VerifyMethodHandles && !for_compiler_entry) {
- // make sure recv is already on stack
+ // Make sure recv is already on stack.
__ ld(temp2, in_bytes(Method::const_offset()), method_temp);
__ load_sized_value(temp2, in_bytes(ConstMethod::size_of_parameters_offset()), temp2,
sizeof(u2), /*is_signed*/ false);
@@ -259,8 +259,9 @@
}
if (TraceMethodHandles) {
- if (tmp_mh != noreg)
+ if (tmp_mh != noreg) {
__ mr(R23_method_handle, tmp_mh); // make stub happy
+ }
trace_method_handle_interpreter_entry(_masm, iid);
}
@@ -332,7 +333,7 @@
if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) {
Label L_ok;
Register temp2_defc = temp2;
- __ load_heap_oop_not_null(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg);
+ __ load_heap_oop_not_null(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg, temp3);
load_klass_from_Class(_masm, temp2_defc, temp3, temp4);
__ verify_klass_ptr(temp2_defc);
__ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, temp4, L_ok);
@@ -407,7 +408,7 @@
}
Register temp2_intf = temp2;
- __ load_heap_oop_not_null(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg);
+ __ load_heap_oop_not_null(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg, temp3);
load_klass_from_Class(_masm, temp2_intf, temp3, temp4);
__ verify_klass_ptr(temp2_intf);
@@ -464,7 +465,7 @@
strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH
const char* mh_reg_name = has_mh ? "R23_method_handle" : "G23";
tty->print_cr("MH %s %s="INTPTR_FORMAT " sp=" INTPTR_FORMAT,
- adaptername, mh_reg_name, (intptr_t) mh, (intptr_t) entry_sp);
+ adaptername, mh_reg_name, (intptr_t) mh, entry_sp);
if (Verbose) {
tty->print_cr("Registers:");
@@ -535,23 +536,22 @@
BLOCK_COMMENT("trace_method_handle {");
- int nbytes_save = 10 * 8; // 10 volatile gprs
- __ save_LR_CR(R0);
- __ mr(R0, R1_SP); // saved_sp
- assert(Assembler::is_simm(-nbytes_save, 16), "Overwriting R0");
- // Push_frame_reg_args only uses R0 if nbytes_save is wider than 16 bit.
- __ push_frame_reg_args(nbytes_save, R0);
- __ save_volatile_gprs(R1_SP, frame::abi_reg_args_size); // Except R0.
+ const Register tmp = R11; // Will be preserved.
+ const int nbytes_save = 11*8; // volatile gprs except R0
+ __ save_volatile_gprs(R1_SP, -nbytes_save); // except R0
+ __ save_LR_CR(tmp); // save in old frame
- __ load_const(R3_ARG1, (address)adaptername);
+ __ mr(R5_ARG3, R1_SP); // saved_sp
+ __ push_frame_reg_args(nbytes_save, tmp);
+
+ __ load_const_optimized(R3_ARG1, (address)adaptername, tmp);
__ mr(R4_ARG2, R23_method_handle);
- __ mr(R5_ARG3, R0); // saved_sp
__ mr(R6_ARG4, R1_SP);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub));
- __ restore_volatile_gprs(R1_SP, 112); // Except R0.
__ pop_frame();
- __ restore_LR_CR(R0);
+ __ restore_LR_CR(tmp);
+ __ restore_volatile_gprs(R1_SP, -nbytes_save); // except R0
BLOCK_COMMENT("} trace_method_handle");
}
diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad
index 51a9762..a9d576c 100644
--- a/hotspot/src/cpu/ppc/vm/ppc.ad
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad
@@ -1,6 +1,6 @@
//
-// Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
-// Copyright 2012, 2014 SAP AG. All rights reserved.
+// Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+// Copyright 2012, 2015 SAP AG. 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
@@ -2698,7 +2698,7 @@
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
__ relocate(a.rspec());
} else if (constant_reloc == relocInfo::metadata_type) {
- AddressLiteral a = __ allocate_metadata_address((Metadata *)val);
+ AddressLiteral a = __ constant_metadata_address((Metadata *)val);
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
__ relocate(a.rspec());
} else {
@@ -2727,7 +2727,7 @@
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
__ relocate(a.rspec());
} else if (constant_reloc == relocInfo::metadata_type) {
- AddressLiteral a = __ allocate_metadata_address((Metadata *)val);
+ AddressLiteral a = __ constant_metadata_address((Metadata *)val);
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
__ relocate(a.rspec());
} else { // non-oop pointers, e.g. card mark base, heap top
@@ -6029,6 +6029,20 @@
ins_pipe(pipe_class_default);
%}
+// Optimize DecodeN for disjoint base.
+// Load base of compressed oops into a register
+instruct loadBase(iRegLdst dst) %{
+ effect(DEF dst);
+
+ format %{ "MR $dst, r30_heapbase" %}
+ size(4);
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_or);
+ __ mr($dst$$Register, R30);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
// Loading ConN must be postalloc expanded so that edges between
// the nodes are safe. They may not interfere with a safepoint.
// GL TODO: This needs three instructions: better put this into the constant pool.
@@ -6724,13 +6738,12 @@
ins_pipe(pipe_class_default);
%}
-// base != 0
-// 32G aligned narrow oop base.
-instruct encodeP_32GAligned(iRegNdst dst, iRegPsrc src) %{
+// Disjoint narrow oop base.
+instruct encodeP_Disjoint(iRegNdst dst, iRegPsrc src) %{
match(Set dst (EncodeP src));
- predicate(false /* TODO: PPC port Universe::narrow_oop_base_disjoint()*/);
+ predicate(Universe::narrow_oop_base_disjoint());
- format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with 32G aligned base" %}
+ format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with disjoint base" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_rldicl);
@@ -6745,7 +6758,7 @@
effect(TEMP crx);
predicate(n->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull &&
Universe::narrow_oop_shift() != 0 &&
- true /* TODO: PPC port Universe::narrow_oop_base_overlaps()*/);
+ Universe::narrow_oop_base_overlaps());
format %{ "EncodeP $dst, $crx, $src \t// postalloc expanded" %}
postalloc_expand( postalloc_expand_encode_oop(dst, src, crx));
@@ -6756,7 +6769,7 @@
match(Set dst (EncodeP src));
predicate(n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull &&
Universe::narrow_oop_shift() != 0 &&
- true /* TODO: PPC port Universe::narrow_oop_base_overlaps()*/);
+ Universe::narrow_oop_base_overlaps());
format %{ "EncodeP $dst, $src\t// $src != Null, postalloc expanded" %}
postalloc_expand( postalloc_expand_encode_oop_not_null(dst, src) );
@@ -6876,6 +6889,7 @@
n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant) &&
Universe::narrow_oop_shift() != 0 &&
Universe::narrow_oop_base() != 0);
+ ins_cost(4 * DEFAULT_COST); // Should be more expensive than decodeN_Disjoint_isel_Ex.
effect(TEMP crx);
format %{ "DecodeN $dst, $src \t// Kills $crx, postalloc expanded" %}
@@ -6897,6 +6911,106 @@
ins_pipe(pipe_class_default);
%}
+// Optimize DecodeN for disjoint base.
+// Shift narrow oop and or it into register that already contains the heap base.
+// Base == dst must hold, and is assured by construction in postaloc_expand.
+instruct decodeN_mergeDisjoint(iRegPdst dst, iRegNsrc src, iRegLsrc base) %{
+ match(Set dst (DecodeN src));
+ effect(TEMP base);
+ predicate(false);
+
+ format %{ "RLDIMI $dst, $src, shift, 32-shift \t// DecodeN (disjoint base)" %}
+ size(4);
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_rldimi);
+ __ rldimi($dst$$Register, $src$$Register, Universe::narrow_oop_shift(), 32-Universe::narrow_oop_shift());
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// Optimize DecodeN for disjoint base.
+// This node requires only one cycle on the critical path.
+// We must postalloc_expand as we can not express use_def effects where
+// the used register is L and the def'ed register P.
+instruct decodeN_Disjoint_notNull_Ex(iRegPdst dst, iRegNsrc src) %{
+ match(Set dst (DecodeN src));
+ effect(TEMP_DEF dst);
+ predicate((n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull ||
+ n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant) &&
+ Universe::narrow_oop_base_disjoint());
+ ins_cost(DEFAULT_COST);
+
+ format %{ "MOV $dst, R30 \t\n"
+ "RLDIMI $dst, $src, shift, 32-shift \t// decode with disjoint base" %}
+ postalloc_expand %{
+ loadBaseNode *n1 = new loadBaseNode();
+ n1->add_req(NULL);
+ n1->_opnds[0] = op_dst;
+
+ decodeN_mergeDisjointNode *n2 = new decodeN_mergeDisjointNode();
+ n2->add_req(n_region, n_src, n1);
+ n2->_opnds[0] = op_dst;
+ n2->_opnds[1] = op_src;
+ n2->_opnds[2] = op_dst;
+ n2->_bottom_type = _bottom_type;
+
+ ra_->set_pair(n1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+ ra_->set_pair(n2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+
+ nodes->push(n1);
+ nodes->push(n2);
+ %}
+%}
+
+instruct decodeN_Disjoint_isel_Ex(iRegPdst dst, iRegNsrc src, flagsReg crx) %{
+ match(Set dst (DecodeN src));
+ effect(TEMP_DEF dst, TEMP crx);
+ predicate((n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull &&
+ n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant) &&
+ Universe::narrow_oop_base_disjoint() && VM_Version::has_isel());
+ ins_cost(3 * DEFAULT_COST);
+
+ format %{ "DecodeN $dst, $src \t// decode with disjoint base using isel" %}
+ postalloc_expand %{
+ loadBaseNode *n1 = new loadBaseNode();
+ n1->add_req(NULL);
+ n1->_opnds[0] = op_dst;
+
+ cmpN_reg_imm0Node *n_compare = new cmpN_reg_imm0Node();
+ n_compare->add_req(n_region, n_src);
+ n_compare->_opnds[0] = op_crx;
+ n_compare->_opnds[1] = op_src;
+ n_compare->_opnds[2] = new immN_0Oper(TypeNarrowOop::NULL_PTR);
+
+ decodeN_mergeDisjointNode *n2 = new decodeN_mergeDisjointNode();
+ n2->add_req(n_region, n_src, n1);
+ n2->_opnds[0] = op_dst;
+ n2->_opnds[1] = op_src;
+ n2->_opnds[2] = op_dst;
+ n2->_bottom_type = _bottom_type;
+
+ cond_set_0_ptrNode *n_cond_set = new cond_set_0_ptrNode();
+ n_cond_set->add_req(n_region, n_compare, n2);
+ n_cond_set->_opnds[0] = op_dst;
+ n_cond_set->_opnds[1] = op_crx;
+ n_cond_set->_opnds[2] = op_dst;
+ n_cond_set->_bottom_type = _bottom_type;
+
+ assert(ra_->is_oop(this) == true, "A decodeN node must produce an oop!");
+ ra_->set_oop(n_cond_set, true);
+
+ ra_->set_pair(n1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+ ra_->set_pair(n_compare->_idx, ra_->get_reg_second(n_crx), ra_->get_reg_first(n_crx));
+ ra_->set_pair(n2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+ ra_->set_pair(n_cond_set->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+
+ nodes->push(n1);
+ nodes->push(n_compare);
+ nodes->push(n2);
+ nodes->push(n_cond_set);
+ %}
+%}
+
// src != 0, shift != 0, base != 0
instruct decodeN_notNull_addBase_Ex(iRegPdst dst, iRegNsrc src) %{
match(Set dst (DecodeN src));
@@ -6904,6 +7018,7 @@
n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant) &&
Universe::narrow_oop_shift() != 0 &&
Universe::narrow_oop_base() != 0);
+ ins_cost(2 * DEFAULT_COST);
format %{ "DecodeN $dst, $src \t// $src != NULL, postalloc expanded" %}
postalloc_expand( postalloc_expand_decode_oop_not_null(dst, src));
@@ -6973,13 +7088,12 @@
ins_pipe(pipe_class_default);
%}
-// base != 0
-// 32G aligned narrow oop base.
-instruct encodePKlass_32GAligned(iRegNdst dst, iRegPsrc src) %{
+// Disjoint narrow oop base.
+instruct encodePKlass_Disjoint(iRegNdst dst, iRegPsrc src) %{
match(Set dst (EncodePKlass src));
predicate(false /* TODO: PPC port Universe::narrow_klass_base_disjoint()*/);
- format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with 32G aligned base" %}
+ format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with disjoint base" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_rldicl);
@@ -7486,7 +7600,7 @@
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_compound);
__ cmpxchgd($crx$$CondRegister, R0, $oldVal$$Register, $newVal$$Register, $mem_ptr$$Register,
- MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+ MacroAssembler::MemBarAcq, MacroAssembler::cmpxchgx_hint_atomic_update(),
noreg, NULL, true);
%}
ins_pipe(pipe_class_default);
@@ -10476,7 +10590,7 @@
match(Set crx (CmpN src1 src2));
size(4);
- ins_cost(DEFAULT_COST);
+ ins_cost(2);
format %{ "CMPLW $crx, $src1, $src2 \t// compressed ptr" %}
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_cmpl);
@@ -10488,7 +10602,7 @@
instruct cmpN_reg_imm0(flagsReg crx, iRegNsrc src1, immN_0 src2) %{
match(Set crx (CmpN src1 src2));
// Make this more expensive than zeroCheckN_iReg_imm0.
- ins_cost(DEFAULT_COST);
+ ins_cost(2);
format %{ "CMPLWI $crx, $src1, $src2 \t// compressed ptr" %}
size(4);
@@ -10508,6 +10622,7 @@
_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne &&
_leaf->as_If()->_prob >= PROB_LIKELY_MAG(4) &&
Matcher::branches_to_uncommon_trap(_leaf));
+ ins_cost(1); // Should not be cheaper than zeroCheckN.
ins_is_TrapBasedCheckNode(true);
@@ -10889,7 +11004,7 @@
instruct partialSubtypeCheck(iRegPdst result, iRegP_N2P subklass, iRegP_N2P superklass,
iRegPdst tmp_klass, iRegPdst tmp_arrayptr) %{
match(Set result (PartialSubtypeCheck subklass superklass));
- effect(TEMP result, TEMP tmp_klass, TEMP tmp_arrayptr);
+ effect(TEMP_DEF result, TEMP tmp_klass, TEMP tmp_arrayptr);
ins_cost(DEFAULT_COST*10);
format %{ "PartialSubtypeCheck $result = ($subklass instanceOf $superklass) tmp: $tmp_klass, $tmp_arrayptr" %}
@@ -11000,7 +11115,7 @@
predicate(SpecialStringIndexOf); // type check implicit by parameter type, See Matcher::match_rule_supported
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm)));
- effect(TEMP result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1);
+ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1);
ins_cost(150);
format %{ "String IndexOf CSCL1 $haystack[0..$haycnt], $needleImm+$offsetImm[0..$needlecntImm]"
@@ -11037,7 +11152,7 @@
iRegIdst tmp1, iRegIdst tmp2,
flagsRegCR0 cr0, flagsRegCR1 cr1) %{
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
- effect(USE_KILL needle, /* TDEF needle, */ TEMP result,
+ effect(USE_KILL needle, /* TDEF needle, */ TEMP_DEF result,
TEMP tmp1, TEMP tmp2);
// Required for EA: check if it is still a type_array.
predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
@@ -11084,7 +11199,7 @@
iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5,
flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6) %{
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
- effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP result,
+ effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6);
// Required for EA: check if it is still a type_array.
predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
@@ -11118,7 +11233,7 @@
flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6) %{
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt)));
effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/
- TEMP result,
+ TEMP_DEF result,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6);
predicate(SpecialStringIndexOf); // See Matcher::match_rule_supported.
ins_cost(300);
@@ -11142,7 +11257,7 @@
iRegPdst tmp1, iRegPdst tmp2,
flagsRegCR0 cr0, flagsRegCR6 cr6, regCTR ctr) %{
match(Set result (StrEquals (Binary str1 str2) cntImm));
- effect(TEMP result, TEMP tmp1, TEMP tmp2,
+ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2,
KILL cr0, KILL cr6, KILL ctr);
predicate(SpecialStringEquals); // See Matcher::match_rule_supported.
ins_cost(250);
@@ -11165,7 +11280,7 @@
iRegPdst tmp1, iRegPdst tmp2, iRegPdst tmp3, iRegPdst tmp4, iRegPdst tmp5,
flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{
match(Set result (StrEquals (Binary str1 str2) cnt));
- effect(TEMP result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5,
+ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5,
KILL cr0, KILL cr1, KILL cr6, KILL ctr);
predicate(SpecialStringEquals); // See Matcher::match_rule_supported.
ins_cost(300);
@@ -11188,7 +11303,7 @@
instruct string_compare(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result,
iRegPdst tmp, flagsRegCR0 cr0, regCTR ctr) %{
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP result, TEMP tmp, KILL cr0, KILL ctr);
+ effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP_DEF result, TEMP tmp, KILL cr0, KILL ctr);
ins_cost(300);
ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
diff --git a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp
index f3709eb..1187443 100644
--- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -483,15 +483,6 @@
}
-jbyte* G1PostBarrierStub::_byte_map_base = NULL;
-
-jbyte* G1PostBarrierStub::byte_map_base_slow() {
- BarrierSet* bs = Universe::heap()->barrier_set();
- assert(bs->is_a(BarrierSet::G1SATBCTLogging),
- "Must be if we're using this.");
- return ((G1SATBCardTableModRefBS*)bs)->byte_map_base;
-}
-
void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp
index 51f237b..153bfbd 100644
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp
@@ -1374,6 +1374,7 @@
}
void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocation_count,
+ Register method_counters,
Register Rtmp,
Label &profile_continue) {
assert(ProfileInterpreter, "must be profiling interpreter");
@@ -1386,9 +1387,8 @@
br_notnull_short(ImethodDataPtr, Assembler::pn, done);
// Test to see if we should create a method data oop
- AddressLiteral profile_limit((address) &InvocationCounter::InterpreterProfileLimit);
- sethi(profile_limit, Rtmp);
- ld(Rtmp, profile_limit.low10(), Rtmp);
+ Address profile_limit(method_counters, MethodCounters::interpreter_profile_limit_offset());
+ ld(profile_limit, Rtmp);
cmp(invocation_count, Rtmp);
// Use long branches because call_VM() code and following code generated by
// test_backedge_count_for_osr() is large in debug VM.
@@ -2375,6 +2375,7 @@
#ifndef CC_INTERP
void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_count,
+ Register method_counters,
Register branch_bcp,
Register Rtmp ) {
Label did_not_overflow;
@@ -2382,8 +2383,8 @@
assert_different_registers(backedge_count, Rtmp, branch_bcp);
assert(UseOnStackReplacement,"Must UseOnStackReplacement to test_backedge_count_for_osr");
- AddressLiteral limit(&InvocationCounter::InterpreterBackwardBranchLimit);
- load_contents(limit, Rtmp);
+ Address limit(method_counters, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()));
+ ld(limit, Rtmp);
cmp_and_br_short(backedge_count, Rtmp, Assembler::lessUnsigned, Assembler::pt, did_not_overflow);
// When ProfileInterpreter is on, the backedge_count comes from the
@@ -2500,17 +2501,13 @@
// Jump if ((*counter_addr += increment) & mask) satisfies the condition.
void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
- int increment, int mask,
+ int increment, Address mask_addr,
Register scratch1, Register scratch2,
Condition cond, Label *where) {
ld(counter_addr, scratch1);
add(scratch1, increment, scratch1);
- if (is_simm13(mask)) {
- andcc(scratch1, mask, G0);
- } else {
- set(mask, scratch2);
- andcc(scratch1, scratch2, G0);
- }
+ ld(mask_addr, scratch2);
+ andcc(scratch1, scratch2, G0);
br(cond, false, Assembler::pn, *where);
delayed()->st(scratch1, counter_addr);
}
diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp
index 5ba547d..862611c 100644
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp
@@ -267,7 +267,7 @@
void increment_invocation_counter( Register Rcounters, Register Rtmp, Register Rtmp2 );
void increment_backedge_counter( Register Rcounters, Register Rtmp, Register Rtmp2 );
#ifndef CC_INTERP
- void test_backedge_count_for_osr( Register backedge_count, Register branch_bcp, Register Rtmp );
+ void test_backedge_count_for_osr(Register backedge_count, Register method_counters, Register branch_bcp, Register Rtmp );
#endif /* CC_INTERP */
// Object locking
@@ -280,7 +280,7 @@
void set_method_data_pointer_for_bcp();
void test_method_data_pointer(Label& zero_continue);
void verify_method_data_pointer();
- void test_invocation_counter_for_mdp(Register invocation_count, Register Rtmp, Label &profile_continue);
+ void test_invocation_counter_for_mdp(Register invocation_count, Register method_counters, Register Rtmp, Label &profile_continue);
void set_mdp_data_at(int constant, Register value);
void increment_mdp_data_at(Address counter, Register bumped_count,
@@ -291,7 +291,7 @@
Register bumped_count, Register scratch2,
bool decrement = false);
void increment_mask_and_jump(Address counter_addr,
- int increment, int mask,
+ int increment, Address mask_addr,
Register scratch1, Register scratch2,
Condition cond, Label *where);
void set_mdp_flag_at(int flag_constant, Register scratch);
diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
index 93f8780..c3039d5 100644
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
@@ -282,12 +282,11 @@
void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue) {
// Note: In tiered we increment either counters in MethodCounters* or in
// MDO depending if we're profiling or not.
- const Register Rcounters = G3_scratch;
+ const Register G3_method_counters = G3_scratch;
Label done;
if (TieredCompilation) {
const int increment = InvocationCounter::count_increment;
- const int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
Label no_mdo;
if (ProfileInterpreter) {
// If no method data exists, go to profile_continue.
@@ -297,6 +296,7 @@
Address mdo_invocation_counter(G4_scratch,
in_bytes(MethodData::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ Address mask(G4_scratch, in_bytes(MethodData::invoke_mask_offset()));
__ increment_mask_and_jump(mdo_invocation_counter, increment, mask,
G3_scratch, Lscratch,
Assembler::zero, overflow);
@@ -305,20 +305,21 @@
// Increment counter in MethodCounters*
__ bind(no_mdo);
- Address invocation_counter(Rcounters,
+ Address invocation_counter(G3_method_counters,
in_bytes(MethodCounters::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
- __ get_method_counters(Lmethod, Rcounters, done);
+ __ get_method_counters(Lmethod, G3_method_counters, done);
+ Address mask(G3_method_counters, in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask,
G4_scratch, Lscratch,
Assembler::zero, overflow);
__ bind(done);
- } else {
+ } else { // not TieredCompilation
// Update standard invocation counters
- __ get_method_counters(Lmethod, Rcounters, done);
- __ increment_invocation_counter(Rcounters, O0, G4_scratch);
+ __ get_method_counters(Lmethod, G3_method_counters, done);
+ __ increment_invocation_counter(G3_method_counters, O0, G4_scratch);
if (ProfileInterpreter) {
- Address interpreter_invocation_counter(Rcounters,
+ Address interpreter_invocation_counter(G3_method_counters,
in_bytes(MethodCounters::interpreter_invocation_counter_offset()));
__ ld(interpreter_invocation_counter, G4_scratch);
__ inc(G4_scratch);
@@ -327,16 +328,16 @@
if (ProfileInterpreter && profile_method != NULL) {
// Test to see if we should create a method data oop
- AddressLiteral profile_limit((address)&InvocationCounter::InterpreterProfileLimit);
- __ load_contents(profile_limit, G3_scratch);
- __ cmp_and_br_short(O0, G3_scratch, Assembler::lessUnsigned, Assembler::pn, *profile_method_continue);
+ Address profile_limit(G3_method_counters, in_bytes(MethodCounters::interpreter_profile_limit_offset()));
+ __ ld(profile_limit, G1_scratch);
+ __ cmp_and_br_short(O0, G1_scratch, Assembler::lessUnsigned, Assembler::pn, *profile_method_continue);
// if no method data exists, go to profile_method
__ test_method_data_pointer(*profile_method);
}
- AddressLiteral invocation_limit((address)&InvocationCounter::InterpreterInvocationLimit);
- __ load_contents(invocation_limit, G3_scratch);
+ Address invocation_limit(G3_method_counters, in_bytes(MethodCounters::interpreter_invocation_limit_offset()));
+ __ ld(invocation_limit, G3_scratch);
__ cmp(O0, G3_scratch);
__ br(Assembler::greaterEqualUnsigned, false, Assembler::pn, *overflow); // Far distance
__ delayed()->nop();
diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp
index 9424b1b..438d376 100644
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp
@@ -1599,13 +1599,12 @@
// Bump bytecode pointer by displacement (take the branch)
__ delayed()->add( O1_disp, Lbcp, Lbcp ); // add to bc addr
- const Register Rcounters = G3_scratch;
- __ get_method_counters(Lmethod, Rcounters, Lforward);
+ const Register G3_method_counters = G3_scratch;
+ __ get_method_counters(Lmethod, G3_method_counters, Lforward);
if (TieredCompilation) {
Label Lno_mdo, Loverflow;
int increment = InvocationCounter::count_increment;
- int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
if (ProfileInterpreter) {
// If no method data exists, go to profile_continue.
__ ld_ptr(Lmethod, Method::method_data_offset(), G4_scratch);
@@ -1614,6 +1613,7 @@
// Increment backedge counter in the MDO
Address mdo_backedge_counter(G4_scratch, in_bytes(MethodData::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ Address mask(G4_scratch, in_bytes(MethodData::backedge_mask_offset()));
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask, G3_scratch, O0,
Assembler::notZero, &Lforward);
__ ba_short(Loverflow);
@@ -1621,9 +1621,10 @@
// If there's no MDO, increment counter in MethodCounters*
__ bind(Lno_mdo);
- Address backedge_counter(Rcounters,
+ Address backedge_counter(G3_method_counters,
in_bytes(MethodCounters::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ Address mask(G3_method_counters, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(backedge_counter, increment, mask, G4_scratch, O0,
Assembler::notZero, &Lforward);
__ bind(Loverflow);
@@ -1663,18 +1664,19 @@
__ jmp(O2, G0);
__ delayed()->nop();
- } else {
+ } else { // not TieredCompilation
// Update Backedge branch separately from invocations
const Register G4_invoke_ctr = G4;
- __ increment_backedge_counter(Rcounters, G4_invoke_ctr, G1_scratch);
+ __ increment_backedge_counter(G3_method_counters, G4_invoke_ctr, G1_scratch);
if (ProfileInterpreter) {
- __ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_scratch, Lforward);
+ __ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_method_counters, G1_scratch, Lforward);
if (UseOnStackReplacement) {
- __ test_backedge_count_for_osr(O2_bumped_count, l_cur_bcp, G3_scratch);
+
+ __ test_backedge_count_for_osr(O2_bumped_count, G3_method_counters, l_cur_bcp, G1_scratch);
}
} else {
if (UseOnStackReplacement) {
- __ test_backedge_count_for_osr(G4_invoke_ctr, l_cur_bcp, G3_scratch);
+ __ test_backedge_count_for_osr(G4_invoke_ctr, G3_method_counters, l_cur_bcp, G1_scratch);
}
}
}
diff --git a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp
index 718c829..919c2a6 100644
--- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -541,15 +541,6 @@
}
-jbyte* G1PostBarrierStub::_byte_map_base = NULL;
-
-jbyte* G1PostBarrierStub::byte_map_base_slow() {
- BarrierSet* bs = Universe::heap()->barrier_set();
- assert(bs->is_a(BarrierSet::G1SATBCTLogging),
- "Must be if we're using this.");
- return ((G1SATBCardTableModRefBS*)bs)->byte_map_base;
-}
-
void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
assert(addr()->is_register(), "Precondition.");
diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp
index 181ee15..9aa4587 100644
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp
@@ -1360,7 +1360,7 @@
// Jump if ((*counter_addr += increment) & mask) satisfies the condition.
void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
- int increment, int mask,
+ int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where) {
if (!preloaded) {
diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp
index e4d6136..2cd8e16 100644
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp
@@ -182,7 +182,7 @@
void increment_mdp_data_at(Register mdp_in, Register reg, int constant,
bool decrement = false);
void increment_mask_and_jump(Address counter_addr,
- int increment, int mask,
+ int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where);
void set_mdp_flag_at(Register mdp_in, int flag_constant);
diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp
index 23e3b97..76335ca 100644
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp
@@ -1426,7 +1426,7 @@
// Jump if ((*counter_addr += increment) & mask) satisfies the condition.
void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
- int increment, int mask,
+ int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where) {
if (!preloaded) {
diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp
index a1cd446..c4ed238 100644
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp
@@ -191,7 +191,7 @@
void increment_mdp_data_at(Register mdp_in, Register reg, int constant,
bool decrement = false);
void increment_mask_and_jump(Address counter_addr,
- int increment, int mask,
+ int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where);
void set_mdp_flag_at(Register mdp_in, int flag_constant);
diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
index 93772f3..69c8533 100644
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
@@ -346,7 +346,6 @@
// depending if we're profiling or not.
if (TieredCompilation) {
int increment = InvocationCounter::count_increment;
- int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
Label no_mdo;
if (ProfileInterpreter) {
// Are we profiling?
@@ -356,6 +355,7 @@
// Increment counter in the MDO
const Address mdo_invocation_counter(rax, in_bytes(MethodData::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ const Address mask(rax, in_bytes(MethodData::invoke_mask_offset()));
__ increment_mask_and_jump(mdo_invocation_counter, increment, mask, rcx, false, Assembler::zero, overflow);
__ jmp(done);
}
@@ -366,11 +366,12 @@
InvocationCounter::counter_offset());
__ get_method_counters(rbx, rax, done);
+ const Address mask(rax, in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask,
rcx, false, Assembler::zero, overflow);
__ bind(done);
- } else {
- const Address backedge_counter (rax,
+ } else { // not TieredCompilation
+ const Address backedge_counter(rax,
MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset());
const Address invocation_counter(rax,
@@ -400,16 +401,16 @@
if (ProfileInterpreter && profile_method != NULL) {
// Test to see if we should create a method data oop
- __ cmp32(rcx,
- ExternalAddress((address)&InvocationCounter::InterpreterProfileLimit));
+ __ movptr(rax, Address(rbx, Method::method_counters_offset()));
+ __ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, *profile_method_continue);
// if no method data exists, go to profile_method
__ test_method_data_pointer(rax, *profile_method);
}
- __ cmp32(rcx,
- ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
+ __ movptr(rax, Address(rbx, Method::method_counters_offset()));
+ __ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_invocation_limit_offset())));
__ jcc(Assembler::aboveEqual, *overflow);
__ bind(done);
}
diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
index f3390c9..6318a95 100644
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
@@ -299,7 +299,6 @@
// Note: In tiered we increment either counters in Method* or in MDO depending if we're profiling or not.
if (TieredCompilation) {
int increment = InvocationCounter::count_increment;
- int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
Label no_mdo;
if (ProfileInterpreter) {
// Are we profiling?
@@ -309,6 +308,7 @@
// Increment counter in the MDO
const Address mdo_invocation_counter(rax, in_bytes(MethodData::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ const Address mask(rax, in_bytes(MethodData::invoke_mask_offset()));
__ increment_mask_and_jump(mdo_invocation_counter, increment, mask, rcx, false, Assembler::zero, overflow);
__ jmp(done);
}
@@ -318,10 +318,11 @@
MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset());
__ get_method_counters(rbx, rax, done);
+ const Address mask(rax, in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask, rcx,
false, Assembler::zero, overflow);
__ bind(done);
- } else {
+ } else { // not TieredCompilation
const Address backedge_counter(rax,
MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset());
@@ -350,14 +351,16 @@
if (ProfileInterpreter && profile_method != NULL) {
// Test to see if we should create a method data oop
- __ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterProfileLimit));
+ __ movptr(rax, Address(rbx, Method::method_counters_offset()));
+ __ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, *profile_method_continue);
// if no method data exists, go to profile_method
__ test_method_data_pointer(rax, *profile_method);
}
- __ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
+ __ movptr(rax, Address(rbx, Method::method_counters_offset()));
+ __ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_invocation_limit_offset())));
__ jcc(Assembler::aboveEqual, *overflow);
__ bind(done);
}
diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp
index 2187056..d0bdc33 100644
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp
@@ -1621,7 +1621,6 @@
if (TieredCompilation) {
Label no_mdo;
int increment = InvocationCounter::count_increment;
- int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
if (ProfileInterpreter) {
// Are we profiling?
__ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset())));
@@ -1630,6 +1629,7 @@
// Increment the MDO backedge counter
const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset()));
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
__ jmp(dispatch);
@@ -1637,9 +1637,10 @@
__ bind(no_mdo);
// Increment backedge counter in MethodCounters*
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
+ const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
- } else {
+ } else { // not TieredCompilation
// increment counter
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
__ movl(rax, Address(rcx, be_offset)); // load backedge counter
@@ -1653,8 +1654,7 @@
if (ProfileInterpreter) {
// Test to see if we should create a method data oop
- __ cmp32(rax,
- ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit));
+ __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, dispatch);
// if no method data exists, go to profile method
@@ -1662,8 +1662,7 @@
if (UseOnStackReplacement) {
// check for overflow against rbx, which is the MDO taken count
- __ cmp32(rbx,
- ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
+ __ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::below, dispatch);
// When ProfileInterpreter is on, the backedge_count comes from the
@@ -1678,8 +1677,7 @@
} else {
if (UseOnStackReplacement) {
// check for overflow against rax, which is the sum of the counters
- __ cmp32(rax,
- ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
+ __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::aboveEqual, backedge_counter_overflow);
}
diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp
index b1b1b00..82072f0 100644
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp
@@ -1642,7 +1642,6 @@
if (TieredCompilation) {
Label no_mdo;
int increment = InvocationCounter::count_increment;
- int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
if (ProfileInterpreter) {
// Are we profiling?
__ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset())));
@@ -1651,6 +1650,7 @@
// Increment the MDO backedge counter
const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset()));
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
__ jmp(dispatch);
@@ -1658,9 +1658,10 @@
__ bind(no_mdo);
// Increment backedge counter in MethodCounters*
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
+ const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
- } else {
+ } else { // not TieredCompilation
// increment counter
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
__ movl(rax, Address(rcx, be_offset)); // load backedge counter
@@ -1674,8 +1675,7 @@
if (ProfileInterpreter) {
// Test to see if we should create a method data oop
- __ cmp32(rax,
- ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit));
+ __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, dispatch);
// if no method data exists, go to profile method
@@ -1683,8 +1683,7 @@
if (UseOnStackReplacement) {
// check for overflow against ebx which is the MDO taken count
- __ cmp32(rbx,
- ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
+ __ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::below, dispatch);
// When ProfileInterpreter is on, the backedge_count comes
@@ -1702,8 +1701,7 @@
if (UseOnStackReplacement) {
// check for overflow against eax, which is the sum of the
// counters
- __ cmp32(rax,
- ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
+ __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::aboveEqual, backedge_counter_overflow);
}
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
index fb09815..f8f17d5 100644
--- a/hotspot/src/os/windows/vm/os_windows.cpp
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
@@ -428,9 +428,9 @@
}
// Diagnostic code to investigate JDK-6573254
- int res = 50115; // non-java thread
+ int res = 30115; // non-java thread
if (thread->is_Java_thread()) {
- res = 40115; // java thread
+ res = 20115; // java thread
}
// Install a win32 structured exception handler around every thread created
@@ -3791,6 +3791,7 @@
static INIT_ONCE init_once_crit_sect = INIT_ONCE_STATIC_INIT;
static CRITICAL_SECTION crit_sect;
+ static volatile jint process_exiting = 0;
int i, j;
DWORD res;
HANDLE hproc, hthr;
@@ -3798,10 +3799,10 @@
// The first thread that reached this point, initializes the critical section.
if (!InitOnceExecuteOnce(&init_once_crit_sect, init_crit_sect_call, &crit_sect, NULL)) {
warning("crit_sect initialization failed in %s: %d\n", __FILE__, __LINE__);
- } else {
+ } else if (OrderAccess::load_acquire(&process_exiting) == 0) {
EnterCriticalSection(&crit_sect);
- if (what == EPT_THREAD) {
+ if (what == EPT_THREAD && OrderAccess::load_acquire(&process_exiting) == 0) {
// Remove from the array those handles of the threads that have completed exiting.
for (i = 0, j = 0; i < handle_count; ++i) {
res = WaitForSingleObject(handles[i], 0 /* don't wait */);
@@ -3856,7 +3857,7 @@
// The current exiting thread has stored its handle in the array, and now
// should leave the critical section before calling _endthreadex().
- } else { // what != EPT_THREAD
+ } else if (what != EPT_THREAD) {
if (handle_count > 0) {
// Before ending the process, make sure all the threads that had called
// _endthreadex() completed.
@@ -3882,24 +3883,28 @@
handle_count = 0;
}
- // End the process, not leaving critical section.
- // This makes sure no other thread executes exit-related code at the same
- // time, thus a race is avoided.
- if (what == EPT_PROCESS) {
- ::exit(exit_code);
- } else {
- _exit(exit_code);
- }
+ OrderAccess::release_store(&process_exiting, 1);
}
LeaveCriticalSection(&crit_sect);
}
+
+ if (what == EPT_THREAD) {
+ while (OrderAccess::load_acquire(&process_exiting) != 0) {
+ // Some other thread is about to call exit(), so we
+ // don't let the current thread proceed to _endthreadex()
+ SuspendThread(GetCurrentThread());
+ // Avoid busy-wait loop, if SuspendThread() failed.
+ Sleep(EXIT_TIMEOUT);
+ }
+ }
}
// We are here if either
// - there's no 'race at exit' bug on this OS release;
// - initialization of the critical section failed (unlikely);
- // - the current thread has stored its handle and left the critical section.
+ // - the current thread has stored its handle and left the critical section;
+ // - the process-exiting thread has raised the flag and left the critical section.
if (what == EPT_THREAD) {
_endthreadex((unsigned)exit_code);
} else if (what == EPT_PROCESS) {
diff --git a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp
index e3a4f4d..05a8c70 100644
--- a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp
+++ b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -601,15 +601,6 @@
LIR_Opr _addr;
LIR_Opr _new_val;
- static jbyte* _byte_map_base;
- static jbyte* byte_map_base_slow();
- static jbyte* byte_map_base() {
- if (_byte_map_base == NULL) {
- _byte_map_base = byte_map_base_slow();
- }
- return _byte_map_base;
- }
-
public:
// addr (the address of the object head) and new_val must be registers.
G1PostBarrierStub(LIR_Opr addr, LIR_Opr new_val): _addr(addr), _new_val(new_val) { }
diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp
index 2beb72a..8fe99af 100644
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp
@@ -32,6 +32,7 @@
#include "ci/ciArrayKlass.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciObjArray.hpp"
+#include "runtime/arguments.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/vm_version.hpp"
@@ -3351,7 +3352,12 @@
if (!x->inlinee()->is_accessor()) {
CodeEmitInfo* info = state_for(x, x->state(), true);
// Notify the runtime very infrequently only to take care of counter overflows
- increment_event_counter_impl(info, x->inlinee(), (1 << Tier23InlineeNotifyFreqLog) - 1, InvocationEntryBci, false, true);
+ int freq_log = Tier23InlineeNotifyFreqLog;
+ double scale;
+ if (_method->has_option_value("CompileThresholdScaling", scale)) {
+ freq_log = Arguments::scaled_freq_log(freq_log, scale);
+ }
+ increment_event_counter_impl(info, x->inlinee(), right_n_bits(freq_log), InvocationEntryBci, false, true);
}
}
@@ -3366,7 +3372,11 @@
ShouldNotReachHere();
}
// Increment the appropriate invocation/backedge counter and notify the runtime.
- increment_event_counter_impl(info, info->scope()->method(), (1 << freq_log) - 1, bci, backedge, true);
+ double scale;
+ if (_method->has_option_value("CompileThresholdScaling", scale)) {
+ freq_log = Arguments::scaled_freq_log(freq_log, scale);
+ }
+ increment_event_counter_impl(info, info->scope()->method(), right_n_bits(freq_log), bci, backedge, true);
}
void LIRGenerator::decrement_age(CodeEmitInfo* info) {
diff --git a/hotspot/src/share/vm/classfile/compactHashtable.cpp b/hotspot/src/share/vm/classfile/compactHashtable.cpp
index 157b168..bd19755 100644
--- a/hotspot/src/share/vm/classfile/compactHashtable.cpp
+++ b/hotspot/src/share/vm/classfile/compactHashtable.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -221,6 +221,30 @@
return (const char*)end;
}
+template <class T, class N> void CompactHashtable<T, N>::symbols_do(SymbolClosure *cl) {
+ assert(!DumpSharedSpaces, "run-time only");
+ for (juint i = 0; i < _bucket_count; i ++) {
+ juint bucket_info = _buckets[i];
+ juint bucket_offset = BUCKET_OFFSET(bucket_info);
+ int bucket_type = BUCKET_TYPE(bucket_info);
+ juint* bucket = _buckets + bucket_offset;
+ juint* bucket_end = _buckets;
+
+ Symbol* sym;
+ if (bucket_type == COMPACT_BUCKET_TYPE) {
+ sym = (Symbol*)((void*)(_base_address + bucket[0]));
+ cl->do_symbol(&sym);
+ } else {
+ bucket_end += BUCKET_OFFSET(_buckets[i + 1]);
+ while (bucket < bucket_end) {
+ sym = (Symbol*)((void*)(_base_address + bucket[1]));
+ cl->do_symbol(&sym);
+ bucket += 2;
+ }
+ }
+ }
+}
+
// Explicitly instantiate these types
template class CompactHashtable<Symbol*, char>;
diff --git a/hotspot/src/share/vm/classfile/compactHashtable.hpp b/hotspot/src/share/vm/classfile/compactHashtable.hpp
index ac01fa7..3e32fc0 100644
--- a/hotspot/src/share/vm/classfile/compactHashtable.hpp
+++ b/hotspot/src/share/vm/classfile/compactHashtable.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -249,6 +249,9 @@
}
return NULL;
}
+
+ // iterate over symbols
+ void symbols_do(SymbolClosure *cl);
};
////////////////////////////////////////////////////////////////////////
diff --git a/hotspot/src/share/vm/classfile/symbolTable.cpp b/hotspot/src/share/vm/classfile/symbolTable.cpp
index 4df696f..3d08364 100644
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -82,6 +82,10 @@
// Call function for all symbols in the symbol table.
void SymbolTable::symbols_do(SymbolClosure *cl) {
+ // all symbols from shared table
+ _shared_table.symbols_do(cl);
+
+ // all symbols from the dynamic table
const int n = the_table()->table_size();
for (int i = 0; i < n; i++) {
for (HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp
index a44dd5c..6797d5d 100644
--- a/hotspot/src/share/vm/classfile/verifier.cpp
+++ b/hotspot/src/share/vm/classfile/verifier.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1546,10 +1546,15 @@
no_control_flow = true; break;
case Bytecodes::_getstatic :
case Bytecodes::_putstatic :
+ // pass TRUE, operand can be an array type for getstatic/putstatic.
+ verify_field_instructions(
+ &bcs, ¤t_frame, cp, true, CHECK_VERIFY(this));
+ no_control_flow = false; break;
case Bytecodes::_getfield :
case Bytecodes::_putfield :
+ // pass FALSE, operand can't be an array type for getfield/putfield.
verify_field_instructions(
- &bcs, ¤t_frame, cp, CHECK_VERIFY(this));
+ &bcs, ¤t_frame, cp, false, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_invokevirtual :
case Bytecodes::_invokespecial :
@@ -2107,6 +2112,7 @@
void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs,
StackMapFrame* current_frame,
constantPoolHandle cp,
+ bool allow_arrays,
TRAPS) {
u2 index = bcs->get_index_u2();
verify_cp_type(bcs->bci(), index, cp,
@@ -2126,8 +2132,8 @@
// Get referenced class type
VerificationType ref_class_type = cp_ref_index_to_type(
index, cp, CHECK_VERIFY(this));
- if (!ref_class_type.is_object()) {
- /* Unreachable? Class file parser verifies Fieldref contents */
+ if (!ref_class_type.is_object() &&
+ (!allow_arrays || !ref_class_type.is_array())) {
verify_error(ErrorContext::bad_type(bcs->bci(),
TypeOrigin::cp(index, ref_class_type)),
"Expecting reference to class in class %s at constant pool index %d",
diff --git a/hotspot/src/share/vm/classfile/verifier.hpp b/hotspot/src/share/vm/classfile/verifier.hpp
index 3495805..113e404 100644
--- a/hotspot/src/share/vm/classfile/verifier.hpp
+++ b/hotspot/src/share/vm/classfile/verifier.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -297,7 +297,7 @@
void verify_field_instructions(
RawBytecodeStream* bcs, StackMapFrame* current_frame,
- constantPoolHandle cp, TRAPS);
+ constantPoolHandle cp, bool allow_arrays, TRAPS);
void verify_invoke_init(
RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp
index af50207..5a546f5 100644
--- a/hotspot/src/share/vm/code/codeCache.cpp
+++ b/hotspot/src/share/vm/code/codeCache.cpp
@@ -233,8 +233,8 @@
ReservedCodeSpace CodeCache::reserve_heap_memory(size_t size) {
// Determine alignment
const size_t page_size = os::can_execute_large_page_memory() ?
- MIN2(os::page_size_for_region(InitialCodeCacheSize, 8),
- os::page_size_for_region(size, 8)) :
+ MIN2(os::page_size_for_region_aligned(InitialCodeCacheSize, 8),
+ os::page_size_for_region_aligned(size, 8)) :
os::vm_page_size();
const size_t granularity = os::vm_allocation_granularity();
const size_t r_align = MAX2(page_size, granularity);
diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp
index 4f0def8..71b3fc5 100644
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp
@@ -1470,7 +1470,9 @@
// The method may be explicitly excluded by the user.
bool quietly;
- if (CompilerOracle::should_exclude(method, quietly)) {
+ double scale;
+ if (CompilerOracle::should_exclude(method, quietly)
+ || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
if (!quietly) {
// This does not happen quietly...
ResourceMark rm;
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp
index 5ead54b..d5eaf9f 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp
@@ -162,8 +162,8 @@
"we should have already filtered out humongous regions");
assert(_end == orig_end(),
"we should have already filtered out humongous regions");
-
- _in_collection_set = false;
+ assert(!_in_collection_set,
+ err_msg("Should not clear heap region %u in the collection set", hrm_index()));
set_allocation_context(AllocationContext::system());
set_young_index_in_cset(-1);
diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
index a56c948..30ef7ce 100644
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
@@ -1194,8 +1194,10 @@
return real_forwardee(old);
}
- new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
- old, m, sz);
+ if (!_promotion_failed) {
+ new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
+ old, m, sz);
+ }
if (new_obj == NULL) {
// promotion failed, forward to self
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp
index 29fb547..a6cef46 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp
@@ -61,9 +61,9 @@
void GenerationSizer::initialize_size_info() {
trace_gen_sizes("ps heap raw");
- const size_t max_page_sz = os::page_size_for_region(_max_heap_byte_size, 8);
+ const size_t max_page_sz = os::page_size_for_region_aligned(_max_heap_byte_size, 8);
const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old
- const size_t min_page_sz = os::page_size_for_region(_min_heap_byte_size, min_pages);
+ const size_t min_page_sz = os::page_size_for_region_aligned(_min_heap_byte_size, min_pages);
const size_t page_sz = MIN2(max_page_sz, min_page_sz);
// Can a page size be something else than a power of two?
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp
index a8ab193..33e8f3f 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp
@@ -41,7 +41,7 @@
const size_t words = bits / BitsPerWord;
const size_t raw_bytes = words * sizeof(idx_t);
- const size_t page_sz = os::page_size_for_region(raw_bytes, 10);
+ const size_t page_sz = os::page_size_for_region_aligned(raw_bytes, 10);
const size_t granularity = os::vm_allocation_granularity();
_reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity));
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
index a546e54..28cff78 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
@@ -403,7 +403,7 @@
ParallelCompactData::create_vspace(size_t count, size_t element_size)
{
const size_t raw_bytes = count * element_size;
- const size_t page_sz = os::page_size_for_region(raw_bytes, 10);
+ const size_t page_sz = os::page_size_for_region_aligned(raw_bytes, 10);
const size_t granularity = os::vm_allocation_granularity();
_reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity));
diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp
index 2bf9a20..5ec7ec8 100644
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp
@@ -53,7 +53,7 @@
/*
* USELABELS - If using GCC, then use labels for the opcode dispatching
* rather -then a switch statement. This improves performance because it
- * gives us the oportunity to have the instructions that calculate the
+ * gives us the opportunity to have the instructions that calculate the
* next opcode to jump to be intermixed with the rest of the instructions
* that implement the opcode (see UPDATE_PC_AND_TOS_AND_CONTINUE macro).
*/
diff --git a/hotspot/src/share/vm/interpreter/invocationCounter.hpp b/hotspot/src/share/vm/interpreter/invocationCounter.hpp
index e0cb50c..0409b02 100644
--- a/hotspot/src/share/vm/interpreter/invocationCounter.hpp
+++ b/hotspot/src/share/vm/interpreter/invocationCounter.hpp
@@ -36,7 +36,7 @@
// Implementation notes: For space reasons, state & counter are both encoded in one word,
// The state is encoded using some of the least significant bits, the counter is using the
// more significant bits. The counter is incremented before a method is activated and an
-// action is triggered when when count() > limit().
+// action is triggered when count() > limit().
class InvocationCounter VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
@@ -48,7 +48,6 @@
number_of_state_bits = 2,
number_of_carry_bits = 1,
number_of_noncount_bits = number_of_state_bits + number_of_carry_bits,
- number_of_count_bits = BitsPerInt - number_of_noncount_bits,
state_limit = nth_bit(number_of_state_bits),
count_grain = nth_bit(number_of_state_bits + number_of_carry_bits),
carry_mask = right_n_bits(number_of_carry_bits) << number_of_state_bits,
@@ -68,6 +67,7 @@
count_increment = count_grain, // use this value to increment the 32bit _counter word
count_mask_value = count_mask, // use this value to mask the backedge counter
count_shift = number_of_noncount_bits,
+ number_of_count_bits = BitsPerInt - number_of_noncount_bits,
count_limit = nth_bit(number_of_count_bits - 1)
};
diff --git a/hotspot/src/share/vm/memory/heap.cpp b/hotspot/src/share/vm/memory/heap.cpp
index 5501700..67cc033 100644
--- a/hotspot/src/share/vm/memory/heap.cpp
+++ b/hotspot/src/share/vm/memory/heap.cpp
@@ -104,8 +104,8 @@
size_t page_size = os::vm_page_size();
if (os::can_execute_large_page_memory()) {
const size_t min_pages = 8;
- page_size = MIN2(os::page_size_for_region(committed_size, min_pages),
- os::page_size_for_region(rs.size(), min_pages));
+ page_size = MIN2(os::page_size_for_region_aligned(committed_size, min_pages),
+ os::page_size_for_region_aligned(rs.size(), min_pages));
}
const size_t granularity = os::vm_allocation_granularity();
diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp
index 62a1501..9e37b0b 100644
--- a/hotspot/src/share/vm/oops/method.cpp
+++ b/hotspot/src/share/vm/oops/method.cpp
@@ -412,15 +412,14 @@
}
methodHandle mh(m);
- ClassLoaderData* loader_data = mh->method_holder()->class_loader_data();
- MethodCounters* counters = MethodCounters::allocate(loader_data, THREAD);
+ MethodCounters* counters = MethodCounters::allocate(mh, THREAD);
if (HAS_PENDING_EXCEPTION) {
CompileBroker::log_metaspace_failure();
ClassLoaderDataGraph::set_metaspace_oom(true);
return NULL; // return the exception (which is cleared)
}
if (!mh->init_method_counters(counters)) {
- MetadataFactory::free_metadata(loader_data, counters);
+ MetadataFactory::free_metadata(mh->method_holder()->class_loader_data(), counters);
}
return mh->method_counters();
}
diff --git a/hotspot/src/share/vm/oops/methodCounters.cpp b/hotspot/src/share/vm/oops/methodCounters.cpp
index 25379d2..b78b6e8 100644
--- a/hotspot/src/share/vm/oops/methodCounters.cpp
+++ b/hotspot/src/share/vm/oops/methodCounters.cpp
@@ -23,10 +23,11 @@
*/
#include "precompiled.hpp"
#include "oops/methodCounters.hpp"
-#include "runtime/thread.inline.hpp"
+#include "runtime/handles.inline.hpp"
-MethodCounters* MethodCounters::allocate(ClassLoaderData* loader_data, TRAPS) {
- return new(loader_data, size(), false, MetaspaceObj::MethodCountersType, THREAD) MethodCounters();
+MethodCounters* MethodCounters::allocate(methodHandle mh, TRAPS) {
+ ClassLoaderData* loader_data = mh->method_holder()->class_loader_data();
+ return new(loader_data, size(), false, MetaspaceObj::MethodCountersType, THREAD) MethodCounters(mh);
}
void MethodCounters::clear_counters() {
diff --git a/hotspot/src/share/vm/oops/methodCounters.hpp b/hotspot/src/share/vm/oops/methodCounters.hpp
index a21d376..7d042bf 100644
--- a/hotspot/src/share/vm/oops/methodCounters.hpp
+++ b/hotspot/src/share/vm/oops/methodCounters.hpp
@@ -26,7 +26,9 @@
#define SHARE_VM_OOPS_METHODCOUNTERS_HPP
#include "oops/metadata.hpp"
+#include "compiler/compilerOracle.hpp"
#include "interpreter/invocationCounter.hpp"
+#include "runtime/arguments.hpp"
class MethodCounters: public MetaspaceObj {
friend class VMStructs;
@@ -45,7 +47,11 @@
// 3. (INT_MIN..0] - method is hot and will deopt and get
// recompiled without the counters
int _nmethod_age;
-
+ int _interpreter_invocation_limit; // per-method InterpreterInvocationLimit
+ int _interpreter_backward_branch_limit; // per-method InterpreterBackwardBranchLimit
+ int _interpreter_profile_limit; // per-method InterpreterProfileLimit
+ int _invoke_mask; // per-method Tier0InvokeNotifyFreqLog
+ int _backedge_mask; // per-method Tier0BackedgeNotifyFreqLog
#ifdef TIERED
float _rate; // Events (invocation and backedge counter increments) per millisecond
jlong _prev_time; // Previous time the rate was acquired
@@ -53,15 +59,15 @@
u1 _highest_osr_comp_level; // Same for OSR level
#endif
- MethodCounters() : _interpreter_invocation_count(0),
- _interpreter_throwout_count(0),
- _number_of_breakpoints(0),
- _nmethod_age(INT_MAX)
+ MethodCounters(methodHandle mh) : _interpreter_invocation_count(0),
+ _interpreter_throwout_count(0),
+ _number_of_breakpoints(0),
+ _nmethod_age(INT_MAX)
#ifdef TIERED
- , _rate(0),
- _prev_time(0),
- _highest_comp_level(0),
- _highest_osr_comp_level(0)
+ , _rate(0),
+ _prev_time(0),
+ _highest_comp_level(0),
+ _highest_osr_comp_level(0)
#endif
{
invocation_counter()->init();
@@ -70,10 +76,28 @@
if (StressCodeAging) {
set_nmethod_age(HotMethodDetectionLimit);
}
+
+ // Set per-method thresholds.
+ double scale = 1.0;
+ CompilerOracle::has_option_value(mh, "CompileThresholdScaling", scale);
+
+ int compile_threshold = Arguments::scaled_compile_threshold(CompileThreshold, scale);
+ _interpreter_invocation_limit = compile_threshold << InvocationCounter::count_shift;
+ if (ProfileInterpreter) {
+ // If interpreter profiling is enabled, the backward branch limit
+ // is compared against the method data counter rather than an invocation
+ // counter, therefore no shifting of bits is required.
+ _interpreter_backward_branch_limit = (compile_threshold * (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100;
+ } else {
+ _interpreter_backward_branch_limit = ((compile_threshold * OnStackReplacePercentage) / 100) << InvocationCounter::count_shift;
+ }
+ _interpreter_profile_limit = ((compile_threshold * InterpreterProfilePercentage) / 100) << InvocationCounter::count_shift;
+ _invoke_mask = right_n_bits(Arguments::scaled_freq_log(Tier0InvokeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
+ _backedge_mask = right_n_bits(Arguments::scaled_freq_log(Tier0BackedgeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
}
public:
- static MethodCounters* allocate(ClassLoaderData* loader_data, TRAPS);
+ static MethodCounters* allocate(methodHandle mh, TRAPS);
void deallocate_contents(ClassLoaderData* loader_data) {}
DEBUG_ONLY(bool on_stack() { return false; }) // for template
@@ -161,5 +185,24 @@
return offset_of(MethodCounters, _interpreter_invocation_count);
}
+ static ByteSize interpreter_invocation_limit_offset() {
+ return byte_offset_of(MethodCounters, _interpreter_invocation_limit);
+ }
+
+ static ByteSize interpreter_backward_branch_limit_offset() {
+ return byte_offset_of(MethodCounters, _interpreter_backward_branch_limit);
+ }
+
+ static ByteSize interpreter_profile_limit_offset() {
+ return byte_offset_of(MethodCounters, _interpreter_profile_limit);
+ }
+
+ static ByteSize invoke_mask_offset() {
+ return byte_offset_of(MethodCounters, _invoke_mask);
+ }
+
+ static ByteSize backedge_mask_offset() {
+ return byte_offset_of(MethodCounters, _backedge_mask);
+ }
};
#endif //SHARE_VM_OOPS_METHODCOUNTERS_HPP
diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp
index ef21558..f9e187f 100644
--- a/hotspot/src/share/vm/oops/methodData.cpp
+++ b/hotspot/src/share/vm/oops/methodData.cpp
@@ -31,6 +31,7 @@
#include "memory/heapInspection.hpp"
#include "oops/methodData.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
+#include "runtime/arguments.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/handles.inline.hpp"
@@ -1131,6 +1132,13 @@
_backedge_counter.init();
_invocation_counter_start = 0;
_backedge_counter_start = 0;
+
+ // Set per-method invoke- and backedge mask.
+ double scale = 1.0;
+ CompilerOracle::has_option_value(_method, "CompileThresholdScaling", scale);
+ _invoke_mask = right_n_bits(Arguments::scaled_freq_log(Tier0InvokeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
+ _backedge_mask = right_n_bits(Arguments::scaled_freq_log(Tier0BackedgeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
+
_tenure_traps = 0;
_num_loops = 0;
_num_blocks = 0;
diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp
index e91cffb..d069746 100644
--- a/hotspot/src/share/vm/oops/methodData.hpp
+++ b/hotspot/src/share/vm/oops/methodData.hpp
@@ -2088,6 +2088,8 @@
int _invocation_counter_start;
int _backedge_counter_start;
uint _tenure_traps;
+ int _invoke_mask; // per-method Tier0InvokeNotifyFreqLog
+ int _backedge_mask; // per-method Tier0BackedgeNotifyFreqLog
#if INCLUDE_RTM_OPT
// State of RTM code generation during compilation of the method
@@ -2447,10 +2449,19 @@
static ByteSize invocation_counter_offset() {
return byte_offset_of(MethodData, _invocation_counter);
}
+
static ByteSize backedge_counter_offset() {
return byte_offset_of(MethodData, _backedge_counter);
}
+ static ByteSize invoke_mask_offset() {
+ return byte_offset_of(MethodData, _invoke_mask);
+ }
+
+ static ByteSize backedge_mask_offset() {
+ return byte_offset_of(MethodData, _backedge_mask);
+ }
+
static ByteSize parameters_type_data_di_offset() {
return byte_offset_of(MethodData, _parameters_type_data_di);
}
diff --git a/hotspot/src/share/vm/opto/chaitin.cpp b/hotspot/src/share/vm/opto/chaitin.cpp
index c03c0f4..106e228 100644
--- a/hotspot/src/share/vm/opto/chaitin.cpp
+++ b/hotspot/src/share/vm/opto/chaitin.cpp
@@ -582,6 +582,9 @@
// Peephole remove copies
post_allocate_copy_removal();
+ // Merge multidefs if multiple defs representing the same value are used in a single block.
+ merge_multidefs();
+
#ifdef ASSERT
// Veify the graph after RA.
verify(&live_arena);
diff --git a/hotspot/src/share/vm/opto/chaitin.hpp b/hotspot/src/share/vm/opto/chaitin.hpp
index 99194cf..51915c5 100644
--- a/hotspot/src/share/vm/opto/chaitin.hpp
+++ b/hotspot/src/share/vm/opto/chaitin.hpp
@@ -681,6 +681,32 @@
// Extend the node to LRG mapping
void add_reference( const Node *node, const Node *old_node);
+ // Record the first use of a def in the block for a register.
+ class RegDefUse {
+ Node* _def;
+ Node* _first_use;
+ public:
+ RegDefUse() : _def(NULL), _first_use(NULL) { }
+ Node* def() const { return _def; }
+ Node* first_use() const { return _first_use; }
+
+ void update(Node* def, Node* use) {
+ if (_def != def) {
+ _def = def;
+ _first_use = use;
+ }
+ }
+ void clear() {
+ _def = NULL;
+ _first_use = NULL;
+ }
+ };
+ typedef GrowableArray<RegDefUse> RegToDefUseMap;
+ int possibly_merge_multidef(Node *n, uint k, Block *block, RegToDefUseMap& reg2defuse);
+
+ // Merge nodes that are a part of a multidef lrg and produce the same value within a block.
+ void merge_multidefs();
+
private:
static int _final_loads, _final_stores, _final_copies, _final_memoves;
diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp
index 7397f9e..1697d7e 100644
--- a/hotspot/src/share/vm/opto/doCall.cpp
+++ b/hotspot/src/share/vm/opto/doCall.cpp
@@ -94,7 +94,7 @@
if (log != NULL) {
int rid = (receiver_count >= 0)? log->identify(profile.receiver(0)): -1;
int r2id = (rid != -1 && profile.has_receiver(1))? log->identify(profile.receiver(1)):-1;
- log->begin_elem("call method='%d' count='%d' prof_factor='%g'",
+ log->begin_elem("call method='%d' count='%d' prof_factor='%f'",
log->identify(callee), site_count, prof_factor);
if (call_does_dispatch) log->print(" virtual='1'");
if (allow_inline) log->print(" inline='1'");
diff --git a/hotspot/src/share/vm/opto/escape.cpp b/hotspot/src/share/vm/opto/escape.cpp
index 7362481..42ba126 100644
--- a/hotspot/src/share/vm/opto/escape.cpp
+++ b/hotspot/src/share/vm/opto/escape.cpp
@@ -2010,14 +2010,9 @@
bt = field->layout_type();
} else {
// Check for unsafe oop field access
- for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
- int opcode = n->fast_out(i)->Opcode();
- if (opcode == Op_StoreP || opcode == Op_LoadP ||
- opcode == Op_StoreN || opcode == Op_LoadN) {
- bt = T_OBJECT;
- (*unsafe) = true;
- break;
- }
+ if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN)) {
+ bt = T_OBJECT;
+ (*unsafe) = true;
}
}
} else if (adr_type->isa_aryptr()) {
@@ -2031,13 +2026,8 @@
}
} else if (adr_type->isa_rawptr() || adr_type->isa_klassptr()) {
// Allocation initialization, ThreadLocal field access, unsafe access
- for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
- int opcode = n->fast_out(i)->Opcode();
- if (opcode == Op_StoreP || opcode == Op_LoadP ||
- opcode == Op_StoreN || opcode == Op_LoadN) {
- bt = T_OBJECT;
- break;
- }
+ if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN)) {
+ bt = T_OBJECT;
}
}
}
@@ -3092,13 +3082,7 @@
continue;
} else if (n->Opcode() == Op_EncodeISOArray) {
// get the memory projection
- for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
- Node *use = n->fast_out(i);
- if (use->Opcode() == Op_SCMemProj) {
- n = use;
- break;
- }
- }
+ n = n->find_out_with(Op_SCMemProj);
assert(n->Opcode() == Op_SCMemProj, "memory projection required");
} else {
assert(n->is_Mem(), "memory node required.");
@@ -3122,13 +3106,7 @@
continue; // don't push users
} else if (n->is_LoadStore()) {
// get the memory projection
- for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
- Node *use = n->fast_out(i);
- if (use->Opcode() == Op_SCMemProj) {
- n = use;
- break;
- }
- }
+ n = n->find_out_with(Op_SCMemProj);
assert(n->Opcode() == Op_SCMemProj, "memory projection required");
}
}
diff --git a/hotspot/src/share/vm/opto/ifg.cpp b/hotspot/src/share/vm/opto/ifg.cpp
index 61e1343..f01cd40 100644
--- a/hotspot/src/share/vm/opto/ifg.cpp
+++ b/hotspot/src/share/vm/opto/ifg.cpp
@@ -535,12 +535,8 @@
// The method add_input_to_liveout() keeps such nodes alive (put them on liveout list)
// when it sees SCMemProj node in a block. Unfortunately SCMemProj node could be placed
// in block in such order that KILL MachProj nodes are processed first.
- uint cnt = def->outcnt();
- for (uint i = 0; i < cnt; i++) {
- Node* proj = def->raw_out(i);
- if (proj->Opcode() == Op_SCMemProj) {
- return false;
- }
+ if (def->has_out_with(Op_SCMemProj)) {
+ return false;
}
}
b->remove_node(location);
diff --git a/hotspot/src/share/vm/opto/loopTransform.cpp b/hotspot/src/share/vm/opto/loopTransform.cpp
index b917ee1..f61e335 100644
--- a/hotspot/src/share/vm/opto/loopTransform.cpp
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp
@@ -2057,10 +2057,9 @@
}
Node *main_cmp = main_bol->in(1);
if( main_cmp->outcnt() > 1 ) { // CmpNode shared?
- _igvn.hash_delete(main_bol);
main_cmp = main_cmp->clone();// Clone a private CmpNode
register_new_node( main_cmp, main_cle->in(0) );
- main_bol->set_req(1,main_cmp);
+ _igvn.replace_input_of(main_bol, 1, main_cmp);
}
// Hack the now-private loop bounds
_igvn.replace_input_of(main_cmp, 2, main_limit);
diff --git a/hotspot/src/share/vm/opto/machnode.hpp b/hotspot/src/share/vm/opto/machnode.hpp
index a557c02..e30e234 100644
--- a/hotspot/src/share/vm/opto/machnode.hpp
+++ b/hotspot/src/share/vm/opto/machnode.hpp
@@ -616,6 +616,29 @@
#endif
};
+// MachMergeNode is similar to a PhiNode in a sense it merges multiple values,
+// however it doesn't have a control input and is more like a MergeMem.
+// It is inserted after the register allocation is done to ensure that nodes use single
+// definition of a multidef lrg in a block.
+class MachMergeNode : public MachIdealNode {
+public:
+ MachMergeNode(Node *n1) {
+ init_class_id(Class_MachMerge);
+ add_req(NULL);
+ add_req(n1);
+ }
+ virtual const RegMask &out_RegMask() const { return in(1)->out_RegMask(); }
+ virtual const RegMask &in_RegMask(uint idx) const { return in(1)->in_RegMask(idx); }
+ virtual const class Type *bottom_type() const { return in(1)->bottom_type(); }
+ virtual uint ideal_reg() const { return bottom_type()->ideal_reg(); }
+ virtual uint oper_input_base() const { return 1; }
+ virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { }
+ virtual uint size(PhaseRegAlloc *ra_) const { return 0; }
+#ifndef PRODUCT
+ virtual const char *Name() const { return "MachMerge"; }
+#endif
+};
+
//------------------------------MachBranchNode--------------------------------
// Abstract machine branch Node
class MachBranchNode : public MachIdealNode {
diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp
index b393745..93659c3 100644
--- a/hotspot/src/share/vm/opto/macro.cpp
+++ b/hotspot/src/share/vm/opto/macro.cpp
@@ -258,14 +258,7 @@
// Search for CastP2X->Xor->URShift->Cmp path which
// checks if the store done to a different from the value's region.
// And replace Cmp with #0 (false) to collapse G1 post barrier.
- Node* xorx = NULL;
- for (DUIterator_Fast imax, i = p2x->fast_outs(imax); i < imax; i++) {
- Node* u = p2x->fast_out(i);
- if (u->Opcode() == Op_XorX) {
- xorx = u;
- break;
- }
- }
+ Node* xorx = p2x->find_out_with(Op_XorX);
assert(xorx != NULL, "missing G1 post barrier");
Node* shift = xorx->unique_out();
Node* cmpx = shift->unique_out();
diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp
index 966bcbe..3afa49c 100644
--- a/hotspot/src/share/vm/opto/memnode.cpp
+++ b/hotspot/src/share/vm/opto/memnode.cpp
@@ -2609,7 +2609,6 @@
return false; // if not a distinct instance, there may be aliases of the address
for (DUIterator_Fast imax, i = adr->fast_outs(imax); i < imax; i++) {
Node *use = adr->fast_out(i);
- int opc = use->Opcode();
if (use->is_Load() || use->is_LoadStore()) {
return false;
}
diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp
index 8ed950a..225b20c 100644
--- a/hotspot/src/share/vm/opto/node.cpp
+++ b/hotspot/src/share/vm/opto/node.cpp
@@ -881,6 +881,34 @@
return (Node*) this;
}
+// Find out of current node that matches opcode.
+Node* Node::find_out_with(int opcode) {
+ for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
+ Node* use = fast_out(i);
+ if (use->Opcode() == opcode) {
+ return use;
+ }
+ }
+ return NULL;
+}
+
+// Return true if the current node has an out that matches opcode.
+bool Node::has_out_with(int opcode) {
+ return (find_out_with(opcode) != NULL);
+}
+
+// Return true if the current node has an out that matches any of the opcodes.
+bool Node::has_out_with(int opcode1, int opcode2, int opcode3, int opcode4) {
+ for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
+ int opcode = fast_out(i)->Opcode();
+ if (opcode == opcode1 || opcode == opcode2 || opcode == opcode3 || opcode == opcode4) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
//---------------------------uncast_helper-------------------------------------
Node* Node::uncast_helper(const Node* p) {
#ifdef ASSERT
diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp
index bcf6911..ce591dc 100644
--- a/hotspot/src/share/vm/opto/node.hpp
+++ b/hotspot/src/share/vm/opto/node.hpp
@@ -98,6 +98,7 @@
class MachSafePointNode;
class MachSpillCopyNode;
class MachTempNode;
+class MachMergeNode;
class Matcher;
class MemBarNode;
class MemBarStoreStoreNode;
@@ -436,6 +437,13 @@
return (this->uncast() == n->uncast());
}
+ // Find out of current node that matches opcode.
+ Node* find_out_with(int opcode);
+ // Return true if the current node has an out that matches opcode.
+ bool has_out_with(int opcode);
+ // Return true if the current node has an out that matches any of the opcodes.
+ bool has_out_with(int opcode1, int opcode2, int opcode3, int opcode4);
+
private:
static Node* uncast_helper(const Node* n);
@@ -507,18 +515,25 @@
//----------------- Other Node Properties
- // Generate class id for some ideal nodes to avoid virtual query
- // methods is_<Node>().
- // Class id is the set of bits corresponded to the node class and all its
- // super classes so that queries for super classes are also valid.
- // Subclasses of the same super class have different assigned bit
- // (the third parameter in the macro DEFINE_CLASS_ID).
- // Classes with deeper hierarchy are declared first.
- // Classes with the same hierarchy depth are sorted by usage frequency.
+ // Generate class IDs for (some) ideal nodes so that it is possible to determine
+ // the type of a node using a non-virtual method call (the method is_<Node>() below).
//
- // The query method masks the bits to cut off bits of subclasses
- // and then compare the result with the class id
- // (see the macro DEFINE_CLASS_QUERY below).
+ // A class ID of an ideal node is a set of bits. In a class ID, a single bit determines
+ // the type of the node the ID represents; another subset of an ID's bits are reserved
+ // for the superclasses of the node represented by the ID.
+ //
+ // By design, if A is a supertype of B, A.is_B() returns true and B.is_A()
+ // returns false. A.is_A() returns true.
+ //
+ // If two classes, A and B, have the same superclass, a different bit of A's class id
+ // is reserved for A's type than for B's type. That bit is specified by the third
+ // parameter in the macro DEFINE_CLASS_ID.
+ //
+ // By convention, classes with deeper hierarchy are declared first. Moreover,
+ // classes with the same hierarchy depth are sorted by usage frequency.
+ //
+ // The query method masks the bits to cut off bits of subclasses and then compares
+ // the result with the class id (see the macro DEFINE_CLASS_QUERY below).
//
// Class_MachCall=30, ClassMask_MachCall=31
// 12 8 4 0
@@ -592,6 +607,7 @@
DEFINE_CLASS_ID(MachTemp, Mach, 3)
DEFINE_CLASS_ID(MachConstantBase, Mach, 4)
DEFINE_CLASS_ID(MachConstant, Mach, 5)
+ DEFINE_CLASS_ID(MachMerge, Mach, 6)
DEFINE_CLASS_ID(Type, Node, 2)
DEFINE_CLASS_ID(Phi, Type, 0)
@@ -763,6 +779,7 @@
DEFINE_CLASS_QUERY(MachSafePoint)
DEFINE_CLASS_QUERY(MachSpillCopy)
DEFINE_CLASS_QUERY(MachTemp)
+ DEFINE_CLASS_QUERY(MachMerge)
DEFINE_CLASS_QUERY(Mem)
DEFINE_CLASS_QUERY(MemBar)
DEFINE_CLASS_QUERY(MemBarStoreStore)
diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp
index 402ccfe..35728e6 100644
--- a/hotspot/src/share/vm/opto/parse1.cpp
+++ b/hotspot/src/share/vm/opto/parse1.cpp
@@ -441,7 +441,7 @@
CompileLog* log = C->log();
if (log != NULL) {
- log->begin_head("parse method='%d' uses='%g'",
+ log->begin_head("parse method='%d' uses='%f'",
log->identify(parse_method), expected_uses);
if (depth() == 1 && C->is_osr_compilation()) {
log->print(" osr_bci='%d'", C->entry_bci());
diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp
index 8a319f8..c99ac96 100644
--- a/hotspot/src/share/vm/opto/parse2.cpp
+++ b/hotspot/src/share/vm/opto/parse2.cpp
@@ -832,7 +832,7 @@
sprintf(prob_str_buf, "%g", prob);
prob_str = prob_str_buf;
}
- C->log()->elem("branch target_bci='%d' taken='%d' not_taken='%d' cnt='%g' prob='%s'",
+ C->log()->elem("branch target_bci='%d' taken='%d' not_taken='%d' cnt='%f' prob='%s'",
iter().get_dest(), taken, not_taken, cnt, prob_str);
}
return prob;
diff --git a/hotspot/src/share/vm/opto/phase.cpp b/hotspot/src/share/vm/opto/phase.cpp
index 0c9c697..9662bbc 100644
--- a/hotspot/src/share/vm/opto/phase.cpp
+++ b/hotspot/src/share/vm/opto/phase.cpp
@@ -110,6 +110,7 @@
tty->print_cr (" Compute Liveness: %7.3f s", timers[_t_computeLive].seconds());
tty->print_cr (" Regalloc Split: %7.3f s", timers[_t_regAllocSplit].seconds());
tty->print_cr (" Postalloc Copy Rem: %7.3f s", timers[_t_postAllocCopyRemoval].seconds());
+ tty->print_cr (" Merge multidefs: %7.3f s", timers[_t_mergeMultidefs].seconds());
tty->print_cr (" Fixup Spills: %7.3f s", timers[_t_fixupSpills].seconds());
tty->print_cr (" Compact: %7.3f s", timers[_t_chaitinCompact].seconds());
tty->print_cr (" Coalesce 1: %7.3f s", timers[_t_chaitinCoalesce1].seconds());
@@ -126,6 +127,7 @@
timers[_t_computeLive].seconds() +
timers[_t_regAllocSplit].seconds() +
timers[_t_postAllocCopyRemoval].seconds() +
+ timers[_t_mergeMultidefs].seconds() +
timers[_t_fixupSpills].seconds() +
timers[_t_chaitinCompact].seconds() +
timers[_t_chaitinCoalesce1].seconds() +
diff --git a/hotspot/src/share/vm/opto/phase.hpp b/hotspot/src/share/vm/opto/phase.hpp
index f273947..4b5d53d 100644
--- a/hotspot/src/share/vm/opto/phase.hpp
+++ b/hotspot/src/share/vm/opto/phase.hpp
@@ -88,6 +88,7 @@
_t_computeLive,
_t_regAllocSplit,
_t_postAllocCopyRemoval,
+ _t_mergeMultidefs,
_t_fixupSpills,
_t_chaitinCompact,
_t_chaitinCoalesce1,
diff --git a/hotspot/src/share/vm/opto/postaloc.cpp b/hotspot/src/share/vm/opto/postaloc.cpp
index 35e3974..d6ac102 100644
--- a/hotspot/src/share/vm/opto/postaloc.cpp
+++ b/hotspot/src/share/vm/opto/postaloc.cpp
@@ -263,20 +263,6 @@
// intermediate copies might be illegal, i.e., value is stored down to stack
// then reloaded BUT survives in a register the whole way.
Node *val = skip_copies(n->in(k));
-
- if (val == x && nk_idx != 0 &&
- regnd[nk_reg] != NULL && regnd[nk_reg] != x &&
- _lrg_map.live_range_id(x) == _lrg_map.live_range_id(regnd[nk_reg])) {
- // When rematerialzing nodes and stretching lifetimes, the
- // allocator will reuse the original def for multidef LRG instead
- // of the current reaching def because it can't know it's safe to
- // do so. After allocation completes if they are in the same LRG
- // then it should use the current reaching def instead.
- n->set_req(k, regnd[nk_reg]);
- blk_adjust += yank_if_dead(val, current_block, &value, ®nd);
- val = skip_copies(n->in(k));
- }
-
if (val == x) return blk_adjust; // No progress?
int n_regs = RegMask::num_registers(val->ideal_reg());
@@ -382,6 +368,94 @@
return false;
}
+// The algorithms works as follows:
+// We traverse the block top to bottom. possibly_merge_multidef() is invoked for every input edge k
+// of the instruction n. We check to see if the input is a multidef lrg. If it is, we record the fact that we've
+// seen a definition (coming as an input) and add that fact to the reg2defuse array. The array maps registers to their
+// current reaching definitions (we track only multidefs though). With each definition we also associate the first
+// instruction we saw use it. If we encounter the situation when we observe an def (an input) that is a part of the
+// same lrg but is different from the previous seen def we merge the two with a MachMerge node and substitute
+// all the uses that we've seen so far to use the merge. After that we keep replacing the new defs in the same lrg
+// as they get encountered with the merge node and keep adding these defs to the merge inputs.
+void PhaseChaitin::merge_multidefs() {
+ Compile::TracePhase tp("mergeMultidefs", &timers[_t_mergeMultidefs]);
+ ResourceMark rm;
+ // Keep track of the defs seen in registers and collect their uses in the block.
+ RegToDefUseMap reg2defuse(_max_reg, _max_reg, RegDefUse());
+ for (uint i = 0; i < _cfg.number_of_blocks(); i++) {
+ Block* block = _cfg.get_block(i);
+ for (uint j = 1; j < block->number_of_nodes(); j++) {
+ Node* n = block->get_node(j);
+ if (n->is_Phi()) continue;
+ for (uint k = 1; k < n->req(); k++) {
+ j += possibly_merge_multidef(n, k, block, reg2defuse);
+ }
+ // Null out the value produced by the instruction itself, since we're only interested in defs
+ // implicitly defined by the uses. We are actually interested in tracking only redefinitions
+ // of the multidef lrgs in the same register. For that matter it's enough to track changes in
+ // the base register only and ignore other effects of multi-register lrgs and fat projections.
+ // It is also ok to ignore defs coming from singledefs. After an implicit overwrite by one of
+ // those our register is guaranteed to be used by another lrg and we won't attempt to merge it.
+ uint lrg = _lrg_map.live_range_id(n);
+ if (lrg > 0 && lrgs(lrg).is_multidef()) {
+ OptoReg::Name reg = lrgs(lrg).reg();
+ reg2defuse.at(reg).clear();
+ }
+ }
+ // Clear reg->def->use tracking for the next block
+ for (int j = 0; j < reg2defuse.length(); j++) {
+ reg2defuse.at(j).clear();
+ }
+ }
+}
+
+int PhaseChaitin::possibly_merge_multidef(Node *n, uint k, Block *block, RegToDefUseMap& reg2defuse) {
+ int blk_adjust = 0;
+
+ uint lrg = _lrg_map.live_range_id(n->in(k));
+ if (lrg > 0 && lrgs(lrg).is_multidef()) {
+ OptoReg::Name reg = lrgs(lrg).reg();
+
+ Node* def = reg2defuse.at(reg).def();
+ if (def != NULL && lrg == _lrg_map.live_range_id(def) && def != n->in(k)) {
+ // Same lrg but different node, we have to merge.
+ MachMergeNode* merge;
+ if (def->is_MachMerge()) { // is it already a merge?
+ merge = def->as_MachMerge();
+ } else {
+ merge = new MachMergeNode(def);
+
+ // Insert the merge node into the block before the first use.
+ uint use_index = block->find_node(reg2defuse.at(reg).first_use());
+ block->insert_node(merge, use_index++);
+
+ // Let the allocator know about the new node, use the same lrg
+ _lrg_map.extend(merge->_idx, lrg);
+ blk_adjust++;
+
+ // Fixup all the uses (there is at least one) that happened between the first
+ // use and before the current one.
+ for (; use_index < block->number_of_nodes(); use_index++) {
+ Node* use = block->get_node(use_index);
+ if (use == n) {
+ break;
+ }
+ use->replace_edge(def, merge);
+ }
+ }
+ if (merge->find_edge(n->in(k)) == -1) {
+ merge->add_req(n->in(k));
+ }
+ n->set_req(k, merge);
+ }
+
+ // update the uses
+ reg2defuse.at(reg).update(n->in(k), n);
+ }
+
+ return blk_adjust;
+}
+
//------------------------------post_allocate_copy_removal---------------------
// Post-Allocation peephole copy removal. We do this in 1 pass over the
diff --git a/hotspot/src/share/vm/opto/stringopts.cpp b/hotspot/src/share/vm/opto/stringopts.cpp
index 1d9bae5..5f7da1f 100644
--- a/hotspot/src/share/vm/opto/stringopts.cpp
+++ b/hotspot/src/share/vm/opto/stringopts.cpp
@@ -1507,10 +1507,12 @@
}
case StringConcat::StringMode: {
const Type* type = kit.gvn().type(arg);
+ Node* count = NULL;
if (type == TypePtr::NULL_PTR) {
// replace the argument with the null checked version
arg = null_string;
sc->set_argument(argi, arg);
+ count = kit.load_String_length(kit.control(), arg);
} else if (!type->higher_equal(TypeInstPtr::NOTNULL)) {
// s = s != null ? s : "null";
// length = length + (s.count - s.offset);
@@ -1533,10 +1535,13 @@
// replace the argument with the null checked version
arg = phi;
sc->set_argument(argi, arg);
+ count = kit.load_String_length(kit.control(), arg);
+ } else {
+ // A corresponding nullcheck will be connected during IGVN MemNode::Ideal_common_DU_postCCP
+ // kit.control might be a different test, that can be hoisted above the actual nullcheck
+ // in case, that the control input is not null, Ideal_common_DU_postCCP will not look for a nullcheck.
+ count = kit.load_String_length(NULL, arg);
}
-
- Node* count = kit.load_String_length(kit.control(), arg);
-
length = __ AddI(length, count);
string_sizes->init_req(argi, NULL);
break;
diff --git a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp
index be05366..b0c5a43 100644
--- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp
+++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp
@@ -68,11 +68,11 @@
~JvmtiConstantPoolReconstituter() {
if (_symmap != NULL) {
- os::free(_symmap);
+ delete _symmap;
_symmap = NULL;
}
if (_classmap != NULL) {
- os::free(_classmap);
+ delete _classmap;
_classmap = NULL;
}
}
diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp
index 89680d1..31ab6f5 100644
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp
@@ -1046,10 +1046,16 @@
{
assert(str->klass() == SystemDictionary::String_klass(), "not a string");
+ typeArrayOop s_value = java_lang_String::value(str);
+
+ // JDK-6584008: the value field may be null if a String instance is
+ // partially constructed.
+ if (s_value == NULL) {
+ return 0;
+ }
// get the string value and length
// (string value may be offset from the base)
int s_len = java_lang_String::length(str);
- typeArrayOop s_value = java_lang_String::value(str);
int s_offset = java_lang_String::offset(str);
jchar* value;
if (s_len > 0) {
diff --git a/hotspot/src/share/vm/prims/perf.cpp b/hotspot/src/share/vm/prims/perf.cpp
index 9ad0f4c..bddb1f7 100644
--- a/hotspot/src/share/vm/prims/perf.cpp
+++ b/hotspot/src/share/vm/prims/perf.cpp
@@ -100,6 +100,11 @@
PerfWrapper("Perf_Detach");
+ if (!UsePerfData) {
+ // With -XX:-UsePerfData, detach is just a NOP
+ return;
+ }
+
void* address = 0;
jlong capacity = 0;
diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp
index 68a729a..f681cce 100644
--- a/hotspot/src/share/vm/prims/unsafe.cpp
+++ b/hotspot/src/share/vm/prims/unsafe.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1104,43 +1104,6 @@
-UNSAFE_ENTRY(void, Unsafe_MonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
- UnsafeWrapper("Unsafe_MonitorEnter");
- {
- if (jobj == NULL) {
- THROW(vmSymbols::java_lang_NullPointerException());
- }
- Handle obj(thread, JNIHandles::resolve_non_null(jobj));
- ObjectSynchronizer::jni_enter(obj, CHECK);
- }
-UNSAFE_END
-
-
-UNSAFE_ENTRY(jboolean, Unsafe_TryMonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
- UnsafeWrapper("Unsafe_TryMonitorEnter");
- {
- if (jobj == NULL) {
- THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
- }
- Handle obj(thread, JNIHandles::resolve_non_null(jobj));
- bool res = ObjectSynchronizer::jni_try_enter(obj, CHECK_0);
- return (res ? JNI_TRUE : JNI_FALSE);
- }
-UNSAFE_END
-
-
-UNSAFE_ENTRY(void, Unsafe_MonitorExit(JNIEnv *env, jobject unsafe, jobject jobj))
- UnsafeWrapper("Unsafe_MonitorExit");
- {
- if (jobj == NULL) {
- THROW(vmSymbols::java_lang_NullPointerException());
- }
- Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
- ObjectSynchronizer::jni_exit(obj(), CHECK);
- }
-UNSAFE_END
-
-
UNSAFE_ENTRY(void, Unsafe_ThrowException(JNIEnv *env, jobject unsafe, jthrowable thr))
UnsafeWrapper("Unsafe_ThrowException");
{
@@ -1365,8 +1328,6 @@
{CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
- {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
- {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
{CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)}
};
@@ -1411,8 +1372,6 @@
{CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
- {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
- {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
{CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)}
};
@@ -1461,8 +1420,6 @@
{CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
- {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
- {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
{CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)},
{CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
{CC"compareAndSwapInt", CC"("OBJ"J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
@@ -1515,9 +1472,6 @@
{CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
- {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
- {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
- {CC"tryMonitorEnter", CC"("OBJ")Z", FN_PTR(Unsafe_TryMonitorEnter)},
{CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)},
{CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
{CC"compareAndSwapInt", CC"("OBJ"J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
@@ -1571,9 +1525,6 @@
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
- {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
- {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
- {CC"tryMonitorEnter", CC"("OBJ")Z", FN_PTR(Unsafe_TryMonitorEnter)},
{CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)},
{CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
{CC"compareAndSwapInt", CC"("OBJ"J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
index bd78c3d..eb83161 100644
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
@@ -155,7 +155,7 @@
if (mdo != NULL) {
int i = mdo->invocation_count_delta();
int b = mdo->backedge_count_delta();
- return call_predicate_helper<CompLevel_full_profile>(i, b, 1);
+ return call_predicate_helper<CompLevel_full_profile>(i, b, 1, method);
}
return false;
}
@@ -229,32 +229,32 @@
// Tier?LoadFeedback is basically a coefficient that determines of
// how many methods per compiler thread can be in the queue before
// the threshold values double.
-bool AdvancedThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level) {
+bool AdvancedThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level, Method* method) {
switch(cur_level) {
case CompLevel_none:
case CompLevel_limited_profile: {
double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
- return loop_predicate_helper<CompLevel_none>(i, b, k);
+ return loop_predicate_helper<CompLevel_none>(i, b, k, method);
}
case CompLevel_full_profile: {
double k = threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback);
- return loop_predicate_helper<CompLevel_full_profile>(i, b, k);
+ return loop_predicate_helper<CompLevel_full_profile>(i, b, k, method);
}
default:
return true;
}
}
-bool AdvancedThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level) {
+bool AdvancedThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level, Method* method) {
switch(cur_level) {
case CompLevel_none:
case CompLevel_limited_profile: {
double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
- return call_predicate_helper<CompLevel_none>(i, b, k);
+ return call_predicate_helper<CompLevel_none>(i, b, k, method);
}
case CompLevel_full_profile: {
double k = threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback);
- return call_predicate_helper<CompLevel_full_profile>(i, b, k);
+ return call_predicate_helper<CompLevel_full_profile>(i, b, k, method);
}
default:
return true;
@@ -271,7 +271,7 @@
int i = method->invocation_count();
int b = method->backedge_count();
double k = Tier0ProfilingStartPercentage / 100.0;
- return call_predicate_helper<CompLevel_none>(i, b, k) || loop_predicate_helper<CompLevel_none>(i, b, k);
+ return call_predicate_helper<CompLevel_none>(i, b, k, method) || loop_predicate_helper<CompLevel_none>(i, b, k, method);
}
return false;
}
@@ -348,7 +348,7 @@
// If we were at full profile level, would we switch to full opt?
if (common(p, method, CompLevel_full_profile, disable_feedback) == CompLevel_full_optimization) {
next_level = CompLevel_full_optimization;
- } else if ((this->*p)(i, b, cur_level)) {
+ } else if ((this->*p)(i, b, cur_level, method)) {
// C1-generated fully profiled code is about 30% slower than the limited profile
// code that has only invocation and backedge counters. The observation is that
// if C2 queue is large enough we can spend too much time in the fully profiled code
@@ -374,7 +374,7 @@
if (mdo->would_profile()) {
if (disable_feedback || (CompileBroker::queue_size(CompLevel_full_optimization) <=
Tier3DelayOff * compiler_count(CompLevel_full_optimization) &&
- (this->*p)(i, b, cur_level))) {
+ (this->*p)(i, b, cur_level, method))) {
next_level = CompLevel_full_profile;
}
} else {
@@ -390,7 +390,7 @@
if (mdo->would_profile()) {
int mdo_i = mdo->invocation_count_delta();
int mdo_b = mdo->backedge_count_delta();
- if ((this->*p)(mdo_i, mdo_b, cur_level)) {
+ if ((this->*p)(mdo_i, mdo_b, cur_level, method)) {
next_level = CompLevel_full_optimization;
}
} else {
diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp
index a224511..5ec4063 100644
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp
@@ -84,7 +84,7 @@
* invocation and backedge notifications. Basically every n-th invocation or backedge a mutator thread
* makes a call into the runtime.
*
- * - Tier?CompileThreshold, Tier?BackEdgeThreshold, Tier?MinInvocationThreshold control
+ * - Tier?InvocationThreshold, Tier?CompileThreshold, Tier?BackEdgeThreshold, Tier?MinInvocationThreshold control
* compilation thresholds.
* Level 2 thresholds are not used and are provided for option-compatibility and potential future use.
* Other thresholds work as follows:
@@ -100,7 +100,9 @@
* The same predicate is used to control the transition from level 3 to level 4 (C2). It should be
* noted though that the thresholds are relative. Moreover i and b for the 0->3 transition come
* from Method* and for 3->4 transition they come from MDO (since profiled invocations are
- * counted separately).
+ * counted separately). Finally, if a method does not contain anything worth profiling, a transition
+ * from level 3 to level 4 occurs without considering thresholds (e.g., with fewer invocations than
+ * what is specified by Tier4InvocationThreshold).
*
* OSR transitions are controlled simply with b > TierXBackEdgeThreshold * s predicates.
*
@@ -164,9 +166,9 @@
// Call and loop predicates determine whether a transition to a higher compilation
// level should be performed (pointers to predicate functions are passed to common().
// Predicates also take compiler load into account.
- typedef bool (AdvancedThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level);
- bool call_predicate(int i, int b, CompLevel cur_level);
- bool loop_predicate(int i, int b, CompLevel cur_level);
+ typedef bool (AdvancedThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level, Method* method);
+ bool call_predicate(int i, int b, CompLevel cur_level, Method* method);
+ bool loop_predicate(int i, int b, CompLevel cur_level, Method* method);
// Common transition function. Given a predicate determines if a method should transition to another level.
CompLevel common(Predicate p, Method* method, CompLevel cur_level, bool disable_feedback = false);
// Transition functions.
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 6650090..0c31c9b 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -1126,16 +1126,35 @@
}
#endif
-// Returns threshold scaled with CompileThresholdScaling
-intx Arguments::get_scaled_compile_threshold(intx threshold) {
- return (intx)(threshold * CompileThresholdScaling);
+intx Arguments::scaled_compile_threshold(intx threshold, double scale) {
+ if (scale == 1.0 || scale < 0.0) {
+ return threshold;
+ } else {
+ return (intx)(threshold * scale);
+ }
}
// Returns freq_log scaled with CompileThresholdScaling
-intx Arguments::get_scaled_freq_log(intx freq_log) {
- intx scaled_freq = get_scaled_compile_threshold((intx)1 << freq_log);
- if (scaled_freq == 0) {
- return 0;
+intx Arguments::scaled_freq_log(intx freq_log, double scale) {
+ // Check if scaling is necessary or negative value was specified.
+ if (scale == 1.0 || scale < 0.0) {
+ return freq_log;
+ }
+
+ // Check value to avoid calculating log2 of 0.
+ if (scale == 0.0) {
+ return 1;
+ }
+
+ intx scaled_freq = scaled_compile_threshold((intx)1 << freq_log, scale);
+ // Determine the maximum notification frequency value currently supported.
+ // The largest mask value that the interpreter/C1 can handle is
+ // of length InvocationCounter::number_of_count_bits. Mask values are always
+ // one bit shorter then the value of the notification frequency. Set
+ // max_freq_bits accordingly.
+ intx max_freq_bits = InvocationCounter::number_of_count_bits + 1;
+ if (scaled_freq > nth_bit(max_freq_bits)) {
+ return max_freq_bits;
} else {
return log2_intptr(scaled_freq);
}
@@ -1180,31 +1199,36 @@
Tier3InvokeNotifyFreqLog = 0;
Tier4InvocationThreshold = 0;
}
+
+ if (CompileThresholdScaling < 0) {
+ vm_exit_during_initialization("Negative value specified for CompileThresholdScaling", NULL);
+ }
+
// Scale tiered compilation thresholds
if (!FLAG_IS_DEFAULT(CompileThresholdScaling)) {
- FLAG_SET_ERGO(intx, Tier0InvokeNotifyFreqLog, get_scaled_freq_log(Tier0InvokeNotifyFreqLog));
- FLAG_SET_ERGO(intx, Tier0BackedgeNotifyFreqLog, get_scaled_freq_log(Tier0BackedgeNotifyFreqLog));
+ FLAG_SET_ERGO(intx, Tier0InvokeNotifyFreqLog, scaled_freq_log(Tier0InvokeNotifyFreqLog));
+ FLAG_SET_ERGO(intx, Tier0BackedgeNotifyFreqLog, scaled_freq_log(Tier0BackedgeNotifyFreqLog));
- FLAG_SET_ERGO(intx, Tier3InvocationThreshold, get_scaled_compile_threshold(Tier3InvocationThreshold));
- FLAG_SET_ERGO(intx, Tier3MinInvocationThreshold, get_scaled_compile_threshold(Tier3MinInvocationThreshold));
- FLAG_SET_ERGO(intx, Tier3CompileThreshold, get_scaled_compile_threshold(Tier3CompileThreshold));
- FLAG_SET_ERGO(intx, Tier3BackEdgeThreshold, get_scaled_compile_threshold(Tier3BackEdgeThreshold));
+ FLAG_SET_ERGO(intx, Tier3InvocationThreshold, scaled_compile_threshold(Tier3InvocationThreshold));
+ FLAG_SET_ERGO(intx, Tier3MinInvocationThreshold, scaled_compile_threshold(Tier3MinInvocationThreshold));
+ FLAG_SET_ERGO(intx, Tier3CompileThreshold, scaled_compile_threshold(Tier3CompileThreshold));
+ FLAG_SET_ERGO(intx, Tier3BackEdgeThreshold, scaled_compile_threshold(Tier3BackEdgeThreshold));
// Tier2{Invocation,MinInvocation,Compile,Backedge}Threshold should be scaled here
// once these thresholds become supported.
- FLAG_SET_ERGO(intx, Tier2InvokeNotifyFreqLog, get_scaled_freq_log(Tier2InvokeNotifyFreqLog));
- FLAG_SET_ERGO(intx, Tier2BackedgeNotifyFreqLog, get_scaled_freq_log(Tier2BackedgeNotifyFreqLog));
+ FLAG_SET_ERGO(intx, Tier2InvokeNotifyFreqLog, scaled_freq_log(Tier2InvokeNotifyFreqLog));
+ FLAG_SET_ERGO(intx, Tier2BackedgeNotifyFreqLog, scaled_freq_log(Tier2BackedgeNotifyFreqLog));
- FLAG_SET_ERGO(intx, Tier3InvokeNotifyFreqLog, get_scaled_freq_log(Tier3InvokeNotifyFreqLog));
- FLAG_SET_ERGO(intx, Tier3BackedgeNotifyFreqLog, get_scaled_freq_log(Tier3BackedgeNotifyFreqLog));
+ FLAG_SET_ERGO(intx, Tier3InvokeNotifyFreqLog, scaled_freq_log(Tier3InvokeNotifyFreqLog));
+ FLAG_SET_ERGO(intx, Tier3BackedgeNotifyFreqLog, scaled_freq_log(Tier3BackedgeNotifyFreqLog));
- FLAG_SET_ERGO(intx, Tier23InlineeNotifyFreqLog, get_scaled_freq_log(Tier23InlineeNotifyFreqLog));
+ FLAG_SET_ERGO(intx, Tier23InlineeNotifyFreqLog, scaled_freq_log(Tier23InlineeNotifyFreqLog));
- FLAG_SET_ERGO(intx, Tier4InvocationThreshold, get_scaled_compile_threshold(Tier4InvocationThreshold));
- FLAG_SET_ERGO(intx, Tier4MinInvocationThreshold, get_scaled_compile_threshold(Tier4MinInvocationThreshold));
- FLAG_SET_ERGO(intx, Tier4CompileThreshold, get_scaled_compile_threshold(Tier4CompileThreshold));
- FLAG_SET_ERGO(intx, Tier4BackEdgeThreshold, get_scaled_compile_threshold(Tier4BackEdgeThreshold));
+ FLAG_SET_ERGO(intx, Tier4InvocationThreshold, scaled_compile_threshold(Tier4InvocationThreshold));
+ FLAG_SET_ERGO(intx, Tier4MinInvocationThreshold, scaled_compile_threshold(Tier4MinInvocationThreshold));
+ FLAG_SET_ERGO(intx, Tier4CompileThreshold, scaled_compile_threshold(Tier4CompileThreshold));
+ FLAG_SET_ERGO(intx, Tier4BackEdgeThreshold, scaled_compile_threshold(Tier4BackEdgeThreshold));
}
}
@@ -3456,7 +3480,7 @@
}
if ((TieredCompilation && CompileThresholdScaling == 0)
- || (!TieredCompilation && get_scaled_compile_threshold(CompileThreshold) == 0)) {
+ || (!TieredCompilation && scaled_compile_threshold(CompileThreshold) == 0)) {
set_mode_flags(_int);
}
@@ -3896,7 +3920,7 @@
}
// Scale CompileThreshold
if (!FLAG_IS_DEFAULT(CompileThresholdScaling)) {
- FLAG_SET_ERGO(intx, CompileThreshold, get_scaled_compile_threshold(CompileThreshold));
+ FLAG_SET_ERGO(intx, CompileThreshold, scaled_compile_threshold(CompileThreshold));
}
}
diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp
index a0edd81..ae726b8 100644
--- a/hotspot/src/share/vm/runtime/arguments.hpp
+++ b/hotspot/src/share/vm/runtime/arguments.hpp
@@ -328,9 +328,6 @@
static bool _ClipInlining;
static bool _CIDynamicCompilePriority;
- // Scale compile thresholds
- static intx get_scaled_compile_threshold(intx threshold);
- static intx get_scaled_freq_log(intx freq_log);
// Tiered
static void set_tiered_flags();
static int get_min_number_of_compiler_threads();
@@ -452,6 +449,18 @@
static char* SharedArchivePath;
public:
+ // Scale compile thresholds
+ // Returns threshold scaled with CompileThresholdScaling
+ static intx scaled_compile_threshold(intx threshold, double scale);
+ static intx scaled_compile_threshold(intx threshold) {
+ return scaled_compile_threshold(threshold, CompileThresholdScaling);
+ }
+ // Returns freq_log scaled with CompileThresholdScaling
+ static intx scaled_freq_log(intx freq_log, double scale);
+ static intx scaled_freq_log(intx freq_log) {
+ return scaled_freq_log(freq_log, CompileThresholdScaling);
+ }
+
// Parses the arguments, first phase
static jint parse(const JavaVMInitArgs* args);
// Apply ergonomics
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
index 6d56c2f..dd01436 100644
--- a/hotspot/src/share/vm/runtime/globals.hpp
+++ b/hotspot/src/share/vm/runtime/globals.hpp
@@ -2477,7 +2477,7 @@
"Number of compiler threads to run") \
\
product(intx, CompilationPolicyChoice, 0, \
- "which compilation policy (0/1)") \
+ "which compilation policy (0-3)") \
\
develop(bool, UseStackBanging, true, \
"use stack banging for stack overflow checks (required for " \
@@ -3528,7 +3528,16 @@
\
product(double, CompileThresholdScaling, 1.0, \
"Factor to control when first compilation happens " \
- "(both with and without tiered compilation)") \
+ "(both with and without tiered compilation): " \
+ "values greater than 1.0 delay counter overflow, " \
+ "values between 0 and 1.0 rush counter overflow, " \
+ "value of 1.0 leave compilation thresholds unchanged " \
+ "value of 0.0 is equivalent to -Xint. " \
+ "" \
+ "Flag can be set as per-method option. " \
+ "If a value is specified for a method, compilation thresholds " \
+ "for that method are scaled by both the value of the global flag "\
+ "and the value of the per-method flag.") \
\
product(intx, Tier0InvokeNotifyFreqLog, 7, \
"Interpreter (tier 0) invocation notification frequency") \
diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp
index 31cffe2..0a7f654 100644
--- a/hotspot/src/share/vm/runtime/os.cpp
+++ b/hotspot/src/share/vm/runtime/os.cpp
@@ -1401,15 +1401,17 @@
return (sp > (stack_limit + reserved_area));
}
-size_t os::page_size_for_region(size_t region_size, size_t min_pages) {
+size_t os::page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned) {
assert(min_pages > 0, "sanity");
if (UseLargePages) {
const size_t max_page_size = region_size / min_pages;
for (size_t i = 0; _page_sizes[i] != 0; ++i) {
const size_t page_size = _page_sizes[i];
- if (page_size <= max_page_size && is_size_aligned(region_size, page_size)) {
- return page_size;
+ if (page_size <= max_page_size) {
+ if (!must_be_aligned || is_size_aligned(region_size, page_size)) {
+ return page_size;
+ }
}
}
}
@@ -1417,6 +1419,14 @@
return vm_page_size();
}
+size_t os::page_size_for_region_aligned(size_t region_size, size_t min_pages) {
+ return page_size_for_region(region_size, min_pages, true);
+}
+
+size_t os::page_size_for_region_unaligned(size_t region_size, size_t min_pages) {
+ return page_size_for_region(region_size, min_pages, false);
+}
+
#ifndef PRODUCT
void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count)
{
@@ -1665,17 +1675,17 @@
static size_t large_page_size() {
const size_t large_page_size_example = 4 * M;
- return os::page_size_for_region(large_page_size_example, 1);
+ return os::page_size_for_region_aligned(large_page_size_example, 1);
}
- static void test_page_size_for_region() {
+ static void test_page_size_for_region_aligned() {
if (UseLargePages) {
const size_t small_page = small_page_size();
const size_t large_page = large_page_size();
if (large_page > small_page) {
size_t num_small_pages_in_large = large_page / small_page;
- size_t page = os::page_size_for_region(large_page, num_small_pages_in_large);
+ size_t page = os::page_size_for_region_aligned(large_page, num_small_pages_in_large);
assert_eq(page, small_page);
}
@@ -1688,21 +1698,53 @@
const size_t large_page = large_page_size();
if (large_page > small_page) {
const size_t unaligned_region = large_page + 17;
- size_t page = os::page_size_for_region(unaligned_region, 1);
+ size_t page = os::page_size_for_region_aligned(unaligned_region, 1);
assert_eq(page, small_page);
const size_t num_pages = 5;
const size_t aligned_region = large_page * num_pages;
- page = os::page_size_for_region(aligned_region, num_pages);
+ page = os::page_size_for_region_aligned(aligned_region, num_pages);
assert_eq(page, large_page);
}
}
}
+ static void test_page_size_for_region_unaligned() {
+ if (UseLargePages) {
+ // Given exact page size, should return that page size.
+ for (size_t i = 0; os::_page_sizes[i] != 0; i++) {
+ size_t expected = os::_page_sizes[i];
+ size_t actual = os::page_size_for_region_unaligned(expected, 1);
+ assert_eq(expected, actual);
+ }
+
+ // Given slightly larger size than a page size, return the page size.
+ for (size_t i = 0; os::_page_sizes[i] != 0; i++) {
+ size_t expected = os::_page_sizes[i];
+ size_t actual = os::page_size_for_region_unaligned(expected + 17, 1);
+ assert_eq(expected, actual);
+ }
+
+ // Given a slightly smaller size than a page size,
+ // return the next smaller page size.
+ if (os::_page_sizes[1] > os::_page_sizes[0]) {
+ size_t expected = os::_page_sizes[0];
+ size_t actual = os::page_size_for_region_unaligned(os::_page_sizes[1] - 17, 1);
+ assert_eq(actual, expected);
+ }
+
+ // Return small page size for values less than a small page.
+ size_t small_page = small_page_size();
+ size_t actual = os::page_size_for_region_unaligned(small_page - 17, 1);
+ assert_eq(small_page, actual);
+ }
+ }
+
public:
static void run_tests() {
- test_page_size_for_region();
+ test_page_size_for_region_aligned();
test_page_size_for_region_alignment();
+ test_page_size_for_region_unaligned();
}
};
diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp
index ecd2e24..67f2226 100644
--- a/hotspot/src/share/vm/runtime/os.hpp
+++ b/hotspot/src/share/vm/runtime/os.hpp
@@ -148,6 +148,7 @@
static void pd_free_memory(char *addr, size_t bytes, size_t alignment_hint);
static void pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint);
+ static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned);
public:
static void init(void); // Called before command line parsing
@@ -267,8 +268,13 @@
// Returns the page size to use for a region of memory.
// region_size / min_pages will always be greater than or equal to the
- // returned value.
- static size_t page_size_for_region(size_t region_size, size_t min_pages);
+ // returned value. The returned value will divide region_size.
+ static size_t page_size_for_region_aligned(size_t region_size, size_t min_pages);
+
+ // Returns the page size to use for a region of memory.
+ // region_size / min_pages will always be greater than or equal to the
+ // returned value. The returned value might not divide region_size.
+ static size_t page_size_for_region_unaligned(size_t region_size, size_t min_pages);
// Return the largest page size that can be used
static size_t max_page_size() {
diff --git a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp
index 11803f1..4b17ca2 100644
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp
@@ -257,28 +257,28 @@
// Call and loop predicates determine whether a transition to a higher
// compilation level should be performed (pointers to predicate functions
// are passed to common() transition function).
-bool SimpleThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level) {
+bool SimpleThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level, Method* method) {
switch(cur_level) {
case CompLevel_none:
case CompLevel_limited_profile: {
- return loop_predicate_helper<CompLevel_none>(i, b, 1.0);
+ return loop_predicate_helper<CompLevel_none>(i, b, 1.0, method);
}
case CompLevel_full_profile: {
- return loop_predicate_helper<CompLevel_full_profile>(i, b, 1.0);
+ return loop_predicate_helper<CompLevel_full_profile>(i, b, 1.0, method);
}
default:
return true;
}
}
-bool SimpleThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level) {
+bool SimpleThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level, Method* method) {
switch(cur_level) {
case CompLevel_none:
case CompLevel_limited_profile: {
- return call_predicate_helper<CompLevel_none>(i, b, 1.0);
+ return call_predicate_helper<CompLevel_none>(i, b, 1.0, method);
}
case CompLevel_full_profile: {
- return call_predicate_helper<CompLevel_full_profile>(i, b, 1.0);
+ return call_predicate_helper<CompLevel_full_profile>(i, b, 1.0, method);
}
default:
return true;
@@ -293,8 +293,8 @@
int i = mdo->invocation_count();
int b = mdo->backedge_count();
double k = ProfileMaturityPercentage / 100.0;
- return call_predicate_helper<CompLevel_full_profile>(i, b, k) ||
- loop_predicate_helper<CompLevel_full_profile>(i, b, k);
+ return call_predicate_helper<CompLevel_full_profile>(i, b, k, method) ||
+ loop_predicate_helper<CompLevel_full_profile>(i, b, k, method);
}
return false;
}
@@ -313,7 +313,7 @@
// If we were at full profile level, would we switch to full opt?
if (common(p, method, CompLevel_full_profile) == CompLevel_full_optimization) {
next_level = CompLevel_full_optimization;
- } else if ((this->*p)(i, b, cur_level)) {
+ } else if ((this->*p)(i, b, cur_level, method)) {
next_level = CompLevel_full_profile;
}
break;
@@ -325,7 +325,7 @@
if (mdo->would_profile()) {
int mdo_i = mdo->invocation_count_delta();
int mdo_b = mdo->backedge_count_delta();
- if ((this->*p)(mdo_i, mdo_b, cur_level)) {
+ if ((this->*p)(mdo_i, mdo_b, cur_level, method)) {
next_level = CompLevel_full_optimization;
}
} else {
diff --git a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp
index 49a9d89..87d009e 100644
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp
@@ -43,9 +43,9 @@
// Call and loop predicates determine whether a transition to a higher compilation
// level should be performed (pointers to predicate functions are passed to common_TF().
// Predicates also take compiler load into account.
- typedef bool (SimpleThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level);
- bool call_predicate(int i, int b, CompLevel cur_level);
- bool loop_predicate(int i, int b, CompLevel cur_level);
+ typedef bool (SimpleThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level, Method* method);
+ bool call_predicate(int i, int b, CompLevel cur_level, Method* method);
+ bool loop_predicate(int i, int b, CompLevel cur_level, Method* method);
// Common transition function. Given a predicate determines if a method should transition to another level.
CompLevel common(Predicate p, Method* method, CompLevel cur_level);
// Transition functions.
@@ -76,8 +76,8 @@
// Predicate helpers are used by .*_predicate() methods as well as others.
// They check the given counter values, multiplied by the scale against the thresholds.
- template<CompLevel level> static inline bool call_predicate_helper(int i, int b, double scale);
- template<CompLevel level> static inline bool loop_predicate_helper(int i, int b, double scale);
+ template<CompLevel level> static inline bool call_predicate_helper(int i, int b, double scale, Method* method);
+ template<CompLevel level> static inline bool loop_predicate_helper(int i, int b, double scale, Method* method);
// Get a compilation level for a given method.
static CompLevel comp_level(Method* method) {
diff --git a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp
index ff0a6cf..05b37c4 100644
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp
@@ -25,8 +25,14 @@
#ifndef SHARE_VM_RUNTIME_SIMPLETHRESHOLDPOLICY_INLINE_HPP
#define SHARE_VM_RUNTIME_SIMPLETHRESHOLDPOLICY_INLINE_HPP
+#include "compiler/compilerOracle.hpp"
+
template<CompLevel level>
-bool SimpleThresholdPolicy::call_predicate_helper(int i, int b, double scale) {
+bool SimpleThresholdPolicy::call_predicate_helper(int i, int b, double scale, Method* method) {
+ double threshold_scaling;
+ if (CompilerOracle::has_option_value(method, "CompileThresholdScaling", threshold_scaling)) {
+ scale *= threshold_scaling;
+ }
switch(level) {
case CompLevel_none:
case CompLevel_limited_profile:
@@ -40,7 +46,11 @@
}
template<CompLevel level>
-bool SimpleThresholdPolicy::loop_predicate_helper(int i, int b, double scale) {
+bool SimpleThresholdPolicy::loop_predicate_helper(int i, int b, double scale, Method* method) {
+ double threshold_scaling;
+ if (CompilerOracle::has_option_value(method, "CompileThresholdScaling", threshold_scaling)) {
+ scale *= threshold_scaling;
+ }
switch(level) {
case CompLevel_none:
case CompLevel_limited_profile:
diff --git a/hotspot/src/share/vm/runtime/synchronizer.cpp b/hotspot/src/share/vm/runtime/synchronizer.cpp
index a64d5b9..7f829ba 100644
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -276,18 +276,6 @@
THREAD->set_current_pending_monitor_is_from_java(true);
}
-// NOTE: must use heavy weight monitor to handle jni monitor enter
-bool ObjectSynchronizer::jni_try_enter(Handle obj, Thread* THREAD) {
- if (UseBiasedLocking) {
- BiasedLocking::revoke_and_rebias(obj, false, THREAD);
- assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
- }
-
- ObjectMonitor* monitor = ObjectSynchronizer::inflate_helper(obj());
- return monitor->try_enter(THREAD);
-}
-
-
// NOTE: must use heavy weight monitor to handle jni monitor exit
void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
TEVENT(jni_exit);
diff --git a/hotspot/src/share/vm/runtime/synchronizer.hpp b/hotspot/src/share/vm/runtime/synchronizer.hpp
index a823b54..f2ff4c6 100644
--- a/hotspot/src/share/vm/runtime/synchronizer.hpp
+++ b/hotspot/src/share/vm/runtime/synchronizer.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -65,7 +65,6 @@
// Used only to handle jni locks or other unmatched monitor enter/exit
// Internally they will use heavy weight monitor.
static void jni_enter(Handle obj, TRAPS);
- static bool jni_try_enter(Handle obj, Thread* THREAD); // Implements Unsafe.tryMonitorEnter
static void jni_exit(oop obj, Thread* THREAD);
// Handle all interpreter, compiler and jni cases
diff --git a/hotspot/src/share/vm/runtime/virtualspace.cpp b/hotspot/src/share/vm/runtime/virtualspace.cpp
index b659ec5..d57f1be 100644
--- a/hotspot/src/share/vm/runtime/virtualspace.cpp
+++ b/hotspot/src/share/vm/runtime/virtualspace.cpp
@@ -38,7 +38,8 @@
}
ReservedSpace::ReservedSpace(size_t size) {
- size_t page_size = os::page_size_for_region(size, 1);
+ // Want to use large pages where possible and pad with small pages.
+ size_t page_size = os::page_size_for_region_unaligned(size, 1);
bool large_pages = page_size != (size_t)os::vm_page_size();
// Don't force the alignment to be large page aligned,
// since that will waste memory.
@@ -617,7 +618,7 @@
bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) {
- const size_t max_commit_granularity = os::page_size_for_region(rs.size(), 1);
+ const size_t max_commit_granularity = os::page_size_for_region_unaligned(rs.size(), 1);
return initialize_with_granularity(rs, committed_size, max_commit_granularity);
}
@@ -1239,7 +1240,7 @@
case Disable:
return vs.initialize_with_granularity(rs, 0, os::vm_page_size());
case Commit:
- return vs.initialize_with_granularity(rs, 0, os::page_size_for_region(rs.size(), 1));
+ return vs.initialize_with_granularity(rs, 0, os::page_size_for_region_unaligned(rs.size(), 1));
}
}
diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp
index 182052c..5b3ca8a 100644
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp
@@ -351,11 +351,18 @@
nonstatic_field(MethodData, _arg_stack, intx) \
nonstatic_field(MethodData, _arg_returned, intx) \
nonstatic_field(MethodData, _tenure_traps, uint) \
+ nonstatic_field(MethodData, _invoke_mask, int) \
+ nonstatic_field(MethodData, _backedge_mask, int) \
nonstatic_field(DataLayout, _header._struct._tag, u1) \
nonstatic_field(DataLayout, _header._struct._flags, u1) \
nonstatic_field(DataLayout, _header._struct._bci, u2) \
nonstatic_field(DataLayout, _cells[0], intptr_t) \
nonstatic_field(MethodCounters, _nmethod_age, int) \
+ nonstatic_field(MethodCounters, _interpreter_invocation_limit, int) \
+ nonstatic_field(MethodCounters, _interpreter_backward_branch_limit, int) \
+ nonstatic_field(MethodCounters, _interpreter_profile_limit, int) \
+ nonstatic_field(MethodCounters, _invoke_mask, int) \
+ nonstatic_field(MethodCounters, _backedge_mask, int) \
nonstatic_field(MethodCounters, _interpreter_invocation_count, int) \
nonstatic_field(MethodCounters, _interpreter_throwout_count, u2) \
nonstatic_field(MethodCounters, _number_of_breakpoints, u2) \
diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp
index 784db46..652da09 100644
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp
@@ -1142,17 +1142,18 @@
return ((x != NoLongBits) && (mask_long_bits(x, x - 1) == NoLongBits));
}
-//* largest i such that 2^i <= x
-// A negative value of 'x' will return '31'
+// Returns largest i such that 2^i <= x.
+// If x < 0, the function returns 31 on a 32-bit machine and 63 on a 64-bit machine.
+// If x == 0, the function returns -1.
inline int log2_intptr(intptr_t x) {
int i = -1;
- uintptr_t p = 1;
+ uintptr_t p = 1;
while (p != 0 && p <= (uintptr_t)x) {
// p = 2^(i+1) && p <= x (i.e., 2^(i+1) <= x)
i++; p *= 2;
}
// p = 2^(i+1) && x < p (i.e., 2^i <= x < 2^(i+1))
- // (if p = 0 then overflow occurred and i = 31)
+ // If p = 0, overflow has occurred and i = 31 or i = 63 (depending on the machine word size).
return i;
}
diff --git a/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java b/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java
index b9837c2..5e61102 100644
--- a/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java
+++ b/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java
@@ -54,7 +54,7 @@
//
// Tier0InvokeNotifyFreqLog, Tier0BackedgeNotifyFreqLog,
// Tier3InvocationThreshold, Tier3MinInvocationThreshold,
- // Tier3CompileThreshold, and Tier3BackEdgeThreshold,
+ // Tier3CompileThreshold, Tier3BackEdgeThreshold,
// Tier2InvokeNotifyFreqLog, Tier2BackedgeNotifyFreqLog,
// Tier3InvokeNotifyFreqLog, Tier3BackedgeNotifyFreqLog,
// Tier23InlineeNotifyFreqLog, Tier4InvocationThreshold,
diff --git a/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java b/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java
index 04551a2..8e390c1 100644
--- a/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java
+++ b/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java
@@ -98,11 +98,13 @@
return false;
});
for (BlobType bt : BlobType.getAvailable()) {
- int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0;
- Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(),
- expectedNotificationsAmount, String.format("Unexpected "
- + "amount of notifications for pool: %s",
- bt.getMemoryPool().getName()));
+ if (CodeCacheUtils.isCodeHeapPredictable(bt)) {
+ int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0;
+ Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(),
+ expectedNotificationsAmount, String.format("Unexpected "
+ + "amount of notifications for pool: %s",
+ bt.getMemoryPool().getName()));
+ }
}
try {
((NotificationEmitter) ManagementFactory.getMemoryMXBean()).
diff --git a/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java b/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java
index b03fbc2..fea786e 100644
--- a/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java
+++ b/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java
@@ -52,7 +52,9 @@
public static void main(String[] args) {
for (BlobType bt : BlobType.getAvailable()) {
- new ThresholdNotificationsTest(bt).runTest();
+ if (CodeCacheUtils.isCodeHeapPredictable(bt)) {
+ new ThresholdNotificationsTest(bt).runTest();
+ }
}
}
diff --git a/hotspot/test/compiler/loopopts/7052494/Test7052494.java b/hotspot/test/compiler/loopopts/7052494/Test7052494.java
index fa45411..62aa12f 100644
--- a/hotspot/test/compiler/loopopts/7052494/Test7052494.java
+++ b/hotspot/test/compiler/loopopts/7052494/Test7052494.java
@@ -25,7 +25,6 @@
/**
* @test
* @bug 7052494
- * @ignore 7154567
* @summary Eclipse test fails on JDK 7 b142
*
* @run main/othervm -Xbatch Test7052494
diff --git a/hotspot/test/compiler/stringopts/TestOptimizeStringConcat.java b/hotspot/test/compiler/stringopts/TestOptimizeStringConcat.java
new file mode 100644
index 0000000..771ffb0
--- /dev/null
+++ b/hotspot/test/compiler/stringopts/TestOptimizeStringConcat.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2015 SAP AG. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8068909
+ * @key regression
+ * @summary test that string optimizations produce code, that doesn't lead to a crash.
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestOptimizeStringConcat
+ * @author axel.siebenborn@sap.com
+ */
+public class TestOptimizeStringConcat {
+
+ static boolean checkArgumentSyntax(String value, String allowedchars, String notallowedchars, String logmsg) {
+ String rc = null;
+
+ int maxchar = 99999;
+ int minchar = 1;
+ if ((allowedchars != null && notallowedchars != null) || minchar > maxchar) {
+ rc = "internal error";
+ } else {
+ if (value == null) {
+ rc = "the value null is not allowed, it is missing";
+ } else if (value != null && minchar > 0 && value.trim().equals("")) {
+ rc = "the value must not be empty";
+ } else if (value != null) {
+ if (value.length() < minchar || value.length() > maxchar) {
+ if (rc == null) {
+ rc = "the value length must be between +minchar+ and +maxchar";
+ }
+ }
+ char[] _value = value.toCharArray();
+ boolean dotfound = false;
+ int i = 1;
+ if (_value[i] == '.' && !dotfound) {
+ dotfound = true;
+ } else if (allowedchars != null && allowedchars.indexOf(_value[i]) == -1) {
+ if (rc == null) {
+ rc = "the value contains an illegal character: '" + _value[i] + "', only following characters are allowed: '+allowedchars+'";
+ } else {
+ rc += " / the value contains an illegal character: '" + _value[i] + "', only following characters are allowed: '+allowedchars+'";
+ }
+ } else if (notallowedchars != null && notallowedchars.indexOf(_value[i]) != -1) {
+ if (rc == null) {
+ rc = "the value contains an illegal character: '" + _value[i] + "', following characters are not allowed '+notallowedchars+'";
+ } else {
+ rc += " / the value contains an illegal character: '" + _value[i] + "', following characters are not allowed '+notallowedchars+'";
+ }
+ }
+ }
+ }
+
+ if (rc != null) {
+ System.out.println(logmsg + " ==> " + rc);
+ return false;
+ }
+ return true;
+ }
+
+ public static void main(String[] args) {
+ boolean failed = false;
+ for (int i = 0; i < 10000; i++) {
+ failed |= !checkArgumentSyntax("theName", null, "\"<&", "Error consistencyCheck: name in component definition");
+ failed |= !checkArgumentSyntax(null, null, "\"<&", "Error consistencyCheck: name in component definition");
+ failed |= !checkArgumentSyntax("42", "0123456789.", null, "Error consistencyCheck: counter in component definition");
+ }
+ System.out.println(failed);
+ }
+}
diff --git a/hotspot/test/compiler/testlibrary/rtm/BusyLock.java b/hotspot/test/compiler/testlibrary/rtm/BusyLock.java
index 55985b6..879edb8 100644
--- a/hotspot/test/compiler/testlibrary/rtm/BusyLock.java
+++ b/hotspot/test/compiler/testlibrary/rtm/BusyLock.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,9 +24,6 @@
package rtm;
-import com.oracle.java.testlibrary.Utils;
-import sun.misc.Unsafe;
-
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
@@ -42,7 +39,6 @@
// Following field have to be static in order to avoid escape analysis.
@SuppressWarnings("UnsuedDeclaration")
private static int field = 0;
- private static final Unsafe UNSAFE = Utils.getUnsafe();
protected final Object monitor;
protected final int timeout;
@@ -59,18 +55,9 @@
@Override
public void run() {
try {
- // wait until forceAbort leave monitor
- barrier.await();
- if (UNSAFE.tryMonitorEnter(monitor)) {
- try {
- barrier.await();
- Thread.sleep(timeout);
- } finally {
- UNSAFE.monitorExit(monitor);
- }
- } else {
- throw new RuntimeException("Monitor should be entered by " +
- "::run() first.");
+ synchronized (monitor) {
+ barrier.await();
+ Thread.sleep(timeout);
}
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException("Synchronization error happened.", e);
@@ -79,7 +66,6 @@
public void syncAndTest() {
try {
- barrier.await();
// wait until monitor is locked by a ::run method
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
diff --git a/hotspot/test/gc/TestNUMAPageSize.java b/hotspot/test/gc/TestNUMAPageSize.java
index 1a3b5dd..9537f0f 100644
--- a/hotspot/test/gc/TestNUMAPageSize.java
+++ b/hotspot/test/gc/TestNUMAPageSize.java
@@ -25,6 +25,7 @@
* @test TestNUMAPageSize
* @summary Make sure that start up with NUMA support does not cause problems.
* @bug 8061467
+ * @requires (vm.opt.AggressiveOpts == null) | (vm.opt.AggressiveOpts == false)
* @key gc
* @key regression
* @run main/othervm -Xmx8M -XX:+UseNUMA TestNUMAPageSize
diff --git a/hotspot/test/gc/TestSmallHeap.java b/hotspot/test/gc/TestSmallHeap.java
index 170b539..abe6ed3 100644
--- a/hotspot/test/gc/TestSmallHeap.java
+++ b/hotspot/test/gc/TestSmallHeap.java
@@ -25,6 +25,7 @@
* @test TestSmallHeap
* @bug 8067438
* @requires vm.gc=="null"
+ * @requires (vm.opt.AggressiveOpts=="null") | (vm.opt.AggressiveOpts=="false")
* @summary Verify that starting the VM with a small heap works
* @library /testlibrary /../../test/lib
* @build TestSmallHeap
@@ -33,8 +34,9 @@
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseSerialGC TestSmallHeap
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseG1GC TestSmallHeap
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseConcMarkSweepGC TestSmallHeap
- *
- * Note: It would be nice to verify the minimal supported heap size (2m) here,
+ */
+
+/* Note: It would be nice to verify the minimal supported heap size (2m) here,
* but we align the heap size based on the card table size. And the card table
* size is aligned based on the minimal pages size provided by the os. This
* means that on most platforms, where the minimal page size is 4k, we get a
diff --git a/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java b/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java
index c4a81e2..c24b3ec 100644
--- a/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java
+++ b/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java
@@ -116,7 +116,14 @@
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldHaveExitValue(0);
+ try {
+ output.shouldHaveExitValue(0);
+ } catch (RuntimeException e) {
+ // It's ok if there is no client vm in the jdk.
+ if (output.firstMatch("Unrecognized option: -client") == null) {
+ throw e;
+ }
+ }
return output;
}
diff --git a/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java b/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java
index 9ce9f76..2ad3fc1 100644
--- a/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java
+++ b/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
- "-Xmx64m", "-XX:-TransmitErrorReport", Crasher.class.getName());
+ "-Xmx64m", "-XX:-TransmitErrorReport", "-XX:-CreateMinidumpOnCrash", Crasher.class.getName());
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldNotMatch("error occurred during error reporting \\(printing problematic frame\\)");
}
diff --git a/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java b/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java
index 1a96dd8..3bd7cf3 100644
--- a/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java
+++ b/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java
@@ -25,6 +25,7 @@
* @test CompilerQueueTest
* @bug 8054889
* @library ..
+ * @ignore 8069160
* @build DcmdUtil CompilerQueueTest
* @run main CompilerQueueTest
* @run main/othervm -XX:-TieredCompilation CompilerQueueTest