--- a/hotspot/agent/src/os/win32/windbg/sawindbg.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/agent/src/os/win32/windbg/sawindbg.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -112,7 +112,9 @@
return;}
static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) {
- env->ThrowNew(env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
+ jclass clazz = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException");
+ CHECK_EXCEPTION;
+ env->ThrowNew(clazz, errMsg);
}
/*
@@ -310,15 +312,18 @@
static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) {
jboolean isCopy;
jclass clazz = env->GetObjectClass(obj);
+ CHECK_EXCEPTION_(false);
jstring path;
const char* buf;
path = (jstring) env->GetStaticObjectField(clazz, imagePath_ID);
+ CHECK_EXCEPTION_(false);
buf = env->GetStringUTFChars(path, &isCopy);
CHECK_EXCEPTION_(false);
AutoJavaString imagePath(env, path, buf);
path = (jstring) env->GetStaticObjectField(clazz, symbolPath_ID);
+ CHECK_EXCEPTION_(false);
buf = env->GetStringUTFChars(path, &isCopy);
CHECK_EXCEPTION_(false);
AutoJavaString symbolPath(env, path, buf);
--- a/hotspot/make/Makefile Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/Makefile Fri Sep 12 04:22:19 2014 -0700
@@ -95,6 +95,7 @@
COMMON_VM_PRODUCT_TARGETS=product product1 docs export_product
COMMON_VM_FASTDEBUG_TARGETS=fastdebug fastdebug1 docs export_fastdebug
COMMON_VM_DEBUG_TARGETS=debug debug1 docs export_debug
+COMMON_VM_OPTIMIZED_TARGETS=optimized optimized1 docs export_optimized
# JDK directory list
JDK_DIRS=bin include jre lib demo
@@ -111,20 +112,21 @@
all_product: product1 docs export_product
all_fastdebug: fastdebug1 docs export_fastdebug
all_debug: debug1 docs export_debug
+all_optimized: optimized1 docs export_optimized
else
ifeq ($(MACOSX_UNIVERSAL),true)
all_product: universal_product
all_fastdebug: universal_fastdebug
all_debug: universal_debug
+all_optimized: universal_optimized
else
all_product: $(COMMON_VM_PRODUCT_TARGETS)
all_fastdebug: $(COMMON_VM_FASTDEBUG_TARGETS)
all_debug: $(COMMON_VM_DEBUG_TARGETS)
+all_optimized: $(COMMON_VM_OPTIMIZED_TARGETS)
endif
endif
-all_optimized: optimized optimized1 docs export_optimized
-
allzero: all_productzero all_fastdebugzero
all_productzero: productzero docs export_product
all_fastdebugzero: fastdebugzero docs export_fastdebug
@@ -890,3 +892,5 @@
create_jdk copy_jdk update_jdk test_jdk \
copy_product_jdk copy_fastdebug_jdk copy_debug_jdk \
$(HS_ALT_MAKE)/Makefile.make remove_old_debuginfo
+
+.NOTPARALLEL:
--- a/hotspot/make/aix/Makefile Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/aix/Makefile Fri Sep 12 04:22:19 2014 -0700
@@ -256,36 +256,36 @@
$(SUBDIRS_TIERED): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered
+ +$(BUILDTREE) VARIANT=tiered
$(SUBDIRS_C2): $(BUILDTREE_MAKE)
ifeq ($(FORCE_TIERED),1)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
+ +$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
else
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler2
+ +$(BUILDTREE) VARIANT=compiler2
endif
$(SUBDIRS_C1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler1
+ +$(BUILDTREE) VARIANT=compiler1
$(SUBDIRS_CORE): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=core
+ +$(BUILDTREE) VARIANT=core
$(SUBDIRS_ZERO): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
+ +$(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_SHARK): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
+ +$(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_MINIMAL1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=minimal1
+ +$(BUILDTREE) VARIANT=minimal1
platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in
@@ -379,3 +379,5 @@
.PHONY: all compiler1 compiler2 core zero shark
.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs
.PHONY: checks check_os_version check_j2se_version
+
+.NOTPARALLEL:
--- a/hotspot/make/aix/makefiles/buildtree.make Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/aix/makefiles/buildtree.make Fri Sep 12 04:22:19 2014 -0700
@@ -173,7 +173,7 @@
# Run make in each subdirectory recursively.
$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE
$(QUIETLY) [ -d $@ ] || { mkdir -p $@; }
- $(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
+ +$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
$(QUIETLY) touch $@
$(SIMPLE_DIRS):
@@ -364,3 +364,5 @@
FORCE:
.PHONY: all FORCE
+
+.NOTPARALLEL:
--- a/hotspot/make/aix/makefiles/top.make Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/aix/makefiles/top.make Fri Sep 12 04:22:19 2014 -0700
@@ -69,7 +69,13 @@
# Wierd argument adjustment for "gnumake -j..."
adjust-mflags = $(GENERATED)/adjust-mflags
-MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+# If SPEC is set, it's from configure and it's already controlling concurrency
+# for us. Skip setting -j with HOTSPOT_BUILD_JOBS.
+ifeq ($(SPEC), )
+ MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+else
+ MFLAGS-adjusted = -r $(MFLAGS)
+endif
# default target: update lists, make vm
@@ -116,7 +122,7 @@
@+mv $@+ $@
the_vm: vm_build_preliminaries $(adjust-mflags)
- @$(UpdatePCH)
+ +@$(UpdatePCH)
@$(MAKE) -f vm.make $(MFLAGS-adjusted)
install gamma: the_vm
@@ -125,7 +131,7 @@
# next rules support "make foo.[ois]"
%.o %.i %.s:
- $(UpdatePCH)
+ +$(UpdatePCH)
$(MAKE) -f vm.make $(MFLAGS) $@
#$(MAKE) -f vm.make $@
@@ -142,3 +148,5 @@
.PHONY: default vm_build_preliminaries
.PHONY: lists ad_stuff jvmti_stuff sa_stuff the_vm clean realclean
.PHONY: checks check_os_version install
+
+.NOTPARALLEL:
--- a/hotspot/make/bsd/Makefile Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/bsd/Makefile Fri Sep 12 04:22:19 2014 -0700
@@ -250,36 +250,36 @@
$(SUBDIRS_TIERED): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered
+ +$(BUILDTREE) VARIANT=tiered
$(SUBDIRS_C2): $(BUILDTREE_MAKE)
ifeq ($(FORCE_TIERED),1)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
+ +$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
else
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler2
+ +$(BUILDTREE) VARIANT=compiler2
endif
$(SUBDIRS_C1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler1
+ +$(BUILDTREE) VARIANT=compiler1
$(SUBDIRS_CORE): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=core
+ +$(BUILDTREE) VARIANT=core
$(SUBDIRS_ZERO): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
+ +$(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_SHARK): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
+ +$(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_MINIMAL1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=minimal1
+ +$(BUILDTREE) VARIANT=minimal1
platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in
$(SED) 's/@ZERO_ARCHDEF@/$(ZERO_ARCHDEF)/g;s/@ZERO_LIBARCH@/$(ZERO_LIBARCH)/g;' < $< > $@
@@ -392,3 +392,5 @@
.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs
.PHONY: checks check_os_version check_j2se_version
.PHONY: $(HS_ALT_MAKE)/$(OSNAME)/Makefile.make
+
+.NOTPARALLEL:
--- a/hotspot/make/bsd/makefiles/buildtree.make Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/bsd/makefiles/buildtree.make Fri Sep 12 04:22:19 2014 -0700
@@ -178,7 +178,7 @@
# Run make in each subdirectory recursively.
$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE
$(QUIETLY) [ -d $@ ] || { mkdir -p $@; }
- $(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
+ +$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
$(QUIETLY) touch $@
$(SIMPLE_DIRS):
@@ -378,3 +378,5 @@
FORCE:
.PHONY: all FORCE
+
+.NOTPARALLEL:
--- a/hotspot/make/bsd/makefiles/top.make Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/bsd/makefiles/top.make Fri Sep 12 04:22:19 2014 -0700
@@ -69,7 +69,13 @@
# Wierd argument adjustment for "gnumake -j..."
adjust-mflags = $(GENERATED)/adjust-mflags
-MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+# If SPEC is set, it's from configure and it's already controlling concurrency
+# for us. Skip setting -j with HOTSPOT_BUILD_JOBS.
+ifeq ($(SPEC), )
+ MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+else
+ MFLAGS-adjusted = -r $(MFLAGS)
+endif
# default target: update lists, make vm
@@ -125,7 +131,7 @@
@+mv $@+ $@
the_vm: vm_build_preliminaries $(adjust-mflags)
- @$(UpdatePCH)
+ +@$(UpdatePCH)
@$(MAKE) -f vm.make $(MFLAGS-adjusted)
install : the_vm
@@ -134,7 +140,7 @@
# next rules support "make foo.[ois]"
%.o %.i %.s:
- $(UpdatePCH)
+ +$(UpdatePCH)
$(MAKE) -f vm.make $(MFLAGS) $@
#$(MAKE) -f vm.make $@
@@ -151,3 +157,5 @@
.PHONY: default vm_build_preliminaries
.PHONY: lists ad_stuff jvmti_stuff sa_stuff the_vm clean realclean
.PHONY: checks check_os_version install
+
+.NOTPARALLEL:
--- a/hotspot/make/bsd/makefiles/universal.gmk Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/bsd/makefiles/universal.gmk Fri Sep 12 04:22:19 2014 -0700
@@ -25,6 +25,8 @@
# macosx universal builds
universal_product:
$(MAKE) MACOSX_UNIVERSAL=true all_product_universal
+universal_optimized:
+ $(MAKE) MACOSX_UNIVERSAL=true all_optimized_universal
universal_fastdebug:
$(MAKE) MACOSX_UNIVERSAL=true all_fastdebug_universal
universal_debug:
@@ -36,6 +38,10 @@
# $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_PRODUCT_TARGETS)
$(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_PRODUCT_TARGETS)
$(QUIETLY) $(MAKE) BUILD_FLAVOR=product EXPORT_SUBDIR= universalize
+all_optimized_universal:
+# $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_OPTIMIZED_TARGETS)
+ $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_OPTIMIZED_TARGETS)
+ $(QUIETLY) $(MAKE) BUILD_FLAVOR=optimized EXPORT_SUBDIR=/optimized universalize
all_fastdebug_universal:
# $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_FASTDEBUG_TARGETS)
$(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_FASTDEBUG_TARGETS)
@@ -98,13 +104,15 @@
export_product_jdk::
$(MAKE) EXPORT_SUBDIR= export_universal
export_optimized_jdk::
- $(MAKE) EXPORT_SUBDIR= export_universal
+ $(MAKE) EXPORT_SUBDIR=/optimized export_universal
export_fastdebug_jdk::
$(MAKE) EXPORT_SUBDIR=/fastdebug export_universal
export_debug_jdk::
$(MAKE) EXPORT_SUBDIR=/debug export_universal
copy_product_jdk::
$(MAKE) COPY_SUBDIR= copy_universal
+copy_optimized_jdk::
+ $(MAKE) COPY_SUBDIR=/optimized copy_universal
copy_fastdebug_jdk::
$(MAKE) COPY_SUBDIR=/fastdebug copy_universal
copy_debug_jdk::
@@ -112,5 +120,6 @@
.PHONY: universal_product universal_fastdebug universal_debug \
all_product_universal all_fastdebug_universal all_debug_universal \
+ universal_optimized all_optimized_universal \
universalize export_universal copy_universal \
$(UNIVERSAL_LIPO_LIST) $(UNIVERSAL_COPY_LIST)
--- a/hotspot/make/linux/Makefile Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/linux/Makefile Fri Sep 12 04:22:19 2014 -0700
@@ -256,36 +256,36 @@
$(SUBDIRS_TIERED): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered
+ +$(BUILDTREE) VARIANT=tiered
$(SUBDIRS_C2): $(BUILDTREE_MAKE)
ifeq ($(FORCE_TIERED),1)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
+ +$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
else
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler2
+ +$(BUILDTREE) VARIANT=compiler2
endif
$(SUBDIRS_C1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler1
+ +$(BUILDTREE) VARIANT=compiler1
$(SUBDIRS_CORE): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=core
+ +$(BUILDTREE) VARIANT=core
$(SUBDIRS_ZERO): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
+ +$(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_SHARK): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
+ +$(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_MINIMAL1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=minimal1
+ +$(BUILDTREE) VARIANT=minimal1
platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in
@@ -399,3 +399,5 @@
.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs
.PHONY: checks check_os_version check_j2se_version
.PHONY: $(HS_ALT_MAKE)/$(OSNAME)/Makefile.make
+
+.NOTPARALLEL:
--- a/hotspot/make/linux/makefiles/buildtree.make Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/linux/makefiles/buildtree.make Fri Sep 12 04:22:19 2014 -0700
@@ -172,7 +172,7 @@
# Run make in each subdirectory recursively.
$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE
$(QUIETLY) [ -d $@ ] || { mkdir -p $@; }
- $(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
+ +$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
$(QUIETLY) touch $@
$(SIMPLE_DIRS):
@@ -377,3 +377,5 @@
FORCE:
.PHONY: all FORCE
+
+.NOTPARALLEL:
--- a/hotspot/make/linux/makefiles/top.make Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/linux/makefiles/top.make Fri Sep 12 04:22:19 2014 -0700
@@ -69,7 +69,13 @@
# Wierd argument adjustment for "gnumake -j..."
adjust-mflags = $(GENERATED)/adjust-mflags
-MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+# If SPEC is set, it's from configure and it's already controlling concurrency
+# for us. Skip setting -j with HOTSPOT_BUILD_JOBS.
+ifeq ($(SPEC), )
+ MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+else
+ MFLAGS-adjusted = -r $(MFLAGS)
+endif
# default target: update lists, make vm
@@ -119,7 +125,7 @@
@+mv $@+ $@
the_vm: vm_build_preliminaries $(adjust-mflags)
- @$(UpdatePCH)
+ +@$(UpdatePCH)
@$(MAKE) -f vm.make $(MFLAGS-adjusted)
install: the_vm
@@ -128,7 +134,7 @@
# next rules support "make foo.[ois]"
%.o %.i %.s:
- $(UpdatePCH)
+ +$(UpdatePCH)
$(MAKE) -f vm.make $(MFLAGS) $@
#$(MAKE) -f vm.make $@
@@ -145,3 +151,5 @@
.PHONY: default vm_build_preliminaries
.PHONY: lists ad_stuff jvmti_stuff sa_stuff the_vm clean realclean
.PHONY: checks check_os_version install
+
+.NOTPARALLEL:
--- a/hotspot/make/solaris/Makefile Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/solaris/Makefile Fri Sep 12 04:22:19 2014 -0700
@@ -200,24 +200,24 @@
$(SUBDIRS_TIERED): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered
+ +$(BUILDTREE) VARIANT=tiered
$(SUBDIRS_C2): $(BUILDTREE_MAKE)
ifeq ($(FORCE_TIERED),1)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
+ +$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
else
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler2
+ +$(BUILDTREE) VARIANT=compiler2
endif
$(SUBDIRS_C1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=compiler1
+ +$(BUILDTREE) VARIANT=compiler1
$(SUBDIRS_CORE): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
- $(BUILDTREE) VARIANT=core
+ +$(BUILDTREE) VARIANT=core
# Define INSTALL=y at command line to automatically copy JVM into JAVA_HOME
@@ -292,3 +292,5 @@
.PHONY: all compiler1 compiler2 core
.PHONY: clean clean_compiler1 clean_compiler2 clean_core docs clean_docs
.PHONY: checks check_os_version check_j2se_version
+
+.NOTPARALLEL:
--- a/hotspot/make/solaris/makefiles/buildtree.make Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/solaris/makefiles/buildtree.make Fri Sep 12 04:22:19 2014 -0700
@@ -165,7 +165,7 @@
# Run make in each subdirectory recursively.
$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE
$(QUIETLY) [ -d $@ ] || { mkdir -p $@; }
- $(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
+ +$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
$(QUIETLY) touch $@
$(SIMPLE_DIRS):
@@ -364,3 +364,5 @@
FORCE:
.PHONY: all FORCE
+
+.NOTPARALLEL:
--- a/hotspot/make/solaris/makefiles/top.make Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/solaris/makefiles/top.make Fri Sep 12 04:22:19 2014 -0700
@@ -62,7 +62,13 @@
# Wierd argument adjustment for "gnumake -j..."
adjust-mflags = $(GENERATED)/adjust-mflags
-MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+# If SPEC is set, it's from configure and it's already controlling concurrency
+# for us. Skip setting -j with HOTSPOT_BUILD_JOBS.
+ifeq ($(SPEC), )
+ MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
+else
+ MFLAGS-adjusted = -r $(MFLAGS)
+endif
# default target: update lists, make vm
@@ -136,3 +142,5 @@
.PHONY: default vm_build_preliminaries
.PHONY: lists ad_stuff jvmti_stuff trace_stuff sa_stuff the_vm clean realclean
.PHONY: checks check_os_version install
+
+.NOTPARALLEL:
--- a/hotspot/make/solaris/makefiles/vm.make Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/make/solaris/makefiles/vm.make Fri Sep 12 04:22:19 2014 -0700
@@ -143,7 +143,7 @@
LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle
endif # sparcWorks
-LIBS += -lkstat
+LIBS += -lkstat -lpicl
# By default, link the *.o into the library, not the executable.
LINK_INTO$(LINK_INTO) = LIBJVM
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -32,6 +32,7 @@
int VM_Version::_features = VM_Version::unknown_m;
const char* VM_Version::_features_str = "";
+unsigned int VM_Version::_L2_cache_line_size = 0;
void VM_Version::initialize() {
_features = determine_features();
@@ -192,7 +193,7 @@
}
assert(BlockZeroingLowLimit > 0, "invalid value");
- if (has_block_zeroing()) {
+ if (has_block_zeroing() && cache_line_size > 0) {
if (FLAG_IS_DEFAULT(UseBlockZeroing)) {
FLAG_SET_DEFAULT(UseBlockZeroing, true);
}
@@ -202,7 +203,7 @@
}
assert(BlockCopyLowLimit > 0, "invalid value");
- if (has_block_zeroing()) { // has_blk_init() && is_T4(): core's local L2 cache
+ if (has_block_zeroing() && cache_line_size > 0) { // has_blk_init() && is_T4(): core's local L2 cache
if (FLAG_IS_DEFAULT(UseBlockCopy)) {
FLAG_SET_DEFAULT(UseBlockCopy, true);
}
@@ -252,49 +253,6 @@
// buf is started with ", " or is empty
_features_str = os::strdup(strlen(buf) > 2 ? buf + 2 : buf);
- // There are three 64-bit SPARC families that do not overlap, e.g.,
- // both is_ultra3() and is_sparc64() cannot be true at the same time.
- // Within these families, there can be more than one chip, e.g.,
- // is_T4() and is_T7() machines are also is_niagara().
- if (is_ultra3()) {
- assert(_L1_data_cache_line_size == 0, "overlap with Ultra3 family");
- // Ref: UltraSPARC III Cu Processor
- _L1_data_cache_line_size = 64;
- }
- if (is_niagara()) {
- assert(_L1_data_cache_line_size == 0, "overlap with niagara family");
- // All Niagara's are sun4v's, but not all sun4v's are Niagaras, e.g.,
- // Fujitsu SPARC64 is sun4v, but we don't want it in this block.
- //
- // Ref: UltraSPARC T1 Supplement to the UltraSPARC Architecture 2005
- // Appendix F.1.3.1 Cacheable Accesses
- // -> 16-byte L1 cache line size
- //
- // Ref: UltraSPARC T2: A Highly-Threaded, Power-Efficient, SPARC SOC
- // Section III: SPARC Processor Core
- // -> 16-byte L1 cache line size
- //
- // Ref: Oracle's SPARC T4-1, SPARC T4-2, SPARC T4-4, and SPARC T4-1B Server Architecture
- // Section SPARC T4 Processor Cache Architecture
- // -> 32-byte L1 cache line size (no longer see that info on this ref)
- //
- // XXX - still need a T7 reference here
- //
- if (is_T7()) { // T7 or newer
- _L1_data_cache_line_size = 64;
- } else if (is_T4()) { // T4 or newer (until T7)
- _L1_data_cache_line_size = 32;
- } else { // T1 or newer (until T4)
- _L1_data_cache_line_size = 16;
- }
- }
- if (is_sparc64()) {
- guarantee(_L1_data_cache_line_size == 0, "overlap with SPARC64 family");
- // Ref: Fujitsu SPARC64 VII Processor
- // Section 4 Cache System
- _L1_data_cache_line_size = 64;
- }
-
// UseVIS is set to the smallest of what hardware supports and what
// the command line requires. I.e., you cannot set UseVIS to 3 on
// older UltraSparc which do not support it.
@@ -401,6 +359,7 @@
#ifndef PRODUCT
if (PrintMiscellaneous && Verbose) {
tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size());
+ tty->print_cr("L2 cache line size: %u", L2_cache_line_size());
tty->print("Allocation");
if (AllocatePrefetchStyle <= 0) {
tty->print_cr(": no prefetching");
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -96,6 +96,9 @@
static int _features;
static const char* _features_str;
+ static unsigned int _L2_cache_line_size;
+ static unsigned int L2_cache_line_size() { return _L2_cache_line_size; }
+
static void print_features();
static int determine_features();
static int platform_features(int features);
@@ -167,9 +170,8 @@
static const char* cpu_features() { return _features_str; }
- static intx prefetch_data_size() {
- return is_T4() && !is_T7() ? 32 : 64; // default prefetch block size on sparc
- }
+ // default prefetch block size on sparc
+ static intx prefetch_data_size() { return L2_cache_line_size(); }
// Prefetch
static intx prefetch_copy_interval_in_bytes() {
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -26,6 +26,7 @@
#define CPU_X86_VM_ASSEMBLER_X86_HPP
#include "asm/register.hpp"
+#include "vm_version_x86.hpp"
class BiasedLockingCounters;
@@ -1292,14 +1293,34 @@
if (order_constraint & StoreLoad) {
// All usable chips support "locked" instructions which suffice
// as barriers, and are much faster than the alternative of
- // using cpuid instruction. We use here a locked add [esp],0.
+ // using cpuid instruction. We use here a locked add [esp-C],0.
// This is conveniently otherwise a no-op except for blowing
- // flags.
+ // flags, and introducing a false dependency on target memory
+ // location. We can't do anything with flags, but we can avoid
+ // memory dependencies in the current method by locked-adding
+ // somewhere else on the stack. Doing [esp+C] will collide with
+ // something on stack in current method, hence we go for [esp-C].
+ // It is convenient since it is almost always in data cache, for
+ // any small C. We need to step back from SP to avoid data
+ // dependencies with other things on below SP (callee-saves, for
+ // example). Without a clear way to figure out the minimal safe
+ // distance from SP, it makes sense to step back the complete
+ // cache line, as this will also avoid possible second-order effects
+ // with locked ops against the cache line. Our choice of offset
+ // is bounded by x86 operand encoding, which should stay within
+ // [-128; +127] to have the 8-byte displacement encoding.
+ //
// Any change to this code may need to revisit other places in
// the code where this idiom is used, in particular the
// orderAccess code.
+
+ int offset = -VM_Version::L1_line_size();
+ if (offset < -128) {
+ offset = -128;
+ }
+
lock();
- addl(Address(rsp, 0), 0);// Assert the lock# signal here
+ addl(Address(rsp, offset), 0);// Assert the lock# signal here
}
}
}
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -820,14 +820,10 @@
}
address InterpreterGenerator::generate_native_entry(bool synchronized) {
- assert(synchronized == false, "should be");
-
return generate_entry((address) CppInterpreter::native_entry);
}
address InterpreterGenerator::generate_normal_entry(bool synchronized) {
- assert(synchronized == false, "should be");
-
return generate_entry((address) CppInterpreter::normal_entry);
}
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -1644,8 +1644,20 @@
return true;
}
+int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
+ outputStream * out = (outputStream *) param;
+ out->print_cr(PTR_FORMAT " \t%s", base_address, name);
+ return 0;
+}
+
void os::print_dll_info(outputStream *st) {
st->print_cr("Dynamic libraries:");
+ if (get_loaded_modules_info(_print_dll_info_cb, (void *)st)) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ }
+}
+
+int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
#ifdef RTLD_DI_LINKMAP
Dl_info dli;
void *handle;
@@ -1654,36 +1666,41 @@
if (dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli) == 0 ||
dli.dli_fname == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
+ return 1;
}
handle = dlopen(dli.dli_fname, RTLD_LAZY);
if (handle == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
+ return 1;
}
dlinfo(handle, RTLD_DI_LINKMAP, &map);
if (map == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
+ dlclose(handle);
+ return 1;
}
while (map->l_prev != NULL)
map = map->l_prev;
while (map != NULL) {
- st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name);
+ // Value for top_address is returned as 0 since we don't have any information about module size
+ if (callback(map->l_name, (address)map->l_addr, (address)0, param)) {
+ dlclose(handle);
+ return 1;
+ }
map = map->l_next;
}
dlclose(handle);
#elif defined(__APPLE__)
for (uint32_t i = 1; i < _dyld_image_count(); i++) {
- st->print_cr(PTR_FORMAT " \t%s", _dyld_get_image_header(i),
- _dyld_get_image_name(i));
+ // Value for top_address is returned as 0 since we don't have any information about module size
+ if (callback(_dyld_get_image_name(i), (address)_dyld_get_image_header(i), (address)0, param)) {
+ return 1;
+ }
}
+ return 0;
#else
- st->print_cr("Error: Cannot print dynamic libraries.");
+ return 1;
#endif
}
--- a/hotspot/src/os/linux/vm/os_linux.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -2120,6 +2120,40 @@
}
}
+int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
+ FILE *procmapsFile = NULL;
+
+ // Open the procfs maps file for the current process
+ if ((procmapsFile = fopen("/proc/self/maps", "r")) != NULL) {
+ // Allocate PATH_MAX for file name plus a reasonable size for other fields.
+ char line[PATH_MAX + 100];
+
+ // Read line by line from 'file'
+ while (fgets(line, sizeof(line), procmapsFile) != NULL) {
+ u8 base, top, offset, inode;
+ char permissions[5];
+ char device[6];
+ char name[PATH_MAX + 1];
+
+ // Parse fields from line
+ sscanf(line, "%lx-%lx %4s %lx %5s %ld %s", &base, &top, permissions, &offset, device, &inode, name);
+
+ // Filter by device id '00:00' so that we only get file system mapped files.
+ if (strcmp(device, "00:00") != 0) {
+
+ // Call callback with the fields of interest
+ if(callback(name, (address)base, (address)top, param)) {
+ // Oops abort, callback aborted
+ fclose(procmapsFile);
+ return 1;
+ }
+ }
+ }
+ fclose(procmapsFile);
+ }
+ return 0;
+}
+
void os::print_os_info_brief(outputStream* st) {
os::Linux::print_distro_info(st);
--- a/hotspot/src/os/posix/vm/os_posix.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os/posix/vm/os_posix.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -215,6 +215,9 @@
struct utsname name;
uname(&name);
st->print("%s ", name.sysname);
+#ifdef ASSERT
+ st->print("%s ", name.nodename);
+#endif
st->print("%s ", name.release);
st->print("%s ", name.version);
st->print("%s", name.machine);
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -1722,41 +1722,54 @@
return false;
}
-// Prints the names and full paths of all opened dynamic libraries
-// for current process
-void os::print_dll_info(outputStream * st) {
+int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
Dl_info dli;
- void *handle;
+ // Sanity check?
+ if (dladdr(CAST_FROM_FN_PTR(void *, os::get_loaded_modules_info), &dli) == 0 ||
+ dli.dli_fname == NULL) {
+ return 1;
+ }
+
+ void * handle = dlopen(dli.dli_fname, RTLD_LAZY);
+ if (handle == NULL) {
+ return 1;
+ }
+
Link_map *map;
- Link_map *p;
-
- st->print_cr("Dynamic libraries:"); st->flush();
-
- if (dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli) == 0 ||
- dli.dli_fname == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
- handle = dlopen(dli.dli_fname, RTLD_LAZY);
- if (handle == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
dlinfo(handle, RTLD_DI_LINKMAP, &map);
if (map == NULL) {
- st->print_cr("Error: Cannot print dynamic libraries.");
- return;
- }
-
- while (map->l_prev != NULL)
+ dlclose(handle);
+ return 1;
+ }
+
+ while (map->l_prev != NULL) {
map = map->l_prev;
+ }
while (map != NULL) {
- st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name);
+ // Iterate through all map entries and call callback with fields of interest
+ if(callback(map->l_name, (address)map->l_addr, (address)0, param)) {
+ dlclose(handle);
+ return 1;
+ }
map = map->l_next;
}
dlclose(handle);
+ return 0;
+}
+
+int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
+ outputStream * out = (outputStream *) param;
+ out->print_cr(PTR_FORMAT " \t%s", base_address, name);
+ return 0;
+}
+
+void os::print_dll_info(outputStream * st) {
+ st->print_cr("Dynamic libraries:"); st->flush();
+ if (get_loaded_modules_info(_print_dll_info_cb, (void *)st)) {
+ st->print_cr("Error: Cannot print dynamic libraries.");
+ }
}
// Loads .dll/.so and
--- a/hotspot/src/os/windows/vm/os_windows.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -1301,120 +1301,6 @@
}
#endif
-
-// Enumerate all modules for a given process ID
-//
-// Notice that Windows 95/98/Me and Windows NT/2000/XP have
-// different API for doing this. We use PSAPI.DLL on NT based
-// Windows and ToolHelp on 95/98/Me.
-
-// Callback function that is called by enumerate_modules() on
-// every DLL module.
-// Input parameters:
-// int pid,
-// char* module_file_name,
-// address module_base_addr,
-// unsigned module_size,
-// void* param
-typedef int (*EnumModulesCallbackFunc)(int, char *, address, unsigned, void *);
-
-// enumerate_modules for Windows NT, using PSAPI
-static int _enumerate_modules_winnt( int pid, EnumModulesCallbackFunc func, void * param)
-{
- HANDLE hProcess;
-
-# define MAX_NUM_MODULES 128
- HMODULE modules[MAX_NUM_MODULES];
- static char filename[MAX_PATH];
- int result = 0;
-
- if (!os::PSApiDll::PSApiAvailable()) {
- return 0;
- }
-
- hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
- FALSE, pid);
- if (hProcess == NULL) return 0;
-
- DWORD size_needed;
- if (!os::PSApiDll::EnumProcessModules(hProcess, modules,
- sizeof(modules), &size_needed)) {
- CloseHandle(hProcess);
- return 0;
- }
-
- // number of modules that are currently loaded
- int num_modules = size_needed / sizeof(HMODULE);
-
- for (int i = 0; i < MIN2(num_modules, MAX_NUM_MODULES); i++) {
- // Get Full pathname:
- if (!os::PSApiDll::GetModuleFileNameEx(hProcess, modules[i],
- filename, sizeof(filename))) {
- filename[0] = '\0';
- }
-
- MODULEINFO modinfo;
- if (!os::PSApiDll::GetModuleInformation(hProcess, modules[i],
- &modinfo, sizeof(modinfo))) {
- modinfo.lpBaseOfDll = NULL;
- modinfo.SizeOfImage = 0;
- }
-
- // Invoke callback function
- result = func(pid, filename, (address)modinfo.lpBaseOfDll,
- modinfo.SizeOfImage, param);
- if (result) break;
- }
-
- CloseHandle(hProcess);
- return result;
-}
-
-
-// enumerate_modules for Windows 95/98/ME, using TOOLHELP
-static int _enumerate_modules_windows( int pid, EnumModulesCallbackFunc func, void *param)
-{
- HANDLE hSnapShot;
- static MODULEENTRY32 modentry;
- int result = 0;
-
- if (!os::Kernel32Dll::HelpToolsAvailable()) {
- return 0;
- }
-
- // Get a handle to a Toolhelp snapshot of the system
- hSnapShot = os::Kernel32Dll::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
- if (hSnapShot == INVALID_HANDLE_VALUE) {
- return FALSE;
- }
-
- // iterate through all modules
- modentry.dwSize = sizeof(MODULEENTRY32);
- bool not_done = os::Kernel32Dll::Module32First( hSnapShot, &modentry ) != 0;
-
- while (not_done) {
- // invoke the callback
- result=func(pid, modentry.szExePath, (address)modentry.modBaseAddr,
- modentry.modBaseSize, param);
- if (result) break;
-
- modentry.dwSize = sizeof(MODULEENTRY32);
- not_done = os::Kernel32Dll::Module32Next( hSnapShot, &modentry ) != 0;
- }
-
- CloseHandle(hSnapShot);
- return result;
-}
-
-int enumerate_modules( int pid, EnumModulesCallbackFunc func, void * param )
-{
- // Get current process ID if caller doesn't provide it.
- if (!pid) pid = os::current_process_id();
-
- if (os::win32::is_nt()) return _enumerate_modules_winnt (pid, func, param);
- else return _enumerate_modules_windows(pid, func, param);
-}
-
struct _modinfo {
address addr;
char* full_path; // point to a char buffer
@@ -1422,13 +1308,13 @@
address base_addr;
};
-static int _locate_module_by_addr(int pid, char * mod_fname, address base_addr,
- unsigned size, void * param) {
+static int _locate_module_by_addr(const char * mod_fname, address base_addr,
+ address top_address, void * param) {
struct _modinfo *pmod = (struct _modinfo *)param;
if (!pmod) return -1;
- if (base_addr <= pmod->addr &&
- base_addr+size > pmod->addr) {
+ if (base_addr <= pmod->addr &&
+ top_address > pmod->addr) {
// if a buffer is provided, copy path name to the buffer
if (pmod->full_path) {
jio_snprintf(pmod->full_path, pmod->buflen, "%s", mod_fname);
@@ -1453,8 +1339,7 @@
mi.addr = addr;
mi.full_path = buf;
mi.buflen = buflen;
- int pid = os::current_process_id();
- if (enumerate_modules(pid, _locate_module_by_addr, (void *)&mi)) {
+ if (get_loaded_modules_info(_locate_module_by_addr, (void *)&mi)) {
// buf already contains path name
if (offset) *offset = addr - mi.base_addr;
return true;
@@ -1479,14 +1364,14 @@
}
// save the start and end address of jvm.dll into param[0] and param[1]
-static int _locate_jvm_dll(int pid, char* mod_fname, address base_addr,
- unsigned size, void * param) {
+static int _locate_jvm_dll(const char* mod_fname, address base_addr,
+ address top_address, void * param) {
if (!param) return -1;
- if (base_addr <= (address)_locate_jvm_dll &&
- base_addr+size > (address)_locate_jvm_dll) {
+ if (base_addr <= (address)_locate_jvm_dll &&
+ top_address > (address)_locate_jvm_dll) {
((address*)param)[0] = base_addr;
- ((address*)param)[1] = base_addr + size;
+ ((address*)param)[1] = top_address;
return 1;
}
return 0;
@@ -1497,8 +1382,7 @@
// check if addr is inside jvm.dll
bool os::address_is_in_vm(address addr) {
if (!vm_lib_location[0] || !vm_lib_location[1]) {
- int pid = os::current_process_id();
- if (!enumerate_modules(pid, _locate_jvm_dll, (void *)vm_lib_location)) {
+ if (!get_loaded_modules_info(_locate_jvm_dll, (void *)vm_lib_location)) {
assert(false, "Can't find jvm module.");
return false;
}
@@ -1508,14 +1392,13 @@
}
// print module info; param is outputStream*
-static int _print_module(int pid, char* fname, address base,
- unsigned size, void* param) {
+static int _print_module(const char* fname, address base_address,
+ address top_address, void* param) {
if (!param) return -1;
outputStream* st = (outputStream*)param;
- address end_addr = base + size;
- st->print(PTR_FORMAT " - " PTR_FORMAT " \t%s\n", base, end_addr, fname);
+ st->print(PTR_FORMAT " - " PTR_FORMAT " \t%s\n", base_address, top_address, fname);
return 0;
}
@@ -1644,11 +1527,60 @@
return NULL;
}
-
void os::print_dll_info(outputStream *st) {
- int pid = os::current_process_id();
st->print_cr("Dynamic libraries:");
- enumerate_modules(pid, _print_module, (void *)st);
+ get_loaded_modules_info(_print_module, (void *)st);
+}
+
+int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
+ HANDLE hProcess;
+
+# define MAX_NUM_MODULES 128
+ HMODULE modules[MAX_NUM_MODULES];
+ static char filename[MAX_PATH];
+ int result = 0;
+
+ if (!os::PSApiDll::PSApiAvailable()) {
+ return 0;
+ }
+
+ int pid = os::current_process_id();
+ hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
+ FALSE, pid);
+ if (hProcess == NULL) return 0;
+
+ DWORD size_needed;
+ if (!os::PSApiDll::EnumProcessModules(hProcess, modules,
+ sizeof(modules), &size_needed)) {
+ CloseHandle(hProcess);
+ return 0;
+ }
+
+ // number of modules that are currently loaded
+ int num_modules = size_needed / sizeof(HMODULE);
+
+ for (int i = 0; i < MIN2(num_modules, MAX_NUM_MODULES); i++) {
+ // Get Full pathname:
+ if (!os::PSApiDll::GetModuleFileNameEx(hProcess, modules[i],
+ filename, sizeof(filename))) {
+ filename[0] = '\0';
+ }
+
+ MODULEINFO modinfo;
+ if (!os::PSApiDll::GetModuleInformation(hProcess, modules[i],
+ &modinfo, sizeof(modinfo))) {
+ modinfo.lpBaseOfDll = NULL;
+ modinfo.SizeOfImage = 0;
+ }
+
+ // Invoke callback function
+ result = callback(filename, (address)modinfo.lpBaseOfDll,
+ (address)((u8)modinfo.lpBaseOfDll + (u8)modinfo.SizeOfImage), param);
+ if (result) break;
+ }
+
+ CloseHandle(hProcess);
+ return result;
}
void os::print_os_info_brief(outputStream* st) {
@@ -1656,8 +1588,17 @@
}
void os::print_os_info(outputStream* st) {
- st->print("OS:");
-
+#ifdef ASSERT
+ char buffer[1024];
+ DWORD size = sizeof(buffer);
+ st->print(" HostName: ");
+ if (GetComputerNameEx(ComputerNameDnsHostname, buffer, &size)) {
+ st->print("%s", buffer);
+ } else {
+ st->print("N/A");
+ }
+#endif
+ st->print(" OS:");
os::win32::print_windows_version(st);
}
--- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -563,3 +563,8 @@
assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // PPC does not require the additional stack bang.
+ return 0;
+}
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -1030,3 +1030,8 @@
void os::verify_stack_alignment() {
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // JDK-8050147 requires the full cache line bang for x86.
+ return VM_Version::L1_line_size();
+}
--- a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -465,3 +465,8 @@
void os::verify_stack_alignment() {
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // Zero does not require an additional stack bang.
+ return 0;
+}
--- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -612,3 +612,8 @@
assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // PPC does not require the additional stack bang.
+ return 0;
+}
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -752,3 +752,8 @@
void os::verify_stack_alignment() {
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // SPARC does not require the additional stack bang.
+ return 0;
+}
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -930,3 +930,8 @@
// keep the page mapped so CS limit isn't reduced.
#endif
}
+
+int os::extra_bang_size_in_bytes() {
+ // JDK-8050147 requires the full cache line bang for x86.
+ return VM_Version::L1_line_size();
+}
--- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -495,3 +495,8 @@
void os::verify_stack_alignment() {
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // Zero does not require an additional stack banging.
+ return 0;
+}
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -774,3 +774,8 @@
void os::verify_stack_alignment() {
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // SPARC does not require an additional stack bang.
+ return 0;
+}
--- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -28,10 +28,140 @@
#include "runtime/os.hpp"
#include "vm_version_sparc.hpp"
-# include <sys/auxv.h>
-# include <sys/auxv_SPARC.h>
-# include <sys/systeminfo.h>
-# include <kstat.h>
+#include <sys/auxv.h>
+#include <sys/auxv_SPARC.h>
+#include <sys/systeminfo.h>
+#include <kstat.h>
+#include <picl.h>
+
+extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
+extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
+
+class PICL {
+ // Get a value of the integer property. The value in the tree can be either 32 or 64 bit
+ // depending on the platform. The result is converted to int.
+ static int get_int_property(picl_nodehdl_t nodeh, const char* name, int* result) {
+ picl_propinfo_t pinfo;
+ picl_prophdl_t proph;
+ if (picl_get_prop_by_name(nodeh, name, &proph) != PICL_SUCCESS ||
+ picl_get_propinfo(proph, &pinfo) != PICL_SUCCESS) {
+ return PICL_FAILURE;
+ }
+
+ if (pinfo.type != PICL_PTYPE_INT && pinfo.type != PICL_PTYPE_UNSIGNED_INT) {
+ assert(false, "Invalid property type");
+ return PICL_FAILURE;
+ }
+ if (pinfo.size == sizeof(int64_t)) {
+ int64_t val;
+ if (picl_get_propval(proph, &val, sizeof(int64_t)) != PICL_SUCCESS) {
+ return PICL_FAILURE;
+ }
+ *result = static_cast<int>(val);
+ } else if (pinfo.size == sizeof(int32_t)) {
+ int32_t val;
+ if (picl_get_propval(proph, &val, sizeof(int32_t)) != PICL_SUCCESS) {
+ return PICL_FAILURE;
+ }
+ *result = static_cast<int>(val);
+ } else {
+ assert(false, "Unexpected integer property size");
+ return PICL_FAILURE;
+ }
+ return PICL_SUCCESS;
+ }
+
+ // Visitor and a state machine that visits integer properties and verifies that the
+ // values are the same. Stores the unique value observed.
+ class UniqueValueVisitor {
+ enum {
+ INITIAL, // Start state, no assignments happened
+ ASSIGNED, // Assigned a value
+ INCONSISTENT // Inconsistent value seen
+ } _state;
+ int _value;
+ public:
+ UniqueValueVisitor() : _state(INITIAL) { }
+ int value() {
+ assert(_state == ASSIGNED, "Precondition");
+ return _value;
+ }
+ void set_value(int value) {
+ assert(_state == INITIAL, "Precondition");
+ _value = value;
+ _state = ASSIGNED;
+ }
+ bool is_initial() { return _state == INITIAL; }
+ bool is_assigned() { return _state == ASSIGNED; }
+ bool is_inconsistent() { return _state == INCONSISTENT; }
+ void set_inconsistent() { _state = INCONSISTENT; }
+
+ static int visit(picl_nodehdl_t nodeh, const char* name, void *arg) {
+ UniqueValueVisitor *state = static_cast<UniqueValueVisitor*>(arg);
+ assert(!state->is_inconsistent(), "Precondition");
+ int curr;
+ if (PICL::get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
+ if (!state->is_assigned()) { // first iteration
+ state->set_value(curr);
+ } else if (curr != state->value()) { // following iterations
+ state->set_inconsistent();
+ }
+ }
+ if (state->is_inconsistent()) {
+ return PICL_WALK_TERMINATE;
+ }
+ return PICL_WALK_CONTINUE;
+ }
+ };
+
+ int _L1_data_cache_line_size;
+ int _L2_cache_line_size;
+public:
+ static int get_l1_data_cache_line_size(picl_nodehdl_t nodeh, void *state) {
+ return UniqueValueVisitor::visit(nodeh, "l1-dcache-line-size", state);
+ }
+ static int get_l2_cache_line_size(picl_nodehdl_t nodeh, void *state) {
+ return UniqueValueVisitor::visit(nodeh, "l2-cache-line-size", state);
+ }
+
+ PICL() : _L1_data_cache_line_size(0), _L2_cache_line_size(0) {
+ if (picl_initialize() == PICL_SUCCESS) {
+ picl_nodehdl_t rooth;
+ if (picl_get_root(&rooth) == PICL_SUCCESS) {
+ UniqueValueVisitor L1_state;
+ // Visit all "cpu" class instances
+ picl_walk_tree_by_class(rooth, "cpu", &L1_state, PICL_get_l1_data_cache_line_size_helper);
+ if (L1_state.is_initial()) { // Still initial, iteration found no values
+ // Try walk all "core" class instances, it might be a Fujitsu machine
+ picl_walk_tree_by_class(rooth, "core", &L1_state, PICL_get_l1_data_cache_line_size_helper);
+ }
+ if (L1_state.is_assigned()) { // Is there a value?
+ _L1_data_cache_line_size = L1_state.value();
+ }
+
+ UniqueValueVisitor L2_state;
+ picl_walk_tree_by_class(rooth, "cpu", &L2_state, PICL_get_l2_cache_line_size_helper);
+ if (L2_state.is_initial()) {
+ picl_walk_tree_by_class(rooth, "core", &L2_state, PICL_get_l2_cache_line_size_helper);
+ }
+ if (L2_state.is_assigned()) {
+ _L2_cache_line_size = L2_state.value();
+ }
+ }
+ picl_shutdown();
+ }
+ }
+
+ unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; }
+ unsigned int L2_cache_line_size() const { return _L2_cache_line_size; }
+};
+
+extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
+ return PICL::get_l1_data_cache_line_size(nodeh, result);
+}
+extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
+ return PICL::get_l2_cache_line_size(nodeh, result);
+}
// We need to keep these here as long as we have to build on Solaris
// versions before 10.
@@ -211,5 +341,10 @@
kstat_close(kc);
}
+ // Figure out cache line sizes using PICL
+ PICL picl;
+ _L1_data_cache_line_size = picl.L1_data_cache_line_size();
+ _L2_cache_line_size = picl.L2_cache_line_size();
+
return features;
}
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -918,3 +918,8 @@
#endif
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // JDK-8050147 requires the full cache line bang for x86.
+ return VM_Version::L1_line_size();
+}
--- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -639,3 +639,8 @@
#endif
}
#endif
+
+int os::extra_bang_size_in_bytes() {
+ // JDK-8050147 requires the full cache line bang for x86.
+ return VM_Version::L1_line_size();
+}
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -170,7 +170,7 @@
// removes the need to bang the stack in the deoptimization blob which
// in turn simplifies stack overflow handling.
int LIR_Assembler::bang_size_in_bytes() const {
- return MAX2(initial_frame_size_in_bytes(), _compilation->interpreter_frame_size());
+ return MAX2(initial_frame_size_in_bytes() + os::extra_bang_size_in_bytes(), _compilation->interpreter_frame_size());
}
void LIR_Assembler::emit_exception_entries(ExceptionInfoList* info_list) {
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -926,7 +926,7 @@
#ifdef ASSERT
if (!counter_changed && !PrintCompilation) {
// Print out the compile task that failed
- _task->print_line();
+ _task->print_tty();
}
#endif
assert(counter_changed, "failed dependencies, but counter didn't change");
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -1528,7 +1528,7 @@
if (TieredCompilation && TieredStopAtLevel >= CompLevel_full_optimization) {
// Clobber the first compile and force second tier compilation
nmethod* nm = m->code();
- if (nm != NULL) {
+ if (nm != NULL && !m->is_method_handle_intrinsic()) {
// Throw out the code so that the code cache doesn't fill up
nm->make_not_entrant();
m->clear_code();
@@ -1547,7 +1547,7 @@
}
nmethod* nm = m->code();
- if (nm != NULL) {
+ if (nm != NULL && !m->is_method_handle_intrinsic()) {
// Throw out the code so that the code cache doesn't fill up
nm->make_not_entrant();
m->clear_code();
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -746,7 +746,7 @@
// mark metadata seen on the stack and code cache so we can delete
// unneeded entries.
bool has_redefined_a_class = JvmtiExport::has_redefined_a_class();
- MetadataOnStackMark md_on_stack;
+ MetadataOnStackMark md_on_stack(has_redefined_a_class);
if (has_redefined_a_class) {
// purge_previous_versions also cleans weak method links. Because
// one method's MDO can reference another method from another
--- a/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -41,7 +41,7 @@
// Walk metadata on the stack and mark it so that redefinition doesn't delete
// it. Class unloading also walks the previous versions and might try to
// delete it, so this class is used by class unloading also.
-MetadataOnStackMark::MetadataOnStackMark() {
+MetadataOnStackMark::MetadataOnStackMark(bool has_redefined_a_class) {
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
NOT_PRODUCT(_is_active = true;)
if (_marked_objects == NULL) {
@@ -49,7 +49,7 @@
}
Threads::metadata_do(Metadata::mark_on_stack);
- if (JvmtiExport::has_redefined_a_class()) {
+ if (has_redefined_a_class) {
CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
}
CompileBroker::mark_on_stack();
--- a/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, 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
@@ -37,7 +37,7 @@
class MetadataOnStackMark : public StackObj {
NOT_PRODUCT(static bool _is_active;)
public:
- MetadataOnStackMark();
+ MetadataOnStackMark(bool has_redefined_a_class);
~MetadataOnStackMark();
static void record(Metadata* m);
};
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -52,6 +52,7 @@
#include "oops/typeArrayKlass.hpp"
#include "prims/jvmtiEnvBase.hpp"
#include "prims/methodHandles.hpp"
+#include "runtime/arguments.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/fieldType.hpp"
#include "runtime/handles.inline.hpp"
@@ -2274,7 +2275,11 @@
m = Method::make_method_handle_intrinsic(iid, signature, CHECK_(empty));
CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_highest_tier,
methodHandle(), CompileThreshold, "MH", CHECK_(empty));
-
+ // Check if we need to have compiled code but we don't.
+ if (!Arguments::is_interpreter_only() && !m->has_compiled_code()) {
+ THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(),
+ "out of space in CodeCache for method handle intrinsic", empty);
+ }
// Now grab the lock. We might have to throw away the new method,
// if a racing thread has managed to install one at the same time.
{
@@ -2288,6 +2293,9 @@
}
assert(spe != NULL && spe->method() != NULL, "");
+ assert(Arguments::is_interpreter_only() || (spe->method()->has_compiled_code() &&
+ spe->method()->code()->entry_point() == spe->method()->from_compiled_entry()),
+ "MH intrinsic invariant");
return spe->method();
}
--- a/hotspot/src/share/vm/code/codeCache.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/code/codeCache.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -249,6 +249,7 @@
#define FOR_ALL_BLOBS(var) for (CodeBlob *var = first() ; var != NULL; var = next(var) )
#define FOR_ALL_ALIVE_BLOBS(var) for (CodeBlob *var = alive(first()); var != NULL; var = alive(next(var)))
#define FOR_ALL_ALIVE_NMETHODS(var) for (nmethod *var = alive_nmethod(first()); var != NULL; var = alive_nmethod(next(var)))
+#define FOR_ALL_NMETHODS(var) for (nmethod *var = first_nmethod(); var != NULL; var = next_nmethod(var))
bool CodeCache::contains(void *p) {
@@ -687,7 +688,9 @@
void CodeCache::mark_all_nmethods_for_deoptimization() {
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
FOR_ALL_ALIVE_NMETHODS(nm) {
- nm->mark_for_deoptimization();
+ if (!nm->method()->is_method_handle_intrinsic()) {
+ nm->mark_for_deoptimization();
+ }
}
}
@@ -967,6 +970,25 @@
}
}
+void CodeCache::print_codelist(outputStream* st) {
+ assert_locked_or_safepoint(CodeCache_lock);
+
+ FOR_ALL_NMETHODS(p) {
+ ResourceMark rm;
+ char *method_name = p->method()->name_and_sig_as_C_string();
+ st->print_cr("%d %d %s ["INTPTR_FORMAT", "INTPTR_FORMAT" - "INTPTR_FORMAT"]",
+ p->compile_id(), p->comp_level(), method_name, (intptr_t)p->header_begin(),
+ (intptr_t)p->code_begin(), (intptr_t)p->code_end());
+ }
+}
+
+void CodeCache::print_layout(outputStream* st) {
+ assert_locked_or_safepoint(CodeCache_lock);
+ ResourceMark rm;
+
+ print_summary(st, true);
+}
+
void CodeCache::log_state(outputStream* st) {
st->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'"
" adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
--- a/hotspot/src/share/vm/code/codeCache.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/code/codeCache.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -152,6 +152,10 @@
static void print_summary(outputStream* st, bool detailed = true); // Prints a summary of the code cache usage
static void log_state(outputStream* st);
+ // Dcmd (Diagnostic commands)
+ static void print_codelist(outputStream* st);
+ static void print_layout(outputStream* st);
+
// The full limits of the codeCache
static address low_bound() { return (address) _heap->low_boundary(); }
static address high_bound() { return (address) _heap->high_boundary(); }
--- a/hotspot/src/share/vm/code/compiledIC.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/code/compiledIC.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -595,6 +595,7 @@
} else {
// Callee is interpreted code. In any case entering the interpreter
// puts a converter-frame on the stack to save arguments.
+ assert(!m->is_method_handle_intrinsic(), "Compiled code should never call interpreter MH intrinsics");
info._to_interpreter = true;
info._entry = m()->get_c2i_entry();
}
--- a/hotspot/src/share/vm/code/nmethod.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/code/nmethod.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -2062,7 +2062,7 @@
"metadata must be found in exactly one place");
if (r->metadata_is_immediate() && r->metadata_value() != NULL) {
Metadata* md = r->metadata_value();
- f(md);
+ if (md != _method) f(md);
}
} else if (iter.type() == relocInfo::virtual_call_type) {
// Check compiledIC holders associated with this nmethod
--- a/hotspot/src/share/vm/code/nmethod.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/code/nmethod.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -448,7 +448,10 @@
// alive. It is used when an uncommon trap happens. Returns true
// if this thread changed the state of the nmethod or false if
// another thread performed the transition.
- bool make_not_entrant() { return make_not_entrant_or_zombie(not_entrant); }
+ bool make_not_entrant() {
+ assert(!method()->is_method_handle_intrinsic(), "Cannot make MH intrinsic not entrant");
+ return make_not_entrant_or_zombie(not_entrant);
+ }
bool make_zombie() { return make_not_entrant_or_zombie(zombie); }
// used by jvmti to track if the unload event has been reported
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -166,7 +166,7 @@
StringLogMessage lm;
stringStream sstr = lm.stream();
// msg.time_stamp().update_to(tty->time_stamp().ticks());
- task->print_compilation(&sstr, NULL, true);
+ task->print_compilation(&sstr, NULL, true, false);
log(thread, "%s", (const char*)lm);
}
@@ -328,7 +328,6 @@
if (nm == NULL) _code_handle = NULL; // drop the handle also
}
-
void CompileTask::mark_on_stack() {
// Mark these methods as something redefine classes cannot remove.
_method->set_on_stack(true);
@@ -338,18 +337,6 @@
}
// ------------------------------------------------------------------
-// CompileTask::print
-void CompileTask::print() {
- tty->print("<CompileTask compile_id=%d ", _compile_id);
- tty->print("method=");
- _method->print_name(tty);
- tty->print_cr(" osr_bci=%d is_blocking=%s is_complete=%s is_success=%s>",
- _osr_bci, bool_to_str(_is_blocking),
- bool_to_str(_is_complete), bool_to_str(_is_success));
-}
-
-
-// ------------------------------------------------------------------
// CompileTask::print_line_on_error
//
// This function is called by fatal error handler when the thread
@@ -367,19 +354,18 @@
// ------------------------------------------------------------------
// CompileTask::print_line
-void CompileTask::print_line() {
+void CompileTask::print_tty() {
ttyLocker ttyl; // keep the following output all in one block
// print compiler name if requested
if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level()));
- print_compilation();
+ print_compilation(tty);
}
-
// ------------------------------------------------------------------
// CompileTask::print_compilation_impl
void CompileTask::print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level,
bool is_osr_method, int osr_bci, bool is_blocking,
- const char* msg, bool short_form) {
+ const char* msg, bool short_form, bool cr) {
if (!short_form) {
st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp
}
@@ -428,7 +414,7 @@
if (msg != NULL) {
st->print(" %s", msg);
}
- if (!short_form) {
+ if (cr) {
st->cr();
}
}
@@ -494,9 +480,9 @@
// ------------------------------------------------------------------
// CompileTask::print_compilation
-void CompileTask::print_compilation(outputStream* st, const char* msg, bool short_form) {
+void CompileTask::print_compilation(outputStream* st, const char* msg, bool short_form, bool cr) {
bool is_osr_method = osr_bci() != InvocationEntryBci;
- print_compilation_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form);
+ print_compilation_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form, cr);
}
// ------------------------------------------------------------------
@@ -621,7 +607,9 @@
// Mark the method as being in the compile queue.
task->method()->set_queued_for_compilation();
- NOT_PRODUCT(print();)
+ if (CIPrintCompileQueue) {
+ print_tty();
+ }
if (LogCompilation && xtty != NULL) {
task->log_task_queued();
@@ -786,24 +774,40 @@
}
}
-#ifndef PRODUCT
-/**
- * Print entire compilation queue.
- */
-void CompileQueue::print() {
- if (CIPrintCompileQueue) {
- ttyLocker ttyl;
- tty->print_cr("Contents of %s", name());
- tty->print_cr("----------------------");
- CompileTask* task = _first;
+
+CompileQueue* CompileBroker::compile_queue(int comp_level) {
+ if (is_c2_compile(comp_level)) return _c2_compile_queue;
+ if (is_c1_compile(comp_level)) return _c1_compile_queue;
+ return NULL;
+}
+
+
+void CompileBroker::print_compile_queues(outputStream* st) {
+ _c1_compile_queue->print(st);
+ _c2_compile_queue->print(st);
+}
+
+
+void CompileQueue::print(outputStream* st) {
+ assert_locked_or_safepoint(lock());
+ st->print_cr("Contents of %s", name());
+ st->print_cr("----------------------------");
+ CompileTask* task = _first;
+ if (task == NULL) {
+ st->print_cr("Empty");;
+ } else {
while (task != NULL) {
- task->print_line();
+ task->print_compilation(st, NULL, true, true);
task = task->next();
}
- tty->print_cr("----------------------");
}
+ st->print_cr("----------------------------");
}
-#endif // PRODUCT
+
+void CompileQueue::print_tty() {
+ ttyLocker ttyl;
+ print(tty);
+}
CompilerCounters::CompilerCounters(const char* thread_name, int instance, TRAPS) {
@@ -1068,11 +1072,11 @@
#endif // !ZERO && !SHARK
// Initialize the compilation queue
if (c2_compiler_count > 0) {
- _c2_compile_queue = new CompileQueue("C2 CompileQueue", MethodCompileQueue_lock);
+ _c2_compile_queue = new CompileQueue("C2 compile queue", MethodCompileQueue_lock);
_compilers[1]->set_num_compiler_threads(c2_compiler_count);
}
if (c1_compiler_count > 0) {
- _c1_compile_queue = new CompileQueue("C1 CompileQueue", MethodCompileQueue_lock);
+ _c1_compile_queue = new CompileQueue("C1 compile queue", MethodCompileQueue_lock);
_compilers[0]->set_num_compiler_threads(c1_compiler_count);
}
@@ -1892,7 +1896,7 @@
void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
if (PrintCompilation) {
ResourceMark rm;
- task->print_line();
+ task->print_tty();
}
elapsedTimer time;
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -111,14 +111,14 @@
private:
static void print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level,
bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false,
- const char* msg = NULL, bool short_form = false);
+ const char* msg = NULL, bool short_form = false, bool cr = true);
public:
- void print_compilation(outputStream* st = tty, const char* msg = NULL, bool short_form = false);
- static void print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false) {
+ void print_compilation(outputStream* st = tty, const char* msg = NULL, bool short_form = false, bool cr = true);
+ static void print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false, bool cr = true) {
print_compilation_impl(st, nm->method(), nm->compile_id(), nm->comp_level(),
nm->is_osr_method(), nm->is_osr_method() ? nm->osr_entry_bci() : -1, /*is_blocking*/ false,
- msg, short_form);
+ msg, short_form, cr);
}
static void print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg = NULL);
@@ -131,8 +131,7 @@
static void print_inline_indent(int inline_level, outputStream* st = tty);
- void print();
- void print_line();
+ void print_tty();
void print_line_on_error(outputStream* st, char* buf, int buflen);
void log_task(xmlStream* log);
@@ -234,7 +233,8 @@
// Redefine Classes support
void mark_on_stack();
void free_all();
- NOT_PRODUCT (void print();)
+ void print_tty();
+ void print(outputStream* st = tty);
~CompileQueue() {
assert (is_empty(), " Compile Queue must be empty");
@@ -341,7 +341,7 @@
static void init_compiler_threads(int c1_compiler_count, int c2_compiler_count);
static bool compilation_is_complete (methodHandle method, int osr_bci, int comp_level);
static bool compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level);
- static bool is_compile_blocking ();
+ static bool is_compile_blocking();
static void preload_classes (methodHandle method, TRAPS);
static CompileTask* create_compile_task(CompileQueue* queue,
@@ -369,11 +369,8 @@
int hot_count,
const char* comment,
Thread* thread);
- static CompileQueue* compile_queue(int comp_level) {
- if (is_c2_compile(comp_level)) return _c2_compile_queue;
- if (is_c1_compile(comp_level)) return _c1_compile_queue;
- return NULL;
- }
+
+ static CompileQueue* compile_queue(int comp_level);
static bool init_compiler_runtime();
static void shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread);
@@ -390,6 +387,7 @@
}
static bool compilation_is_in_queue(methodHandle method);
+ static void print_compile_queues(outputStream* st);
static int queue_size(int comp_level) {
CompileQueue *q = compile_queue(comp_level);
return q != NULL ? q->size() : 0;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -369,33 +369,45 @@
#endif
}
-bool
-G1BlockOffsetArray::verify_for_object(HeapWord* obj_start,
- size_t word_size) const {
- size_t first_card = _array->index_for(obj_start);
- size_t last_card = _array->index_for(obj_start + word_size - 1);
- if (!_array->is_card_boundary(obj_start)) {
- // If the object is not on a card boundary the BOT entry of the
- // first card should point to another object so we should not
- // check that one.
- first_card += 1;
- }
- for (size_t card = first_card; card <= last_card; card += 1) {
- HeapWord* card_addr = _array->address_for_index(card);
- HeapWord* block_start = block_start_const(card_addr);
- if (block_start != obj_start) {
- gclog_or_tty->print_cr("block start: "PTR_FORMAT" is incorrect - "
- "card index: "SIZE_FORMAT" "
- "card addr: "PTR_FORMAT" BOT entry: %u "
- "obj: "PTR_FORMAT" word size: "SIZE_FORMAT" "
- "cards: ["SIZE_FORMAT","SIZE_FORMAT"]",
- p2i(block_start), card, p2i(card_addr),
- _array->offset_array(card),
- p2i(obj_start), word_size, first_card, last_card);
- return false;
+void G1BlockOffsetArray::verify() const {
+ assert(gsp()->bottom() < gsp()->top(), "Only non-empty regions should be verified.");
+ size_t start_card = _array->index_for(gsp()->bottom());
+ size_t end_card = _array->index_for(gsp()->top() - 1);
+
+ for (size_t current_card = start_card; current_card < end_card; current_card++) {
+ u_char entry = _array->offset_array(current_card);
+ if (entry < N_words) {
+ // The entry should point to an object before the current card. Verify that
+ // it is possible to walk from that object in to the current card by just
+ // iterating over the objects following it.
+ HeapWord* card_address = _array->address_for_index(current_card);
+ HeapWord* obj_end = card_address - entry;
+ while (obj_end < card_address) {
+ HeapWord* obj = obj_end;
+ size_t obj_size = block_size(obj);
+ obj_end = obj + obj_size;
+ guarantee(obj_end > obj && obj_end <= gsp()->top(),
+ err_msg("Invalid object end. obj: " PTR_FORMAT " obj_size: " SIZE_FORMAT " obj_end: " PTR_FORMAT " top: " PTR_FORMAT,
+ p2i(obj), obj_size, p2i(obj_end), p2i(gsp()->top())));
+ }
+ } else {
+ // Because we refine the BOT based on which cards are dirty there is not much we can verify here.
+ // We need to make sure that we are going backwards and that we don't pass the start of the
+ // corresponding heap region. But that is about all we can verify.
+ size_t backskip = BlockOffsetArray::entry_to_cards_back(entry);
+ guarantee(backskip >= 1, "Must be going back at least one card.");
+
+ size_t max_backskip = current_card - start_card;
+ guarantee(backskip <= max_backskip,
+ err_msg("Going backwards beyond the start_card. start_card: " SIZE_FORMAT " current_card: " SIZE_FORMAT " backskip: " SIZE_FORMAT,
+ start_card, current_card, backskip));
+
+ HeapWord* backskip_address = _array->address_for_index(current_card - backskip);
+ guarantee(backskip_address >= gsp()->bottom(),
+ err_msg("Going backwards beyond bottom of the region: bottom: " PTR_FORMAT ", backskip_address: " PTR_FORMAT,
+ p2i(gsp()->bottom()), p2i(backskip_address)));
}
}
- return true;
}
#ifndef PRODUCT
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -304,13 +304,9 @@
virtual HeapWord* block_start_unsafe(const void* addr);
virtual HeapWord* block_start_unsafe_const(const void* addr) const;
- // Used by region verification. Checks that the contents of the
- // BOT reflect that there's a single object that spans the address
- // range [obj_start, obj_start + word_size); returns true if this is
- // the case, returns false if it's not.
- bool verify_for_object(HeapWord* obj_start, size_t word_size) const;
+ void check_all_cards(size_t left_card, size_t right_card) const;
- void check_all_cards(size_t left_card, size_t right_card) const;
+ void verify() const;
virtual void print_on(outputStream* out) PRODUCT_RETURN;
};
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -48,6 +48,7 @@
return hash ^ (hash >> 7); // code heap blocks are 128byte aligned
}
+ void remove_entry(Entry* e, Entry* previous);
Entry* new_entry(nmethod* nm);
public:
@@ -67,7 +68,7 @@
void nmethods_do(CodeBlobClosure* blk);
template<typename CB>
- void remove_if(CB& should_remove);
+ int remove_if(CB& should_remove);
static void purge_list_append(CodeRootSetTable* tbl);
static void purge();
@@ -91,6 +92,18 @@
return entry;
}
+void CodeRootSetTable::remove_entry(Entry* e, Entry* previous) {
+ int index = hash_to_index(e->hash());
+ assert((e == bucket(index)) == (previous == NULL), "if e is the first entry then previous should be null");
+
+ if (previous == NULL) {
+ set_entry(index, e->next());
+ } else {
+ previous->set_next(e->next());
+ }
+ free_entry(e);
+}
+
CodeRootSetTable::~CodeRootSetTable() {
for (int index = 0; index < table_size(); ++index) {
for (Entry* e = bucket(index); e != NULL; ) {
@@ -133,12 +146,7 @@
Entry* previous = NULL;
for (Entry* e = bucket(index); e != NULL; previous = e, e = e->next()) {
if (e->literal() == nm) {
- if (previous != NULL) {
- previous->set_next(e->next());
- } else {
- set_entry(index, e->next());
- }
- free_entry(e);
+ remove_entry(e, previous);
return true;
}
}
@@ -163,25 +171,23 @@
}
template<typename CB>
-void CodeRootSetTable::remove_if(CB& should_remove) {
+int CodeRootSetTable::remove_if(CB& should_remove) {
+ int num_removed = 0;
for (int index = 0; index < table_size(); ++index) {
Entry* previous = NULL;
Entry* e = bucket(index);
while (e != NULL) {
Entry* next = e->next();
if (should_remove(e->literal())) {
- if (previous != NULL) {
- previous->set_next(next);
- } else {
- set_entry(index, next);
- }
- free_entry(e);
+ remove_entry(e, previous);
+ ++num_removed;
} else {
previous = e;
}
e = next;
}
}
+ return num_removed;
}
G1CodeRootSet::~G1CodeRootSet() {
@@ -320,14 +326,19 @@
bool operator() (nmethod* nm) {
_detector._points_into = false;
_blobs.do_code_blob(nm);
- return _detector._points_into;
+ return !_detector._points_into;
}
};
void G1CodeRootSet::clean(HeapRegion* owner) {
CleanCallback should_clean(owner);
if (_table != NULL) {
- _table->remove_if(should_clean);
+ int removed = _table->remove_if(should_clean);
+ assert((size_t)removed <= _length, "impossible");
+ _length -= removed;
+ }
+ if (_length == 0) {
+ clear();
}
}
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -861,7 +861,6 @@
HeapWord* prev_p = NULL;
VerifyLiveClosure vl_cl(g1, vo);
bool is_humongous = isHumongous();
- bool do_bot_verify = !is_young();
size_t object_num = 0;
while (p < top()) {
oop obj = oop(p);
@@ -878,15 +877,6 @@
return;
}
- // If it returns false, verify_for_object() will output the
- // appropriate message.
- if (do_bot_verify &&
- !g1->is_obj_dead(obj, this) &&
- !_offsets.verify_for_object(p, obj_size)) {
- *failures = true;
- return;
- }
-
if (!g1->is_obj_dead_cond(obj, this, vo)) {
if (obj->is_oop()) {
Klass* klass = obj->klass();
@@ -924,6 +914,10 @@
p += obj_size;
}
+ if (!is_young() && !is_empty()) {
+ _offsets.verify();
+ }
+
if (p != top()) {
gclog_or_tty->print_cr("end of last object "PTR_FORMAT" "
"does not match top "PTR_FORMAT, p, top());
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -460,6 +460,8 @@
oop InstanceKlass::init_lock() const {
// return the init lock from the mirror
oop lock = java_lang_Class::init_lock(java_mirror());
+ // Prevent reordering with any access of initialization state
+ OrderAccess::loadload();
assert((oop)lock != NULL || !is_not_initialized(), // initialized or in_error state
"only fully initialized state can have a null lock");
return lock;
@@ -2437,16 +2439,6 @@
assert(breakpoints() == 0x0, "should have cleared breakpoints");
}
- // deallocate information about previous versions
- if (_previous_versions != NULL) {
- for (int i = _previous_versions->length() - 1; i >= 0; i--) {
- PreviousVersionNode * pv_node = _previous_versions->at(i);
- delete pv_node;
- }
- delete _previous_versions;
- _previous_versions = NULL;
- }
-
// deallocate the cached class file
if (_cached_class_file != NULL) {
os::free(_cached_class_file, mtClass);
@@ -3020,16 +3012,17 @@
st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr();
{
bool have_pv = false;
- PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this);
- for (PreviousVersionNode * pv_node = pvw.next_previous_version();
- pv_node != NULL; pv_node = pvw.next_previous_version()) {
+ // previous versions are linked together through the InstanceKlass
+ for (InstanceKlass* pv_node = _previous_versions;
+ pv_node != NULL;
+ pv_node = pv_node->previous_versions()) {
if (!have_pv)
st->print(BULLET"previous version: ");
have_pv = true;
- pv_node->prev_constant_pool()->print_value_on(st);
+ pv_node->constants()->print_value_on(st);
}
if (have_pv) st->cr();
- } // pvw is cleaned up
+ }
if (generic_signature() != NULL) {
st->print(BULLET"generic signature: ");
@@ -3443,92 +3436,92 @@
// RedefineClasses() support for previous versions:
// Purge previous versions
-static void purge_previous_versions_internal(InstanceKlass* ik, int emcp_method_count) {
+void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
if (ik->previous_versions() != NULL) {
// This klass has previous versions so see what we can cleanup
// while it is safe to do so.
int deleted_count = 0; // leave debugging breadcrumbs
int live_count = 0;
- ClassLoaderData* loader_data = ik->class_loader_data() == NULL ?
- ClassLoaderData::the_null_class_loader_data() :
- ik->class_loader_data();
+ ClassLoaderData* loader_data = ik->class_loader_data();
+ assert(loader_data != NULL, "should never be null");
// RC_TRACE macro has an embedded ResourceMark
- RC_TRACE(0x00000200, ("purge: %s: previous version length=%d",
- ik->external_name(), ik->previous_versions()->length()));
-
- for (int i = ik->previous_versions()->length() - 1; i >= 0; i--) {
- // check the previous versions array
- PreviousVersionNode * pv_node = ik->previous_versions()->at(i);
- ConstantPool* cp_ref = pv_node->prev_constant_pool();
- assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
-
- ConstantPool* pvcp = cp_ref;
+ RC_TRACE(0x00000200, ("purge: %s: previous versions", ik->external_name()));
+
+ // previous versions are linked together through the InstanceKlass
+ InstanceKlass* pv_node = ik->previous_versions();
+ InstanceKlass* last = ik;
+ int version = 0;
+
+ // check the previous versions list
+ for (; pv_node != NULL; ) {
+
+ ConstantPool* pvcp = pv_node->constants();
+ assert(pvcp != NULL, "cp ref was unexpectedly cleared");
+
if (!pvcp->on_stack()) {
// If the constant pool isn't on stack, none of the methods
- // are executing. Delete all the methods, the constant pool and
- // and this previous version node.
- GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
- if (method_refs != NULL) {
- for (int j = method_refs->length() - 1; j >= 0; j--) {
- Method* method = method_refs->at(j);
- assert(method != NULL, "method ref was unexpectedly cleared");
- method_refs->remove_at(j);
- // method will be freed with associated class.
- }
- }
- // Remove the constant pool
- delete pv_node;
- // Since we are traversing the array backwards, we don't have to
- // do anything special with the index.
- ik->previous_versions()->remove_at(i);
+ // are executing. Unlink this previous_version.
+ // The previous version InstanceKlass is on the ClassLoaderData deallocate list
+ // so will be deallocated during the next phase of class unloading.
+ pv_node = pv_node->previous_versions();
+ last->link_previous_versions(pv_node);
deleted_count++;
+ version++;
continue;
} else {
- RC_TRACE(0x00000200, ("purge: previous version @%d is alive", i));
+ RC_TRACE(0x00000200, ("purge: previous version " INTPTR_FORMAT " is alive",
+ pv_node));
assert(pvcp->pool_holder() != NULL, "Constant pool with no holder");
guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack");
live_count++;
}
- // At least one method is live in this previous version, clean out
- // the others or mark them as obsolete.
- GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
+ // At least one method is live in this previous version so clean its MethodData.
+ // Reset dead EMCP methods not to get breakpoints.
+ // All methods are deallocated when all of the methods for this class are no
+ // longer running.
+ Array<Method*>* method_refs = pv_node->methods();
if (method_refs != NULL) {
RC_TRACE(0x00000200, ("purge: previous methods length=%d",
method_refs->length()));
- for (int j = method_refs->length() - 1; j >= 0; j--) {
+ for (int j = 0; j < method_refs->length(); j++) {
Method* method = method_refs->at(j);
- assert(method != NULL, "method ref was unexpectedly cleared");
-
- // Remove the emcp method if it's not executing
- // If it's been made obsolete by a redefinition of a non-emcp
- // method, mark it as obsolete but leave it to clean up later.
+
if (!method->on_stack()) {
- method_refs->remove_at(j);
- } else if (emcp_method_count == 0) {
- method->set_is_obsolete();
+ // no breakpoints for non-running methods
+ if (method->is_running_emcp()) {
+ method->set_running_emcp(false);
+ }
} else {
+ assert (method->is_obsolete() || method->is_running_emcp(),
+ "emcp method cannot run after emcp bit is cleared");
// RC_TRACE macro has an embedded ResourceMark
RC_TRACE(0x00000200,
("purge: %s(%s): prev method @%d in version @%d is alive",
method->name()->as_C_string(),
- method->signature()->as_C_string(), j, i));
+ method->signature()->as_C_string(), j, version));
if (method->method_data() != NULL) {
- // Clean out any weak method links
+ // Clean out any weak method links for running methods
+ // (also should include not EMCP methods)
method->method_data()->clean_weak_method_links();
}
}
}
}
+ // next previous version
+ last = pv_node;
+ pv_node = pv_node->previous_versions();
+ version++;
}
- assert(ik->previous_versions()->length() == live_count, "sanity check");
RC_TRACE(0x00000200,
("purge: previous version stats: live=%d, deleted=%d", live_count,
deleted_count));
}
+ // Clean MethodData of this class's methods so they don't refer to
+ // old methods that are no longer running.
Array<Method*>* methods = ik->methods();
int num_methods = methods->length();
for (int index2 = 0; index2 < num_methods; ++index2) {
@@ -3538,122 +3531,30 @@
}
}
-// External interface for use during class unloading.
-void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
- // Call with >0 emcp methods since they are not currently being redefined.
- purge_previous_versions_internal(ik, 1);
-}
-
-
-// Potentially add an information node that contains pointers to the
-// interesting parts of the previous version of the_class.
-// This is also where we clean out any unused references.
-// Note that while we delete nodes from the _previous_versions
-// array, we never delete the array itself until the klass is
-// unloaded. The has_been_redefined() query depends on that fact.
-//
-void InstanceKlass::add_previous_version(instanceKlassHandle ikh,
- BitMap* emcp_methods, int emcp_method_count) {
- assert(Thread::current()->is_VM_thread(),
- "only VMThread can add previous versions");
-
- if (_previous_versions == NULL) {
- // This is the first previous version so make some space.
- // Start with 2 elements under the assumption that the class
- // won't be redefined much.
- _previous_versions = new (ResourceObj::C_HEAP, mtClass)
- GrowableArray<PreviousVersionNode *>(2, true);
- }
-
- ConstantPool* cp_ref = ikh->constants();
-
- // RC_TRACE macro has an embedded ResourceMark
- RC_TRACE(0x00000400, ("adding previous version ref for %s @%d, EMCP_cnt=%d "
- "on_stack=%d",
- ikh->external_name(), _previous_versions->length(), emcp_method_count,
- cp_ref->on_stack()));
-
- // If the constant pool for this previous version of the class
- // is not marked as being on the stack, then none of the methods
- // in this previous version of the class are on the stack so
- // we don't need to create a new PreviousVersionNode. However,
- // we still need to examine older previous versions below.
- Array<Method*>* old_methods = ikh->methods();
-
- if (cp_ref->on_stack()) {
- PreviousVersionNode * pv_node = NULL;
- if (emcp_method_count == 0) {
- // non-shared ConstantPool gets a reference
- pv_node = new PreviousVersionNode(cp_ref, NULL);
- RC_TRACE(0x00000400,
- ("add: all methods are obsolete; flushing any EMCP refs"));
- } else {
- int local_count = 0;
- GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass)
- GrowableArray<Method*>(emcp_method_count, true);
- for (int i = 0; i < old_methods->length(); i++) {
- if (emcp_methods->at(i)) {
- // this old method is EMCP. Save it only if it's on the stack
- Method* old_method = old_methods->at(i);
- if (old_method->on_stack()) {
- method_refs->append(old_method);
- }
- if (++local_count >= emcp_method_count) {
- // no more EMCP methods so bail out now
- break;
- }
- }
- }
- // non-shared ConstantPool gets a reference
- pv_node = new PreviousVersionNode(cp_ref, method_refs);
- }
- // append new previous version.
- _previous_versions->append(pv_node);
- }
-
- // Since the caller is the VMThread and we are at a safepoint, this
- // is a good time to clear out unused references.
-
- RC_TRACE(0x00000400, ("add: previous version length=%d",
- _previous_versions->length()));
-
- // Purge previous versions not executing on the stack
- purge_previous_versions_internal(this, emcp_method_count);
-
+void InstanceKlass::mark_newly_obsolete_methods(Array<Method*>* old_methods,
+ int emcp_method_count) {
int obsolete_method_count = old_methods->length() - emcp_method_count;
if (emcp_method_count != 0 && obsolete_method_count != 0 &&
- _previous_versions->length() > 0) {
+ _previous_versions != NULL) {
// We have a mix of obsolete and EMCP methods so we have to
// clear out any matching EMCP method entries the hard way.
int local_count = 0;
for (int i = 0; i < old_methods->length(); i++) {
- if (!emcp_methods->at(i)) {
+ Method* old_method = old_methods->at(i);
+ if (old_method->is_obsolete()) {
// only obsolete methods are interesting
- Method* old_method = old_methods->at(i);
Symbol* m_name = old_method->name();
Symbol* m_signature = old_method->signature();
- // we might not have added the last entry
- for (int j = _previous_versions->length() - 1; j >= 0; j--) {
- // check the previous versions array for non executing obsolete methods
- PreviousVersionNode * pv_node = _previous_versions->at(j);
-
- GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
- if (method_refs == NULL) {
- // We have run into a PreviousVersion generation where
- // all methods were made obsolete during that generation's
- // RedefineClasses() operation. At the time of that
- // operation, all EMCP methods were flushed so we don't
- // have to go back any further.
- //
- // A NULL method_refs is different than an empty method_refs.
- // We cannot infer any optimizations about older generations
- // from an empty method_refs for the current generation.
- break;
- }
-
- for (int k = method_refs->length() - 1; k >= 0; k--) {
+ // previous versions are linked together through the InstanceKlass
+ int j = 0;
+ for (InstanceKlass* prev_version = _previous_versions;
+ prev_version != NULL;
+ prev_version = prev_version->previous_versions(), j++) {
+
+ Array<Method*>* method_refs = prev_version->methods();
+ for (int k = 0; k < method_refs->length(); k++) {
Method* method = method_refs->at(k);
if (!method->is_obsolete() &&
@@ -3661,14 +3562,11 @@
method->signature() == m_signature) {
// The current RedefineClasses() call has made all EMCP
// versions of this method obsolete so mark it as obsolete
- // and remove the reference.
RC_TRACE(0x00000400,
("add: %s(%s): flush obsolete method @%d in version @%d",
m_name->as_C_string(), m_signature->as_C_string(), k, j));
method->set_is_obsolete();
- // Leave obsolete methods on the previous version list to
- // clean up later.
break;
}
}
@@ -3676,9 +3574,9 @@
// The previous loop may not find a matching EMCP method, but
// that doesn't mean that we can optimize and not go any
// further back in the PreviousVersion generations. The EMCP
- // method for this generation could have already been deleted,
+ // method for this generation could have already been made obsolete,
// but there still may be an older EMCP method that has not
- // been deleted.
+ // been made obsolete.
}
if (++local_count >= obsolete_method_count) {
@@ -3688,15 +3586,69 @@
}
}
}
+}
+
+// Save the scratch_class as the previous version if any of the methods are running.
+// The previous_versions are used to set breakpoints in EMCP methods and they are
+// also used to clean MethodData links to redefined methods that are no longer running.
+void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class,
+ int emcp_method_count) {
+ assert(Thread::current()->is_VM_thread(),
+ "only VMThread can add previous versions");
+
+ // RC_TRACE macro has an embedded ResourceMark
+ RC_TRACE(0x00000400, ("adding previous version ref for %s, EMCP_cnt=%d",
+ scratch_class->external_name(), emcp_method_count));
+
+ // Clean out old previous versions
+ purge_previous_versions(this);
+
+ // Mark newly obsolete methods in remaining previous versions. An EMCP method from
+ // a previous redefinition may be made obsolete by this redefinition.
+ Array<Method*>* old_methods = scratch_class->methods();
+ mark_newly_obsolete_methods(old_methods, emcp_method_count);
+
+ // If the constant pool for this previous version of the class
+ // is not marked as being on the stack, then none of the methods
+ // in this previous version of the class are on the stack so
+ // we don't need to add this as a previous version.
+ ConstantPool* cp_ref = scratch_class->constants();
+ if (!cp_ref->on_stack()) {
+ RC_TRACE(0x00000400, ("add: scratch class not added; no methods are running"));
+ return;
+ }
+
+ if (emcp_method_count != 0) {
+ // At least one method is still running, check for EMCP methods
+ for (int i = 0; i < old_methods->length(); i++) {
+ Method* old_method = old_methods->at(i);
+ if (!old_method->is_obsolete() && old_method->on_stack()) {
+ // if EMCP method (not obsolete) is on the stack, mark as EMCP so that
+ // we can add breakpoints for it.
+
+ // We set the method->on_stack bit during safepoints for class redefinition and
+ // class unloading and use this bit to set the is_running_emcp bit.
+ // After the safepoint, the on_stack bit is cleared and the running emcp
+ // method may exit. If so, we would set a breakpoint in a method that
+ // is never reached, but this won't be noticeable to the programmer.
+ old_method->set_running_emcp(true);
+ RC_TRACE(0x00000400, ("add: EMCP method %s is on_stack " INTPTR_FORMAT,
+ old_method->name_and_sig_as_C_string(), old_method));
+ } else if (!old_method->is_obsolete()) {
+ RC_TRACE(0x00000400, ("add: EMCP method %s is NOT on_stack " INTPTR_FORMAT,
+ old_method->name_and_sig_as_C_string(), old_method));
+ }
+ }
+ }
+
+ // Add previous version if any methods are still running.
+ RC_TRACE(0x00000400, ("add: scratch class added; one of its methods is on_stack"));
+ assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
+ scratch_class->link_previous_versions(previous_versions());
+ link_previous_versions(scratch_class());
} // end add_previous_version()
-// Determine if InstanceKlass has a previous version.
-bool InstanceKlass::has_previous_version() const {
- return (_previous_versions != NULL && _previous_versions->length() > 0);
-} // end has_previous_version()
-
-
Method* InstanceKlass::method_with_idnum(int idnum) {
Method* m = NULL;
if (idnum < methods()->length()) {
@@ -3722,61 +3674,3 @@
unsigned char * InstanceKlass::get_cached_class_file_bytes() {
return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
}
-
-
-// Construct a PreviousVersionNode entry for the array hung off
-// the InstanceKlass.
-PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool,
- GrowableArray<Method*>* prev_EMCP_methods) {
-
- _prev_constant_pool = prev_constant_pool;
- _prev_EMCP_methods = prev_EMCP_methods;
-}
-
-
-// Destroy a PreviousVersionNode
-PreviousVersionNode::~PreviousVersionNode() {
- if (_prev_constant_pool != NULL) {
- _prev_constant_pool = NULL;
- }
-
- if (_prev_EMCP_methods != NULL) {
- delete _prev_EMCP_methods;
- }
-}
-
-// Construct a helper for walking the previous versions array
-PreviousVersionWalker::PreviousVersionWalker(Thread* thread, InstanceKlass *ik) {
- _thread = thread;
- _previous_versions = ik->previous_versions();
- _current_index = 0;
- _current_p = NULL;
- _current_constant_pool_handle = constantPoolHandle(thread, ik->constants());
-}
-
-
-// Return the interesting information for the next previous version
-// of the klass. Returns NULL if there are no more previous versions.
-PreviousVersionNode* PreviousVersionWalker::next_previous_version() {
- if (_previous_versions == NULL) {
- // no previous versions so nothing to return
- return NULL;
- }
-
- _current_p = NULL; // reset to NULL
- _current_constant_pool_handle = NULL;
-
- int length = _previous_versions->length();
-
- while (_current_index < length) {
- PreviousVersionNode * pv_node = _previous_versions->at(_current_index++);
-
- // Save a handle to the constant pool for this previous version,
- // which keeps all the methods from being deallocated.
- _current_constant_pool_handle = constantPoolHandle(_thread, pv_node->prev_constant_pool());
- _current_p = pv_node;
- return pv_node;
- }
-
- return NULL;
-} // end next_previous_version()
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -59,7 +59,6 @@
class fieldDescriptor;
class DepChange;
class nmethodBucket;
-class PreviousVersionNode;
class JvmtiCachedClassFieldMap;
class MemberNameTable;
@@ -205,7 +204,8 @@
_misc_should_verify_class = 1 << 2, // allow caching of preverification
_misc_is_anonymous = 1 << 3, // has embedded _host_klass field
_misc_is_contended = 1 << 4, // marked with contended annotation
- _misc_has_default_methods = 1 << 5 // class/superclass/implemented interfaces has default methods
+ _misc_has_default_methods = 1 << 5, // class/superclass/implemented interfaces has default methods
+ _misc_has_been_redefined = 1 << 6 // class has been redefined
};
u2 _misc_flags;
u2 _minor_version; // minor version number of class file
@@ -220,9 +220,8 @@
nmethodBucket* _dependencies; // list of dependent nmethods
nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class
BreakpointInfo* _breakpoints; // bpt lists, managed by Method*
- // Array of interesting part(s) of the previous version(s) of this
- // InstanceKlass. See PreviousVersionWalker below.
- GrowableArray<PreviousVersionNode *>* _previous_versions;
+ // Linked instanceKlasses of previous versions
+ InstanceKlass* _previous_versions;
// JVMTI fields can be moved to their own structure - see 6315920
// JVMTI: cached class file, before retransformable agent modified it in CFLH
JvmtiCachedClassFileData* _cached_class_file;
@@ -608,19 +607,20 @@
}
// RedefineClasses() support for previous versions:
- void add_previous_version(instanceKlassHandle ikh, BitMap *emcp_methods,
- int emcp_method_count);
- // If the _previous_versions array is non-NULL, then this klass
- // has been redefined at least once even if we aren't currently
- // tracking a previous version.
- bool has_been_redefined() const { return _previous_versions != NULL; }
- bool has_previous_version() const;
+ void add_previous_version(instanceKlassHandle ikh, int emcp_method_count);
+
+ InstanceKlass* previous_versions() const { return _previous_versions; }
+
+ bool has_been_redefined() const {
+ return (_misc_flags & _misc_has_been_redefined) != 0;
+ }
+ void set_has_been_redefined() {
+ _misc_flags |= _misc_has_been_redefined;
+ }
+
void init_previous_versions() {
_previous_versions = NULL;
}
- GrowableArray<PreviousVersionNode *>* previous_versions() const {
- return _previous_versions;
- }
static void purge_previous_versions(InstanceKlass* ik);
@@ -1042,6 +1042,10 @@
// Free CHeap allocated fields.
void release_C_heap_structures();
+
+ // RedefineClasses support
+ void link_previous_versions(InstanceKlass* pv) { _previous_versions = pv; }
+ void mark_newly_obsolete_methods(Array<Method*>* old_methods, int emcp_method_count);
public:
// CDS support - remove and restore oops from metadata. Oops are not shared.
virtual void remove_unshareable_info();
@@ -1141,62 +1145,6 @@
};
-// If breakpoints are more numerous than just JVMTI breakpoints,
-// consider compressing this data structure.
-// It is currently a simple linked list defined in method.hpp.
-
-class BreakpointInfo;
-
-
-// A collection point for interesting information about the previous
-// version(s) of an InstanceKlass. A GrowableArray of PreviousVersionNodes
-// is attached to the InstanceKlass as needed. See PreviousVersionWalker below.
-class PreviousVersionNode : public CHeapObj<mtClass> {
- private:
- ConstantPool* _prev_constant_pool;
-
- // If the previous version of the InstanceKlass doesn't have any
- // EMCP methods, then _prev_EMCP_methods will be NULL. If all the
- // EMCP methods have been collected, then _prev_EMCP_methods can
- // have a length of zero.
- GrowableArray<Method*>* _prev_EMCP_methods;
-
-public:
- PreviousVersionNode(ConstantPool* prev_constant_pool,
- GrowableArray<Method*>* prev_EMCP_methods);
- ~PreviousVersionNode();
- ConstantPool* prev_constant_pool() const {
- return _prev_constant_pool;
- }
- GrowableArray<Method*>* prev_EMCP_methods() const {
- return _prev_EMCP_methods;
- }
-};
-
-
-// Helper object for walking previous versions.
-class PreviousVersionWalker : public StackObj {
- private:
- Thread* _thread;
- GrowableArray<PreviousVersionNode *>* _previous_versions;
- int _current_index;
-
- // A pointer to the current node object so we can handle the deletes.
- PreviousVersionNode* _current_p;
-
- // The constant pool handle keeps all the methods in this class from being
- // deallocated from the metaspace during class unloading.
- constantPoolHandle _current_constant_pool_handle;
-
- public:
- PreviousVersionWalker(Thread* thread, InstanceKlass *ik);
-
- // Return the interesting information for the next previous version
- // of the klass. Returns NULL if there are no more previous versions.
- PreviousVersionNode* next_previous_version();
-};
-
-
//
// nmethodBucket is used to record dependent nmethods for
// deoptimization. nmethod dependencies are actually <klass, method>
--- a/hotspot/src/share/vm/oops/method.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/method.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -1635,34 +1635,34 @@
}
int Method::highest_comp_level() const {
- const MethodData* mdo = method_data();
- if (mdo != NULL) {
- return mdo->highest_comp_level();
+ const MethodCounters* mcs = method_counters();
+ if (mcs != NULL) {
+ return mcs->highest_comp_level();
} else {
return CompLevel_none;
}
}
int Method::highest_osr_comp_level() const {
- const MethodData* mdo = method_data();
- if (mdo != NULL) {
- return mdo->highest_osr_comp_level();
+ const MethodCounters* mcs = method_counters();
+ if (mcs != NULL) {
+ return mcs->highest_osr_comp_level();
} else {
return CompLevel_none;
}
}
void Method::set_highest_comp_level(int level) {
- MethodData* mdo = method_data();
- if (mdo != NULL) {
- mdo->set_highest_comp_level(level);
+ MethodCounters* mcs = method_counters();
+ if (mcs != NULL) {
+ mcs->set_highest_comp_level(level);
}
}
void Method::set_highest_osr_comp_level(int level) {
- MethodData* mdo = method_data();
- if (mdo != NULL) {
- mdo->set_highest_osr_comp_level(level);
+ MethodCounters* mcs = method_counters();
+ if (mcs != NULL) {
+ mcs->set_highest_osr_comp_level(level);
}
}
--- a/hotspot/src/share/vm/oops/method.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/method.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -80,7 +80,8 @@
_caller_sensitive = 1 << 1,
_force_inline = 1 << 2,
_dont_inline = 1 << 3,
- _hidden = 1 << 4
+ _hidden = 1 << 4,
+ _running_emcp = 1 << 5
};
u1 _flags;
@@ -688,6 +689,21 @@
void set_is_obsolete() { _access_flags.set_is_obsolete(); }
bool is_deleted() const { return access_flags().is_deleted(); }
void set_is_deleted() { _access_flags.set_is_deleted(); }
+
+ bool is_running_emcp() const {
+ // EMCP methods are old but not obsolete or deleted. Equivalent
+ // Modulo Constant Pool means the method is equivalent except
+ // the constant pool and instructions that access the constant
+ // pool might be different.
+ // If a breakpoint is set in a redefined method, its EMCP methods that are
+ // still running must have a breakpoint also.
+ return (_flags & _running_emcp) != 0;
+ }
+
+ void set_running_emcp(bool x) {
+ _flags = x ? (_flags | _running_emcp) : (_flags & ~_running_emcp);
+ }
+
bool on_stack() const { return access_flags().on_stack(); }
void set_on_stack(const bool value);
--- a/hotspot/src/share/vm/oops/methodCounters.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/methodCounters.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -35,4 +35,40 @@
set_interpreter_throwout_count(0);
set_interpreter_invocation_count(0);
set_nmethod_age(INT_MAX);
+#ifdef TIERED
+ set_prev_time(0);
+ set_rate(0);
+ set_highest_comp_level(0);
+ set_highest_osr_comp_level(0);
+#endif
}
+
+
+int MethodCounters::highest_comp_level() const {
+#ifdef TIERED
+ return _highest_comp_level;
+#else
+ return CompLevel_none;
+#endif
+}
+
+void MethodCounters::set_highest_comp_level(int level) {
+#ifdef TIERED
+ _highest_comp_level = level;
+#endif
+}
+
+int MethodCounters::highest_osr_comp_level() const {
+#ifdef TIERED
+ return _highest_osr_comp_level;
+#else
+ return CompLevel_none;
+#endif
+}
+
+void MethodCounters::set_highest_osr_comp_level(int level) {
+#ifdef TIERED
+ _highest_osr_comp_level = level;
+#endif
+}
+
--- a/hotspot/src/share/vm/oops/methodCounters.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/methodCounters.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -49,6 +49,8 @@
#ifdef TIERED
float _rate; // Events (invocation and backedge counter increments) per millisecond
jlong _prev_time; // Previous time the rate was acquired
+ u1 _highest_comp_level; // Highest compile level this method has ever seen.
+ u1 _highest_osr_comp_level; // Same for OSR level
#endif
MethodCounters() : _interpreter_invocation_count(0),
@@ -57,7 +59,9 @@
_nmethod_age(INT_MAX)
#ifdef TIERED
, _rate(0),
- _prev_time(0)
+ _prev_time(0),
+ _highest_comp_level(0),
+ _highest_osr_comp_level(0)
#endif
{
invocation_counter()->init();
@@ -114,6 +118,11 @@
void set_rate(float rate) { _rate = rate; }
#endif
+ int highest_comp_level() const;
+ void set_highest_comp_level(int level);
+ int highest_osr_comp_level() const;
+ void set_highest_osr_comp_level(int level);
+
// invocation counter
InvocationCounter* invocation_counter() { return &_invocation_counter; }
InvocationCounter* backedge_counter() { return &_backedge_counter; }
--- a/hotspot/src/share/vm/oops/methodData.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/methodData.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -1134,8 +1134,6 @@
_tenure_traps = 0;
_num_loops = 0;
_num_blocks = 0;
- _highest_comp_level = 0;
- _highest_osr_comp_level = 0;
_would_profile = true;
#if INCLUDE_RTM_OPT
--- a/hotspot/src/share/vm/oops/methodData.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/oops/methodData.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -2095,10 +2095,6 @@
// time with C1. It is used to determine if method is trivial.
short _num_loops;
short _num_blocks;
- // Highest compile level this method has ever seen.
- u1 _highest_comp_level;
- // Same for OSR level
- u1 _highest_osr_comp_level;
// Does this method contain anything worth profiling?
bool _would_profile;
@@ -2277,11 +2273,6 @@
void set_would_profile(bool p) { _would_profile = p; }
bool would_profile() const { return _would_profile; }
- int highest_comp_level() const { return _highest_comp_level; }
- void set_highest_comp_level(int level) { _highest_comp_level = level; }
- int highest_osr_comp_level() const { return _highest_osr_comp_level; }
- void set_highest_osr_comp_level(int level) { _highest_osr_comp_level = level; }
-
int num_loops() const { return _num_loops; }
void set_num_loops(int n) { _num_loops = n; }
int num_blocks() const { return _num_blocks; }
--- a/hotspot/src/share/vm/opto/compile.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/compile.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -430,7 +430,7 @@
// removes the need to bang the stack in the deoptimization blob which
// in turn simplifies stack overflow handling.
int Compile::bang_size_in_bytes() const {
- return MAX2(_interpreter_frame_size, frame_size_in_bytes());
+ return MAX2(frame_size_in_bytes() + os::extra_bang_size_in_bytes(), _interpreter_frame_size);
}
// ============================================================================
--- a/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/opto/library_call.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -4968,7 +4968,8 @@
// Allocate the result array
Node* zlen = _gvn.transform(new AddINode(xlen, ylen));
- Node* klass_node = makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_INT)));
+ ciKlass* klass = ciTypeArrayKlass::make(T_INT);
+ Node* klass_node = makecon(TypeKlassPtr::make(klass));
IdealKit ideal(this);
@@ -5002,7 +5003,8 @@
sync_kit(ideal);
z = __ value(z_alloc);
- _gvn.set_type(z, TypeAryPtr::INTS);
+ // Can't use TypeAryPtr::INTS which uses Bottom offset.
+ _gvn.set_type(z, TypeOopPtr::make_from_klass(klass));
// Final sync IdealKit and GraphKit.
final_sync(ideal);
#undef __
--- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -282,39 +282,22 @@
void JvmtiBreakpoint::each_method_version_do(method_action meth_act) {
((Method*)_method->*meth_act)(_bci);
- // add/remove breakpoint to/from versions of the method that
- // are EMCP. Directly or transitively obsolete methods are
- // not saved in the PreviousVersionNodes.
+ // add/remove breakpoint to/from versions of the method that are EMCP.
Thread *thread = Thread::current();
instanceKlassHandle ikh = instanceKlassHandle(thread, _method->method_holder());
Symbol* m_name = _method->name();
Symbol* m_signature = _method->signature();
// search previous versions if they exist
- PreviousVersionWalker pvw(thread, (InstanceKlass *)ikh());
- for (PreviousVersionNode * pv_node = pvw.next_previous_version();
- pv_node != NULL; pv_node = pvw.next_previous_version()) {
- GrowableArray<Method*>* methods = pv_node->prev_EMCP_methods();
-
- if (methods == NULL) {
- // We have run into a PreviousVersion generation where
- // all methods were made obsolete during that generation's
- // RedefineClasses() operation. At the time of that
- // operation, all EMCP methods were flushed so we don't
- // have to go back any further.
- //
- // A NULL methods array is different than an empty methods
- // array. We cannot infer any optimizations about older
- // generations from an empty methods array for the current
- // generation.
- break;
- }
+ for (InstanceKlass* pv_node = ikh->previous_versions();
+ pv_node != NULL;
+ pv_node = pv_node->previous_versions()) {
+ Array<Method*>* methods = pv_node->methods();
for (int i = methods->length() - 1; i >= 0; i--) {
Method* method = methods->at(i);
- // obsolete methods that are running are not deleted from
- // previous version array, but they are skipped here.
- if (!method->is_obsolete() &&
+ // Only set breakpoints in running EMCP methods.
+ if (method->is_running_emcp() &&
method->name() == m_name &&
method->signature() == m_signature) {
RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)",
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -135,7 +135,7 @@
// Mark methods seen on stack and everywhere else so old methods are not
// cleaned up if they're on the stack.
- MetadataOnStackMark md_on_stack;
+ MetadataOnStackMark md_on_stack(true);
HandleMark hm(thread); // make sure any handles created are deleted
// before the stack walk again.
@@ -2826,11 +2826,10 @@
}
// the previous versions' constant pool caches may need adjustment
- PreviousVersionWalker pvw(_thread, ik);
- for (PreviousVersionNode * pv_node = pvw.next_previous_version();
- pv_node != NULL; pv_node = pvw.next_previous_version()) {
- other_cp = pv_node->prev_constant_pool();
- cp_cache = other_cp->cache();
+ for (InstanceKlass* pv_node = ik->previous_versions();
+ pv_node != NULL;
+ pv_node = pv_node->previous_versions()) {
+ cp_cache = pv_node->constants()->cache();
if (cp_cache != NULL) {
cp_cache->adjust_method_entries(_matching_old_methods,
_matching_new_methods,
@@ -2855,9 +2854,8 @@
}
}
-void VM_RedefineClasses::check_methods_and_mark_as_obsolete(
- BitMap *emcp_methods, int * emcp_method_count_p) {
- *emcp_method_count_p = 0;
+int VM_RedefineClasses::check_methods_and_mark_as_obsolete() {
+ int emcp_method_count = 0;
int obsolete_count = 0;
int old_index = 0;
for (int j = 0; j < _matching_methods_length; ++j, ++old_index) {
@@ -2931,9 +2929,9 @@
// that we get from effectively overwriting the old methods
// when the new methods are attached to the_class.
- // track which methods are EMCP for add_previous_version() call
- emcp_methods->set_bit(old_index);
- (*emcp_method_count_p)++;
+ // Count number of methods that are EMCP. The method will be marked
+ // old but not obsolete if it is EMCP.
+ emcp_method_count++;
// An EMCP method is _not_ obsolete. An obsolete method has a
// different jmethodID than the current method. An EMCP method
@@ -2982,10 +2980,11 @@
old_method->name()->as_C_string(),
old_method->signature()->as_C_string()));
}
- assert((*emcp_method_count_p + obsolete_count) == _old_methods->length(),
+ assert((emcp_method_count + obsolete_count) == _old_methods->length(),
"sanity check");
- RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", *emcp_method_count_p,
+ RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", emcp_method_count,
obsolete_count));
+ return emcp_method_count;
}
// This internal class transfers the native function registration from old methods
@@ -3379,11 +3378,8 @@
old_constants->set_pool_holder(scratch_class());
#endif
- // track which methods are EMCP for add_previous_version() call below
- BitMap emcp_methods(_old_methods->length());
- int emcp_method_count = 0;
- emcp_methods.clear(); // clears 0..(length() - 1)
- check_methods_and_mark_as_obsolete(&emcp_methods, &emcp_method_count);
+ // track number of methods that are EMCP for add_previous_version() call below
+ int emcp_method_count = check_methods_and_mark_as_obsolete();
transfer_old_native_function_registrations(the_class);
// The class file bytes from before any retransformable agents mucked
@@ -3471,9 +3467,10 @@
scratch_class->enclosing_method_method_index());
scratch_class->set_enclosing_method_indices(old_class_idx, old_method_idx);
+ the_class->set_has_been_redefined();
+
// keep track of previous versions of this class
- the_class->add_previous_version(scratch_class, &emcp_methods,
- emcp_method_count);
+ the_class->add_previous_version(scratch_class, emcp_method_count);
RC_TIMER_STOP(_timer_rsc_phase1);
RC_TIMER_START(_timer_rsc_phase2);
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, 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
@@ -403,14 +403,9 @@
// Change jmethodIDs to point to the new methods
void update_jmethod_ids();
- // In addition to marking methods as obsolete, this routine
- // records which methods are EMCP (Equivalent Module Constant
- // Pool) in the emcp_methods BitMap and returns the number of
- // EMCP methods via emcp_method_count_p. This information is
- // used when information about the previous version of the_class
- // is squirreled away.
- void check_methods_and_mark_as_obsolete(BitMap *emcp_methods,
- int * emcp_method_count_p);
+ // In addition to marking methods as old and/or obsolete, this routine
+ // counts the number of methods that are EMCP (Equivalent Module Constant Pool).
+ int check_methods_and_mark_as_obsolete();
void transfer_old_native_function_registrations(instanceKlassHandle the_class);
// Install the redefinition of a class
--- a/hotspot/src/share/vm/runtime/arguments.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -590,7 +590,9 @@
static void fix_appclasspath();
// Operation modi
- static Mode mode() { return _mode; }
+ static Mode mode() { return _mode; }
+ static bool is_interpreter_only() { return mode() == _int; }
+
// Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid.
static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen);
--- a/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/globals.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -2473,7 +2473,7 @@
develop(bool, CIPrintCompilerName, false, \
"when CIPrint is active, print the name of the active compiler") \
\
- develop(bool, CIPrintCompileQueue, false, \
+ diagnostic(bool, CIPrintCompileQueue, false, \
"display the contents of the compile queue whenever a " \
"compilation is enqueued") \
\
--- a/hotspot/src/share/vm/runtime/os.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/os.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -53,6 +53,7 @@
#include "runtime/vm_version.hpp"
#include "services/attachListener.hpp"
#include "services/nmtCommon.hpp"
+#include "services/mallocTracker.hpp"
#include "services/memTracker.hpp"
#include "services/threadService.hpp"
#include "utilities/defaultStream.hpp"
@@ -570,6 +571,17 @@
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
+#if INCLUDE_NMT
+ // NMT can not track malloc allocation size > MAX_MALLOC_SIZE, which is
+ // (1GB - 1) on 32-bit system. It is not an issue on 64-bit system, where
+ // MAX_MALLOC_SIZE = ((1 << 62) - 1).
+ // VM code does not have such large malloc allocation. However, it can come
+ // Unsafe call.
+ if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) {
+ return NULL;
+ }
+#endif
+
#ifdef ASSERT
// checking for the WatcherThread and crash_protection first
// since os::malloc can be called when the libjvm.{dll,so} is
@@ -640,6 +652,13 @@
}
void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
+#if INCLUDE_NMT
+ // See comments in os::malloc() above
+ if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) {
+ return NULL;
+ }
+#endif
+
#ifndef ASSERT
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
--- a/hotspot/src/share/vm/runtime/os.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/os.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -557,6 +557,16 @@
// Unload library
static void dll_unload(void *lib);
+ // Callback for loaded module information
+ // Input parameters:
+ // char* module_file_name,
+ // address module_base_addr,
+ // address module_top_addr,
+ // void* param
+ typedef int (*LoadedModulesCallbackFunc)(const char *, address, address, void *);
+
+ static int get_loaded_modules_info(LoadedModulesCallbackFunc callback, void *param);
+
// Return the handle of this process
static void* get_default_process_handle();
@@ -761,6 +771,9 @@
// Hook for os specific jvm options that we don't want to abort on seeing
static bool obsolete_option(const JavaVMOption *option);
+ // Amount beyond the callee frame size that we bang the stack.
+ static int extra_bang_size_in_bytes();
+
// Extensions
#include "runtime/os_ext.hpp"
--- a/hotspot/src/share/vm/runtime/sweeper.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -618,7 +618,7 @@
if (mc == NULL) {
// Sometimes we can get here without MethodCounters. For example if we run with -Xcomp.
// Try to allocate them.
- mc = Method::build_method_counters(nm->method(), Thread::current());
+ mc = nm->method()->get_method_counters(Thread::current());
}
if (mc != NULL) {
// Snapshot the value as it's changed concurrently
--- a/hotspot/src/share/vm/runtime/vm_operations.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/vm_operations.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -470,3 +470,15 @@
ShouldNotReachHere();
}
}
+
+void VM_PrintCompileQueue::doit() {
+ CompileBroker::print_compile_queues(_out);
+}
+
+void VM_PrintCodeList::doit() {
+ CodeCache::print_codelist(_out);
+}
+
+void VM_PrintCodeCache::doit() {
+ CodeCache::print_layout(_out);
+}
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -99,6 +99,9 @@
template(RotateGCLog) \
template(WhiteBoxOperation) \
template(ClassLoaderStatsOperation) \
+ template(PrintCompileQueue) \
+ template(PrintCodeList) \
+ template(PrintCodeCache) \
class VM_Operation: public CHeapObj<mtInternal> {
public:
@@ -413,4 +416,35 @@
void doit() { gclog_or_tty->rotate_log(true, _out); }
};
+class VM_PrintCompileQueue: public VM_Operation {
+ private:
+ outputStream* _out;
+
+ public:
+ VM_PrintCompileQueue(outputStream* st) : _out(st) {}
+ VMOp_Type type() const { return VMOp_PrintCompileQueue; }
+ void doit();
+};
+
+class VM_PrintCodeList: public VM_Operation {
+ private:
+ outputStream* _out;
+
+ public:
+ VM_PrintCodeList(outputStream* st) : _out(st) {}
+ VMOp_Type type() const { return VMOp_PrintCodeList; }
+ void doit();
+};
+
+class VM_PrintCodeCache: public VM_Operation {
+ private:
+ outputStream* _out;
+
+ public:
+ VM_PrintCodeCache(outputStream* st) : _out(st) {}
+ VMOp_Type type() const { return VMOp_PrintCodeCache; }
+ void doit();
+};
+
+
#endif // SHARE_VM_RUNTIME_VM_OPERATIONS_HPP
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp Fri Sep 12 04:22:19 2014 -0700
@@ -60,6 +60,9 @@
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RotateGCLogDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderStatsDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompileQueueDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeListDCmd>(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export, true, false));
// Enhanced JMX Agent Support
// These commands won't be exported via the DiagnosticCommandMBean until an
@@ -674,3 +677,18 @@
}
}
+void CompileQueueDCmd::execute(DCmdSource source, TRAPS) {
+ VM_PrintCompileQueue printCompileQueueOp(output());
+ VMThread::execute(&printCompileQueueOp);
+}
+
+void CodeListDCmd::execute(DCmdSource source, TRAPS) {
+ VM_PrintCodeList printCodeListOp(output());
+ VMThread::execute(&printCodeListOp);
+}
+
+void CodeCacheDCmd::execute(DCmdSource source, TRAPS) {
+ VM_PrintCodeCache printCodeCacheOp(output());
+ VMThread::execute(&printCodeCacheOp);
+}
+
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp Fri Sep 12 04:22:19 2014 -0700
@@ -399,4 +399,68 @@
}
};
+class CompileQueueDCmd : public DCmd {
+public:
+ CompileQueueDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+ static const char* name() {
+ return "Compiler.queue";
+ }
+ static const char* description() {
+ return "Print methods queued for compilation.";
+ }
+ static const char* impact() {
+ return "Low";
+ }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
+ static int num_arguments() { return 0; }
+ virtual void execute(DCmdSource source, TRAPS);
+};
+
+class CodeListDCmd : public DCmd {
+public:
+ CodeListDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+ static const char* name() {
+ return "Compiler.codelist";
+ }
+ static const char* description() {
+ return "Print all compiled methods in code cache.";
+ }
+ static const char* impact() {
+ return "Medium";
+ }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
+ static int num_arguments() { return 0; }
+ virtual void execute(DCmdSource source, TRAPS);
+};
+
+
+class CodeCacheDCmd : public DCmd {
+public:
+ CodeCacheDCmd(outputStream* output, bool heap) : DCmd(output, heap) {}
+ static const char* name() {
+ return "Compiler.codecache";
+ }
+ static const char* description() {
+ return "Print code cache layout and bounds.";
+ }
+ static const char* impact() {
+ return "Low";
+ }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "monitor", NULL};
+ return p;
+ }
+ static int num_arguments() { return 0; }
+ virtual void execute(DCmdSource source, TRAPS);
+};
+
#endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP
--- a/hotspot/test/TEST.groups Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/test/TEST.groups Fri Sep 12 04:22:19 2014 -0700
@@ -80,6 +80,7 @@
runtime/NMT/MallocSiteHashOverflow.java \
runtime/NMT/MallocStressTest.java \
runtime/NMT/MallocTestType.java \
+ runtime/NMT/MallocTrackingVerify.java \
runtime/NMT/ReleaseCommittedMemory.java \
runtime/NMT/ReleaseNoCommit.java \
runtime/NMT/ShutdownTwice.java \
@@ -87,6 +88,7 @@
runtime/NMT/SummarySanityCheck.java \
runtime/NMT/ThreadedMallocTestType.java \
runtime/NMT/ThreadedVirtualAllocTestType.java \
+ runtime/NMT/UnsafeMallocLimit.java \
runtime/NMT/VirtualAllocCommitUncommitRecommit.java \
runtime/NMT/VirtualAllocTestType.java \
runtime/RedefineObject/TestRedefineObject.java \
--- a/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java Fri Sep 12 04:22:19 2014 -0700
@@ -22,7 +22,7 @@
*/
/*
- * @ignore 8027915
+ * @ignore 8049864
* @test TestParallelHeapSizeFlags
* @key gc
* @bug 8006088
--- a/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java Fri Sep 12 04:22:19 2014 -0700
@@ -22,7 +22,6 @@
*/
/*
- * @ignore 8025645
* @test TestUseCompressedOopsErgo
* @key gc
* @bug 8010722
--- a/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java Fri Sep 12 04:22:19 2014 -0700
@@ -22,7 +22,7 @@
*/
/**
- * @ignore 8042051
+ * @ignore 8019361
* @test TestDynShrinkHeap
* @bug 8016479
* @summary Verify that the heap shrinks after full GC according to the current values of the Min/MaxHeapFreeRatio flags
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/NMT/MallocTrackingVerify.java Fri Sep 12 04:22:19 2014 -0700
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8054836
+ * @summary Test to verify correctness of malloc tracking
+ * @key nmt jcmd
+ * @library /testlibrary /testlibrary/whitebox
+ * @build MallocTrackingVerify
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTrackingVerify
+ *
+ */
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import com.oracle.java.testlibrary.*;
+
+import sun.hotspot.WhiteBox;
+
+public class MallocTrackingVerify {
+ private static int MAX_ALLOC = 4 * 1024;
+
+ static ArrayList<MallocMemory> mallocd_memory = new ArrayList<MallocMemory>();
+ static long mallocd_total = 0;
+ public static WhiteBox wb = WhiteBox.getWhiteBox();
+
+ public static void main(String args[]) throws Exception {
+ OutputAnalyzer output;
+
+ // Grab my own PID
+ String pid = Integer.toString(ProcessTools.getProcessId());
+ ProcessBuilder pb = new ProcessBuilder();
+
+ Random random = new Random();
+ // Allocate small amounts of memory with random pseudo call stack
+ while (mallocd_total < MAX_ALLOC) {
+ int size = random.nextInt(31) + 1;
+ long addr = wb.NMTMallocWithPseudoStack(size, random.nextInt());
+ if (addr != 0) {
+ MallocMemory mem = new MallocMemory(addr, size);
+ mallocd_memory.add(mem);
+ mallocd_total += size;
+ } else {
+ System.out.println("Out of malloc memory");
+ break;
+ }
+ }
+
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary" });
+ output = new OutputAnalyzer(pb.start());
+ output.shouldContain("Test (reserved=4KB, committed=4KB)");
+
+ // Free
+ for (MallocMemory mem : mallocd_memory) {
+ wb.NMTFree(mem.addr());
+ }
+
+ // Run 'jcmd <pid> VM.native_memory summary', check for expected output
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid,
+ "VM.native_memory", "summary" });
+ output = new OutputAnalyzer(pb.start());
+ output.shouldNotContain("Test (reserved=");
+ }
+
+ static class MallocMemory {
+ private long addr;
+ private int size;
+
+ MallocMemory(long addr, int size) {
+ this.addr = addr;
+ this.size = size;
+ }
+
+ long addr() {
+ return this.addr;
+ }
+
+ int size() {
+ return this.size;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/NMT/UnsafeMallocLimit.java Fri Sep 12 04:22:19 2014 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8055289
+ * @library /testlibrary
+ * @build UnsafeMallocLimit
+ * @run main/othervm -Xmx32m -XX:NativeMemoryTracking=summary UnsafeMallocLimit
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+
+public class UnsafeMallocLimit {
+
+ public static void main(String args[]) throws Exception {
+ if (Platform.is32bit()) {
+ Unsafe unsafe = Utils.getUnsafe();
+ try {
+ unsafe.allocateMemory(1 << 30);
+ throw new RuntimeException("Did not get expected OOME");
+ } catch (OutOfMemoryError e) {
+ // Expected exception
+ }
+ } else {
+ System.out.println("Test only valid on 32-bit platforms");
+ }
+ }
+}
--- a/hotspot/test/runtime/RedefineFinalizer/RedefineFinalizer.java Wed Jul 05 20:01:04 2017 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 6904403
- * @summary Don't assert if we redefine finalize method
- * @library /testlibrary
- * @build RedefineClassHelper
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
- */
-
-/*
- * Regression test for hitting:
- *
- * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
- *
- * when redefining finalizer method
- */
-public class RedefineFinalizer {
-
- public static String newB =
- "class RedefineFinalizer$B {" +
- " protected void finalize() { " +
- " System.out.println(\"Finalizer called\");" +
- " }" +
- "}";
-
- public static void main(String[] args) throws Exception {
- RedefineClassHelper.redefineClass(B.class, newB);
-
- A a = new A();
- }
-
- static class A extends B {
- }
-
- static class B {
- protected void finalize() {
- // should be empty
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/RedefineTests/RedefineFinalizer.java Fri Sep 12 04:22:19 2014 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6904403
+ * @summary Don't assert if we redefine finalize method
+ * @library /testlibrary
+ * @build RedefineClassHelper
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
+ */
+
+/*
+ * Regression test for hitting:
+ *
+ * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
+ *
+ * when redefining finalizer method
+ */
+public class RedefineFinalizer {
+
+ public static String newB =
+ "class RedefineFinalizer$B {" +
+ " protected void finalize() { " +
+ " System.out.println(\"Finalizer called\");" +
+ " }" +
+ "}";
+
+ public static void main(String[] args) throws Exception {
+ RedefineClassHelper.redefineClass(B.class, newB);
+
+ A a = new A();
+ }
+
+ static class A extends B {
+ }
+
+ static class B {
+ protected void finalize() {
+ // should be empty
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/RedefineTests/RedefineRunningMethods.java Fri Sep 12 04:22:19 2014 -0700
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8055008
+ * @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
+ * @library /testlibrary
+ * @build RedefineClassHelper
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -XX:TraceRedefineClasses=0x600 RedefineRunningMethods
+ */
+public class RedefineRunningMethods {
+
+ public static String newB =
+ "class RedefineRunningMethods$B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.currentThread().sleep(10);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { " +
+ " System.out.println(\"infinite called\");" +
+ " }" +
+ " public static void infinite_emcp() { " +
+ " while (!stop) { count2++; localSleep(); }" +
+ " }" +
+ "}";
+
+ public static String evenNewerB =
+ "class RedefineRunningMethods$B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.currentThread().sleep(1);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { }" +
+ " public static void infinite_emcp() { " +
+ " System.out.println(\"infinite_emcp now obsolete called\");" +
+ " }" +
+ "}";
+
+ static class B {
+ static int count1 = 0;
+ static int count2 = 0;
+ public static volatile boolean stop = false;
+ static void localSleep() {
+ try{
+ Thread.currentThread().sleep(10);//sleep for 10 ms
+ } catch(InterruptedException ie) {
+ }
+ }
+
+ public static void infinite() {
+ while (!stop) { count1++; localSleep(); }
+ }
+ public static void infinite_emcp() {
+ while (!stop) { count2++; localSleep(); }
+ }
+ }
+
+
+ public static void main(String[] args) throws Exception {
+
+ new Thread() {
+ public void run() {
+ B.infinite();
+ }
+ }.start();
+
+ new Thread() {
+ public void run() {
+ B.infinite_emcp();
+ }
+ }.start();
+
+ RedefineClassHelper.redefineClass(B.class, newB);
+
+ System.gc();
+
+ B.infinite();
+
+ // Start a thread with the second version of infinite_emcp running
+ new Thread() {
+ public void run() {
+ B.infinite_emcp();
+ }
+ }.start();
+
+ for (int i = 0; i < 20 ; i++) {
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ RedefineClassHelper.redefineClass(B.class, evenNewerB);
+ System.gc();
+
+ for (int i = 0; i < 20 ; i++) {
+ B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ B.infinite_emcp();
+
+ // purge should clean everything up.
+ B.stop = true;
+
+ for (int i = 0; i < 20 ; i++) {
+ B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+ }
+}
--- a/hotspot/test/runtime/SharedArchiveFile/ArchiveDoesNotExist.java Wed Jul 05 20:01:04 2017 +0200
+++ b/hotspot/test/runtime/SharedArchiveFile/ArchiveDoesNotExist.java Fri Sep 12 04:22:19 2014 -0700
@@ -61,7 +61,7 @@
"-version");
output = new OutputAnalyzer(pb.start());
- output.shouldContain("java version");
+ output.shouldMatch("(java|openjdk) version");
output.shouldNotContain("sharing");
output.shouldHaveExitValue(0);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/CodeCacheTest.java Fri Sep 12 04:22:19 2014 -0700
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test CodeCacheTest
+ * @bug 8054889
+ * @build DcmdUtil CodeCacheTest
+ * @run main CodeCacheTest
+ * @summary Test of diagnostic command Compiler.codecache
+ */
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CodeCacheTest {
+
+ /**
+ * This test calls Jcmd (diagnostic command tool) Compiler.codecache and then parses the output,
+ * making sure that all number look ok
+ *
+ *
+ * Expected output:
+ *
+ * CodeCache: size=245760Kb used=4680Kb max_used=4680Kb free=241079Kb
+ * bounds [0x00007f5bd9000000, 0x00007f5bd94a0000, 0x00007f5be8000000]
+ * total_blobs=575 nmethods=69 adapters=423
+ * compilation: enabled
+ */
+
+ static Pattern line1 = Pattern.compile("CodeCache: size=(\\p{Digit}*)Kb used=(\\p{Digit}*)Kb max_used=(\\p{Digit}*)Kb free=(\\p{Digit}*)Kb");
+ static Pattern line2 = Pattern.compile(" bounds \\[0x(\\p{XDigit}*), 0x(\\p{XDigit}*), 0x(\\p{XDigit}*)\\]");
+ static Pattern line3 = Pattern.compile(" total_blobs=(\\p{Digit}*) nmethods=(\\p{Digit}*) adapters=(\\p{Digit}*)");
+ static Pattern line4 = Pattern.compile(" compilation: (\\w*)");
+
+ public static void main(String arg[]) throws Exception {
+
+ // Get output from dcmd (diagnostic command)
+ String result = DcmdUtil.executeDcmd("Compiler.codecache");
+ BufferedReader r = new BufferedReader(new StringReader(result));
+
+ // Validate first line
+ String line;
+ line = r.readLine();
+ Matcher m = line1.matcher(line);
+ if (m.matches()) {
+ for(int i = 1; i <= 4; i++) {
+ int val = Integer.parseInt(m.group(i));
+ if (val < 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ }
+ } else {
+ throw new Exception("Regexp 1 failed");
+ }
+
+ // Validate second line
+ line = r.readLine();
+ m = line2.matcher(line);
+ if (m.matches()) {
+ long start = Long.parseLong(m.group(1), 16);
+ if (start < 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ long mark = Long.parseLong(m.group(2), 16);
+ if (mark < 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ long top = Long.parseLong(m.group(3), 16);
+ if (top < 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ if (start > mark) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ if (mark > top) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ } else {
+ throw new Exception("Regexp 2 failed line: " + line);
+ }
+
+ // Validate third line
+ line = r.readLine();
+ m = line3.matcher(line);
+ if (m.matches()) {
+ int blobs = Integer.parseInt(m.group(1));
+ if (blobs <= 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ int nmethods = Integer.parseInt(m.group(2));
+ if (nmethods <= 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ int adapters = Integer.parseInt(m.group(3));
+ if (adapters <= 0) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ if (blobs < (nmethods + adapters)) {
+ throw new Exception("Failed parsing dcmd codecache output");
+ }
+ } else {
+ throw new Exception("Regexp 3 failed");
+ }
+
+ // Validate fourth line
+ line = r.readLine();
+ m = line4.matcher(line);
+ if (m.matches()) {
+ if (!m.group(1).equals("enabled")) {
+ throw new Exception("Invalid message: '" + m.group(1) + "'");
+ }
+ } else {
+ throw new Exception("Regexp 4 failed");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/CodelistTest.java Fri Sep 12 04:22:19 2014 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test CodelistTest
+ * @bug 8054889
+ * @build DcmdUtil MethodIdentifierParser CodelistTest
+ * @run main CodelistTest
+ * @summary Test of diagnostic command Compiler.codelist
+ */
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+
+public class CodelistTest {
+
+ /**
+ * This test calls Jcmd (diagnostic command tool) Compiler.codelist and then parses the output,
+ * making sure that the first methods in the list is valid by reflection.
+ *
+ * Output example:
+ *
+ * 6 0 java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V [0x00007f7b49200910, 0x00007f7b49200aa0 - 0x00007f7b49200d30]
+ * 2 3 java.lang.String.indexOf(II)I [0x00007f7b49200d90, 0x00007f7b49200f60 - 0x00007f7b49201490]
+ * 7 3 java.lang.Math.min(II)I [0x00007f7b4922f010, 0x00007f7b4922f180 - 0x00007f7b4922f338]
+ * 8 3 java.lang.String.equals(Ljava/lang/Object;)Z [0x00007f7b4922fb10, 0x00007f7b4922fd40 - 0x00007f7b49230698]
+ * 9 3 java.lang.AbstractStringBuilder.ensureCapacityInternal(I)V [0x00007f7b49232010, 0x00007f7b492321a0 - 0x00007f7b49232510]
+ * 10 1 java.lang.Object.<init>()V [0x00007f7b49233e90, 0x00007f7b49233fe0 - 0x00007f7b49234118]
+ *
+ */
+
+ public static void main(String arg[]) throws Exception {
+ int ok = 0;
+ int fail = 0;
+
+ // Get output from dcmd (diagnostic command)
+ String result = DcmdUtil.executeDcmd("Compiler.codelist");
+ BufferedReader r = new BufferedReader(new StringReader(result));
+
+ // Grab a method name from the output
+ String line;
+ int count = 0;
+
+ while((line = r.readLine()) != null) {
+ count++;
+
+ String[] parts = line.split(" ");
+ // int compileID = Integer.parseInt(parts[0]);
+ // int compileLevel = Integer.parseInt(parts[1]);
+ String methodPrintedInLogFormat = parts[2];
+
+ // skip inits and clinits - they can not be reflected
+ if (methodPrintedInLogFormat.contains("<init>")) {
+ continue;
+ }
+ if (methodPrintedInLogFormat.contains("<clinit>")) {
+ continue;
+ }
+
+ MethodIdentifierParser mf = new MethodIdentifierParser(methodPrintedInLogFormat);
+ Method m;
+ try {
+ m = mf.getMethod();
+ } catch (NoSuchMethodException e) {
+ m = null;
+ }
+ if (m == null) {
+ throw new Exception("Test failed");
+ }
+ if (count > 10) {
+ // Testing 10 entries is enough. Lets not waste time.
+ break;
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/CompilerQueueTest.java Fri Sep 12 04:22:19 2014 -0700
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test CompilerQueueTest
+ * @bug 8054889
+ * @build DcmdUtil CompilerQueueTest
+ * @run main CompilerQueueTest
+ * @summary Test of diagnostic command Compiler.queue
+ */
+
+import java.io.BufferedReader;
+import java.io.StringReader;
+
+public class CompilerQueueTest {
+
+ /**
+ * This test calls Jcmd (diagnostic command tool) Compiler.queue and
+ * then parses the output, making sure that the output look ok.
+ *
+ *
+ * Output example:
+ *
+ * Contents of C1 compile queue
+ * ----------------------------
+ * 73 3 java.lang.AbstractStringBuilder::append (50 bytes)
+ * 74 1 java.util.TreeMap::size (5 bytes)
+ * 75 3 java.lang.StringBuilder::append (8 bytes)
+ * 83 3 java.util.TreeMap$ValueIterator::next (8 bytes)
+ * 84 1 javax.management.MBeanFeatureInfo::getName (5 bytes)
+ * ----------------------------
+ * Contents of C2 compile queue
+ * ----------------------------
+ * Empty
+ * ----------------------------
+ *
+ **/
+
+ public static void main(String arg[]) throws Exception {
+
+ // Get output from dcmd (diagnostic command)
+ String result = DcmdUtil.executeDcmd("Compiler.queue");
+ BufferedReader r = new BufferedReader(new StringReader(result));
+
+ String line;
+ match(r.readLine(), "Contents of C1 compile queue");
+ match(r.readLine(), "----------------------------");
+ String str = r.readLine();
+ if (!str.equals("Empty")) {
+ while (str.charAt(0) != '-') {
+ validateMethodLine(str);
+ str = r.readLine();
+ }
+ } else {
+ str = r.readLine();
+ }
+
+ match(str, "----------------------------");
+ match(r.readLine(), "Contents of C2 compile queue");
+ match(r.readLine(), "----------------------------");
+ str = r.readLine();
+ if (!str.equals("Empty")) {
+ while (str.charAt(0) != '-') {
+ validateMethodLine(str);
+ str = r.readLine();
+ }
+ } else {
+ str = r.readLine();
+ }
+ match(str, "----------------------------");
+ }
+
+ private static void validateMethodLine(String str) throws Exception {
+ String name = str.substring(19);
+ int sep = name.indexOf("::");
+ try {
+ Class.forName(name.substring(0, sep));
+ } catch (ClassNotFoundException e) {
+ throw new Exception("Failed parsing dcmd queue");
+ }
+ }
+
+ public static void match(String line, String str) throws Exception {
+ if (!line.equals(str)) {
+ throw new Exception("String equals: " + line + ", " + str);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/dcmd/MethodIdentifierParser.java Fri Sep 12 04:22:19 2014 -0700
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+public class MethodIdentifierParser {
+
+ private String logString;
+ private String className;
+ private String methodName;
+ private String methodDescriptor;
+
+ /**
+ * This is a utility class for parsing the log entries for a method. It supplies
+ * a few select methods for reflecting the class and method from that information.
+ *
+ * Example log entries:
+ * "java.util.TreeMap.successor(Ljava/util/TreeMap$Entry;)Ljava/util/TreeMap$Entry;"
+ */
+
+ public MethodIdentifierParser(String logString) {
+ this.logString = logString;
+
+ int i = logString.lastIndexOf("."); // find start of method name
+ className = logString.substring(0, i); // classname is everything before
+ int i2 = logString.indexOf("("); // Signature starts with an '('
+ methodName = logString.substring(i+1, i2);
+ methodDescriptor = logString.substring(i2, logString.length());
+
+ // Add sanity check for extracted fields
+ }
+
+ public Method getMethod() throws NoSuchMethodException, SecurityException, ClassNotFoundException, Exception {
+ try {
+ return Class.forName(className).getDeclaredMethod(methodName, getParamenterDescriptorArray());
+ } catch (UnexpectedTokenException e) {
+ throw new Exception("Parse failed");
+ }
+ }
+
+ public Class<?>[] getParamenterDescriptorArray() throws ClassNotFoundException, UnexpectedTokenException {
+ ParameterDecriptorIterator s = new ParameterDecriptorIterator(methodDescriptor);
+ Class<?> paramType;
+ ArrayList<Class<?>> list = new ArrayList<Class<?>>();
+ while ((paramType = s.nextParamType()) != null) {
+ list.add(paramType);
+ }
+ if (list.size() > 0) {
+ return list.toArray(new Class<?>[list.size()]);
+ } else {
+ return null;
+ }
+ }
+
+ class ParameterDecriptorIterator {
+
+ // This class uses charAt() indexing for startMark and i
+ // That is when i points to the last char it can be retrieved with
+ // charAt(i). Including the last char for a subString requires
+ // substring(startMark, i+1);
+
+ private String methodDescriptor;
+ private int startMark;
+
+ public ParameterDecriptorIterator(String signature) {
+ this.methodDescriptor = signature;
+ this.startMark = 0;
+ if (signature.charAt(0) == '(') {
+ this.startMark = 1;
+ }
+ }
+
+ public Class<?> nextParamType() throws UnexpectedTokenException {
+ int i = startMark;
+ while (methodDescriptor.length() > i) {
+ switch (methodDescriptor.charAt(i)) {
+ case 'C':
+ case 'B':
+ case 'I':
+ case 'J':
+ case 'Z':
+ case 'F':
+ case 'D':
+ case 'S':
+ // Primitive class case, but we may have gotten here with [ as first token
+ break;
+ case 'L':
+ // Internal class name suffixed by ';'
+ while (methodDescriptor.charAt(i) != ';') {
+ i++;
+ }
+ break;
+ case '[':
+ i++; // arrays -> do another pass
+ continue;
+ case ')':
+ return null; // end found
+ case 'V':
+ case ';':
+ default:
+ throw new UnexpectedTokenException(methodDescriptor, i);
+ }
+ break;
+ }
+ if (i == startMark) {
+ // Single char -> primitive class case
+ startMark++; // Update for next iteration
+ switch (methodDescriptor.charAt(i)) {
+ case 'C':
+ return char.class;
+ case 'B':
+ return byte.class;
+ case 'I':
+ return int.class;
+ case 'J':
+ return long.class;
+ case 'F':
+ return float.class;
+ case 'D':
+ return double.class;
+ case 'S':
+ return short.class;
+ case 'Z':
+ return boolean.class;
+ default:
+ throw new UnexpectedTokenException(methodDescriptor, i);
+ }
+ } else {
+ // Multi char case
+ String nextParam;
+ if (methodDescriptor.charAt(startMark) == 'L') {
+ // When reflecting a class the leading 'L' and trailing';' must be removed.
+ // (When reflecting an array of classes, they must remain...)
+ nextParam = methodDescriptor.substring(startMark+1, i);
+ } else {
+ // Any kind of array - simple case, use whole descriptor when reflecting.
+ nextParam = methodDescriptor.substring(startMark, i+1);
+ }
+ startMark = ++i; // Update for next iteration
+ try {
+ // The parameter descriptor uses JVM internal class identifier with '/' as
+ // package separator, but Class.forName expects '.'.
+ nextParam = nextParam.replace('/', '.');
+ return Class.forName(nextParam);
+ } catch (ClassNotFoundException e) {
+ System.out.println("Class not Found: " + nextParam);
+ return null;
+ }
+ }
+ }
+ }
+
+ class UnexpectedTokenException extends Exception {
+ String descriptor;
+ int i;
+ public UnexpectedTokenException(String descriptor, int i) {
+ this.descriptor = descriptor;
+ this.i = i;
+ }
+
+ @Override
+ public String toString() {
+ return "Unexpected token at: " + i + " in signature: " + descriptor;
+ }
+
+ private static final long serialVersionUID = 1L;
+ }
+
+ public void debugPrint() {
+ System.out.println("mlf in: " + logString);
+ System.out.println("mlf class: " + className);
+ System.out.println("mlf method: " + methodName);
+ System.out.println("mlf methodDescriptor: " + methodDescriptor);
+ }
+}