From ad51e6bdec4e24d10ddf832cbcfb66775d1d764a Mon Sep 17 00:00:00 2001 From: Erik Trimble Date: Thu, 13 Jan 2011 22:53:34 -0800 Subject: [PATCH 001/152] 7012348: Bump the HS20 build number to 07 Update the HS20 build number to 07 Reviewed-by: jcoomes --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 8fe599f75e4..0442c544cb6 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2011 HS_MAJOR_VER=20 HS_MINOR_VER=0 -HS_BUILD_NUMBER=06 +HS_BUILD_NUMBER=07 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 From 612faf72b7f0d47f9db03b7a3e24ce883be4f28c Mon Sep 17 00:00:00 2001 From: Yumin Qi Date: Thu, 7 Oct 2010 13:49:40 -0700 Subject: [PATCH 002/152] 6966589: hs16-b08 causes java.lang.StackOverflowError Reviewed-by: mchung, dholmes, chrisphi --- .../src/share/vm/classfile/classLoader.cpp | 58 +++++++ .../src/share/vm/classfile/classLoader.hpp | 146 ++++++------------ 2 files changed, 104 insertions(+), 100 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index 00231243233..593bc9177a9 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -1382,3 +1382,61 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { } #endif //PRODUCT + +// Please keep following two functions at end of this file. With them placed at top or in middle of the file, +// they could get inlined by agressive compiler, an unknown trick, see bug 6966589. +void PerfClassTraceTime::initialize() { + if (!UsePerfData) return; + + if (_eventp != NULL) { + // increment the event counter + _eventp->inc(); + } + + // stop the current active thread-local timer to measure inclusive time + _prev_active_event = -1; + for (int i=0; i < EVENT_TYPE_COUNT; i++) { + if (_timers[i].is_active()) { + assert(_prev_active_event == -1, "should have only one active timer"); + _prev_active_event = i; + _timers[i].stop(); + } + } + + if (_recursion_counters == NULL || (_recursion_counters[_event_type])++ == 0) { + // start the inclusive timer if not recursively called + _t.start(); + } + + // start thread-local timer of the given event type + if (!_timers[_event_type].is_active()) { + _timers[_event_type].start(); + } +} + +PerfClassTraceTime::~PerfClassTraceTime() { + if (!UsePerfData) return; + + // stop the thread-local timer as the event completes + // and resume the thread-local timer of the event next on the stack + _timers[_event_type].stop(); + jlong selftime = _timers[_event_type].ticks(); + + if (_prev_active_event >= 0) { + _timers[_prev_active_event].start(); + } + + if (_recursion_counters != NULL && --(_recursion_counters[_event_type]) > 0) return; + + // increment the counters only on the leaf call + _t.stop(); + _timep->inc(_t.ticks()); + if (_selftimep != NULL) { + _selftimep->inc(selftime); + } + // add all class loading related event selftime to the accumulated time counter + ClassLoader::perf_accumulated_time()->inc(selftime); + + // reset the timer + _timers[_event_type].reset(); +} diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp index 3c6b215f994..5073f882653 100644 --- a/hotspot/src/share/vm/classfile/classLoader.hpp +++ b/hotspot/src/share/vm/classfile/classLoader.hpp @@ -356,111 +356,57 @@ class ClassLoader: AllStatic { // (i.e. only one event type) are active at a time even multiple PerfClassTraceTime // instances have been created as multiple events are happening. class PerfClassTraceTime { - public: - enum { - CLASS_LOAD = 0, - PARSE_CLASS = 1, - CLASS_LINK = 2, - CLASS_VERIFY = 3, - CLASS_CLINIT = 4, - DEFINE_CLASS = 5, - EVENT_TYPE_COUNT = 6 - }; - protected: - // _t tracks time from initialization to destruction of this timer instance - // including time for all other event types, and recursive calls of this type. - // When a timer is called recursively, the elapsedTimer _t would not be used. - elapsedTimer _t; - PerfLongCounter* _timep; - PerfLongCounter* _selftimep; - PerfLongCounter* _eventp; - // pointer to thread-local recursion counter and timer array - // The thread_local timers track cumulative time for specific event types - // exclusive of time for other event types, but including recursive calls - // of the same type. - int* _recursion_counters; - elapsedTimer* _timers; - int _event_type; - int _prev_active_event; + public: + enum { + CLASS_LOAD = 0, + PARSE_CLASS = 1, + CLASS_LINK = 2, + CLASS_VERIFY = 3, + CLASS_CLINIT = 4, + DEFINE_CLASS = 5, + EVENT_TYPE_COUNT = 6 + }; + protected: + // _t tracks time from initialization to destruction of this timer instance + // including time for all other event types, and recursive calls of this type. + // When a timer is called recursively, the elapsedTimer _t would not be used. + elapsedTimer _t; + PerfLongCounter* _timep; + PerfLongCounter* _selftimep; + PerfLongCounter* _eventp; + // pointer to thread-local recursion counter and timer array + // The thread_local timers track cumulative time for specific event types + // exclusive of time for other event types, but including recursive calls + // of the same type. + int* _recursion_counters; + elapsedTimer* _timers; + int _event_type; + int _prev_active_event; - public: + public: - inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */ - PerfLongCounter* selftimep, /* counter incremented with exclusive time */ - PerfLongCounter* eventp, /* event counter */ - int* recursion_counters, /* thread-local recursion counter array */ - elapsedTimer* timers, /* thread-local timer array */ - int type /* event type */ ) : - _timep(timep), _selftimep(selftimep), _eventp(eventp), _recursion_counters(recursion_counters), _timers(timers), _event_type(type) { - initialize(); - } + inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */ + PerfLongCounter* selftimep, /* counter incremented with exclusive time */ + PerfLongCounter* eventp, /* event counter */ + int* recursion_counters, /* thread-local recursion counter array */ + elapsedTimer* timers, /* thread-local timer array */ + int type /* event type */ ) : + _timep(timep), _selftimep(selftimep), _eventp(eventp), _recursion_counters(recursion_counters), _timers(timers), _event_type(type) { + initialize(); + } - inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */ - elapsedTimer* timers, /* thread-local timer array */ - int type /* event type */ ) : - _timep(timep), _selftimep(NULL), _eventp(NULL), _recursion_counters(NULL), _timers(timers), _event_type(type) { - initialize(); - } + inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */ + elapsedTimer* timers, /* thread-local timer array */ + int type /* event type */ ) : + _timep(timep), _selftimep(NULL), _eventp(NULL), _recursion_counters(NULL), _timers(timers), _event_type(type) { + initialize(); + } - void initialize() { - if (!UsePerfData) return; + inline void suspend() { _t.stop(); _timers[_event_type].stop(); } + inline void resume() { _t.start(); _timers[_event_type].start(); } - if (_eventp != NULL) { - // increment the event counter - _eventp->inc(); - } - - // stop the current active thread-local timer to measure inclusive time - _prev_active_event = -1; - for (int i=0; i < EVENT_TYPE_COUNT; i++) { - if (_timers[i].is_active()) { - assert(_prev_active_event == -1, "should have only one active timer"); - _prev_active_event = i; - _timers[i].stop(); - } - } - - if (_recursion_counters == NULL || (_recursion_counters[_event_type])++ == 0) { - // start the inclusive timer if not recursively called - _t.start(); - } - - // start thread-local timer of the given event type - if (!_timers[_event_type].is_active()) { - _timers[_event_type].start(); - } - } - - inline void suspend() { _t.stop(); _timers[_event_type].stop(); } - inline void resume() { _t.start(); _timers[_event_type].start(); } - - ~PerfClassTraceTime() { - if (!UsePerfData) return; - - // stop the thread-local timer as the event completes - // and resume the thread-local timer of the event next on the stack - _timers[_event_type].stop(); - jlong selftime = _timers[_event_type].ticks(); - - if (_prev_active_event >= 0) { - _timers[_prev_active_event].start(); - } - - if (_recursion_counters != NULL && --(_recursion_counters[_event_type]) > 0) return; - - // increment the counters only on the leaf call - _t.stop(); - _timep->inc(_t.ticks()); - if (_selftimep != NULL) { - _selftimep->inc(selftime); - } - // add all class loading related event selftime to the accumulated time counter - ClassLoader::perf_accumulated_time()->inc(selftime); - - // reset the timer - _timers[_event_type].reset(); - } + ~PerfClassTraceTime(); + void initialize(); }; - #endif // SHARE_VM_CLASSFILE_CLASSLOADER_HPP From ab7cdfe74fbb14d1eed0712cb3df41276814157a Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Wed, 5 Jan 2011 14:28:58 -0800 Subject: [PATCH 003/152] 6975326: Problem in install/make/rebase/Makefile, grep on empty pattern 6413588: Add 'ldd -r' and 'dump -Lv' checks to all .so files delivered in the JDK 7000995: Add check in makefiles to verify that msvcp100.dll is NOT used Reviewed-by: mduigou --- jdk/make/com/sun/java/pack/Makefile | 1 + jdk/make/common/Demo.gmk | 1 + jdk/make/common/Library.gmk | 2 + jdk/make/common/Program.gmk | 2 + jdk/make/common/Release.gmk | 46 +++++++++++++-------- jdk/make/common/shared/Compiler-msvc.gmk | 5 ++- jdk/make/common/shared/Defs-linux.gmk | 17 ++++++++ jdk/make/common/shared/Defs-solaris.gmk | 17 ++++++++ jdk/make/common/shared/Defs-utils.gmk | 3 ++ jdk/make/common/shared/Defs-windows.gmk | 47 ++++++++++++++++++++++ jdk/make/common/shared/Sanity-Settings.gmk | 5 +++ jdk/make/common/shared/Sanity.gmk | 16 ++++++++ jdk/make/java/redist/Makefile | 12 ++++++ 13 files changed, 156 insertions(+), 18 deletions(-) diff --git a/jdk/make/com/sun/java/pack/Makefile b/jdk/make/com/sun/java/pack/Makefile index 6b5b0bfc241..e7fe8d44b76 100644 --- a/jdk/make/com/sun/java/pack/Makefile +++ b/jdk/make/com/sun/java/pack/Makefile @@ -155,6 +155,7 @@ ifdef MT $(MT) /manifest $(OBJDIR)/unpack200$(EXE_SUFFIX).manifest /outputresource:$(TEMPDIR)/unpack200$(EXE_SUFFIX);#1 endif $(CP) $(TEMPDIR)/unpack200$(EXE_SUFFIX) $(UNPACK_EXE) + @$(call binary_file_verification,$@) $(install-module-file) ifeq ($(PLATFORM), windows) diff --git a/jdk/make/common/Demo.gmk b/jdk/make/common/Demo.gmk index 0ba5bc19707..3824598d700 100644 --- a/jdk/make/common/Demo.gmk +++ b/jdk/make/common/Demo.gmk @@ -289,6 +289,7 @@ $(DEMO_LIBRARY): $(DEMO_FULL_OBJECTS) @$(prep-target) $(LINK.demo) $(SHARED_LIBRARY_FLAG) $(CC_PROGRAM_OUTPUT_FLAG)$@ \ $(DEMO_FULL_OBJECTS) $(LDLIBS.demo) + @$(call binary_file_verification,$@) # Generation of any javah include file, make sure objects are dependent on it ifdef DEMO_NATIVECLASS diff --git a/jdk/make/common/Library.gmk b/jdk/make/common/Library.gmk index 71758275689..4ed368b415d 100644 --- a/jdk/make/common/Library.gmk +++ b/jdk/make/common/Library.gmk @@ -173,6 +173,7 @@ ifdef MT $(MT) /manifest $(OBJDIR)/$(@F).manifest /outputresource:$(OBJDIR)/$(@F);#2 endif $(CP) $(OBJDIR)/$(@F) $@ + @$(call binary_file_verification,$@) $(install-module-file) $(CP) $(OBJDIR)/$(LIBRARY).map $(@D) $(CP) $(OBJDIR)/$(LIBRARY).pdb $(@D) @@ -239,6 +240,7 @@ ifeq ($(LIBRARY), fdlibm) $(AR) -r $@ $(FILES_o) else # LIBRARY $(LINKER) $(SHARED_LIBRARY_FLAG) -o $@ $(FILES_o) $(LDLIBS) + @$(call binary_file_verification,$@) $(install-module-file) ifeq ($(WRITE_LIBVERSION),true) $(MCS) -d -a "$(FULL_VERSION)" $@ diff --git a/jdk/make/common/Program.gmk b/jdk/make/common/Program.gmk index 005236149d6..77a04430763 100644 --- a/jdk/make/common/Program.gmk +++ b/jdk/make/common/Program.gmk @@ -155,6 +155,7 @@ $(OBJDIR)/$(PROGRAM)$(EXE_SUFFIX):: $(OBJDIR)/$(PROGRAM).lcf $(FILES_o) $(JLI_LC ifdef MT $(MT) /manifest $(OBJDIR)/$(PROGRAM).exe.manifest /outputresource:$@;#1 endif + @$(call binary_file_verification,$@) else # PLATFORM @@ -179,6 +180,7 @@ $(ACTUAL_PROGRAM):: $(FILES_o) @$(MKDIR) -p $(TEMPDIR) $(LINK_PRE_CMD) $(CC) $(CC_OBJECT_OUTPUT_FLAG)$@ $(LDFLAGS) \ $(FILES_o) $(THREADLIBS) $(LDLIBS) + @$(call binary_file_verification,$@) $(install-module-file) endif # PLATFORM diff --git a/jdk/make/common/Release.gmk b/jdk/make/common/Release.gmk index 834d3379875..9d83ae748b1 100644 --- a/jdk/make/common/Release.gmk +++ b/jdk/make/common/Release.gmk @@ -836,11 +836,14 @@ else # PLATFORM endif endif # PLATFORM -# Get list of all Elf files in the jre -JRE_ELF_LIST=$(TEMPDIR)/jre-elf-files.list -$(JRE_ELF_LIST): -ifneq ($(PLATFORM), windows) +# Get list of all binary (COFF or Elf) files in the jre +JRE_BIN_LIST=$(TEMPDIR)/jre-bin-files.list +$(JRE_BIN_LIST): $(RM) $@ +ifeq ($(PLATFORM), windows) + $(FIND) $(JRE_IMAGE_DIR)/bin -type f -name \*.exe \ + -o -name \*.dll | $(EGREP) -v -i "$(MSVCRNN_DLL)" > $@ +else $(FIND) $(JRE_IMAGE_DIR)/lib -type f -name \*.$(LIB_SUFFIX) >> $@ $(FILE) `$(FIND) $(JRE_IMAGE_DIR)/bin -type f -name \*$(EXE_SUFFIX)` \ | $(EGREP) 'ELF' | $(CUT) -d':' -f1 >> $@ @@ -848,9 +851,9 @@ endif # Post process the image (strips and mcs on Elf files we are shipping) # (Note the jdk WILL want the jre image before this processing) -process-image-jre:: $(JRE_ELF_LIST) +process-image-jre:: $(JRE_BIN_LIST) ifneq ($(POST_STRIP_PROCESS), ) - for f in `$(CAT) $(JRE_ELF_LIST)`; do \ + @for f in `$(CAT) $(JRE_BIN_LIST)`; do \ $(CHMOD) u+w $${f}; \ $(ECHO) $(POST_STRIP_PROCESS) $${f}; \ $(POST_STRIP_PROCESS) $${f}; \ @@ -858,14 +861,17 @@ ifneq ($(POST_STRIP_PROCESS), ) done endif ifneq ($(POST_MCS_PROCESS), ) - for f in `$(CAT) $(JRE_ELF_LIST)`; do \ + @for f in `$(CAT) $(JRE_BIN_LIST)`; do \ $(CHMOD) u+w $${f}; \ $(ECHO) $(POST_MCS_PROCESS) $${f}; \ $(POST_MCS_PROCESS) $${f}; \ $(CHMOD) go-w $${f}; \ done endif - $(RM) $(JRE_ELF_LIST) + @for f in `$(CAT) $(JRE_BIN_LIST)`; do \ + $(call binary_file_verification,$${f}); \ + done + $(RM) $(JRE_BIN_LIST) ###################################################### # JDK Image @@ -1093,10 +1099,15 @@ trim-image-jdk:: $(JDK_IMAGE_DIR)/bin/*/native_threads/$${t}$(EXE_SUFFIX); \ done -# Get list of Elf files in the jdk -JDK_ELF_LIST=$(TEMPDIR)/jdk-elf-files.list -$(JDK_ELF_LIST): -ifneq ($(PLATFORM), windows) +# Get list of binary (COFF or Elf) files in the jdk +JDK_BIN_LIST=$(TEMPDIR)/jdk-bin-files.list +$(JDK_BIN_LIST): +ifeq ($(PLATFORM), windows) + $(FIND) $(JDK_IMAGE_DIR)/jre/bin -type f -name \*.exe \ + -o -name \*.dll | $(EGREP) -v -i "$(MSVCRNN_DLL)" > $@ + $(FIND) $(JDK_IMAGE_DIR)/bin -type f -name \*.exe \ + -o -name \*.dll | $(EGREP) -v -i "$(MSVCRNN_DLL)" >> $@ +else $(RM) $@ $(FIND) $(JDK_IMAGE_DIR)/jre/lib -type f -name \*.$(LIB_SUFFIX) >> $@ $(FILE) `$(FIND) $(JDK_IMAGE_DIR)/jre/bin -type f -name \*$(EXE_SUFFIX)` \ @@ -1106,9 +1117,9 @@ ifneq ($(PLATFORM), windows) endif # Post process the image (strips and mcs on files we are shipping) -process-image-jdk:: $(JDK_ELF_LIST) +process-image-jdk:: $(JDK_BIN_LIST) ifneq ($(POST_STRIP_PROCESS), ) - for f in `$(CAT) $(JDK_ELF_LIST)`; do \ + @for f in `$(CAT) $(JDK_BIN_LIST)`; do \ $(CHMOD) u+w $${f}; \ $(ECHO) $(POST_STRIP_PROCESS) $${f}; \ $(POST_STRIP_PROCESS) $${f}; \ @@ -1116,14 +1127,17 @@ ifneq ($(POST_STRIP_PROCESS), ) done endif ifneq ($(POST_MCS_PROCESS), ) - for f in `$(CAT) $(JDK_ELF_LIST)`; do \ + @for f in `$(CAT) $(JDK_BIN_LIST)`; do \ $(CHMOD) u+w $${f}; \ $(ECHO) $(POST_MCS_PROCESS) $${f}; \ $(POST_MCS_PROCESS) $${f}; \ $(CHMOD) go-w $${f}; \ done endif - $(RM) $(JDK_ELF_LIST) + @for f in `$(CAT) $(JDK_BIN_LIST)`; do \ + $(call binary_file_verification,$${f}); \ + done + $(RM) $(JDK_BIN_LIST) ################################################################### # What do we compare against diff --git a/jdk/make/common/shared/Compiler-msvc.gmk b/jdk/make/common/shared/Compiler-msvc.gmk index 49a0d5fe63c..1b6d38d5f7f 100644 --- a/jdk/make/common/shared/Compiler-msvc.gmk +++ b/jdk/make/common/shared/Compiler-msvc.gmk @@ -35,6 +35,7 @@ ifeq ($(PLATFORM), windows) LIBEXE = $(COMPILER_PATH)lib LINK = $(COMPILER_PATH)link LINK32 = $(LINK) + DUMPBIN = $(COMPILER_PATH)dumpbin.exe # Fill in unknown values COMPILER_NAME=Unknown MSVC Compiler @@ -139,8 +140,8 @@ ifeq ($(PLATFORM), windows) _OTHER_TOOLS_BIN = $(WINDOWSSDKDIR)/Bin/x64 endif endif - RC = $(_OTHER_TOOLS_BIN)/rc.exe - REBASE = $(_OTHER_TOOLS_BIN)/rebase.exe + RC = $(_OTHER_TOOLS_BIN)/RC.Exe + REBASE = $(_OTHER_TOOLS_BIN)/ReBase.Exe MT = $(_OTHER_TOOLS_BIN)/mt.exe MTL = $(_OTHER_TOOLS_BIN)/midl.exe endif diff --git a/jdk/make/common/shared/Defs-linux.gmk b/jdk/make/common/shared/Defs-linux.gmk index a6be5365021..db1307056d1 100644 --- a/jdk/make/common/shared/Defs-linux.gmk +++ b/jdk/make/common/shared/Defs-linux.gmk @@ -177,3 +177,20 @@ else endif HOTSPOT_SERVER_PATH:=$(call AltCheckValue,HOTSPOT_SERVER_PATH) +# Special define for checking the binaries + +# Macro to check it's input file for banned dependencies and verify the +# binary built properly. Relies on process exit code. +define binary_file_verification # binary_file +( \ + $(ECHO) "Checking for mapfile use in: $1" && \ + if [ "`$(NM) -D -g --defined-only $1 | $(EGREP) 'SUNWprivate'`" = "" ] ; then \ + $(ECHO) "WARNING: File was not built with a mapfile: $1"; \ + fi && \ + $(ECHO) "Library loads for: $1" && \ + $(LDD) $1 && \ + $(ECHO) "RUNPATH for: $1" && \ + ( $(READELF) -d $1 | $(EGREP) 'NEEDED|RUNPATH|RPATH' ) \ +) +endef + diff --git a/jdk/make/common/shared/Defs-solaris.gmk b/jdk/make/common/shared/Defs-solaris.gmk index 98b054ef3d4..177af974855 100644 --- a/jdk/make/common/shared/Defs-solaris.gmk +++ b/jdk/make/common/shared/Defs-solaris.gmk @@ -186,3 +186,20 @@ else endif HOTSPOT_SERVER_PATH:=$(call AltCheckValue,HOTSPOT_SERVER_PATH) +# Special define for checking the binaries + +# Macro to check it's input file for banned dependencies and verify the +# binary built properly. Relies on process exit code. +define binary_file_verification # binary_file +( \ + $(ECHO) "Checking for mapfile use in: $1" && \ + if [ "`$(NM) -g -D $1 | $(EGREP) -v 'UNDEF' | $(EGREP) 'SUNWprivate'`" = "" ] ; then \ + $(ECHO) "WARNING: File was not built with a mapfile: $1"; \ + fi && \ + $(ECHO) "Library loads for: $1" && \ + $(LDD) $1 && \ + $(ECHO) "RUNPATH for: $1" && \ + ( $(DUMP) -L -v $1 | $(EGREP) 'NEEDED|RUNPATH|RPATH' ) \ +) +endef + diff --git a/jdk/make/common/shared/Defs-utils.gmk b/jdk/make/common/shared/Defs-utils.gmk index 01bb982466f..bb6aa493cf5 100644 --- a/jdk/make/common/shared/Defs-utils.gmk +++ b/jdk/make/common/shared/Defs-utils.gmk @@ -85,6 +85,7 @@ DATE = $(UTILS_COMMAND_PATH)date DF = $(UTILS_COMMAND_PATH)df DIFF = $(UTILS_USR_BIN_PATH)diff DIRNAME = $(UTILS_USR_BIN_PATH)dirname +DUMP = $(UTILS_CCS_BIN_PATH)dump ECHO = $(UTILS_COMMAND_PATH)echo EGREP = $(UTILS_COMMAND_PATH)egrep EXPR = $(UTILS_USR_BIN_PATH)expr @@ -99,6 +100,7 @@ ID = $(UTILS_COMMAND_PATH)id ISAINFO = $(UTILS_COMMAND_PATH)isainfo KSH = $(UTILS_COMMAND_PATH)ksh LD = $(UTILS_CCS_BIN_PATH)ld +LDD = $(UTILS_USR_BIN_PATH)ldd LEX = $(UTILS_CCS_BIN_PATH)lex LN = $(UTILS_COMMAND_PATH)ln LS = $(UTILS_COMMAND_PATH)ls @@ -114,6 +116,7 @@ PKGMK = $(UTILS_COMMAND_PATH)pkgmk PRINTF = $(UTILS_USR_BIN_PATH)printf PWD = $(UTILS_COMMAND_PATH)pwd RC = $(UTILS_COMMAND_PATH)rc +READELF = $(UTILS_USR_BIN_PATH)readelf RMDIR = $(UTILS_COMMAND_PATH)rmdir RPM = $(UTILS_COMMAND_PATH)rpm RPMBUILD = $(UTILS_COMMAND_PATH)rpmbuild diff --git a/jdk/make/common/shared/Defs-windows.gmk b/jdk/make/common/shared/Defs-windows.gmk index 6a6fbffd39a..95a47c206f9 100644 --- a/jdk/make/common/shared/Defs-windows.gmk +++ b/jdk/make/common/shared/Defs-windows.gmk @@ -798,3 +798,50 @@ else endif HOTSPOT_LIB_PATH:=$(call AltCheckSpaces,HOTSPOT_LIB_PATH) HOTSPOT_LIB_PATH:=$(call AltCheckValue,HOTSPOT_LIB_PATH) + +# Special define for checking the binaries + +ifeq ($(VS2010_EXISTS),true) + +# All windows dll and exe files should have been built with /NXCOMPAT +# and be setup for dynamic base addresses. +# In addition, we should not be dependent on certain dll files that +# we do not or cannot redistribute. + +# List of filenames we should NOT be dependent on +BANNED_DLLS=msvcp100[.]dll|msvcr100d[.]dll|msvcrtd[.]dll + +# Macro to check it's input file for banned dependencies and verify the +# binary was built properly. Relies on process exit code. +define binary_file_verification # binary_file +( \ + $(ECHO) "Checking for /NXCOMPAT usage in: $1" && \ + if [ "`$(DUMPBIN) /headers $1 | $(EGREP) -i 'NX compatible'`" = "" ] ; then \ + $(ECHO) "ERROR: Did not find 'NX compatible' in headers: $1" ; \ + $(DUMPBIN) /headers $1 ; \ + exit 7 ; \ + fi ; \ + $(ECHO) "Checking for /DYNAMICBASE usage in: $1" && \ + if [ "`$(DUMPBIN) /headers $1 | $(EGREP) -i 'Dynamic base'`" = "" ] ; then \ + $(ECHO) "ERROR: Did not find 'Dynamic base' in headers: $1" ; \ + $(DUMPBIN) /headers $1 ; \ + exit 8 ; \ + fi ; \ + $(ECHO) "Checking for banned dependencies in: $1" && \ + if [ "`$(DUMPBIN) /dependents $1 | $(EGREP) -i '$(BANNED_DLLS)'`" != "" ] ; then \ + $(ECHO) "ERROR: Found us of $(BANNED_DLLS)"; \ + $(DUMPBIN) /dependents $1 ; \ + exit 9 ; \ + fi ; \ +) +endef + +else + +# Macro to check it's input file for banned dependencies and verify the +# binary was built properly. Relies on process exit code. +define binary_file_verification # binary_file +endef + +endif + diff --git a/jdk/make/common/shared/Sanity-Settings.gmk b/jdk/make/common/shared/Sanity-Settings.gmk index 7e77e11aeb0..b4c86705eae 100644 --- a/jdk/make/common/shared/Sanity-Settings.gmk +++ b/jdk/make/common/shared/Sanity-Settings.gmk @@ -117,6 +117,9 @@ ALL_SETTINGS+=$(call addRequiredVersionSetting,ZIP_VER) ALL_SETTINGS+=$(call addRequiredVersionSetting,UNZIP_VER) ifeq ($(PLATFORM),windows) ALL_SETTINGS+=$(call addRequiredVersionSetting,LINK_VER) + ALL_SETTINGS+=$(call addRequiredSetting,CC) + ALL_SETTINGS+=$(call addRequiredSetting,LINK) + ALL_SETTINGS+=$(call addRequiredSetting,DUMPBIN) endif ALL_SETTINGS+=$(call addRequiredVersionSetting,ANT_VER) ALL_SETTINGS+=$(call addRequiredSetting,TEMPDIR) @@ -226,6 +229,8 @@ ifeq ($(PLATFORM),windows) ALL_SETTINGS+=$(call addAltSetting,DXSDK_INCLUDE_PATH) ALL_SETTINGS+=$(call addAltSetting,DXSDK_LIB_PATH) ALL_SETTINGS+=$(call addAltSetting,WINDOWSSDKDIR) + ALL_SETTINGS+=$(call addRequiredSetting,RC) + ALL_SETTINGS+=$(call addRequiredSetting,REBASE) ifndef OPENJDK ALL_SETTINGS+=$(call addAltSetting,DEPLOY_MSSDK) ALL_SETTINGS+=$(call addAltSetting,INSTALL_MSSDK) diff --git a/jdk/make/common/shared/Sanity.gmk b/jdk/make/common/shared/Sanity.gmk index b17690ca4c2..2ea23e2e1fd 100644 --- a/jdk/make/common/shared/Sanity.gmk +++ b/jdk/make/common/shared/Sanity.gmk @@ -1018,6 +1018,22 @@ ifeq ($(PLATFORM), windows) " and/or check your value of ALT_MSDEVTOOLS_PATH. \n" \ "" >> $(ERROR_FILE) ; \ fi + else + ifeq ($(wildcard $(REBASE)),) + @$(ECHO) "ERROR: Cannot find the REBASE utility from path: $(REBASE)\n" \ + " This is normally obtained from the WINDOWSSDKDIR." \ + "" >> $(ERROR_FILE) + endif + ifeq ($(wildcard $(RC)),) + @$(ECHO) "ERROR: Cannot find the RC utility from path: $(RC)\n" \ + " This is normally obtained from the WINDOWSSDKDIR." \ + "" >> $(ERROR_FILE) + endif + ifeq ($(wildcard $(DUMPBIN)),) + @$(ECHO) "ERROR: Cannot find the DUMPBIN utility from path: $(DUMPBIN)\n" \ + " This is normally obtained from the WINDOWSSDKDIR." \ + "" >> $(ERROR_FILE) + endif endif endif diff --git a/jdk/make/java/redist/Makefile b/jdk/make/java/redist/Makefile index 9f4d420aa42..05cbb872de4 100644 --- a/jdk/make/java/redist/Makefile +++ b/jdk/make/java/redist/Makefile @@ -223,12 +223,15 @@ endif # PLATFORM $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVM_NAME): $(HOTSPOT_CLIENT_PATH)/$(JVM_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(KERNEL_LOCATION)/$(JVM_NAME): $(HOTSPOT_KERNEL_PATH)/$(JVM_NAME) $(install-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(LIBJSIG_NAME): $(HOTSPOT_IMPORT_PATH)/$(ARCH_VM_SUBDIR)/$(LIBJSIG_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(LIBJSIG_NAME) \ $(LIB_LOCATION)/$(SERVER_LOCATION)/$(LIBJSIG_NAME): @@ -237,30 +240,39 @@ $(LIB_LOCATION)/$(SERVER_LOCATION)/$(LIBJSIG_NAME): $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVMDB_NAME): $(HOTSPOT_CLIENT_PATH)/$(JVMDB_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(CLIENT_LOCATION)/64/$(JVMDB_NAME): $(HOTSPOT_CLIENT_PATH)/64/$(JVMDB_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMDB_NAME): $(HOTSPOT_SERVER_PATH)/$(JVMDB_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(SERVER_LOCATION)/64/$(JVMDB_NAME): $(HOTSPOT_SERVER_PATH)/64/$(JVMDB_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVMDTRACE_NAME): $(HOTSPOT_CLIENT_PATH)/$(JVMDTRACE_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(CLIENT_LOCATION)/64/$(JVMDTRACE_NAME): $(HOTSPOT_CLIENT_PATH)/64/$(JVMDTRACE_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMDTRACE_NAME): $(HOTSPOT_SERVER_PATH)/$(JVMDTRACE_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(SERVER_LOCATION)/64/$(JVMDTRACE_NAME): $(HOTSPOT_SERVER_PATH)/64/$(JVMDTRACE_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVM_NAME): $(HOTSPOT_SERVER_PATH)/$(JVM_NAME) $(install-import-file) + @$(call binary_file_verification,$@) $(LIB_LOCATION)/$(SERVER_LOCATION)/Xusage.txt : $(HOTSPOT_SERVER_PATH)/Xusage.txt $(install-import-file) From 88990fd1b006c1b381ac626ef3cefb4d7f11a324 Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Wed, 5 Jan 2011 17:24:58 -0800 Subject: [PATCH 004/152] 7009969: Remove SKIP_OPENJDK_BUILD from top Makefile Reviewed-by: robilad --- Makefile | 90 +----------------------------------------- make/Defs-internal.gmk | 13 +----- 2 files changed, 2 insertions(+), 101 deletions(-) diff --git a/Makefile b/Makefile index 7c5b2db01c0..9bbf467e236 100644 --- a/Makefile +++ b/Makefile @@ -29,15 +29,6 @@ ifndef TOPDIR TOPDIR:=. endif -# Openjdk sources (only used if SKIP_OPENJDK_BUILD!=true) -OPENJDK_SOURCETREE=$(TOPDIR)/openjdk -OPENJDK_BUILDDIR:=$(shell \ - if [ -r $(OPENJDK_SOURCETREE)/Makefile ]; then \ - echo "$(OPENJDK_SOURCETREE)"; \ - else \ - echo "."; \ - fi) - ifndef JDK_TOPDIR JDK_TOPDIR=$(TOPDIR)/jdk endif @@ -70,7 +61,7 @@ include ./make/deploy-rules.gmk all:: @$(START_ECHO) -all:: openjdk_check sanity +all:: sanity ifeq ($(SKIP_FASTDEBUG_BUILD), false) all:: fastdebug_build @@ -80,10 +71,6 @@ ifeq ($(SKIP_DEBUG_BUILD), false) all:: debug_build endif -ifneq ($(SKIP_OPENJDK_BUILD), true) - all:: openjdk_build -endif - all:: all_product_build all:: @@ -267,81 +254,6 @@ product_build:: build_product_image debug_build:: build_debug_image fastdebug_build:: build_fastdebug_image -# Check on whether we really can build the openjdk, need source etc. -openjdk_check: FRC -ifneq ($(SKIP_OPENJDK_BUILD), true) - @$(ECHO) " " - @$(ECHO) "=================================================" - @if [ ! -r $(OPENJDK_BUILDDIR)/Makefile ] ; then \ - $(ECHO) "ERROR: No openjdk source tree available at: $(OPENJDK_BUILDDIR)"; \ - exit 1; \ - else \ - $(ECHO) "OpenJDK will be built after JDK is built"; \ - $(ECHO) " OPENJDK_BUILDDIR=$(OPENJDK_BUILDDIR)"; \ - fi - @$(ECHO) "=================================================" - @$(ECHO) " " -endif - -# If we have bundle rules, we have a chance here to do a complete cycle -# build, of production and open build. -# FIXUP: We should create the openjdk source bundle and build that? -# But how do we reliable create or get at a formal openjdk source tree? -# The one we have needs to be trimmed of built bits and closed dirs. -# The repositories might not be available. -# The openjdk source bundle is probably not available. - -ifneq ($(SKIP_OPENJDK_BUILD), true) - ifeq ($(BUILD_JDK), true) - ifeq ($(BUNDLE_RULES_AVAILABLE), true) - -OPENJDK_OUTPUTDIR=$(ABS_OUTPUTDIR)/open-output -OPENJDK_BUILD_NAME \ - = openjdk-$(JDK_MINOR_VERSION)-$(BUILD_NUMBER)-$(PLATFORM)-$(ARCH)-$(BUNDLE_DATE) -OPENJDK_BUILD_BINARY_ZIP=$(ABS_BIN_BUNDLEDIR)/$(OPENJDK_BUILD_NAME).zip -BUILT_IMAGE=$(ABS_OUTPUTDIR)/j2sdk-image -ifeq ($(PLATFORM)$(ARCH_DATA_MODEL),solaris64) - OPENJDK_BOOTDIR=$(BOOTDIR) - OPENJDK_IMPORTJDK=$(JDK_IMPORT_PATH) -else - OPENJDK_BOOTDIR=$(BUILT_IMAGE) - OPENJDK_IMPORTJDK=$(BUILT_IMAGE) -endif - -openjdk_build: - @$(START_ECHO) - @$(ECHO) " " - @$(ECHO) "=================================================" - @$(ECHO) "Starting openjdk build" - @$(ECHO) " Using: ALT_JDK_DEVTOOLS_DIR=$(JDK_DEVTOOLS_DIR)" - @$(ECHO) "=================================================" - @$(ECHO) " " - $(RM) -r $(OPENJDK_OUTPUTDIR) - $(MKDIR) -p $(OPENJDK_OUTPUTDIR) - ($(CD) $(OPENJDK_BUILDDIR) && $(MAKE) \ - OPENJDK=true \ - GENERATE_DOCS=false \ - ALT_JDK_DEVTOOLS_DIR=$(JDK_DEVTOOLS_DIR) \ - ALT_OUTPUTDIR=$(OPENJDK_OUTPUTDIR) \ - ALT_BOOTDIR=$(OPENJDK_BOOTDIR) \ - ALT_JDK_IMPORT_PATH=$(OPENJDK_IMPORTJDK) \ - product_build ) - $(RM) $(OPENJDK_BUILD_BINARY_ZIP) - ( $(CD) $(OPENJDK_OUTPUTDIR)/j2sdk-image && \ - $(ZIPEXE) -q -r $(OPENJDK_BUILD_BINARY_ZIP) .) - $(RM) -r $(OPENJDK_OUTPUTDIR) - @$(ECHO) " " - @$(ECHO) "=================================================" - @$(ECHO) "Finished openjdk build" - @$(ECHO) " Binary Bundle: $(OPENJDK_BUILD_BINARY_ZIP)" - @$(ECHO) "=================================================" - @$(ECHO) " " - @$(FINISH_ECHO) - - endif - endif -endif - clobber:: $(RM) -r $(OUTPUTDIR)/* $(RM) -r $(OUTPUTDIR)/../$(PLATFORM)-$(ARCH)-debug/* diff --git a/make/Defs-internal.gmk b/make/Defs-internal.gmk index 907ee95ac1e..fe8403fe428 100644 --- a/make/Defs-internal.gmk +++ b/make/Defs-internal.gmk @@ -147,7 +147,7 @@ ifndef BUILD_SPONSORS endif -# Do we build the source and openjdk binary plug bundles? +# Do we build the source bundles? BUNDLE_RULES = $(JDK_TOPDIR)/make/closed/bundles.gmk ifeq ($(SKIP_BUNDLES_BUILD), true) BUNDLE_RULES_AVAILABLE := false @@ -171,7 +171,6 @@ ifdef OPENJDK ifndef SKIP_COMPARE_IMAGES SKIP_COMPARE_IMAGES = true endif - SKIP_OPENJDK_BUILD = true else # Various non-OPENJDK reasons to NOT build the deploy repository @@ -187,21 +186,11 @@ else endif endif - ifndef SKIP_OPENJDK_BUILD - #SKIP_OPENJDK_BUILD = false - # Until 6675289 is resolved, or this feature is removed. - SKIP_OPENJDK_BUILD = true - endif endif ifndef SKIP_PRODUCT_BUILD SKIP_PRODUCT_BUILD = false endif -# Solaris 64 bit builds are not complete enough to ever do this -ifeq ($(PLATFORM)$(ARCH_DATA_MODEL),solaris64) - SKIP_OPENJDK_BUILD = true -endif - # Many reasons why we would want to skip the comparison to previous jdk ifndef SKIP_COMPARE_IMAGES ifeq ($(BUILD_JDK), false) From c6f34365c25dd65c2a893c79c33b4adbafd68ce4 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Thu, 6 Jan 2011 16:03:20 -0800 Subject: [PATCH 005/152] 7010618: C1: array length should be treated at int on 64bit during array allocation Sign-extend the length argument during array allocation Reviewed-by: never, kvn --- hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp | 4 +++- hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 15ca82f28fe..109f7869220 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, 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 @@ -2358,6 +2358,8 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { op->tmp3()->as_register() == G4 && op->tmp4()->as_register() == O1 && op->klass()->as_register() == G5, "must be"); + + LP64_ONLY( __ signx(op->len()->as_register()); ) if (UseSlowPath || (!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) || (!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) { diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index f3ba0a2ce02..2a65de51e5b 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, 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 @@ -1641,12 +1641,14 @@ void LIR_Assembler::emit_alloc_obj(LIR_OpAllocObj* op) { } void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { + Register len = op->len()->as_register(); + LP64_ONLY( __ movslq(len, len); ) + if (UseSlowPath || (!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) || (!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) { __ jmp(*op->stub()->entry()); } else { - Register len = op->len()->as_register(); Register tmp1 = op->tmp1()->as_register(); Register tmp2 = op->tmp2()->as_register(); Register tmp3 = op->tmp3()->as_register(); From d921d72f2093ace6a16898edd28b07fe9ee366df Mon Sep 17 00:00:00 2001 From: "Y. Srinivas Ramakrishna" Date: Thu, 6 Jan 2011 23:50:02 -0800 Subject: [PATCH 006/152] 7008136: CMS: assert((HeapWord*)nextChunk <= _limit) failed: sweep invariant The recorded _sweep_limit may not necessarily remain a block boundary as the old generation expands during a concurrent cycle. Terminal actions inside the sweep closure need to be aware of this as they cross over the limit. Reviewed-by: johnc, minqi --- .../concurrentMarkSweepGeneration.cpp | 130 ++++++++---------- .../concurrentMarkSweepGeneration.hpp | 15 +- 2 files changed, 68 insertions(+), 77 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 36a070a1826..9741b55f45b 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -7881,25 +7881,23 @@ SweepClosure::SweepClosure(CMSCollector* collector, } // We need this destructor to reclaim any space at the end -// of the space, which do_blk below may not have added back to -// the free lists. [basically dealing with the "fringe effect"] +// of the space, which do_blk below may not yet have added back to +// the free lists. SweepClosure::~SweepClosure() { assert_lock_strong(_freelistLock); - // this should be treated as the end of a free run if any - // The current free range should be returned to the free lists - // as one coalesced chunk. + assert(_limit >= _sp->bottom() && _limit <= _sp->end(), + "sweep _limit out of bounds"); + // Flush any remaining coterminal free run as a single + // coalesced chunk to the appropriate free list. if (inFreeRange()) { - flushCurFreeChunk(freeFinger(), - pointer_delta(_limit, freeFinger())); - assert(freeFinger() < _limit, "the finger pointeth off base"); + assert(freeFinger() < _limit, "freeFinger points too high"); + flush_cur_free_chunk(freeFinger(), pointer_delta(_limit, freeFinger())); if (CMSTraceSweeper) { - gclog_or_tty->print("destructor:"); - gclog_or_tty->print("Sweep:put_free_blk 0x%x ("SIZE_FORMAT") " - "[coalesced:"SIZE_FORMAT"]\n", - freeFinger(), pointer_delta(_limit, freeFinger()), - lastFreeRangeCoalesced()); + gclog_or_tty->print("Sweep: last chunk: "); + gclog_or_tty->print("put_free_blk 0x%x ("SIZE_FORMAT") [coalesced:"SIZE_FORMAT"]\n", + freeFinger(), pointer_delta(_limit, freeFinger()), lastFreeRangeCoalesced()); } - } + } // else nothing to flush NOT_PRODUCT( if (Verbose && PrintGC) { gclog_or_tty->print("Collected "SIZE_FORMAT" objects, " @@ -7936,9 +7934,8 @@ SweepClosure::~SweepClosure() { void SweepClosure::initialize_free_range(HeapWord* freeFinger, bool freeRangeInFreeLists) { if (CMSTraceSweeper) { - gclog_or_tty->print("---- Start free range 0x%x with free block [%d] (%d)\n", - freeFinger, _sp->block_size(freeFinger), - freeRangeInFreeLists); + gclog_or_tty->print("---- Start free range at 0x%x with free block (%d)\n", + freeFinger, freeRangeInFreeLists); } assert(!inFreeRange(), "Trampling existing free range"); set_inFreeRange(true); @@ -7993,21 +7990,36 @@ size_t SweepClosure::do_blk_careful(HeapWord* addr) { // may have caused us to coalesce the block ending at the address _limit // with a newly expanded chunk (this happens when _limit was set to the // previous _end of the space), so we may have stepped past _limit; see CR 6977970. - if (addr >= _limit) { // we have swept up to or past the limit, do nothing more + if (addr >= _limit) { // we have swept up to or past the limit: finish up assert(_limit >= _sp->bottom() && _limit <= _sp->end(), "sweep _limit out of bounds"); assert(addr < _sp->end(), "addr out of bounds"); - // help the closure application finish + // Flush any remaining coterminal free run as a single + // coalesced chunk to the appropriate free list. + if (inFreeRange()) { + assert(freeFinger() < _limit, "finger points too high"); + flush_cur_free_chunk(freeFinger(), + pointer_delta(addr, freeFinger())); + if (CMSTraceSweeper) { + gclog_or_tty->print("Sweep: last chunk: "); + gclog_or_tty->print("put_free_blk 0x%x ("SIZE_FORMAT") " + "[coalesced:"SIZE_FORMAT"]\n", + freeFinger(), pointer_delta(addr, freeFinger()), + lastFreeRangeCoalesced()); + } + } + + // help the iterator loop finish return pointer_delta(_sp->end(), addr); } - assert(addr < _limit, "sweep invariant"); + assert(addr < _limit, "sweep invariant"); // check if we should yield do_yield_check(addr); if (fc->isFree()) { // Chunk that is already free res = fc->size(); - doAlreadyFreeChunk(fc); + do_already_free_chunk(fc); debug_only(_sp->verifyFreeLists()); assert(res == fc->size(), "Don't expect the size to change"); NOT_PRODUCT( @@ -8017,7 +8029,7 @@ size_t SweepClosure::do_blk_careful(HeapWord* addr) { NOT_PRODUCT(_last_fc = fc;) } else if (!_bitMap->isMarked(addr)) { // Chunk is fresh garbage - res = doGarbageChunk(fc); + res = do_garbage_chunk(fc); debug_only(_sp->verifyFreeLists()); NOT_PRODUCT( _numObjectsFreed++; @@ -8025,7 +8037,7 @@ size_t SweepClosure::do_blk_careful(HeapWord* addr) { ) } else { // Chunk that is alive. - res = doLiveChunk(fc); + res = do_live_chunk(fc); debug_only(_sp->verifyFreeLists()); NOT_PRODUCT( _numObjectsLive++; @@ -8078,7 +8090,7 @@ size_t SweepClosure::do_blk_careful(HeapWord* addr) { // to a free list which may be overpopulated. // -void SweepClosure::doAlreadyFreeChunk(FreeChunk* fc) { +void SweepClosure::do_already_free_chunk(FreeChunk* fc) { size_t size = fc->size(); // Chunks that cannot be coalesced are not in the // free lists. @@ -8094,22 +8106,20 @@ void SweepClosure::doAlreadyFreeChunk(FreeChunk* fc) { // addr and purported end of this block. _bitMap->verifyNoOneBitsInRange(addr + 1, addr + size); - // Some chunks cannot be coalesced in under any circumstances. + // Some chunks cannot be coalesced under any circumstances. // See the definition of cantCoalesce(). if (!fc->cantCoalesce()) { // This chunk can potentially be coalesced. if (_sp->adaptive_freelists()) { // All the work is done in - doPostIsFreeOrGarbageChunk(fc, size); + do_post_free_or_garbage_chunk(fc, size); } else { // Not adaptive free lists // this is a free chunk that can potentially be coalesced by the sweeper; if (!inFreeRange()) { // if the next chunk is a free block that can't be coalesced // it doesn't make sense to remove this chunk from the free lists FreeChunk* nextChunk = (FreeChunk*)(addr + size); - assert((HeapWord*)nextChunk <= _limit, "sweep invariant"); - if ((HeapWord*)nextChunk < _limit && // there's a next chunk... - nextChunk->isFree() && // which is free... + if (nextChunk->isFree() && // The next chunk is free... nextChunk->cantCoalesce()) { // ... but cant be coalesced // nothing to do } else { @@ -8156,14 +8166,14 @@ void SweepClosure::doAlreadyFreeChunk(FreeChunk* fc) { // as the end of a free run if any if (inFreeRange()) { // we kicked some butt; time to pick up the garbage - assert(freeFinger() < addr, "the finger pointeth off base"); - flushCurFreeChunk(freeFinger(), pointer_delta(addr, freeFinger())); + assert(freeFinger() < addr, "freeFinger points too high"); + flush_cur_free_chunk(freeFinger(), pointer_delta(addr, freeFinger())); } // else, nothing to do, just continue } } -size_t SweepClosure::doGarbageChunk(FreeChunk* fc) { +size_t SweepClosure::do_garbage_chunk(FreeChunk* fc) { // This is a chunk of garbage. It is not in any free list. // Add it to a free list or let it possibly be coalesced into // a larger chunk. @@ -8175,7 +8185,7 @@ size_t SweepClosure::doGarbageChunk(FreeChunk* fc) { // addr and purported end of just dead object. _bitMap->verifyNoOneBitsInRange(addr + 1, addr + size); - doPostIsFreeOrGarbageChunk(fc, size); + do_post_free_or_garbage_chunk(fc, size); } else { if (!inFreeRange()) { // start of a new free range @@ -8214,35 +8224,16 @@ size_t SweepClosure::doGarbageChunk(FreeChunk* fc) { return size; } -size_t SweepClosure::doLiveChunk(FreeChunk* fc) { +size_t SweepClosure::do_live_chunk(FreeChunk* fc) { HeapWord* addr = (HeapWord*) fc; // The sweeper has just found a live object. Return any accumulated // left hand chunk to the free lists. if (inFreeRange()) { - if (_sp->adaptive_freelists()) { - flushCurFreeChunk(freeFinger(), - pointer_delta(addr, freeFinger())); - } else { // not adaptive freelists - set_inFreeRange(false); - // Add the free range back to the free list if it is not already - // there. - if (!freeRangeInFreeLists()) { - assert(freeFinger() < addr, "the finger pointeth off base"); - if (CMSTraceSweeper) { - gclog_or_tty->print("Sweep:put_free_blk 0x%x (%d) " - "[coalesced:%d]\n", - freeFinger(), pointer_delta(addr, freeFinger()), - lastFreeRangeCoalesced()); - } - _sp->addChunkAndRepairOffsetTable(freeFinger(), - pointer_delta(addr, freeFinger()), lastFreeRangeCoalesced()); - } - } + assert(freeFinger() < addr, "freeFinger points too high"); + flush_cur_free_chunk(freeFinger(), pointer_delta(addr, freeFinger())); } - // Common code path for original and adaptive free lists. - - // this object is live: we'd normally expect this to be + // This object is live: we'd normally expect this to be // an oop, and like to assert the following: // assert(oop(addr)->is_oop(), "live block should be an oop"); // However, as we commented above, this may be an object whose @@ -8257,7 +8248,7 @@ size_t SweepClosure::doLiveChunk(FreeChunk* fc) { assert(size == CompactibleFreeListSpace::adjustObjectSize(size), "alignment problem"); - #ifdef DEBUG +#ifdef DEBUG if (oop(addr)->klass_or_null() != NULL && ( !_collector->should_unload_classes() || (oop(addr)->is_parsable()) && @@ -8271,7 +8262,7 @@ size_t SweepClosure::doLiveChunk(FreeChunk* fc) { CompactibleFreeListSpace::adjustObjectSize(oop(addr)->size()), "P-mark and computed size do not agree"); } - #endif +#endif } else { // This should be an initialized object that's alive. @@ -8298,19 +8289,17 @@ size_t SweepClosure::doLiveChunk(FreeChunk* fc) { return size; } -void SweepClosure::doPostIsFreeOrGarbageChunk(FreeChunk* fc, - size_t chunkSize) { - // doPostIsFreeOrGarbageChunk() should only be called in the smart allocation - // scheme. +void SweepClosure::do_post_free_or_garbage_chunk(FreeChunk* fc, + size_t chunkSize) { + // do_post_free_or_garbage_chunk() should only be called in the case + // of the adaptive free list allocator. bool fcInFreeLists = fc->isFree(); assert(_sp->adaptive_freelists(), "Should only be used in this case."); assert((HeapWord*)fc <= _limit, "sweep invariant"); if (CMSTestInFreeList && fcInFreeLists) { - assert(_sp->verifyChunkInFreeLists(fc), - "free chunk is not in free lists"); + assert(_sp->verifyChunkInFreeLists(fc), "free chunk is not in free lists"); } - if (CMSTraceSweeper) { gclog_or_tty->print_cr(" -- pick up another chunk at 0x%x (%d)", fc, chunkSize); } @@ -8382,20 +8371,21 @@ void SweepClosure::doPostIsFreeOrGarbageChunk(FreeChunk* fc, if (inFreeRange()) { // In a free range but cannot coalesce with the right hand chunk. // Put the current free range into the free lists. - flushCurFreeChunk(freeFinger(), - pointer_delta(addr, freeFinger())); + flush_cur_free_chunk(freeFinger(), + pointer_delta(addr, freeFinger())); } // Set up for new free range. Pass along whether the right hand // chunk is in the free lists. initialize_free_range((HeapWord*)fc, fcInFreeLists); } } -void SweepClosure::flushCurFreeChunk(HeapWord* chunk, size_t size) { + +void SweepClosure::flush_cur_free_chunk(HeapWord* chunk, size_t size) { assert(inFreeRange(), "Should only be called if currently in a free range."); assert(size > 0, "A zero sized chunk cannot be added to the free lists."); if (!freeRangeInFreeLists()) { - if(CMSTestInFreeList) { + if (CMSTestInFreeList) { FreeChunk* fc = (FreeChunk*) chunk; fc->setSize(size); assert(!_sp->verifyChunkInFreeLists(fc), @@ -8430,7 +8420,7 @@ void SweepClosure::do_yield_work(HeapWord* addr) { // chunk just flushed, they will need to wait for the next // sweep to be coalesced. if (inFreeRange()) { - flushCurFreeChunk(freeFinger(), pointer_delta(addr, freeFinger())); + flush_cur_free_chunk(freeFinger(), pointer_delta(addr, freeFinger())); } // First give up the locks, then yield, then re-lock. diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp index 118380ddd5d..a54f5eff702 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp @@ -1701,7 +1701,9 @@ class SweepClosure: public BlkClosureCareful { CMSCollector* _collector; // collector doing the work ConcurrentMarkSweepGeneration* _g; // Generation being swept CompactibleFreeListSpace* _sp; // Space being swept - HeapWord* _limit; + HeapWord* _limit;// the address at which the sweep should stop because + // we do not expect blocks eligible for sweeping past + // that address. Mutex* _freelistLock; // Free list lock (in space) CMSBitMap* _bitMap; // Marking bit map (in // generation) @@ -1745,14 +1747,13 @@ class SweepClosure: public BlkClosureCareful { private: // Code that is common to a free chunk or garbage when // encountered during sweeping. - void doPostIsFreeOrGarbageChunk(FreeChunk *fc, - size_t chunkSize); + void do_post_free_or_garbage_chunk(FreeChunk *fc, size_t chunkSize); // Process a free chunk during sweeping. - void doAlreadyFreeChunk(FreeChunk *fc); + void do_already_free_chunk(FreeChunk *fc); // Process a garbage chunk during sweeping. - size_t doGarbageChunk(FreeChunk *fc); + size_t do_garbage_chunk(FreeChunk *fc); // Process a live chunk during sweeping. - size_t doLiveChunk(FreeChunk* fc); + size_t do_live_chunk(FreeChunk* fc); // Accessors. HeapWord* freeFinger() const { return _freeFinger; } @@ -1769,7 +1770,7 @@ class SweepClosure: public BlkClosureCareful { // Initialize a free range. void initialize_free_range(HeapWord* freeFinger, bool freeRangeInFreeLists); // Return this chunk to the free lists. - void flushCurFreeChunk(HeapWord* chunk, size_t size); + void flush_cur_free_chunk(HeapWord* chunk, size_t size); // Check if we should yield and do so when necessary. inline void do_yield_check(HeapWord* addr); From e208093ec827e16ce74f06cde157385dcf55277c Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Fri, 7 Jan 2011 13:08:18 +0000 Subject: [PATCH 007/152] 7000511: PrintStream, PrintWriter, Formatter, Scanner leave files open when exception thrown Reviewed-by: alanb, mduigou --- .../share/classes/java/io/PrintStream.java | 101 ++++++++----- .../share/classes/java/io/PrintWriter.java | 41 +++++- .../share/classes/java/util/Formatter.java | 88 ++++++++---- jdk/src/share/classes/java/util/Scanner.java | 100 +++++++------ jdk/test/ProblemList.txt | 6 - .../io/PrintStream/FailingConstructors.java | 133 ++++++++++++++++++ .../io/PrintWriter/FailingConstructors.java | 133 ++++++++++++++++++ .../java/util/Formatter/Constructors.java | 117 ++++++--------- .../util/Formatter/FailingConstructors.java | 133 ++++++++++++++++++ .../util/Scanner/FailingConstructors.java | 132 +++++++++++++++++ 10 files changed, 790 insertions(+), 194 deletions(-) create mode 100644 jdk/test/java/io/PrintStream/FailingConstructors.java create mode 100644 jdk/test/java/io/PrintWriter/FailingConstructors.java create mode 100644 jdk/test/java/util/Formatter/FailingConstructors.java create mode 100644 jdk/test/java/util/Scanner/FailingConstructors.java diff --git a/jdk/src/share/classes/java/io/PrintStream.java b/jdk/src/share/classes/java/io/PrintStream.java index 2f4168aaf78..87d425bfeb0 100644 --- a/jdk/src/share/classes/java/io/PrintStream.java +++ b/jdk/src/share/classes/java/io/PrintStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2011, 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 @@ -27,7 +27,9 @@ package java.io; import java.util.Formatter; import java.util.Locale; - +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; /** * A PrintStream adds functionality to another output stream, @@ -56,7 +58,7 @@ public class PrintStream extends FilterOutputStream implements Appendable, Closeable { - private boolean autoFlush = false; + private final boolean autoFlush; private boolean trouble = false; private Formatter formatter; @@ -67,6 +69,60 @@ public class PrintStream extends FilterOutputStream private BufferedWriter textOut; private OutputStreamWriter charOut; + /** + * nonNull is explicitly delcared here so as not to create an extra + * dependency on java.util.Objects.nonNull. PrintStream is loaded + * early during system initialization. + */ + private static T nonNull(T obj, String message) { + if (obj == null) + throw new NullPointerException(message); + return obj; + } + + /** + * Returns a charset object for the given charset name. + * @throws NullPointerException is csn is null + * @throws UnsupportedEncodingException if the charset is not supported + */ + private static Charset toCharset(String csn) + throws UnsupportedEncodingException + { + nonNull(csn, "charsetName"); + try { + return Charset.forName(csn); + } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { + // UnsupportedEncodingException should be thrown + throw new UnsupportedEncodingException(csn); + } + } + + /* Private constructors */ + private PrintStream(boolean autoFlush, OutputStream out) { + super(out); + this.autoFlush = autoFlush; + this.charOut = new OutputStreamWriter(this); + this.textOut = new BufferedWriter(charOut); + } + + private PrintStream(boolean autoFlush, OutputStream out, Charset charset) { + super(out); + this.autoFlush = autoFlush; + this.charOut = new OutputStreamWriter(this, charset); + this.textOut = new BufferedWriter(charOut); + } + + /* Variant of the private constructor so that the given charset name + * can be verified before evaluating the OutputStream argument. Used + * by constructors creating a FileOutputStream that also take a + * charset name. + */ + private PrintStream(boolean autoFlush, Charset charset, OutputStream out) + throws UnsupportedEncodingException + { + this(autoFlush, out, charset); + } + /** * Creates a new print stream. This stream will not flush automatically. * @@ -79,27 +135,6 @@ public class PrintStream extends FilterOutputStream this(out, false); } - /* Initialization is factored into a private constructor (note the swapped - * parameters so that this one isn't confused with the public one) and a - * separate init method so that the following two public constructors can - * share code. We use a separate init method so that the constructor that - * takes an encoding will throw an NPE for a null stream before it throws - * an UnsupportedEncodingException for an unsupported encoding. - */ - - private PrintStream(boolean autoFlush, OutputStream out) - { - super(out); - if (out == null) - throw new NullPointerException("Null output stream"); - this.autoFlush = autoFlush; - } - - private void init(OutputStreamWriter osw) { - this.charOut = osw; - this.textOut = new BufferedWriter(osw); - } - /** * Creates a new print stream. * @@ -113,8 +148,7 @@ public class PrintStream extends FilterOutputStream * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream, boolean) */ public PrintStream(OutputStream out, boolean autoFlush) { - this(autoFlush, out); - init(new OutputStreamWriter(this)); + this(autoFlush, nonNull(out, "Null output stream")); } /** @@ -138,8 +172,9 @@ public class PrintStream extends FilterOutputStream public PrintStream(OutputStream out, boolean autoFlush, String encoding) throws UnsupportedEncodingException { - this(autoFlush, out); - init(new OutputStreamWriter(this, encoding)); + this(autoFlush, + nonNull(out, "Null output stream"), + toCharset(encoding)); } /** @@ -171,7 +206,6 @@ public class PrintStream extends FilterOutputStream */ public PrintStream(String fileName) throws FileNotFoundException { this(false, new FileOutputStream(fileName)); - init(new OutputStreamWriter(this)); } /** @@ -210,8 +244,8 @@ public class PrintStream extends FilterOutputStream public PrintStream(String fileName, String csn) throws FileNotFoundException, UnsupportedEncodingException { - this(false, new FileOutputStream(fileName)); - init(new OutputStreamWriter(this, csn)); + // ensure charset is checked before the file is opened + this(false, toCharset(csn), new FileOutputStream(fileName)); } /** @@ -243,7 +277,6 @@ public class PrintStream extends FilterOutputStream */ public PrintStream(File file) throws FileNotFoundException { this(false, new FileOutputStream(file)); - init(new OutputStreamWriter(this)); } /** @@ -282,8 +315,8 @@ public class PrintStream extends FilterOutputStream public PrintStream(File file, String csn) throws FileNotFoundException, UnsupportedEncodingException { - this(false, new FileOutputStream(file)); - init(new OutputStreamWriter(this, csn)); + // ensure charset is checked before the file is opened + this(false, toCharset(csn), new FileOutputStream(file)); } /** Check to make sure that the stream has not been closed */ diff --git a/jdk/src/share/classes/java/io/PrintWriter.java b/jdk/src/share/classes/java/io/PrintWriter.java index afce0f89d4d..16044567065 100644 --- a/jdk/src/share/classes/java/io/PrintWriter.java +++ b/jdk/src/share/classes/java/io/PrintWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2011, 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 @@ -25,8 +25,12 @@ package java.io; +import java.util.Objects; import java.util.Formatter; import java.util.Locale; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; /** * Prints formatted representations of objects to a text-output stream. This @@ -59,7 +63,7 @@ public class PrintWriter extends Writer { */ protected Writer out; - private boolean autoFlush = false; + private final boolean autoFlush; private boolean trouble = false; private Formatter formatter; private PrintStream psOut = null; @@ -68,7 +72,24 @@ public class PrintWriter extends Writer { * Line separator string. This is the value of the line.separator * property at the moment that the stream was created. */ - private String lineSeparator; + private final String lineSeparator; + + /** + * Returns a charset object for the given charset name. + * @throws NullPointerException is csn is null + * @throws UnsupportedEncodingException if the charset is not supported + */ + private static Charset toCharset(String csn) + throws UnsupportedEncodingException + { + Objects.nonNull(csn, "charsetName"); + try { + return Charset.forName(csn); + } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { + // UnsupportedEncodingException should be thrown + throw new UnsupportedEncodingException(csn); + } + } /** * Creates a new PrintWriter, without automatic line flushing. @@ -164,6 +185,14 @@ public class PrintWriter extends Writer { false); } + /* Private constructor */ + private PrintWriter(Charset charset, File file) + throws FileNotFoundException + { + this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)), + false); + } + /** * Creates a new PrintWriter, without automatic line flushing, with the * specified file name and charset. This convenience constructor creates @@ -200,8 +229,7 @@ public class PrintWriter extends Writer { public PrintWriter(String fileName, String csn) throws FileNotFoundException, UnsupportedEncodingException { - this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)), - false); + this(toCharset(csn), new File(fileName)); } /** @@ -272,8 +300,7 @@ public class PrintWriter extends Writer { public PrintWriter(File file, String csn) throws FileNotFoundException, UnsupportedEncodingException { - this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)), - false); + this(toCharset(csn), file); } /** Checks to make sure that the stream has not been closed */ diff --git a/jdk/src/share/classes/java/util/Formatter.java b/jdk/src/share/classes/java/util/Formatter.java index 316135ed0fa..6c9ead3b7f0 100644 --- a/jdk/src/share/classes/java/util/Formatter.java +++ b/jdk/src/share/classes/java/util/Formatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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,6 +41,8 @@ import java.math.BigInteger; import java.math.MathContext; import java.math.RoundingMode; import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; import java.text.DateFormatSymbols; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; @@ -1838,22 +1840,53 @@ import sun.misc.FormattedFloatingDecimal; */ public final class Formatter implements Closeable, Flushable { private Appendable a; - private Locale l; + private final Locale l; private IOException lastException; - private char zero = '0'; + private final char zero; private static double scaleUp; // 1 (sign) + 19 (max # sig digits) + 1 ('.') + 1 ('e') + 1 (sign) // + 3 (max # exp digits) + 4 (error) = 30 private static final int MAX_FD_CHARS = 30; - // Initialize internal data. - private void init(Appendable a, Locale l) { + /** + * Returns a charset object for the given charset name. + * @throws NullPointerException is csn is null + * @throws UnsupportedEncodingException if the charset is not supported + */ + private static Charset toCharset(String csn) + throws UnsupportedEncodingException + { + Objects.nonNull(csn, "charsetName"); + try { + return Charset.forName(csn); + } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { + // UnsupportedEncodingException should be thrown + throw new UnsupportedEncodingException(csn); + } + } + + private static final Appendable nonNullAppendable(Appendable a) { + if (a == null) + return new StringBuilder(); + + return a; + } + + /* Private constructors */ + private Formatter(Locale l, Appendable a) { this.a = a; this.l = l; - setZero(); + this.zero = getZero(l); + } + + private Formatter(Charset charset, Locale l, File file) + throws FileNotFoundException + { + this(l, + new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset))); } /** @@ -1867,7 +1900,7 @@ public final class Formatter implements Closeable, Flushable { * virtual machine. */ public Formatter() { - init(new StringBuilder(), Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), new StringBuilder()); } /** @@ -1881,9 +1914,7 @@ public final class Formatter implements Closeable, Flushable { * {@code null} then a {@link StringBuilder} will be created. */ public Formatter(Appendable a) { - if (a == null) - a = new StringBuilder(); - init(a, Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), nonNullAppendable(a)); } /** @@ -1900,7 +1931,7 @@ public final class Formatter implements Closeable, Flushable { * is applied. */ public Formatter(Locale l) { - init(new StringBuilder(), l); + this(l, new StringBuilder()); } /** @@ -1916,9 +1947,7 @@ public final class Formatter implements Closeable, Flushable { * is applied. */ public Formatter(Appendable a, Locale l) { - if (a == null) - a = new StringBuilder(); - init(a, l); + this(l, nonNullAppendable(a)); } /** @@ -1949,8 +1978,8 @@ public final class Formatter implements Closeable, Flushable { * creating the file */ public Formatter(String fileName) throws FileNotFoundException { - init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))), - Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), + new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName)))); } /** @@ -2025,8 +2054,7 @@ public final class Formatter implements Closeable, Flushable { public Formatter(String fileName, String csn, Locale l) throws FileNotFoundException, UnsupportedEncodingException { - init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)), - l); + this(toCharset(csn), l, new File(fileName)); } /** @@ -2057,8 +2085,8 @@ public final class Formatter implements Closeable, Flushable { * creating the file */ public Formatter(File file) throws FileNotFoundException { - init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))), - Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), + new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)))); } /** @@ -2133,8 +2161,7 @@ public final class Formatter implements Closeable, Flushable { public Formatter(File file, String csn, Locale l) throws FileNotFoundException, UnsupportedEncodingException { - init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)), - l); + this(toCharset(csn), l, file); } /** @@ -2151,9 +2178,8 @@ public final class Formatter implements Closeable, Flushable { * The stream to use as the destination of this formatter. */ public Formatter(PrintStream ps) { - if (ps == null) - throw new NullPointerException(); - init((Appendable)ps, Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), + (Appendable)Objects.nonNull(ps)); } /** @@ -2171,8 +2197,8 @@ public final class Formatter implements Closeable, Flushable { * The output will be buffered. */ public Formatter(OutputStream os) { - init(new BufferedWriter(new OutputStreamWriter(os)), - Locale.getDefault(Locale.Category.FORMAT)); + this(Locale.getDefault(Locale.Category.FORMAT), + new BufferedWriter(new OutputStreamWriter(os))); } /** @@ -2222,13 +2248,15 @@ public final class Formatter implements Closeable, Flushable { public Formatter(OutputStream os, String csn, Locale l) throws UnsupportedEncodingException { - init(new BufferedWriter(new OutputStreamWriter(os, csn)), l); + this(l, new BufferedWriter(new OutputStreamWriter(os, csn))); } - private void setZero() { + private static char getZero(Locale l) { if ((l != null) && !l.equals(Locale.US)) { DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l); - zero = dfs.getZeroDigit(); + return dfs.getZeroDigit(); + } else { + return '0'; } } diff --git a/jdk/src/share/classes/java/util/Scanner.java b/jdk/src/share/classes/java/util/Scanner.java index 9fe2192b61b..834af330ff1 100644 --- a/jdk/src/share/classes/java/util/Scanner.java +++ b/jdk/src/share/classes/java/util/Scanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -571,10 +571,8 @@ public final class Scanner implements Iterator, Closeable { * @return A scanner with the specified source and pattern */ private Scanner(Readable source, Pattern pattern) { - if (source == null) - throw new NullPointerException("source"); - if (pattern == null) - throw new NullPointerException("pattern"); + assert source != null : "source should not be null"; + assert pattern != null : "pattern should not be null"; this.source = source; delimPattern = pattern; buf = CharBuffer.allocate(BUFFER_SIZE); @@ -593,7 +591,7 @@ public final class Scanner implements Iterator, Closeable { * interface */ public Scanner(Readable source) { - this(source, WHITESPACE_PATTERN); + this(Objects.nonNull(source, "source"), WHITESPACE_PATTERN); } /** @@ -620,23 +618,27 @@ public final class Scanner implements Iterator, Closeable { * does not exist */ public Scanner(InputStream source, String charsetName) { - this(makeReadable(source, charsetName), WHITESPACE_PATTERN); + this(makeReadable(Objects.nonNull(source, "source"), toCharset(charsetName)), + WHITESPACE_PATTERN); } - private static Readable makeReadable(InputStream source, - String charsetName) - { - if (source == null) - throw new NullPointerException("source"); - InputStreamReader isr = null; + /** + * Returns a charset object for the given charset name. + * @throws NullPointerException is csn is null + * @throws IllegalArgumentException if the charset is not supported + */ + private static Charset toCharset(String csn) { + Objects.nonNull(csn, "charsetName"); try { - isr = new InputStreamReader(source, charsetName); - } catch (UnsupportedEncodingException uee) { - IllegalArgumentException iae = new IllegalArgumentException(); - iae.initCause(uee); - throw iae; + return Charset.forName(csn); + } catch (IllegalCharsetNameException|UnsupportedCharsetException e) { + // IllegalArgumentException should be thrown + throw new IllegalArgumentException(e); } - return isr; + } + + private static Readable makeReadable(InputStream source, Charset charset) { + return new InputStreamReader(source, charset); } /** @@ -648,9 +650,7 @@ public final class Scanner implements Iterator, Closeable { * @param source A file to be scanned * @throws FileNotFoundException if source is not found */ - public Scanner(File source) - throws FileNotFoundException - { + public Scanner(File source) throws FileNotFoundException { this((ReadableByteChannel)(new FileInputStream(source).getChannel())); } @@ -669,8 +669,27 @@ public final class Scanner implements Iterator, Closeable { public Scanner(File source, String charsetName) throws FileNotFoundException { - this((ReadableByteChannel)(new FileInputStream(source).getChannel()), - charsetName); + this(Objects.nonNull(source), toDecoder(charsetName)); + } + + private Scanner(File source, CharsetDecoder dec) + throws FileNotFoundException + { + this(makeReadable((ReadableByteChannel)(new FileInputStream(source).getChannel()), dec)); + } + + private static CharsetDecoder toDecoder(String charsetName) { + Objects.nonNull(charsetName, "charsetName"); + try { + return Charset.forName(charsetName).newDecoder(); + } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) { + throw new IllegalArgumentException(charsetName); + } + } + + private static Readable makeReadable(ReadableByteChannel source, + CharsetDecoder dec) { + return Channels.newReader(source, dec, -1); } /** @@ -708,10 +727,12 @@ public final class Scanner implements Iterator, Closeable { * if the specified encoding is not found * @since 1.7 */ - public Scanner(FileRef source, String charsetName) - throws IOException - { - this(source.newInputStream(), charsetName); + public Scanner(FileRef source, String charsetName) throws IOException { + this(Objects.nonNull(source), toCharset(charsetName)); + } + + private Scanner(FileRef source, Charset charset) throws IOException { + this(makeReadable(source.newInputStream(), charset)); } /** @@ -733,16 +754,12 @@ public final class Scanner implements Iterator, Closeable { * @param source A channel to scan */ public Scanner(ReadableByteChannel source) { - this(makeReadable(source), WHITESPACE_PATTERN); + this(makeReadable(Objects.nonNull(source, "source")), + WHITESPACE_PATTERN); } private static Readable makeReadable(ReadableByteChannel source) { - if (source == null) - throw new NullPointerException("source"); - String defaultCharsetName = - java.nio.charset.Charset.defaultCharset().name(); - return Channels.newReader(source, - java.nio.charset.Charset.defaultCharset().name()); + return makeReadable(source, Charset.defaultCharset().newDecoder()); } /** @@ -757,17 +774,8 @@ public final class Scanner implements Iterator, Closeable { * does not exist */ public Scanner(ReadableByteChannel source, String charsetName) { - this(makeReadable(source, charsetName), WHITESPACE_PATTERN); - } - - private static Readable makeReadable(ReadableByteChannel source, - String charsetName) - { - if (source == null) - throw new NullPointerException("source"); - if (!Charset.isSupported(charsetName)) - throw new IllegalArgumentException(charsetName); - return Channels.newReader(source, charsetName); + this(makeReadable(Objects.nonNull(source, "source"), toDecoder(charsetName)), + WHITESPACE_PATTERN); } // Private primitives used to support scanning diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index be1f7850556..365de2bc17b 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -718,9 +718,6 @@ java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java generic-all # 11 separate stacktraces created... file reuse problem? java/util/zip/ZipFile/ReadLongZipFileName.java generic-all -# Failing on all -client 32bit platforms starting with b77? See 6908348. -java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java generic-all - # Assert error, failures, on Linux Fedora 9 -server # Windows samevm failure, assert error "Passed = 134, failed = 2" java/util/Arrays/ArrayObjectMethods.java generic-all @@ -737,9 +734,6 @@ java/util/concurrent/locks/Lock/TimedAcquireLeak.java generic-all # Fails on solaris-sparc -server (Set not equal to copy. 1) java/util/EnumSet/EnumSetBash.java solaris-sparc -# Failing to close an input stream? "foo", triggers samevm windows failures -java/util/Formatter/Constructors.java generic-all - # Need to be marked othervm, or changed to be samevm safe java/util/WeakHashMap/GCDuringIteration.java generic-all diff --git a/jdk/test/java/io/PrintStream/FailingConstructors.java b/jdk/test/java/io/PrintStream/FailingConstructors.java new file mode 100644 index 00000000000..1022bb9d311 --- /dev/null +++ b/jdk/test/java/io/PrintStream/FailingConstructors.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2011, 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 7000511 + * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when + * exception thrown + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; + +public class FailingConstructors { + static final String fileName = "FailingConstructorsTest"; + static final String UNSUPPORTED_CHARSET = "unknownCharset"; + static final String FILE_CONTENTS = "This is a small file!"; + + private static void realMain(String[] args) throws Throwable { + test(false, new File(fileName)); + + /* create the file and write its contents */ + File file = File.createTempFile(fileName, null); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(FILE_CONTENTS.getBytes()); + fos.close(); + + test(true, file); + file.delete(); + } + + private static void test(boolean exists, File file) throws Throwable { + /* PrintStream(File file, String csn) */ + try { + new PrintStream(file, UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new PrintStream(file, null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + + /* PrintStream(String fileName, String csn) */ + try { + new PrintStream(file.getName(), UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new PrintStream(file.getName(), null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + } + + private static void check(boolean exists, File file) { + if (exists) { + /* the file should be unchanged */ + verifyContents(file); + } else { + /* the file should not have been created */ + if (file.exists()) { fail(file + " should not have been created"); } + } + } + + private static void verifyContents(File file) { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] contents = FILE_CONTENTS.getBytes(); + int read, count = 0; + while ((read = fis.read()) != -1) { + if (read != contents[count++]) { + fail("file contents have been altered"); + return; + } + } + } catch (IOException ioe) { + unexpected(ioe); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String message) {System.out.println(message); fail(); } + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/jdk/test/java/io/PrintWriter/FailingConstructors.java b/jdk/test/java/io/PrintWriter/FailingConstructors.java new file mode 100644 index 00000000000..af4fa108473 --- /dev/null +++ b/jdk/test/java/io/PrintWriter/FailingConstructors.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2011, 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 7000511 + * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when + * exception thrown + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +public class FailingConstructors { + static final String fileName = "FailingConstructorsTest"; + static final String UNSUPPORTED_CHARSET = "unknownCharset"; + static final String FILE_CONTENTS = "This is a small file!"; + + private static void realMain(String[] args) throws Throwable { + test(false, new File(fileName)); + + /* create the file and write its contents */ + File file = File.createTempFile(fileName, null); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(FILE_CONTENTS.getBytes()); + fos.close(); + + test(true, file); + file.delete(); + } + + private static void test(boolean exists, File file) throws Throwable { + /* PrintWriter(File file, String csn) */ + try { + new PrintWriter(file, UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new PrintWriter(file, null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + + /* PrintWriter(String fileName, String csn) */ + try { + new PrintWriter(file.getName(), UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new PrintWriter(file.getName(), null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + } + + private static void check(boolean exists, File file) { + if (exists) { + /* the file should be unchanged */ + verifyContents(file); + } else { + /* the file should not have been created */ + if (file.exists()) { fail(file + " should not have been created"); } + } + } + + private static void verifyContents(File file) { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] contents = FILE_CONTENTS.getBytes(); + int read, count = 0; + while ((read = fis.read()) != -1) { + if (read != contents[count++]) { + fail("file contents have been altered"); + return; + } + } + } catch (IOException ioe) { + unexpected(ioe); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String message) {System.out.println(message); fail(); } + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/jdk/test/java/util/Formatter/Constructors.java b/jdk/test/java/util/Formatter/Constructors.java index 3748b5d123d..c542e1bbfb8 100644 --- a/jdk/test/java/util/Formatter/Constructors.java +++ b/jdk/test/java/util/Formatter/Constructors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2011, 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 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4981811 4984465 5064492 6240171 + * @bug 4981811 4984465 5064492 6240171 7000511 * @summary Unit test for all constructors introduced by the formatter feature */ @@ -85,10 +85,8 @@ public class Constructors { } public static void main(String [] args) { - // Formatter() - try { - Formatter f = new Formatter(); + try (Formatter f = new Formatter()) { pass(); out(f, StringBuilder.class); locale(f); @@ -97,8 +95,7 @@ public class Constructors { } // Formatter(Appendable a) - try { - Formatter f = new Formatter((Appendable) null); + try (Formatter f = new Formatter((Appendable) null)) { pass(); out(f, StringBuilder.class); locale(f); @@ -107,8 +104,7 @@ public class Constructors { } // Formatter(Locale l) - try { - Formatter f = new Formatter((Locale) null); + try (Formatter f = new Formatter((Locale) null)) { pass(); out(f, StringBuilder.class); locale(f, null); @@ -117,8 +113,7 @@ public class Constructors { } // Formatter(Appendable a, Locale l) - try { - Formatter f = new Formatter((Appendable) null, (Locale) null); + try (Formatter f = new Formatter((Appendable) null, (Locale) null)) { pass(); out(f, StringBuilder.class); locale(f, null); @@ -127,8 +122,7 @@ public class Constructors { } // Formatter(String fileName) - try { - Formatter f = new Formatter("foo"); + try (Formatter f = new Formatter("foo")) { pass(); out(f, BufferedWriter.class); locale(f); @@ -137,7 +131,7 @@ public class Constructors { } try { - Formatter f = new Formatter((String)null); + new Formatter((String)null); fail("new Formatter((String)null)"); } catch (NullPointerException x) { pass(); @@ -146,8 +140,7 @@ public class Constructors { } // Formatter(String fileName, String csn) - try { - Formatter f = new Formatter("foo", "UTF-8"); + try (Formatter f = new Formatter("foo", "UTF-8")) { pass(); out(f, BufferedWriter.class); locale(f); @@ -167,15 +160,14 @@ public class Constructors { try { new Formatter(".", "bar"); fail("new Formatter(\".\", \"bar\")"); - } catch (FileNotFoundException x) { + } catch (FileNotFoundException|UnsupportedEncodingException x) { pass(); } catch (Exception x) { fail("new Formatter(\".\", \"bar\")", x); } // Formatter(String fileName, String csn, Locale l) - try { - Formatter f = new Formatter("foo", "ISO-8859-1", Locale.GERMANY); + try (Formatter f = new Formatter("foo", "ISO-8859-1", Locale.GERMANY)) { pass(); out(f, BufferedWriter.class); locale(f, Locale.GERMANY); @@ -183,8 +175,7 @@ public class Constructors { fail("new Formatter(\"foo\", \"ISO-8859-1\", Locale.GERMANY)", x); } - try { - Formatter f = new Formatter("foo", "ISO-8859-1", null); + try (Formatter f = new Formatter("foo", "ISO-8859-1", null)) { pass(); locale(f, null); out(f, BufferedWriter.class); @@ -193,8 +184,7 @@ public class Constructors { } // Formatter(File) - try { - Formatter f = new Formatter(new File("foo")); + try (Formatter f = new Formatter(new File("foo"))) { pass(); locale(f); out(f, BufferedWriter.class); @@ -203,7 +193,7 @@ public class Constructors { } try { - Formatter f = new Formatter((File)null); + new Formatter((File)null); fail("new Formatter((File)null)"); } catch (NullPointerException x) { pass(); @@ -231,8 +221,7 @@ public class Constructors { fail("new Formatter((PrintStream) null)", x); } - try { - Formatter f = new Formatter(new PrintStream("foo")); + try (Formatter f = new Formatter(new PrintStream("foo"))) { pass(); locale(f); out(f, PrintStream.class); @@ -242,9 +231,8 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\")", x); } - try { - Formatter f = new Formatter(new PrintStream("foo"), - Locale.JAPANESE); + try (Formatter f = new Formatter(new PrintStream("foo"), + Locale.JAPANESE)) { pass(); locale(f, Locale.JAPANESE); out(f, PrintStream.class); @@ -254,12 +242,11 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\")", x); } - try { + try (PrintStream ps = new PrintStream("foo")) { // The cast here is necessary to avoid an ambiguity error // between Formatter(Appendable a, Locale l) - // and Formatter(OutputStream os, String csn) - Formatter f = new Formatter(new PrintStream("foo"), - (String)null); + // and Formatter(OutputStream os, String csn) + new Formatter(ps, (String)null); fail("new Formatter(new PrintStream(\"foo\"), (String)null)"); } catch (FileNotFoundException x) { fail("new Formatter(new PrintStream(\"foo\"), (String)null)", x); @@ -271,12 +258,11 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\"), (String)null)", x); } - try { - // The cast here is necessary to avoid an ambiguity error - // between Formatter(Appendable a, Locale l) - // and Formatter(OutputStream os, String csn) - Formatter f = new Formatter(new PrintStream("foo"), - (Locale)null); + // The cast here is necessary to avoid an ambiguity error + // between Formatter(Appendable a, Locale l) + // and Formatter(OutputStream os, String csn) + try (Formatter f = new Formatter(new PrintStream("foo"), + (Locale)null)) { pass(); locale(f, null); out(f, PrintStream.class); @@ -286,9 +272,8 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\"), (Locale)null)", x); } - try { - Formatter f = new Formatter(new PrintStream("foo"), - Locale.KOREAN); + try (Formatter f = new Formatter(new PrintStream("foo"), + Locale.KOREAN)) { pass(); locale(f, Locale.KOREAN); out(f, PrintStream.class); @@ -298,9 +283,8 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\"), Locale.KOREAN)", x); } - try { - Formatter f = new Formatter(new PrintStream("foo"), - "UTF-16BE", null); + try (Formatter f = new Formatter(new PrintStream("foo"), + "UTF-16BE", null)) { pass(); locale(f, null); out(f, BufferedWriter.class); @@ -312,9 +296,8 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\"), \"UTF-16BE\", null"); } - try { - Formatter f = new Formatter(new PrintStream("foo"), - "UTF-16BE", Locale.ITALIAN); + try (Formatter f = new Formatter(new PrintStream("foo"), + "UTF-16BE", Locale.ITALIAN)) { pass(); locale(f, Locale.ITALIAN); out(f, BufferedWriter.class); @@ -361,8 +344,7 @@ public class Constructors { fail("new Formatter((OutputStream) null)", x); } - try { - Formatter f = new Formatter((OutputStream) new PrintStream("foo")); + try (Formatter f = new Formatter((OutputStream) new PrintStream("foo"))) { pass(); locale(f); out(f, BufferedWriter.class); @@ -380,8 +362,8 @@ public class Constructors { fail("new Formatter((OutputStream) null, \"ISO-8859-1\")", x); } - try { - new Formatter((OutputStream) new PrintStream("foo"), null); + try (PrintStream ps = new PrintStream("foo")) { + new Formatter((OutputStream) ps, null); fail("new Formatter((OutputStream) new PrintStream(\"foo\"), null"); } catch (NullPointerException x) { pass(); @@ -390,8 +372,8 @@ public class Constructors { x); } - try { - new Formatter(new PrintStream("foo"), "bar"); + try (PrintStream ps = new PrintStream("foo")) { + new Formatter(ps, "bar"); fail("new Formatter(new PrintStream(\"foo\"), \"bar\")"); } catch (UnsupportedEncodingException x) { pass(); @@ -399,8 +381,7 @@ public class Constructors { fail("new Formatter(new PrintStream(\"foo\"), \"bar\")", x); } - try { - Formatter f = new Formatter(new PrintStream("foo"), "UTF-8"); + try (Formatter f = new Formatter(new PrintStream("foo"), "UTF-8")) { pass(); locale(f); out(f, BufferedWriter.class); @@ -419,8 +400,8 @@ public class Constructors { x); } - try { - new Formatter(new PrintStream("foo"), null, Locale.UK); + try (PrintStream ps = new PrintStream("foo")) { + new Formatter(ps, null, Locale.UK); fail("new Formatter(new PrintStream(\"foo\"), null, Locale.UK)"); } catch (NullPointerException x) { pass(); @@ -429,8 +410,8 @@ public class Constructors { x); } - try { - new Formatter(new PrintStream("foo"), "bar", Locale.UK); + try (PrintStream ps = new PrintStream("foo")) { + new Formatter(ps, "bar", Locale.UK); fail("new Formatter(new PrintStream(\"foo\"), \"bar\", Locale.UK)"); } catch (UnsupportedEncodingException x) { pass(); @@ -439,9 +420,7 @@ public class Constructors { x); } - try { - Formatter f - = new Formatter(new PrintStream("foo"), "UTF-8", Locale.UK); + try (Formatter f = new Formatter(new PrintStream("foo"), "UTF-8", Locale.UK)) { pass(); out(f, BufferedWriter.class); locale(f, Locale.UK); @@ -451,8 +430,7 @@ public class Constructors { } // PrintStream(String fileName) - try { - new PrintStream("foo"); + try (PrintStream ps = new PrintStream("foo")) { pass(); } catch (Exception x) { fail("new PrintStream(\"foo\")", x); @@ -469,8 +447,7 @@ public class Constructors { } // PrintStream(File file) - try { - new PrintStream(new File("foo")); + try (PrintStream ps = new PrintStream(new File("foo"))) { pass(); } catch (Exception x) { fail("new PrintStream(new File(\"foo\"))", x); @@ -487,8 +464,7 @@ public class Constructors { } // PrintWriter(String fileName) - try { - new PrintWriter("foo"); + try (PrintWriter pw = new PrintWriter("foo")) { pass(); } catch (Exception x) { fail("new PrintWriter(\"foo\")", x); @@ -505,8 +481,7 @@ public class Constructors { } // PrintWriter(File file) - try { - new PrintWriter(new File("foo")); + try (PrintWriter pw = new PrintWriter(new File("foo"))) { pass(); } catch (Exception x) { fail("new PrintWriter(new File(\"foo\"))", x); diff --git a/jdk/test/java/util/Formatter/FailingConstructors.java b/jdk/test/java/util/Formatter/FailingConstructors.java new file mode 100644 index 00000000000..8ef99f146a4 --- /dev/null +++ b/jdk/test/java/util/Formatter/FailingConstructors.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2011, 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 7000511 + * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when + * exception thrown + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Formatter; + +public class FailingConstructors { + static final String fileName = "FailingConstructorsTest"; + static final String UNSUPPORTED_CHARSET = "unknownCharset"; + static final String FILE_CONTENTS = "This is a small file!"; + + private static void realMain(String[] args) throws Throwable { + test(false, new File(fileName)); + + /* create the file and write its contents */ + File file = File.createTempFile(fileName, null); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(FILE_CONTENTS.getBytes()); + fos.close(); + + test(true, file); + file.delete(); + } + + private static void test(boolean exists, File file) throws Throwable { + /* Formatter(File file, String csn) */ + try { + new Formatter(file, UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new Formatter(file, null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + + /* Formatter(String fileName, String csn) */ + try { + new Formatter(file.getName(), UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|UnsupportedEncodingException e) { + pass(); + } + + check(exists, file); + + try { + new Formatter(file.getName(), null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + } + + private static void check(boolean exists, File file) { + if (exists) { + /* the file should be unchanged */ + verifyContents(file); + } else { + /* the file should not have been created */ + if (file.exists()) { fail(file + " should not have been created"); } + } + } + + private static void verifyContents(File file) { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] contents = FILE_CONTENTS.getBytes(); + int read, count = 0; + while ((read = fis.read()) != -1) { + if (read != contents[count++]) { + fail("file contents have been altered"); + return; + } + } + } catch (IOException ioe) { + unexpected(ioe); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String message) {System.out.println(message); fail(); } + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/jdk/test/java/util/Scanner/FailingConstructors.java b/jdk/test/java/util/Scanner/FailingConstructors.java new file mode 100644 index 00000000000..476c000ae1a --- /dev/null +++ b/jdk/test/java/util/Scanner/FailingConstructors.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2011, 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 7000511 + * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when + * exception thrown + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Scanner; + +public class FailingConstructors { + static final String fileName = "FailingConstructorsTest"; + static final String UNSUPPORTED_CHARSET = "unknownCharset"; + static final String FILE_CONTENTS = "This is a small file!"; + + private static void realMain(String[] args) throws Throwable { + test(false, new File(fileName)); + + /* create the file and write its contents */ + File file = File.createTempFile(fileName, null); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(FILE_CONTENTS.getBytes()); + fos.close(); + + test(true, file); + file.delete(); + } + + private static void test(boolean exists, File file) throws Throwable { + /* Scanner(File source, String charsetName) */ + try { + new Scanner(file, UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|IllegalArgumentException e) { + pass(); + } + + check(exists, file); + + try { + new Scanner(file, null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + + /* Scanner(FileRef source, String charsetName) */ + try { + new Scanner(file.toPath(), UNSUPPORTED_CHARSET); + fail(); + } catch(FileNotFoundException|IllegalArgumentException e) { + pass(); + } + + check(exists, file); + + try { + new Scanner(file.toPath(), null); + fail(); + } catch(FileNotFoundException|NullPointerException e) { + pass(); + } + + check(exists, file); + } + + private static void check(boolean exists, File file) { + if (exists) { + /* the file should be unchanged */ + verifyContents(file); + } else { + /* the file should not have been created */ + if (file.exists()) { fail(file + " should not have been created"); } + } + } + + private static void verifyContents(File file) { + try (FileInputStream fis = new FileInputStream(file)) { + byte[] contents = FILE_CONTENTS.getBytes(); + int read, count = 0; + while ((read = fis.read()) != -1) { + if (read != contents[count++]) { + fail("file contents have been altered"); + return; + } + } + } catch (IOException ioe) { + unexpected(ioe); + } + } + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String message) {System.out.println(message); fail(); } + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} From 5182f947a2754b9004913a8d059d1178371e834b Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Fri, 7 Jan 2011 15:49:44 +0000 Subject: [PATCH 008/152] 6993732: Remove the HPI Reviewed-by: ohair, lancea, chegar, mduigou, mchung, mr --- jdk/make/common/Defs-linux.gmk | 9 - jdk/make/common/Defs-solaris.gmk | 9 - jdk/make/common/Defs-windows.gmk | 1 - jdk/make/common/Defs.gmk | 11 +- jdk/make/common/Modules.gmk | 5 +- jdk/make/common/Release.gmk | 6 +- jdk/make/java/Makefile | 2 +- jdk/make/java/fdlibm/Makefile | 2 +- jdk/make/java/hpi/Makefile | 41 - jdk/make/java/hpi/hpi_common.gmk | 90 -- jdk/make/java/hpi/native/Makefile | 93 -- jdk/make/java/hpi/native/mapfile-vers | 32 - jdk/make/java/hpi/native/reorder-i586 | 27 - jdk/make/java/hpi/native/reorder-sparc | 26 - jdk/make/java/hpi/native/reorder-sparcv9 | 26 - jdk/make/java/hpi/windows/Makefile | 69 - jdk/make/tools/reorder/Makefile | 2 - jdk/src/share/hpi/export/bool.h | 37 - jdk/src/share/hpi/export/dll.h | 50 - jdk/src/share/hpi/export/hpi.h | 306 ----- jdk/src/share/hpi/include/hpi_impl.h | 206 --- jdk/src/share/hpi/include/vm_calls.h | 88 -- jdk/src/share/hpi/src/hpi.c | 222 ---- jdk/src/solaris/hpi/export/byteorder_md.h | 35 - jdk/src/solaris/hpi/export/hpi_md.h | 36 - jdk/src/solaris/hpi/export/io_md.h | 45 - jdk/src/solaris/hpi/export/path_md.h | 39 - jdk/src/solaris/hpi/export/timeval_md.h | 34 - jdk/src/solaris/hpi/include/hpi_init.h | 37 - jdk/src/solaris/hpi/include/interrupt.h | 124 -- jdk/src/solaris/hpi/include/largefile.h | 50 - jdk/src/solaris/hpi/include/largefile_linux.h | 36 - .../solaris/hpi/include/largefile_solaris.h | 89 -- .../hpi/native_threads/include/condvar_md.h | 47 - .../hpi/native_threads/include/monitor_md.h | 111 -- .../hpi/native_threads/include/mutex_md.h | 50 - .../solaris/hpi/native_threads/include/np.h | 51 - .../hpi/native_threads/include/porting.h | 82 -- .../hpi/native_threads/include/threads_md.h | 218 ---- .../hpi/native_threads/src/condvar_md.c | 296 ----- .../hpi/native_threads/src/interrupt_md.c | 229 ---- .../hpi/native_threads/src/monitor_md.c | 365 ------ .../solaris/hpi/native_threads/src/mutex_md.c | 53 - .../hpi/native_threads/src/sys_api_td.c | 599 --------- .../hpi/native_threads/src/threads_linux.c | 411 ------ .../hpi/native_threads/src/threads_md.c | 1133 ----------------- .../hpi/native_threads/src/threads_solaris.c | 666 ---------- jdk/src/solaris/hpi/src/interrupt.c | 171 --- jdk/src/solaris/hpi/src/linker_md.c | 161 --- jdk/src/solaris/hpi/src/memory_md.c | 439 ------- jdk/src/solaris/hpi/src/system_md.c | 314 ----- jdk/src/windows/hpi/export/byteorder_md.h | 48 - jdk/src/windows/hpi/export/hpi_md.h | 36 - jdk/src/windows/hpi/export/io_md.h | 58 - jdk/src/windows/hpi/export/path_md.h | 39 - jdk/src/windows/hpi/export/timeval_md.h | 50 - jdk/src/windows/hpi/include/monitor_md.h | 49 - jdk/src/windows/hpi/include/mutex_md.h | 50 - jdk/src/windows/hpi/include/threads_md.h | 92 -- jdk/src/windows/hpi/src/linker_md.c | 129 -- jdk/src/windows/hpi/src/memory_md.c | 296 ----- jdk/src/windows/hpi/src/monitor_md.c | 517 -------- jdk/src/windows/hpi/src/path_md.c | 150 --- jdk/src/windows/hpi/src/socket_md.c | 537 -------- jdk/src/windows/hpi/src/sys_api_md.c | 314 ----- jdk/src/windows/hpi/src/system_md.c | 202 --- jdk/src/windows/hpi/src/threads_md.c | 831 ------------ 67 files changed, 9 insertions(+), 10670 deletions(-) delete mode 100644 jdk/make/java/hpi/Makefile delete mode 100644 jdk/make/java/hpi/hpi_common.gmk delete mode 100644 jdk/make/java/hpi/native/Makefile delete mode 100644 jdk/make/java/hpi/native/mapfile-vers delete mode 100644 jdk/make/java/hpi/native/reorder-i586 delete mode 100644 jdk/make/java/hpi/native/reorder-sparc delete mode 100644 jdk/make/java/hpi/native/reorder-sparcv9 delete mode 100644 jdk/make/java/hpi/windows/Makefile delete mode 100644 jdk/src/share/hpi/export/bool.h delete mode 100644 jdk/src/share/hpi/export/dll.h delete mode 100644 jdk/src/share/hpi/export/hpi.h delete mode 100644 jdk/src/share/hpi/include/hpi_impl.h delete mode 100644 jdk/src/share/hpi/include/vm_calls.h delete mode 100644 jdk/src/share/hpi/src/hpi.c delete mode 100644 jdk/src/solaris/hpi/export/byteorder_md.h delete mode 100644 jdk/src/solaris/hpi/export/hpi_md.h delete mode 100644 jdk/src/solaris/hpi/export/io_md.h delete mode 100644 jdk/src/solaris/hpi/export/path_md.h delete mode 100644 jdk/src/solaris/hpi/export/timeval_md.h delete mode 100644 jdk/src/solaris/hpi/include/hpi_init.h delete mode 100644 jdk/src/solaris/hpi/include/interrupt.h delete mode 100644 jdk/src/solaris/hpi/include/largefile.h delete mode 100644 jdk/src/solaris/hpi/include/largefile_linux.h delete mode 100644 jdk/src/solaris/hpi/include/largefile_solaris.h delete mode 100644 jdk/src/solaris/hpi/native_threads/include/condvar_md.h delete mode 100644 jdk/src/solaris/hpi/native_threads/include/monitor_md.h delete mode 100644 jdk/src/solaris/hpi/native_threads/include/mutex_md.h delete mode 100644 jdk/src/solaris/hpi/native_threads/include/np.h delete mode 100644 jdk/src/solaris/hpi/native_threads/include/porting.h delete mode 100644 jdk/src/solaris/hpi/native_threads/include/threads_md.h delete mode 100644 jdk/src/solaris/hpi/native_threads/src/condvar_md.c delete mode 100644 jdk/src/solaris/hpi/native_threads/src/interrupt_md.c delete mode 100644 jdk/src/solaris/hpi/native_threads/src/monitor_md.c delete mode 100644 jdk/src/solaris/hpi/native_threads/src/mutex_md.c delete mode 100644 jdk/src/solaris/hpi/native_threads/src/sys_api_td.c delete mode 100644 jdk/src/solaris/hpi/native_threads/src/threads_linux.c delete mode 100644 jdk/src/solaris/hpi/native_threads/src/threads_md.c delete mode 100644 jdk/src/solaris/hpi/native_threads/src/threads_solaris.c delete mode 100644 jdk/src/solaris/hpi/src/interrupt.c delete mode 100644 jdk/src/solaris/hpi/src/linker_md.c delete mode 100644 jdk/src/solaris/hpi/src/memory_md.c delete mode 100644 jdk/src/solaris/hpi/src/system_md.c delete mode 100644 jdk/src/windows/hpi/export/byteorder_md.h delete mode 100644 jdk/src/windows/hpi/export/hpi_md.h delete mode 100644 jdk/src/windows/hpi/export/io_md.h delete mode 100644 jdk/src/windows/hpi/export/path_md.h delete mode 100644 jdk/src/windows/hpi/export/timeval_md.h delete mode 100644 jdk/src/windows/hpi/include/monitor_md.h delete mode 100644 jdk/src/windows/hpi/include/mutex_md.h delete mode 100644 jdk/src/windows/hpi/include/threads_md.h delete mode 100644 jdk/src/windows/hpi/src/linker_md.c delete mode 100644 jdk/src/windows/hpi/src/memory_md.c delete mode 100644 jdk/src/windows/hpi/src/monitor_md.c delete mode 100644 jdk/src/windows/hpi/src/path_md.c delete mode 100644 jdk/src/windows/hpi/src/socket_md.c delete mode 100644 jdk/src/windows/hpi/src/sys_api_md.c delete mode 100644 jdk/src/windows/hpi/src/system_md.c delete mode 100644 jdk/src/windows/hpi/src/threads_md.c diff --git a/jdk/make/common/Defs-linux.gmk b/jdk/make/common/Defs-linux.gmk index 6acbaa4b686..4541ec8b829 100644 --- a/jdk/make/common/Defs-linux.gmk +++ b/jdk/make/common/Defs-linux.gmk @@ -74,15 +74,6 @@ SCRIPT_SUFFIX = CC_OBJECT_OUTPUT_FLAG = -o #trailing blank required! CC_PROGRAM_OUTPUT_FLAG = -o #trailing blank required! -# -# Default HPI libraries. Build will build only native, unless -# overriden at the make command line. This makes it convenient for -# people doing, say, a pthreads port -- they can create a posix -# directory here, and say "gnumake HPIS=posix" at the top -# level. -# -HPIS = native - # # Default optimization # diff --git a/jdk/make/common/Defs-solaris.gmk b/jdk/make/common/Defs-solaris.gmk index 637bff575fc..50e5c4bb1de 100644 --- a/jdk/make/common/Defs-solaris.gmk +++ b/jdk/make/common/Defs-solaris.gmk @@ -74,15 +74,6 @@ SCRIPT_SUFFIX = CC_OBJECT_OUTPUT_FLAG = -o #trailing blank required! CC_PROGRAM_OUTPUT_FLAG = -o #trailing blank required! -# -# Default HPI libraries. Build will build only native unless -# overriden at the make command line. This makes it convenient for -# people doing, say, a pthreads port -- they can create a posix -# directory here, and say "gnumake HPIS=posix" at the top -# level. -# -HPIS = native - # # Java default optimization (-x04/-O2) etc. Applies to the VM. # diff --git a/jdk/make/common/Defs-windows.gmk b/jdk/make/common/Defs-windows.gmk index 19a7f6a6f75..d93a4832f70 100644 --- a/jdk/make/common/Defs-windows.gmk +++ b/jdk/make/common/Defs-windows.gmk @@ -43,7 +43,6 @@ FDDLIBM_SUFFIX = lib # The suffix applied to scripts (.bat for windows, nothing for unix) SCRIPT_SUFFIX = .bat -HPIS = windows # LIB_LOCATION, which for windows identifies where .exe files go, may be # set by each GNUmakefile. The default is BINDIR. ifndef LIB_LOCATION diff --git a/jdk/make/common/Defs.gmk b/jdk/make/common/Defs.gmk index 29abffd261e..6854d4e8708 100644 --- a/jdk/make/common/Defs.gmk +++ b/jdk/make/common/Defs.gmk @@ -271,10 +271,9 @@ DEMOSRCDIR = $(SHARE_SRC)/demo # An attempt is made to generate unique enough directories for the # generated files to not have name collisisons. Most build units # defines PRODUCT (except Release.gmk), but then they may or may -# not define PACKAGE, THREADIR (only HPI uses this), PROGRAM, and -# LIBRARY. This code chunk attempts to generate a unique -# OBJDIR/CLASSHDRDIR for each build unit based on which of those -# values are set within each build unit. +# not define PACKAGE, PROGRAM, and LIBRARY. This code attempts to +# generate a unique OBJDIR/CLASSHDRDIR for each build unit based +# on which of those values are set within each build unit. UNIQUE_LOCATION_STRING = tmp @@ -298,10 +297,6 @@ ifneq ($(LIBRARY),) endif endif -ifneq ($(THREADDIR),) - UNIQUE_LOCATION_STRING += /$(THREADDIR) -endif - # # Build units may or may not define MODULE. Default to "other". # diff --git a/jdk/make/common/Modules.gmk b/jdk/make/common/Modules.gmk index 0bca87467f0..c690e905b21 100644 --- a/jdk/make/common/Modules.gmk +++ b/jdk/make/common/Modules.gmk @@ -222,7 +222,7 @@ ifeq ($(PLATFORM), windows) @# Remove certain *.lib files $(CD) $(JRE_MODULE_IMAGE_DIR)/lib && \ $(RM) java.$(LIB_SUFFIX) jvm.$(LIB_SUFFIX) \ - hpi.$(LIB_SUFFIX) awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX) + awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX) ifeq ($(ARCH_DATA_MODEL), 32) @# The Java Kernel JRE image ships with a special VM. It is not included @# in the full JRE image, so remove it. Also, is it only for 32-bit windows. @@ -415,8 +415,7 @@ endif # !windows trim-module-image-jdk:: @# Remove tools that should not be part of SDK. for t in $(NOTJDKTOOLS); do \ - $(RM) $(JDK_MODULE_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX) \ - $(JDK_MODULE_IMAGE_DIR)/bin/*/native_threads/$${t}$(EXE_SUFFIX); \ + $(RM) $(JDK_MODULE_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX); \ done # Get list of Elf files in the jdk diff --git a/jdk/make/common/Release.gmk b/jdk/make/common/Release.gmk index 834d3379875..71d392fe666 100644 --- a/jdk/make/common/Release.gmk +++ b/jdk/make/common/Release.gmk @@ -133,7 +133,6 @@ JRE_DOCFILES += $(JRE_NAMECHANGE_DOCLIST:%=$(JRE_IMAGE_DIR)/%$(TEXT_SUFFIX)) # absolute directory names: note, these must exist prior to build # time - they are created in the main Makefile. JRE_IMAGE_BINDIR = $(JRE_IMAGE_DIR)/bin -JRE_IMAGE_THREADIR = $(JRE_IMAGE_DIR)/bin/*/native_threads MAINMANIFEST = $(JDK_TOPDIR)/make/tools/manifest.mf BEANMANIFEST = $(JDK_TOPDIR)/make/javax/swing/beaninfo/manifest @@ -802,7 +801,7 @@ ifeq ($(PLATFORM), windows) @# Remove certain *.lib files $(CD) $(JRE_IMAGE_DIR)/lib && \ $(RM) java.$(LIB_SUFFIX) jvm.$(LIB_SUFFIX) \ - hpi.$(LIB_SUFFIX) awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX) + awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX) ifeq ($(ARCH_DATA_MODEL), 32) @# The Java Kernel JRE image ships with a special VM. It is not included @# in the full JRE image, so remove it. Also, is it only for 32-bit windows. @@ -1089,8 +1088,7 @@ endif # !windows trim-image-jdk:: @# Remove tools that should not be part of SDK. for t in $(NOTJDKTOOLS); do \ - $(RM) $(JDK_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX) \ - $(JDK_IMAGE_DIR)/bin/*/native_threads/$${t}$(EXE_SUFFIX); \ + $(RM) $(JDK_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX); \ done # Get list of Elf files in the jdk diff --git a/jdk/make/java/Makefile b/jdk/make/java/Makefile index 3a697d2ff86..f988fe95d07 100644 --- a/jdk/make/java/Makefile +++ b/jdk/make/java/Makefile @@ -34,7 +34,7 @@ include $(BUILDDIR)/common/Defs.gmk # # The order of subdirs here is important # -SUBDIRS += hpi version jvm redist verify fdlibm java sun_nio jli main zip +SUBDIRS += version jvm redist verify fdlibm java sun_nio jli main zip # Others # Note: java_crw_demo java_hprof_demo are demos but must be delivered built in sdk diff --git a/jdk/make/java/fdlibm/Makefile b/jdk/make/java/fdlibm/Makefile index 584f67e2dc9..c4778af3e93 100644 --- a/jdk/make/java/fdlibm/Makefile +++ b/jdk/make/java/fdlibm/Makefile @@ -24,7 +24,7 @@ # # -# Makefile for native threads HPI. +# Makefile for fdlibm # # Note: # The fdlibm libraries are built using special rules in Library.gmk. diff --git a/jdk/make/java/hpi/Makefile b/jdk/make/java/hpi/Makefile deleted file mode 100644 index 3d3688a9970..00000000000 --- a/jdk/make/java/hpi/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# 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. -# - -# -# Build HPI (Host Porting Interface) libraries -# - -BUILDDIR = ../.. -include $(BUILDDIR)/common/Defs.gmk - -# -# Build specified the HPI implementations -# -SUBDIRS = $(HPIS) -include $(BUILDDIR)/common/Subdirs.gmk - -all build clean clobber:: - $(SUBDIRS-loop) - diff --git a/jdk/make/java/hpi/hpi_common.gmk b/jdk/make/java/hpi/hpi_common.gmk deleted file mode 100644 index df5796f10e2..00000000000 --- a/jdk/make/java/hpi/hpi_common.gmk +++ /dev/null @@ -1,90 +0,0 @@ -# -# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# 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. -# - -# -# Shared files between the different threads types on Solaris. Be -# careful when including this, you must get your variables right. -# - -# -# Common files on Solaris. -# -ifneq ($(PLATFORM), windows) -FILES_c += \ - interrupt.c \ - linker_md.c \ - memory_md.c \ - system_md.c \ - hpi.c -endif - -# -# Include paths can also be shared. -# -ifneq ($(PLATFORM), windows) -OTHER_INCLUDES += \ - -I$(PLATFORM_SRC)/hpi/$(THREADDIR)/include \ - -I$(PLATFORM_SRC)/hpi/include \ - -I$(PLATFORM_SRC)/hpi/export \ - -I$(SHARE_SRC)/hpi/include \ - -I$(SHARE_SRC)/hpi/export -else -OTHER_INCLUDES += \ - -I$(PLATFORM_SRC)/hpi/include \ - -I$(PLATFORM_SRC)/hpi/export \ - -I$(SHARE_SRC)/hpi/include \ - -I$(SHARE_SRC)/hpi/export -endif - -# -# Add to the default C and assembly file search paths. Clear any initial -# vpath settings to ensure that we don't look in unexpected places for HPI -# files. -# -vpath %.c -vpath %.c $(PLATFORM_SRC)/hpi/$(THREADDIR)/src -vpath %.c $(PLATFORM_SRC)/hpi/src -vpath %.c $(SHARE_SRC)/hpi/src - -vpath %.s -vpath %.s $(PLATFORM_SRC)/hpi/$(THREADDIR)/src -vpath %.s $(PLATFORM_SRC)/hpi/src - -# -# By default leave out locking statistics -# -ifneq ($(PLATFORM), windows) -LOCKSTATS = false -ifeq ($(LOCKSTATS), true) - CFLAGS_COMMON += -DLOCKSTATS -endif -endif - -# -# Things that must be linked in. -# -ifneq ($(PLATFORM), windows) -OTHER_LDLIBS += $(LIBSOCKET) $(LIBNSL) $(LIBM) -ldl -endif diff --git a/jdk/make/java/hpi/native/Makefile b/jdk/make/java/hpi/native/Makefile deleted file mode 100644 index 2655e8248f8..00000000000 --- a/jdk/make/java/hpi/native/Makefile +++ /dev/null @@ -1,93 +0,0 @@ -# -# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# 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. -# - -# -# Makefile for native threads HPI. -# - -BUILDDIR = ../../.. -MODULE = base -LIBRARY = hpi -PRODUCT = java -THREADDIR = native_threads -LIB_LOCATION = $(LIBDIR)/$(LIBARCH)/$(THREADDIR) -include $(BUILDDIR)/common/Defs.gmk - -# -# Native threads specific C and .s files. -# -FILES_c = \ - monitor_md.c \ - threads_md.c \ - condvar_md.c \ - interrupt_md.c \ - mutex_md.c \ - sys_api_td.c \ - threads_$(PLATFORM).c - -# -# Other files/flags shared between the HPIs. -# -include $(BUILDDIR)/java/hpi/hpi_common.gmk - -# -# Rules for the .so file. -# -ifeq ($(PLATFORM), solaris) - ifneq ($(ARCH), amd64) - FILES_reorder += reorder-$(ARCH) - endif -endif -include $(BUILDDIR)/common/Mapfile-vers.gmk -include $(BUILDDIR)/common/Library.gmk - -# -# HPI flags for native threads. -# -OTHER_CPPFLAGS += -D_REENTRANT -DNATIVE - -ifeq ($(USE_PTHREADS),true) -OTHER_CPPFLAGS += -DUSE_PTHREADS -ifeq ($(MOOT_PRIORITIES),true) -OTHER_CPPFLAGS += -DMOOT_PRIORITIES -endif -LIBPOSIX4 = -lposix4 -OTHER_LDLIBS += -lpthread $(LIBPOSIX4) -endif - -HAVE_GETHRVTIME=true -ifeq ($(HAVE_GETHRVTIME),true) -OTHER_CPPFLAGS += -DHAVE_GETHRVTIME -endif - -HAVE_FILIOH=true -ifeq ($(HAVE_FILIOH),true) -OTHER_CPPFLAGS += -DHAVE_FILIOH -endif - -ifeq ($(NO_INTERRUPTIBLE_IO),true) -OTHER_CPPFLAGS += -DNO_INTERRUPTIBLE_IO -endif - diff --git a/jdk/make/java/hpi/native/mapfile-vers b/jdk/make/java/hpi/native/mapfile-vers deleted file mode 100644 index c7b9e6d9ead..00000000000 --- a/jdk/make/java/hpi/native/mapfile-vers +++ /dev/null @@ -1,32 +0,0 @@ -# -# Copyright (c) 2000, 2002, 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. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# 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. -# - -SUNWprivate_1.1 { - global: - DLL_Initialize; - - local: - *; -}; diff --git a/jdk/make/java/hpi/native/reorder-i586 b/jdk/make/java/hpi/native/reorder-i586 deleted file mode 100644 index 69c4ced4a6c..00000000000 --- a/jdk/make/java/hpi/native/reorder-i586 +++ /dev/null @@ -1,27 +0,0 @@ -data = R0x2000; -text = LOAD ?RXO; -# Test Null -text: .text%_init; -text: .text%checkForCorrectLibthread: OUTPUTDIR/tmp/java/hpi/native_threads/obj/threads_solaris.o; -text: .text%init64IO: OUTPUTDIR/tmp/java/hpi/native_threads/obj/system_md.o; -text: .text%DLL_Initialize; -text: .text%GetInterface: OUTPUTDIR/tmp/java/hpi/native_threads/obj/hpi.o; -text: .text%sysBuildLibName; -text: .text%sysLoadLibrary; -text: .text%sysFindLibraryEntry; -text: .text%sysNativePath; -text: .text%sysOpen; -text: .text%sysSeek; -text: .text%lseek64_w; -# Test Exit -# Test Hello -# Test Sleep -# Test IntToString -# Test LoadToolkit -text: .text%sysAvailable; -text: .text%sysFfileMode; -text: .text%sysGetLastErrorString; -# Test LoadFrame -# Test LoadJFrame -# Test JHello -# SwingSet diff --git a/jdk/make/java/hpi/native/reorder-sparc b/jdk/make/java/hpi/native/reorder-sparc deleted file mode 100644 index 4a180d9cbfe..00000000000 --- a/jdk/make/java/hpi/native/reorder-sparc +++ /dev/null @@ -1,26 +0,0 @@ -data = R0x2000; -text = LOAD ?RXO; -# Test Null -text: .text%checkForCorrectLibthread: OUTPUTDIR/tmp/java/hpi/native_threads/obj/threads_solaris.o; -text: .text%init64IO: OUTPUTDIR/tmp/java/hpi/native_threads/obj/system_md.o; -text: .text%DLL_Initialize; -text: .text%GetInterface: OUTPUTDIR/tmp/java/hpi/native_threads/obj/hpi.o; -text: .text%sysBuildLibName; -text: .text%sysLoadLibrary; -text: .text%sysFindLibraryEntry; -text: .text%sysNativePath; -text: .text%sysOpen; -text: .text%sysFfileMode; -text: .text%sysSeek; -text: .text%lseek64_w; -text: .text%sysAvailable; -# Test Exit -# Test Hello -# Test Sleep -# Test IntToString -# Test LoadToolkit -text: .text%sysGetLastErrorString; -# Test LoadFrame -# Test LoadJFrame -# Test JHello -# SwingSet diff --git a/jdk/make/java/hpi/native/reorder-sparcv9 b/jdk/make/java/hpi/native/reorder-sparcv9 deleted file mode 100644 index 6ac7b06a0bc..00000000000 --- a/jdk/make/java/hpi/native/reorder-sparcv9 +++ /dev/null @@ -1,26 +0,0 @@ -data = R0x2000; -text = LOAD ?RXO; -# Test Null -text: .text%checkForCorrectLibthread: OUTPUTDIR/tmp/java/hpi/native_threads/obj64/threads_solaris.o; -text: .text%init64IO: OUTPUTDIR/tmp/java/hpi/native_threads/obj64/system_md.o; -text: .text%DLL_Initialize; -text: .text%GetInterface: OUTPUTDIR/tmp/java/hpi/native_threads/obj64/hpi.o; -text: .text%sysBuildLibName; -text: .text%sysLoadLibrary; -text: .text%sysFindLibraryEntry; -text: .text%sysNativePath; -text: .text%sysOpen; -text: .text%sysFfileMode; -text: .text%sysSeek; -text: .text%lseek64_w; -text: .text%sysAvailable; -# Test Exit -# Test Hello -# Test Sleep -# Test IntToString -# Test LoadToolkit -text: .text%sysGetLastErrorString; -# Test LoadFrame -# Test LoadJFrame -# Test JHello -# SwingSet diff --git a/jdk/make/java/hpi/windows/Makefile b/jdk/make/java/hpi/windows/Makefile deleted file mode 100644 index bf6f818fdf4..00000000000 --- a/jdk/make/java/hpi/windows/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -# -# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# 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. -# - -# -# Makefile for Windows HPI DLL -# -BUILDDIR = ../../.. -MODULE = base -LIBRARY = hpi -PRODUCT = java -THREADDIR = windows_threads -LIB_LOCATION = $(BINDIR) - -include $(BUILDDIR)/common/Defs.gmk - -# windows compiler flags -ifeq ($(PLATFORM),windows) - CPPFLAGS_DBG += -DLOGGING -endif - -FILES_c = \ - linker_md.c \ - memory_md.c \ - monitor_md.c \ - path_md.c \ - socket_md.c \ - sys_api_md.c \ - system_md.c \ - threads_md.c \ - hpi.c # trailing blank required! - -JVMLIB = -JAVALIB = -OTHER_LCF = -export:DLL_Initialize -EXTRA_LIBS = - - -# -# Other files/flags shared between the HPIs. -# -include $(BUILDDIR)/java/hpi/hpi_common.gmk - -# -# Rules for the .so file. -# -include $(BUILDDIR)/common/Library.gmk - diff --git a/jdk/make/tools/reorder/Makefile b/jdk/make/tools/reorder/Makefile index 69178f11ce7..39439667530 100644 --- a/jdk/make/tools/reorder/Makefile +++ b/jdk/make/tools/reorder/Makefile @@ -85,7 +85,6 @@ reorder.jar : $(REORDER_JAR) libs.reorder : ifeq ($(PLATFORM), solaris) $(MAKE) LIBBLDDIR=java/zip LIBTMPDIR=sun/java.util.zip/zip reorder.lib - $(MAKE) LIBBLDDIR=java/hpi/native LIBTMPDIR=java/hpi/native_threads reorder.lib $(MAKE) LIBBLDDIR=java/java LIBTMPDIR=java/java.lang/java reorder.lib $(MAKE) LIBBLDDIR=java/nio LIBTMPDIR=java/java.nio/nio reorder.lib $(MAKE) LIBBLDDIR=sun/font LIBTMPDIR=sun/sun.awt.font/fontmanager reorder.lib @@ -96,7 +95,6 @@ endif libs.copy: ifeq ($(PLATFORM), solaris) $(CP) $(OUTDIR)/reorder_java_zip-$(ARCH) ../../java/zip/reorder-$(ARCH) - $(CP) $(OUTDIR)/reorder_java_hpi_native-$(ARCH) ../../java/hpi/native/reorder-$(ARCH) $(CP) $(OUTDIR)/reorder_java_java-$(ARCH) ../../java/java/reorder-$(ARCH) $(CP) $(OUTDIR)/reorder_sun_font-$(ARCH) ../../sun/font/reorder-$(ARCH) $(CP) $(OUTDIR)/reorder_sun_jpeg-$(ARCH) ../../sun/jpeg/reorder-$(ARCH) diff --git a/jdk/src/share/hpi/export/bool.h b/jdk/src/share/hpi/export/bool.h deleted file mode 100644 index e87c5a9e4ce..00000000000 --- a/jdk/src/share/hpi/export/bool.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#ifndef _JAVASOFT_BOOL_H_ -#define _JAVASOFT_BOOL_H_ - -#undef TRUE -#undef FALSE - -typedef enum { - FALSE = 0, - TRUE = 1 -} bool_t; - -#endif /* !_JAVASOFT_BOOL_H_ */ diff --git a/jdk/src/share/hpi/export/dll.h b/jdk/src/share/hpi/export/dll.h deleted file mode 100644 index 76403eef6d3..00000000000 --- a/jdk/src/share/hpi/export/dll.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#ifndef _JAVASOFT_DLL_H_ -#define _JAVASOFT_DLL_H_ - -#include - -/* DLL.H: A common interface for helper DLLs loaded by the VM. - * Each library exports the main entry point "DLL_Initialize". Through - * that function the programmer can obtain a function pointer which has - * type "GetInterfaceFunc." Through the function pointer the programmer - * can obtain other interfaces supported in the DLL. - */ -#ifdef __cplusplus -extern "C" { -#endif - -typedef jint (JNICALL * GetInterfaceFunc) - (void **intfP, const char *name, jint ver); - -jint JNICALL DLL_Initialize(GetInterfaceFunc *, void *args); - -#ifdef __cplusplus -} -#endif - -#endif /* !_JAVASOFT_DLL_H_ */ diff --git a/jdk/src/share/hpi/export/hpi.h b/jdk/src/share/hpi/export/hpi.h deleted file mode 100644 index 6fb6be84578..00000000000 --- a/jdk/src/share/hpi/export/hpi.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Host Porting Interface. This defines the "porting layer" for - * POSIX.1 compliant operating systems. - */ - -#ifndef _JAVASOFT_HPI_H_ -#define _JAVASOFT_HPI_H_ - -#include -#include - -#include "jni.h" -#include "bool.h" -#include "hpi_md.h" -#include "dll.h" - -#ifdef __solaris__ -#define SSIZE_T ssize_t -#else -#ifdef _LP64 -#define SSIZE_T ssize_t -#else -#define SSIZE_T int -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * memory allocations - */ -typedef struct { - /* - * Malloc must return a unique pointer if size == 0. - */ - void * (*Malloc)(size_t size); - void * (*Realloc)(void *ptr, size_t new_size); - /* - * Free must allow ptr == NULL to be a no-op. - */ - void (*Free)(void *ptr); - /* - * Calloc must return a unique pointer for if - * n_item == 0 || item_size == 0. - */ - void * (*Calloc)(size_t n_item, size_t item_size); - char * (*Strdup)(const char *str); - - void * (*MapMem)(size_t req_size, size_t *maped_size); - void * (*UnmapMem)(void *req_addr, size_t req_size, size_t *unmap_size); - /* - * CommitMem should round the ptr down to the nearest page and - * round the size up to the nearest page so that the committed - * region is at least as large as the requested region. - */ - void * (*CommitMem)(void *ptr, size_t size, size_t *actual); - /* - * sysDecommitMem should round the ptr up to the nearest page and - * round the size down to the nearest page so that the decommitted - * region is no greater than the requested region. - */ - void * (*DecommitMem)(void *ptr, size_t size, size_t *actual); - -#define HPI_PAGE_ALIGNMENT (64 * 1024) - - void * (*AllocBlock)(size_t size, void **headP); - void (*FreeBlock)(void *head); -} HPI_MemoryInterface; - -/* - * dynamic linking libraries - */ -typedef struct { - void (*BuildLibName)(char *buf, int buf_len, char *path, char *name); - int (*BuildFunName)(char *name, int name_len, int arg_size, int en_idx); - - void * (*LoadLibrary)(const char *name, char *err_buf, int err_buflen); - void (*UnloadLibrary)(void *lib); - void * (*FindLibraryEntry)(void *lib, const char *name); -} HPI_LibraryInterface; - -typedef void (*signal_handler_t)(int sig, void *siginfo, void *context); - -#define HPI_SIG_DFL (signal_handler_t)0 -#define HPI_SIG_ERR (signal_handler_t)-1 -#define HPI_SIG_IGN (signal_handler_t)1 - -typedef struct { - char *name; /* name such as green/native threads. */ - int isMP; -} HPI_SysInfo; - -typedef struct { - HPI_SysInfo * (*GetSysInfo)(void); - long (*GetMilliTicks)(void); - jlong (*TimeMillis)(void); - - signal_handler_t (*Signal)(int sig, signal_handler_t handler); - void (*Raise)(int sig); - void (*SignalNotify)(int sig); - int (*SignalWait)(void); - - int (*Shutdown)(void); - - int (*SetLoggingLevel)(int level); - bool_t (*SetMonitoringOn)(bool_t on); - int (*GetLastErrorString)(char *buf, int len); -} HPI_SystemInterface; - -/* - * threads and monitors - */ -typedef struct sys_thread sys_thread_t; -typedef struct sys_mon sys_mon_t; - -#define HPI_OK 0 -#define HPI_ERR -1 -#define HPI_INTRPT -2 /* Operation was interrupted */ -#define HPI_TIMEOUT -3 /* A timer ran out */ -#define HPI_NOMEM -5 /* Ran out of memory */ -#define HPI_NORESOURCE -6 /* Ran out of some system resource */ - -/* There are three basic states: RUNNABLE, MONITOR_WAIT, and CONDVAR_WAIT. - * When the thread is suspended in any of these states, the - * HPI_THREAD_SUSPENDED bit will be set - */ -enum { - HPI_THREAD_RUNNABLE = 1, - HPI_THREAD_MONITOR_WAIT, - HPI_THREAD_CONDVAR_WAIT -}; - -#define HPI_MINIMUM_PRIORITY 1 -#define HPI_MAXIMUM_PRIORITY 10 -#define HPI_NORMAL_PRIORITY 5 - -#define HPI_THREAD_SUSPENDED 0x8000 -#define HPI_THREAD_INTERRUPTED 0x4000 - -typedef struct { - sys_thread_t *owner; - long entry_count; - sys_thread_t **monitor_waiters; - sys_thread_t **condvar_waiters; - int sz_monitor_waiters; - int sz_condvar_waiters; - int n_monitor_waiters; - int n_condvar_waiters; -} sys_mon_info; - -typedef struct { - int (*ThreadBootstrap)(sys_thread_t **tidP, - sys_mon_t **qlockP, - int nReservedBytes); - int (*ThreadCreate)(sys_thread_t **tidP, - long stk_size, - void (*func)(void *), - void *arg); - sys_thread_t * (*ThreadSelf)(void); - void (*ThreadYield)(void); - int (*ThreadSuspend)(sys_thread_t *tid); - int (*ThreadResume)(sys_thread_t *tid); - int (*ThreadSetPriority)(sys_thread_t *tid, int prio); - int (*ThreadGetPriority)(sys_thread_t *tid, int *prio); - void * (*ThreadStackPointer)(sys_thread_t *tid); - void * (*ThreadStackTop)(sys_thread_t *tid); - long * (*ThreadRegs)(sys_thread_t *tid, int *regs); - int (*ThreadSingle)(void); - void (*ThreadMulti)(void); - int (*ThreadEnumerateOver)(int (*func)(sys_thread_t *, void *), - void *arg); - int (*ThreadCheckStack)(void); - void (*ThreadPostException)(sys_thread_t *tid, void *arg); - void (*ThreadInterrupt)(sys_thread_t *tid); - int (*ThreadIsInterrupted)(sys_thread_t *tid, int clear); - int (*ThreadAlloc)(sys_thread_t **tidP); - int (*ThreadFree)(void); - jlong (*ThreadCPUTime)(void); - int (*ThreadGetStatus)(sys_thread_t *tid, sys_mon_t **monitor); - void * (*ThreadInterruptEvent)(void); - void * (*ThreadNativeID)(sys_thread_t *tid); - - /* These three functions are used by the CPU time profiler. - * sysThreadIsRunning determines whether the thread is running (not just - * runnable). It is only safe to call this function after calling - * sysThreadProfSuspend. - */ - bool_t (*ThreadIsRunning)(sys_thread_t *tid); - void (*ThreadProfSuspend)(sys_thread_t *tid); - void (*ThreadProfResume)(sys_thread_t *tid); - - int (*AdjustTimeSlice)(int ms); - - size_t (*MonitorSizeof)(void); - int (*MonitorInit)(sys_mon_t *mid); - int (*MonitorDestroy)(sys_mon_t *mid); - int (*MonitorEnter)(sys_thread_t *self, sys_mon_t *mid); - bool_t (*MonitorEntered)(sys_thread_t *self, sys_mon_t *mid); - int (*MonitorExit)(sys_thread_t *self, sys_mon_t *mid); - int (*MonitorNotify)(sys_thread_t *self, sys_mon_t *mid); - int (*MonitorNotifyAll)(sys_thread_t *self, sys_mon_t *mid); - int (*MonitorWait)(sys_thread_t *self, sys_mon_t *mid, jlong ms); - bool_t (*MonitorInUse)(sys_mon_t *mid); - sys_thread_t * (*MonitorOwner)(sys_mon_t *mid); - int (*MonitorGetInfo)(sys_mon_t *mid, sys_mon_info *info); - -} HPI_ThreadInterface; - -/* - * files - */ - -#define HPI_FILETYPE_REGULAR (0) -#define HPI_FILETYPE_DIRECTORY (1) -#define HPI_FILETYPE_OTHER (2) - -typedef struct { - char * (*NativePath)(char *path); - int (*FileType)(const char *path); - int (*Open)(const char *name, int openMode, int filePerm); - int (*Close)(int fd); - jlong (*Seek)(int fd, jlong offset, int whence); - int (*SetLength)(int fd, jlong length); - int (*Sync)(int fd); - int (*Available)(int fd, jlong *bytes); - size_t (*Read)(int fd, void *buf, unsigned int nBytes); - size_t (*Write)(int fd, const void *buf, unsigned int nBytes); - int (*FileSizeFD)(int fd, jlong *size); -} HPI_FileInterface; - -/* - * sockets - */ -struct sockaddr; -struct hostent; - -typedef struct { - int (*Close)(int fd); - long (*Available)(int fd, jint *pbytes); - int (*Connect)(int fd, struct sockaddr *him, int len); - int (*Accept)(int fd, struct sockaddr *him, int *len); - SSIZE_T (*SendTo)(int fd, char *buf, int len, int flags, - struct sockaddr *to, int tolen); - SSIZE_T (*RecvFrom)(int fd, char *buf, int nbytes, int flags, - struct sockaddr *from, int *fromlen); - int (*Listen)(int fd, int count); - SSIZE_T (*Recv)(int fd, char *buf, int nBytes, int flags); - SSIZE_T (*Send)(int fd, char *buf, int nBytes, int flags); - int (*Timeout)(int fd, long timeout); - struct hostent * (*GetHostByName)(char *hostname); - int (*Socket)(int domain, int type, int protocol); - int (*SocketShutdown)(int fd, int howto); - int (*Bind)(int fd, struct sockaddr *him, int len); - int (*GetSocketName)(int fd, struct sockaddr *him, int *len); - int (*GetHostName)(char *hostname, int namelen); - struct hostent * (*GetHostByAddr)(const char *hostname, int len, int type); - int (*SocketGetOption)(int fd, int level, int optname, char *optval, int *optlen); - int (*SocketSetOption)(int fd, int level, int optname, const char *optval, int optlen); - struct protoent * (*GetProtoByName)(char* name); -} HPI_SocketInterface; - -/* - * callbacks. - */ -typedef struct vm_calls { - int (*jio_fprintf)(FILE *fp, const char *fmt, ...); - void (*panic)(const char *fmt, ...); - void (*monitorRegister)(sys_mon_t *mid, char *info_str); - - void (*monitorContendedEnter)(sys_thread_t *self, sys_mon_t *mid); - void (*monitorContendedEntered)(sys_thread_t *self, sys_mon_t *mid); - void (*monitorContendedExit)(sys_thread_t *self, sys_mon_t *mid); -} vm_calls_t; - -#ifdef __cplusplus -} -#endif - -#endif /* !_JAVASOFT_HPI_H_ */ diff --git a/jdk/src/share/hpi/include/hpi_impl.h b/jdk/src/share/hpi/include/hpi_impl.h deleted file mode 100644 index 72f8d36e2d6..00000000000 --- a/jdk/src/share/hpi/include/hpi_impl.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#ifndef _JAVASOFT_HPI_IMPL_H_ -#define _JAVASOFT_HPI_IMPL_H_ - -#include "hpi.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include "vm_calls.h" - -extern int nReservedBytes; -sys_thread_t *allocThreadBlock(void); -void freeThreadBlock(sys_thread_t *tid); -int threadBootstrapMD(sys_thread_t **tid, sys_mon_t **lockP, int nb); - -HPI_SysInfo *sysGetSysInfo(void); -long sysGetMilliTicks(void); -jlong sysTimeMillis(void); - -signal_handler_t sysSignal(int sig, signal_handler_t handler); -void sysRaise(int sig); -void sysSignalNotify(int sig); -int sysSignalWait(void); -int sysShutdown(void); -int sysSetLoggingLevel(int level); -bool_t sysSetMonitoringOn(bool_t on); -int sysGetLastErrorString(char *buf, int len); - -void * sysMalloc(size_t); -void * sysRealloc(void*, size_t); -void sysFree(void*); -void * sysCalloc(size_t, size_t); -char * sysStrdup(const char * string); -void * sysMapMem(size_t, size_t *); -void * sysUnmapMem(void *, size_t, size_t *); -void * sysCommitMem(void * ptr, size_t size, size_t * actual); -void * sysDecommitMem(void * ptr, size_t size, size_t * actual); -void * sysAllocBlock(size_t, void**); -void sysFreeBlock(void *); - -void sysBuildLibName(char *, int, char *, char *); -int sysBuildFunName(char *, int, int, int); -void * sysLoadLibrary(const char *, char *err_buf, int err_buflen); -void sysUnloadLibrary(void *); -void * sysFindLibraryEntry(void *, const char *); - -int sysThreadBootstrap(sys_thread_t **, sys_mon_t **, int); -int sysThreadCreate(sys_thread_t **, - long, - void (*)(void *), - void *arg); -void sysThreadExit(void); -sys_thread_t * sysThreadSelf(void); -void sysThreadYield(void); -int sysThreadSuspend(sys_thread_t *); -int sysThreadResume(sys_thread_t *); -int sysThreadSetPriority(sys_thread_t *, int); -int sysThreadGetPriority(sys_thread_t *, int *); -void * sysThreadStackPointer(sys_thread_t *); -void * sysThreadStackTop(sys_thread_t *); -long * sysThreadRegs(sys_thread_t *, int *); -int sysThreadSingle(void); -void sysThreadMulti(void); -int sysThreadEnumerateOver(int (*)(sys_thread_t *, void *), void *); -int sysThreadCheckStack(void); -void sysThreadPostException(sys_thread_t *, void *); -void sysThreadInterrupt(sys_thread_t *); -int sysThreadIsInterrupted(sys_thread_t *, int); -int sysThreadAlloc(sys_thread_t **); -int sysThreadFree(void); -size_t sysThreadSizeof(void); -jlong sysThreadCPUTime(void); -int sysThreadGetStatus(sys_thread_t *, sys_mon_t **); -int sysAdjustUserThreadCount(int delta); -bool_t sysThreadIsRunning(sys_thread_t *); -void sysThreadProfSuspend(sys_thread_t *); -void sysThreadProfResume(sys_thread_t *); -int sysAdjustTimeSlice(int); -int sysThreadEnumerateOver(int (*f)(sys_thread_t *, void *), void *arg); -void * sysThreadInterruptEvent(void); -void * sysThreadNativeID(sys_thread_t *); - -size_t sysMonitorSizeof(void); -int sysMonitorInit(sys_mon_t *); -int sysMonitorDestroy(sys_mon_t *); -int sysMonitorEnter(sys_thread_t *, sys_mon_t *); -bool_t sysMonitorEntered(sys_thread_t *, sys_mon_t *); -int sysMonitorExit(sys_thread_t *, sys_mon_t *); -int sysMonitorNotify(sys_thread_t *, sys_mon_t *); -int sysMonitorNotifyAll(sys_thread_t *, sys_mon_t *); -int sysMonitorWait(sys_thread_t *, sys_mon_t *, jlong); -bool_t sysMonitorInUse(sys_mon_t *); -sys_thread_t * sysMonitorOwner(sys_mon_t *); -int sysMonitorGetInfo(sys_mon_t *, sys_mon_info *); - -char *sysNativePath(char *path); -int sysFileType(const char *path); -int sysOpen(const char *name, int openMode, int filePerm); -int sysClose(int fd); -jlong sysSeek(int fd, jlong offset, int whence); -int sysSetLength(int fd, jlong length); -int sysSync(int fd); -int sysAvailable(int fd, jlong *bytes); -size_t sysRead(int fd, void *buf, unsigned int nBytes); -size_t sysWrite(int fd, const void *buf, unsigned int nBytes); -int sysFileSizeFD(int fd, jlong *size); - -int sysSocketClose(int fd); -int sysSocketShutdown(int fd, int howto); -long sysSocketAvailable(int fd, jint *pbytes); -int sysConnect(int fd, struct sockaddr *him, int len); -int sysBind(int fd, struct sockaddr *him, int len); -int sysAccept(int fd, struct sockaddr *him, int *len); -int sysGetSockName(int fd, struct sockaddr *him, int *len); -#ifdef _LP64 -ssize_t sysSendTo(int fd, char *buf, int len, int flags, struct sockaddr *to, - int tolen); -ssize_t sysRecvFrom(int fd, char *buf, int nbytes, int flags, - struct sockaddr *from, int *fromlen); -ssize_t sysRecv(int fd, char *buf, int nBytes, int flags); -ssize_t sysSend(int fd, char *buf, int nBytes, int flags); -#else -int sysSendTo(int fd, char *buf, int len, int flags, struct sockaddr *to, - int tolen); -int sysRecvFrom(int fd, char *buf, int nbytes, int flags, - struct sockaddr *from, int *fromlen); -int sysRecv(int fd, char *buf, int nBytes, int flags); -int sysSend(int fd, char *buf, int nBytes, int flags); -#endif -int sysListen(int fd, int count); -int sysTimeout(int fd, long timeout); -int sysGetHostName(char* name, int namelen); -struct hostent *sysGetHostByAddr(const char* name, int len, int type); -struct hostent *sysGetHostByName(char *hostname); -int sysSocket(int domain, int type, int protocol); -int sysGetSockOpt(int fd, int level, int optname, char *optval, int *optlen); -int sysSetSockOpt(int fd, int level, int optname, const char *optval, int optlen); -struct protoent * sysGetProtoByName(char* name); - -#define SYS_SIG_DFL HPI_SIG_DFL -#define SYS_SIG_ERR HPI_SIG_ERR -#define SYS_SIG_IGN HPI_SIG_IGN - -#define SYS_OK HPI_OK -#define SYS_ERR HPI_ERR -#define SYS_INTRPT HPI_INTRPT -#define SYS_TIMEOUT HPI_TIMEOUT -#define SYS_NOMEM HPI_NOMEM -#define SYS_NORESOURCE HPI_NORESOURCE - -#define SYS_THREAD_RUNNABLE HPI_THREAD_RUNNABLE -#define SYS_THREAD_MONITOR_WAIT HPI_THREAD_MONITOR_WAIT -#define SYS_THREAD_CONDVAR_WAIT HPI_THREAD_CONDVAR_WAIT - -#define MinimumPriority HPI_MINIMUM_PRIORITY -#define MaximumPriority HPI_MAXIMUM_PRIORITY -#define NormalPriority HPI_NORMAL_PRIORITY - -#define SYS_THREAD_SUSPENDED HPI_THREAD_SUSPENDED - -#define PAGE_ALIGNMENT HPI_PAGE_ALIGNMENT - -#define SYS_TIMEOUT_INFINITY HPI_TIMEOUT_INFINITY - -#define SYS_FILETYPE_REGULAR HPI_FILETYPE_REGULAR -#define SYS_FILETYPE_DIRECTORY HPI_FILETYPE_DIRECTORY -#define SYS_FILETYPE_OTHER HPI_FILETYPE_OTHER - -typedef void *stackp_t; - -/* global vars */ - -extern int logging_level; -extern bool_t profiler_on; - -#ifdef __cplusplus -} -#endif - -#endif /* !_JAVASOFT_HPI_IMPL_H_ */ diff --git a/jdk/src/share/hpi/include/vm_calls.h b/jdk/src/share/hpi/include/vm_calls.h deleted file mode 100644 index 10037c4a97b..00000000000 --- a/jdk/src/share/hpi/include/vm_calls.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#ifndef _JAVASOFT_VM_CALLS_H_ -#define _JAVASOFT_VM_CALLS_H_ - -/* This file defines the function table and macros exported from the VM - * for the implementation of HPI. - */ - -extern vm_calls_t *vm_calls; - -#define VM_CALLS_READY() vm_calls -#define VM_CALL(f) (vm_calls->f) - -#undef sysAssert - -#ifdef DEBUG -#define sysAssert(expression) { \ - if (!(expression)) { \ - vm_calls->panic \ - ("\"%s\", line %d: assertion failure\n", __FILE__, __LINE__); \ - } \ -} -#else -#define sysAssert(expression) ((void) 0) -#endif - -#ifdef LOGGING - -#define Log(level, message) { \ - if (vm_calls && level <= logging_level) \ - vm_calls->jio_fprintf(stderr, message); \ -} - -#define Log1(level, message, x1) { \ - if (vm_calls && level <= logging_level) \ - vm_calls->jio_fprintf(stderr, message, (x1)); \ -} - -#define Log2(level, message, x1, x2) { \ - if (vm_calls && level <= logging_level) \ - vm_calls->jio_fprintf(stderr, message, (x1), (x2)); \ -} - -#define Log3(level, message, x1, x2, x3) { \ - if (vm_calls && level <= logging_level) \ - vm_calls->jio_fprintf(stderr, message, (x1), (x2), (x3)); \ -} - -#define Log4(level, message, x1, x2, x3, x4) { \ - if (vm_calls && level <= logging_level) \ - vm_calls->jio_fprintf(stderr, message, (x1), (x2), (x3), (x4)); \ -} - -#else - -#define Log(level, message) ((void) 0) -#define Log1(level, message, x1) ((void) 0) -#define Log2(level, message, x1, x2) ((void) 0) -#define Log3(level, message, x1, x2, x3) ((void) 0) -#define Log4(level, message, x1, x2, x3, x4) ((void) 0) - -#endif /* LOGGING */ - -#endif /* !_JAVASOFT_VM_CALLS_H_ */ diff --git a/jdk/src/share/hpi/src/hpi.c b/jdk/src/share/hpi/src/hpi.c deleted file mode 100644 index 09389d3cf69..00000000000 --- a/jdk/src/share/hpi/src/hpi.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 1998, 1999, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include - -#include "hpi_impl.h" -#include "threads_md.h" - -int logging_level = 0; -bool_t profiler_on = FALSE; - -int sysSetLoggingLevel(int level) -{ - int old = logging_level; - logging_level = level; - return old; -} - -bool_t sysSetMonitoringOn(bool_t s) -{ - bool_t old = profiler_on; - profiler_on = s; - return old; -} - -int nReservedBytes; - -sys_thread_t *allocThreadBlock() -{ - char *p = sysCalloc(nReservedBytes + sizeof(sys_thread_t), 1); - if (p == NULL) { - return NULL; - } - return (sys_thread_t *)(p + nReservedBytes); -} - -void freeThreadBlock(sys_thread_t *tid) -{ - sysFree((char *)tid - nReservedBytes); -} - -vm_calls_t *vm_calls = NULL; - -static HPI_MemoryInterface hpi_memory_interface = { - sysMalloc, - sysRealloc, - sysFree, - sysCalloc, - sysStrdup, - sysMapMem, - sysUnmapMem, - sysCommitMem, - sysDecommitMem, - sysAllocBlock, - sysFreeBlock, -}; - -static HPI_LibraryInterface hpi_library_interface = { - sysBuildLibName, - sysBuildFunName, - sysLoadLibrary, - sysUnloadLibrary, - sysFindLibraryEntry, -}; - -static HPI_SystemInterface hpi_system_interface = { - sysGetSysInfo, - sysGetMilliTicks, - sysTimeMillis, - sysSignal, - sysRaise, - sysSignalNotify, - sysSignalWait, - sysShutdown, - sysSetLoggingLevel, - sysSetMonitoringOn, - sysGetLastErrorString -}; - -static HPI_ThreadInterface hpi_thread_interface = { - sysThreadBootstrap, - sysThreadCreate, - sysThreadSelf, - sysThreadYield, - sysThreadSuspend, - sysThreadResume, - sysThreadSetPriority, - sysThreadGetPriority, - sysThreadStackPointer, - sysThreadStackTop, - sysThreadRegs, - sysThreadSingle, - sysThreadMulti, - sysThreadEnumerateOver, - sysThreadCheckStack, - sysThreadPostException, - sysThreadInterrupt, - sysThreadIsInterrupted, - sysThreadAlloc, - sysThreadFree, - sysThreadCPUTime, - sysThreadGetStatus, - sysThreadInterruptEvent, - sysThreadNativeID, - sysThreadIsRunning, - sysThreadProfSuspend, - sysThreadProfResume, - sysAdjustTimeSlice, - sysMonitorSizeof, - sysMonitorInit, - sysMonitorDestroy, - sysMonitorEnter, - sysMonitorEntered, - sysMonitorExit, - sysMonitorNotify, - sysMonitorNotifyAll, - sysMonitorWait, - sysMonitorInUse, - sysMonitorOwner, - sysMonitorGetInfo, -}; - -static HPI_FileInterface hpi_file_interface = { - sysNativePath, - sysFileType, - sysOpen, - sysClose, - sysSeek, - sysSetLength, - sysSync, - sysAvailable, - sysRead, - sysWrite, - sysFileSizeFD -}; - -static HPI_SocketInterface hpi_socket_interface = { - sysSocketClose, - sysSocketAvailable, - sysConnect, - sysAccept, - sysSendTo, - sysRecvFrom, - sysListen, - sysRecv, - sysSend, - sysTimeout, - sysGetHostByName, - sysSocket, - sysSocketShutdown, - sysBind, - sysGetSockName, - sysGetHostName, - sysGetHostByAddr, - sysGetSockOpt, - sysSetSockOpt, - sysGetProtoByName, -}; - -static jint JNICALL -GetInterface(void **intfP, const char *name, jint version) -{ - *intfP = NULL; - if (version != 1) { - return -1; - } - if (strcmp(name, "Memory") == 0) { - *intfP = &hpi_memory_interface; - return 0; - } - if (strcmp(name, "Library") == 0) { - *intfP = &hpi_library_interface; - return 0; - } - if (strcmp(name, "System") == 0) { - *intfP = &hpi_system_interface; - return 0; - } - if (strcmp(name, "Thread") == 0) { - *intfP = &hpi_thread_interface; - return 0; - } - if (strcmp(name, "File") == 0) { - *intfP = &hpi_file_interface; - return 0; - } - if (strcmp(name, "Socket") == 0) { - *intfP = &hpi_socket_interface; - return 0; - } - return -2; -} - -jint JNICALL -DLL_Initialize(GetInterfaceFunc *gi, void *args) -{ - vm_calls = args; - *gi = GetInterface; - return SYS_OK; -} diff --git a/jdk/src/solaris/hpi/export/byteorder_md.h b/jdk/src/solaris/hpi/export/byteorder_md.h deleted file mode 100644 index 3ba7232bb97..00000000000 --- a/jdk/src/solaris/hpi/export/byteorder_md.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Solaris-dependent byte order include - */ - -#ifndef _JAVASOFT_SOLARIS_BYTE_MD_H_ -#define _JAVASOFT_SOLARIS_BYTE_MD_H_ - -#include - -#endif /* !_JAVASOFT_SOLARIS_BYTE_MD_H_ */ diff --git a/jdk/src/solaris/hpi/export/hpi_md.h b/jdk/src/solaris/hpi/export/hpi_md.h deleted file mode 100644 index 92b96f50fc3..00000000000 --- a/jdk/src/solaris/hpi/export/hpi_md.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#ifndef _JAVASOFT_HPI_MD_H_ -#define _JAVASOFT_HPI_MD_H_ - -#include "timeval_md.h" -#include "io_md.h" -#include "path_md.h" -#include "byteorder_md.h" - -#define HPI_TIMEOUT_INFINITY ((jlong)(-1)) - -#endif /* !_JAVASOFT_HPI_MD_H_ */ diff --git a/jdk/src/solaris/hpi/export/io_md.h b/jdk/src/solaris/hpi/export/io_md.h deleted file mode 100644 index d1cc95d4938..00000000000 --- a/jdk/src/solaris/hpi/export/io_md.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Solaris-dependent I/O - */ - -#ifndef _JAVASOFT_SOLARIS_IO_MD_H_ -#define _JAVASOFT_SOLARIS_IO_MD_H_ - -#include -#include -#include -#include -#include -#include -#include - -#define LINE_SEPARATOR "\n" - -/* file system macros moved to sysmacros_md.h */ - -#endif /* !_JAVASOFT_SOLARIS_IO_MD_H_ */ diff --git a/jdk/src/solaris/hpi/export/path_md.h b/jdk/src/solaris/hpi/export/path_md.h deleted file mode 100644 index 3539437e340..00000000000 --- a/jdk/src/solaris/hpi/export/path_md.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Solaris-dependent search path definitions and API - */ - -#ifndef _JAVASOFT_SOLARIS_PATH_MD_H_ -#define _JAVASOFT_SOLARIS_PATH_MD_H_ - -#define PATH_SEPARATOR ":" -#define PATH_CURDIR "." - -#define DIR_SEPARATOR '/' -#define LOCAL_DIR_SEPARATOR '/' - -#endif /* !_JAVASOFT_SOLARIS_PATH_MD_H_ */ diff --git a/jdk/src/solaris/hpi/export/timeval_md.h b/jdk/src/solaris/hpi/export/timeval_md.h deleted file mode 100644 index 77148a850c4..00000000000 --- a/jdk/src/solaris/hpi/export/timeval_md.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#ifndef _JAVASOFT_SOLARIS_TIMEVAL_H_ -#define _JAVASOFT_SOLARIS_TIMEVAL_H_ - -typedef struct { - long tv_sec; /* seconds */ - long tv_usec; /* microseconds (NOT milliseconds) */ -} timeval_t; - -#endif /* !_JAVASOFT_SOLARIS_TIMEVAL_H_ */ diff --git a/jdk/src/solaris/hpi/include/hpi_init.h b/jdk/src/solaris/hpi/include/hpi_init.h deleted file mode 100644 index b657a86ccf4..00000000000 --- a/jdk/src/solaris/hpi/include/hpi_init.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#ifndef _JAVASOFT_SOLARIS_HPI_INIT_H_ -#define _JAVASOFT_SOLARIS_HPI_INIT_H_ - -#ifndef NATIVE -extern void InitializeSbrk(void); -extern void InitializeAsyncIO(void); -extern void InitializeHelperThreads(void); -#endif /* NATIVE */ - -extern void InitializeMem(void); - -#endif /* _JAVASOFT_SOLARIS_HPI_INIT_H_ */ diff --git a/jdk/src/solaris/hpi/include/interrupt.h b/jdk/src/solaris/hpi/include/interrupt.h deleted file mode 100644 index 9c273c0b8cb..00000000000 --- a/jdk/src/solaris/hpi/include/interrupt.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 1994, 2000, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Interrupt dispatch interface - */ - -#ifndef _JAVASOFT_INTERRUPT_H_ -#define _JAVASOFT_INTERRUPT_H_ - -/* - * Type definitions. - */ - -/*- - * A function that handles interrupt dispatch requests is of type - * intr_handler_t. This type definition is mostly for convenience. - * A declaration of a handler function, should look like this: - * - * void myHandler(int interrupt, void *siginfo, void *context, void *arg); - * - * An intr_handler_t is constrained: - * - * - It runs on the exception stack. - * - It cannot yield. - * - It cannot allocate/free memory. - * - It can only call interrupt-safe routines. - * - * "arg" is set to the "handlerArg" specified in intrRegister(). - */ -typedef void (*intr_handler_t)(int interrupt, void *siginfo, - void *context, void *arg); - -/* - * Routines. - */ - -/* Initialize the interrupt system */ -void intrInit(void); - -/* Set a handler for a particular interrupt */ -signal_handler_t intrRegister(int interrupt, intr_handler_t handler, - void *handlerArg); - -/* Dispatch an interrupt (called from the low-level handlers) */ -void intrDispatch(int interrupt, void *siginfo, void *context); - -/*- - * The target specific header file should define the following - * - * Constants - * - * N_INTERRUPTS - The number of interrupt channels. These - * are numbered from 0 to (N_INTERRUPTS - 1). - */ -#ifdef __linux__ -#define N_INTERRUPTS NSIG /* 0 to NSIG - 1*/ -#else -#define N_INTERRUPTS 32 /* 0 to 31 */ -#endif - -/*- - * Routines/Macros that control whether interrupts are enabled or - * not. - * - * void intrLock(void) - Disable all interrupts. - * void intrUnlock(void) - Enable all interrupts. - * - * Note: intrLock()/intrUnlock() pairs can be nested. - * - */ - -void intrLock(void); -void intrUnlock(void); - -/*- - * intrInitMD() -- - * Initialize the machine-dependant interrupt software. - * - * This routine should leave the all interrupts disabled as if - * one (1) intrLock() had been called. At the end of the - * bootstrap, a single intrUnlock(), will be called to turn - * interrupts on. - */ - -void intrInitMD(void); - -#if defined(__solaris__) && !defined(SA_SIGINFO) -#error signal.h has not been included? -#endif - -#ifdef SA_SIGINFO -/* Thread implementation dependent interrupt dispatcher. */ -void intrDispatchMD(int sig, siginfo_t *info, void *uc); -#else -void intrDispatchMD(int sig); -#endif - -/* Whether the signal is used by the HPI implementation */ -bool_t intrInUse(int sig); - -#endif /* !_JAVASOFT_INTERRUPT_H_ */ diff --git a/jdk/src/solaris/hpi/include/largefile.h b/jdk/src/solaris/hpi/include/largefile.h deleted file mode 100644 index 45305347588..00000000000 --- a/jdk/src/solaris/hpi/include/largefile.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1999, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#ifndef _JAVASOFT_LARGEFILE_SUPPORT_H_ -#define _JAVASOFT_LARGEFILE_SUPPORT_H_ - -#ifdef __solaris__ -#include "largefile_solaris.h" -#endif - -#ifdef __linux__ -#include "largefile_linux.h" -#endif - -/* - * Prototypes for wrappers that we define. These wrapper functions - * are low-level I/O routines that will use 64 bit versions if - * available, else revert to the 32 bit ones. - */ -extern off64_t lseek64_w(int fd, off64_t offset, int whence); -extern int fstat64_w(int fd, struct stat *buf); -extern int ftruncate64_w(int fd, off64_t length); -extern int open64_w(const char *path, int oflag, int mode); - -/* This is defined in system_md.c */ -extern int sysFfileMode(int fd, int* mode); - -#endif /* _JAVASOFT_LARGEFILE_SUPPORT_H_ */ diff --git a/jdk/src/solaris/hpi/include/largefile_linux.h b/jdk/src/solaris/hpi/include/largefile_linux.h deleted file mode 100644 index 580047bf49e..00000000000 --- a/jdk/src/solaris/hpi/include/largefile_linux.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 1999, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#ifndef _JAVASOFT_LINUX_LARGEFILE_SUPPORT_H_ -#define _JAVASOFT_LINUX_LARGEFILE_SUPPORT_H_ - -/* - * For building on glibc-2.0 we need to define stat64 here. - */ - -#include -#include - -#endif /* _JAVASOFT_LINUX_LARGEFILE_SUPPORT_H_ */ diff --git a/jdk/src/solaris/hpi/include/largefile_solaris.h b/jdk/src/solaris/hpi/include/largefile_solaris.h deleted file mode 100644 index b40666ffe97..00000000000 --- a/jdk/src/solaris/hpi/include/largefile_solaris.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 1998, 1999, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#ifndef _JAVASOFT_SOLARIS_LARGEFILE_SUPPORT_H_ -#define _JAVASOFT_SOLARIS_LARGEFILE_SUPPORT_H_ - -#include -#include - -/** - * This file contains the definitions for providing 64 bit File I/O support. - */ - -#if !defined(_LFS_LARGEFILE) || !_LFS_LARGEFILE - -#ifdef __GLIBC__ -typedef jlong longlong_t; -#endif - -/* - * This definition is from Solaris 2.6; it is required by systems that do not - * support large files (e.g., Solaris 2.5.1). - */ - -typedef longlong_t off64_t; /* offsets within files */ - - -#ifdef __GLIBC__ -/* Doesn't matter what these are, there is no 64 bit support. */ -typedef int u_longlong_t; -typedef int timestruc_t; -#define _ST_FSTYPSZ 1 -#endif /* __GLIBC__ */ - -/* - * The stat64 structure must be provided on systems without large file - * support (e.g., Solaris 2.5.1). These definitions are from Solaris 2.6 - * sys/stat.h and sys/types.h. - */ - -typedef u_longlong_t ino64_t; /* expanded inode type */ -typedef longlong_t blkcnt64_t; /* count of file blocks */ - -struct stat64 { - dev_t st_dev; - long st_pad1[3]; - ino64_t st_ino; - mode_t st_mode; - nlink_t st_nlink; - uid_t st_uid; - gid_t st_gid; - dev_t st_rdev; - long st_pad2[2]; - off64_t st_size; - timestruc_t st_atim; - timestruc_t st_mtim; - timestruc_t st_ctim; - long st_blksize; - blkcnt64_t st_blocks; - char st_fstype[_ST_FSTYPSZ]; - long st_pad4[8]; -}; - -#define O_LARGEFILE 0x2000 /* Solaris 2.6 sys/fcntl.h */ -#endif /* !_LFS_LARGEFILE */ - -#endif /* !_JAVASOFT_SOLARIS_LARGEFILE_SUPPORT_H_ */ diff --git a/jdk/src/solaris/hpi/native_threads/include/condvar_md.h b/jdk/src/solaris/hpi/native_threads/include/condvar_md.h deleted file mode 100644 index 0f86fbb5987..00000000000 --- a/jdk/src/solaris/hpi/native_threads/include/condvar_md.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Interface to condition variable HPI implementation for Solaris - */ - -#ifndef _JAVASOFT_CONDVAR_MD_H_ -#define _JAVASOFT_CONDVAR_MD_H_ - -#include "threads_md.h" - -typedef struct condvar { - cond_t cond; /* Manual-reset event for notifications */ - unsigned int counter; /* Current number of notifications */ -} condvar_t; - -int condvarInit(condvar_t *); -int condvarDestroy(condvar_t *); -int condvarWait(condvar_t *, mutex_t *, thread_state_t wtype); -int condvarTimedWait(condvar_t *, mutex_t *, jlong millis, thread_state_t wtype); -int condvarSignal(condvar_t *); -int condvarBroadcast(condvar_t *); - -#endif /* !_JAVASOFT_CONDVAR_MD_H_ */ diff --git a/jdk/src/solaris/hpi/native_threads/include/monitor_md.h b/jdk/src/solaris/hpi/native_threads/include/monitor_md.h deleted file mode 100644 index 7d20da695a3..00000000000 --- a/jdk/src/solaris/hpi/native_threads/include/monitor_md.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Monitor interface 10/25/94 - * - * Private data structures and interfaces used in the monitor code. - * This file is used to share declarations and such between the different - * files implementing monitors. It does not contain exported API. - */ - -#ifndef _JAVASOFT_SOLARIS_MONITOR_MD_H_ -#define _JAVASOFT_SOLARIS_MONITOR_MD_H_ - -#include -#include -#include - -/* - * Type definitions. - */ - -typedef struct monitor_waiter monitor_waiter_t; -typedef struct monitor_wait_queue monitor_wait_queue_t; - -/* Element of the MonitorWaitQ - representing thread doing a monitor wait */ -/* - * The only reason we do the queueing is for sysMonitorDumpInfo. - * The counting, though, is used to avoid extraneous calls to - * condvarBroadcast and condvarSignal, for instance. - */ -struct monitor_waiter { - monitor_waiter_t *next; - monitor_waiter_t **prev; - sys_thread_t *waiting_thread; -}; - -struct monitor_wait_queue { - monitor_waiter_t *head; /* linked list of waiting threads */ - short count; /* number of waiters on the list */ -}; - -#define ANY_WAITING(mwq) ((mwq).count > 0) -#define INIT_MONITOR_WAIT_QUEUE(mwq) { (mwq).head = NULL; (mwq).count = 0; } - -/* The system-level monitor data structure */ -struct sys_mon { - mutex_t mutex; /* The monitor's mutex */ - condvar_t cv_monitor; /* Notify those doing monitorWait on - the monitor */ - /* - * Threads waiting on either of the above condvars put themselves - * on one of these lists. - */ - monitor_wait_queue_t mwait_queue; /* Head of MonitorWaitQ */ - - /* Thread currently executing in this monitor */ - sys_thread_t *monitor_owner; - long entry_count; /* Recursion depth */ - int contention_count; -}; - -void initializeContentionCountMutex(); - -typedef enum { - ASYNC_REGISTER, - ASYNC_UNREGISTER -} async_action_t; - -/* - * Macros - */ - -#define SYS_MID_NULL ((sys_mon_t *) 0) - -typedef enum { - SYS_ASYNC_MON_ALARM = 1, - SYS_ASYNC_MON_IO, - SYS_ASYNC_MON_EVENT, - SYS_ASYNC_MON_CHILD, - SYS_ASYNC_MON_MAX -} async_mon_key_t; - -#define SYS_ASYNC_MON_INPUT SYS_ASYNC_MON_IO -#define SYS_ASYNC_MON_OUTPUT SYS_ASYNC_MON_IO - -sys_mon_t *asyncMon(async_mon_key_t); - -#endif /* !_JAVASOFT_SOLARIS_MONITOR_MD_H_ */ diff --git a/jdk/src/solaris/hpi/native_threads/include/mutex_md.h b/jdk/src/solaris/hpi/native_threads/include/mutex_md.h deleted file mode 100644 index c384d00b280..00000000000 --- a/jdk/src/solaris/hpi/native_threads/include/mutex_md.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Interface to mutex HPI implementation for Solaris - */ - -#ifndef _JAVASOFT_MUTEX_MD_H_ -#define _JAVASOFT_MUTEX_MD_H_ - -#include "porting.h" - -/* - * Generally, we would typedef mutex_t to be whatever the system - * supplies. But Solaris gives us mutex_t directly. - */ - -#ifdef USE_PTHREADS -#define mutexInit(m) pthread_mutex_init(m, 0) -#else -#define mutexInit(m) mutex_init(m, USYNC_THREAD, 0) -#endif -#define mutexDestroy(m) mutex_destroy(m) -#define mutexLock(m) mutex_lock(m) -#define mutexUnlock(m) mutex_unlock(m) -bool_t mutexLocked(mutex_t *); - -#endif /* !_JAVASOFT_MUTEX_MD_H_ */ diff --git a/jdk/src/solaris/hpi/native_threads/include/np.h b/jdk/src/solaris/hpi/native_threads/include/np.h deleted file mode 100644 index 8fab6e19376..00000000000 --- a/jdk/src/solaris/hpi/native_threads/include/np.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1998, 2000, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Non-posix parts of the threads HPI. - */ - -#ifndef _JAVASOFT_NP_H_ -#define _JAVASOFT_NP_H_ - -extern int np_suspend(sys_thread_t *tid); -extern int np_continue(sys_thread_t *tid); - -extern int np_single(void); -extern void np_multi(void); -extern int np_stackinfo(void **addr, long *size); -extern int np_initialize(void); -extern void np_initialize_thread(sys_thread_t *tid); -#ifdef __linux__ -extern int np_initial_suspend(sys_thread_t *tid); -extern void np_free_thread(sys_thread_t *tid); -#endif - -extern void np_profiler_init(sys_thread_t *tid); -extern int np_profiler_suspend(sys_thread_t *tid); -extern int np_profiler_continue(sys_thread_t *tid); -extern bool_t np_profiler_thread_is_running(sys_thread_t *tid); - -#endif /* !_JAVASOFT_NP_H_ */ diff --git a/jdk/src/solaris/hpi/native_threads/include/porting.h b/jdk/src/solaris/hpi/native_threads/include/porting.h deleted file mode 100644 index fdbbec00715..00000000000 --- a/jdk/src/solaris/hpi/native_threads/include/porting.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 1998, 2000, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#ifndef _JAVASOFT_PORTING_H_ -#define _JAVASOFT_PORTING_H_ - -#ifndef USE_PTHREADS - -#include -#include -#include - -#else /* USE_PTHREADS */ - -#include - -/* There is a handshake between a newly created thread and its creator - * at thread startup because the creator thread needs to suspend the - * new thread. Currently there are two ways to do this -- with - * semaphores and with mutexes. The semaphore based implementation is - * cleaner and hence is the default. We wish the mutex based one will - * go away, but turns out the implementation of semaphores on - * Linux/ppc etc is flaky, so the mutex based solution lives for now. - */ -#ifndef USE_MUTEX_HANDSHAKE -#include -#endif - -#undef BOUND_THREADS - -#define thread_t pthread_t - -#define mutex_t pthread_mutex_t -#define mutex_lock pthread_mutex_lock -#define mutex_trylock pthread_mutex_trylock -#define mutex_unlock pthread_mutex_unlock -#define mutex_destroy pthread_mutex_destroy - -#define cond_t pthread_cond_t -#define cond_destroy pthread_cond_destroy -#define cond_wait pthread_cond_wait -#define cond_timedwait pthread_cond_timedwait -#define cond_signal pthread_cond_signal -#define cond_broadcast pthread_cond_broadcast - -#define thread_key_t pthread_key_t -#define thr_setspecific pthread_setspecific -#define thr_keycreate pthread_key_create - -#define thr_sigsetmask pthread_sigmask -#define thr_self pthread_self -#define thr_yield sched_yield -#define thr_kill pthread_kill -#define thr_exit pthread_exit -#ifdef __linux__ -void intrHandler(void*); -#endif -#endif /* USE_PTHREADS */ - -#endif /* !_JAVASOFT_PORTING_H_ */ diff --git a/jdk/src/solaris/hpi/native_threads/include/threads_md.h b/jdk/src/solaris/hpi/native_threads/include/threads_md.h deleted file mode 100644 index a958a40f9cb..00000000000 --- a/jdk/src/solaris/hpi/native_threads/include/threads_md.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 1994, 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Implementation of the Java threads HPI on top of Solaris threads - */ - -#ifndef _JAVASOFT_SOLARIS_THREADS_MD_H_ -#define _JAVASOFT_SOLARIS_THREADS_MD_H_ - -#include "porting.h" - -#ifdef sparc -#define N_TRACED_REGS 12 -#elif i386 -#define N_TRACED_REGS 7 -#elif amd64 -#define N_TRACED_REGS 15 -#elif ppc -#define N_TRACED_REGS 1 -#elif m68k -#define N_TRACED_REGS 8 -#elif ia64 -/* [RGV] I don't think this is referenced in the linux code */ -#define N_TRACED_REGS 32 -#else -// TODO: delete this file - threads_md.[ch] is obsolete. struct sys_thread is -// never used. Define a value just to keep compiler happy. -#define N_TRACED_REGS 32 -#endif - -/* Turn on if we want all java threads to be bound tolwps */ -/* #define BOUND_THREADS */ -/* Use /proc soln to stop lwps in place of siglwp soln */ -#define PROCLWP - -/* - * Thread C stack overflow check -#define sysThreadCheckStack(redzone, var) \ - ((var = sysThreadSelf()) && \ - (unsigned int)((char *)&(var) - (char *)(var)->stack_base)\ - < (redzone)) -*/ -/* - * Forward definition of machine dependent monitor struct - */ -struct sys_mon; - -/* - * The following thread states are really hints since there is no - * interface to get at a native thread's true state. The states - * are maintained by updating the states where ever possible - * such as a transition to CONDVAR_WAIT occurs in the definition of - * the routine condvarWait(). - * This state maintenance should disappear once we have a threads interface - * to obtain a thread's state. - */ -typedef enum { - FIRST_THREAD_STATE, - RUNNABLE = FIRST_THREAD_STATE, - SUSPENDED, - CONDVAR_WAIT, - NUM_THREAD_STATES -} thread_state_t; - -#if defined( USE_PTHREADS) && !defined(__linux__) -/* - * Mechanism for starting a new thread suspended. - */ -typedef enum { - NEW_THREAD_MUST_REQUEST_SUSPEND, - NEW_THREAD_REQUESTED_SUSPEND, - NEW_THREAD_SUSPENDED -} new_thr_state_t; - -typedef struct { - pthread_mutex_t m; - pthread_cond_t c; - new_thr_state_t state; -} new_thr_cond_t; -#endif /* USE_PTHREADS */ - -/* - * Machine dependent info in a sys_thread_t - */ -struct sys_thread { - /* - * Fields below this point may change on a per-architecture basis - * depending on how much work is needed to present the sysThread - * model on any given thread implementation. - */ - mutex_t mutex; /* per thread lock to protect thread fields */ - thread_t sys_thread; /* The native thread id */ - struct sys_thread *next; /* Pointer to next thread in the */ - /* queue of all threads. */ - thread_state_t state; - - /* Thread status flags */ - unsigned int primordial_thread:1; - unsigned int system_thread:1; - unsigned int cpending_suspend:1; -#ifdef __linux__ - unsigned int pending_interrupt:1; -#endif - unsigned int interrupted:1; - unsigned int onproc:1; /* set if thread is on an LWP */ - unsigned int :0; - -#ifdef BOUND_THREADS - lwpid_t lwpid; -#endif - -#ifdef __linux__ - void *sp; -#else - unsigned long sp; /* sp at time of last (native) thread switch */ -#endif - void * stack_bottom; /* The real bottom (high address) of stack */ - void * stack_top; /* should be equal to stack_bottom - stack_size */ - long stack_size; /* The stack size for a native thread */ - - long regs[N_TRACED_REGS]; /* stores registers as GC roots. */ - - /* Monitor specific. - - Every monitor keeps track of the number of times it is - entered. When that count goes to 0, the monitor can be - freed up. But each thread has its own entry count on a - particular monitor, because multiple threads can be using a - single monitor (as one does a wait, another enters, etc.). - Each thread can only be waiting in exactly one monitor. - That monitor waited on is saved in mon_wait, and the value - of the monitor's entry_count when the wait was performed is - saved in monitor_entry_count. That is restored into the - monitor when this waiting thread is notified. */ - - long monitor_entry_count; /* For recursive monitor entry */ - struct sys_mon *mon_wait; /* CONDVAR_WAIT'ing */ - - struct sys_mon *mon_enter; /* blocked waiting to enter */ - - void (*start_proc)(void *); - void *start_parm; - int lwp_id; - long last_sum; - - struct sys_thread *prevBlocked; /* Used by nonblocking close semantics */ - struct sys_thread *nextBlocked; -#ifdef USE_PTHREADS - int suspend_count; -#ifdef __linux__ - sem_t sem_suspended; - sem_t sem_ready_to_suspend; - sem_t sem_selfsuspend; - int selfsuspended; -#endif -#ifdef USE_MUTEX_HANDSHAKE - new_thr_cond_t ntcond; -#else - sem_t sem; -#endif /* USE_MUTEX_HANDSHAKE */ -#endif /* USE_PTHREADS */ -}; - -#define SYS_THREAD_NULL ((sys_thread_t *) 0) - -/* - * following macro copied from sys/signal.h since inside #ifdef _KERNEL there. - */ -#ifndef sigmask -#define sigmask(n) ((unsigned int)1 << (((n) - 1) & (32 - 1))) -#endif - -#ifdef __linux__ -extern thread_key_t intrJmpbufkey; -#else -extern thread_key_t sigusr1Jmpbufkey; -extern sigset_t sigusr1Mask; -#endif - -extern sys_mon_t *_sys_queue_lock; - -#define SYS_QUEUE_LOCK(self) sysMonitorEnter(self, _sys_queue_lock) -#define SYS_QUEUE_LOCKED(self) sysMonitorEntered(self, _sys_queue_lock) -#define SYS_QUEUE_UNLOCK(self) sysMonitorExit(self, _sys_queue_lock) -#define SYS_QUEUE_NOTIFYALL(self) sysMonitorNotifyAll(self, _sys_queue_lock) -#define SYS_QUEUE_WAIT(self) sysMonitorWait(self, _sys_queue_lock, \ - SYS_TIMEOUT_INFINITY) - -extern void setFPMode(void); - -extern sys_thread_t *ThreadQueue; - -extern int ActiveThreadCount; /* All threads */ - -#endif /* !_JAVASOFT_SOLARIS_THREADS_MD_H_ */ diff --git a/jdk/src/solaris/hpi/native_threads/src/condvar_md.c b/jdk/src/solaris/hpi/native_threads/src/condvar_md.c deleted file mode 100644 index 60b3fd75c72..00000000000 --- a/jdk/src/solaris/hpi/native_threads/src/condvar_md.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 1994, 2000, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Condition variable HPI implementation for Solaris - */ - -#include -#include -#include -#include -#include - -#include "hpi_impl.h" - -#include "condvar_md.h" -#include "mutex_md.h" -#include "threads_md.h" - -int -condvarInit(condvar_t *condvar) -{ - int err; - -#ifdef USE_PTHREADS - err = pthread_cond_init(&condvar->cond, NULL); -#else - err = cond_init(&condvar->cond, USYNC_THREAD, 0 /* ignored */); -#endif - condvar->counter = 0; - return (err == 0 ? SYS_OK : SYS_ERR); -} - -int -condvarDestroy(condvar_t *condvar) -{ - int err; - -#ifdef __linux__ - err = pthread_cond_destroy((cond_t *) &condvar->cond); -#else - err = cond_destroy((cond_t *) condvar); -#endif - return (err == 0 ? SYS_OK : SYS_ERR); -} - -int -condvarWait(condvar_t *condvar, mutex_t *mutex, thread_state_t wtype) -{ - sigjmp_buf jmpbuf; - int err; - - sys_thread_t *self = sysThreadSelf(); - /* - * There is no threads interface to get a thread's state. So, instead, - * we use this hack so that the debugger agent can get at this thread's - * state. Of course, this is not very reliable, but when a thread goes - * to sleep, it *will* be reported as sleeping. During the transition - * from running to sleep, it may be incorrectly reported, since the - * setting of the state here is not atomic with the voluntary sleep. - * The better fix is to extend the Solaris threads interface and have - * the debugger agent call this interface OR to use libthread_db for - * intra-process state reporting. - * - * Now, condition variables are used either for waiting to enter a - * monitor (MONITOR_WAIT) or to execute a "wait()" method when already - * holding a monitor (CONDVAR_WAIT). So, when condvarWait() is called - * it could be to wait for a monitor or for a condition within a - * monitor. This is indicated by the "wtype" argument to condvarWait(). - * This type is set in the thread state before going to sleep. - */ - self->state = wtype; - -#ifdef __linux__ - /* - * Register our intrHandler as a cleanup handler. If we get - * interrupted (i.e. canceled), we longjmp out of this handler. - */ - pthread_cleanup_push(intrHandler, NULL); - if (setjmp(jmpbuf) == 0) { - /* - * Set the jmp buf and enable cancellation. - */ - thr_setspecific(intrJmpbufkey, &jmpbuf); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - - /* - * Note: pthread_cond_wait is _not_ interruptible on Linux - */ -#else - thr_setspecific(sigusr1Jmpbufkey, &jmpbuf); - if (sigsetjmp(jmpbuf, 1) == 0) { - sigset_t osigset; - - thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &osigset); -again: -#endif - err = cond_wait((cond_t *) condvar, (mutex_t *) mutex); - switch(err) { - case 0: - err = SYS_OK; - break; -#ifndef __linux__ - case EINTR: /* Signals other than USR1 were received. */ - goto again; -#endif - default: - err = SYS_ERR; - } -#ifdef __linux__ - /* - * Disable cancellation and clear the jump buf. - */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - thr_setspecific(intrJmpbufkey, NULL); -#else - thr_sigsetmask(SIG_SETMASK, &osigset, NULL); -#endif - } else { - /* - * we've received a SIGUSR1 to interrupt our wait. We just return - * and something above use notices the change. - * clear the jump buf just to be paranoid. - */ -#ifndef __linux__ - thr_setspecific(sigusr1Jmpbufkey, NULL); -#endif - err = SYS_INTRPT; - } -#ifdef __linux__ - pthread_cleanup_pop(0); -#endif - /* - * After having woken up, change the thread state to RUNNABLE, since - * it is now runnable. - */ - self->state = RUNNABLE; - - return err; -} - -/* - * Returns 0 if condition variable became true before timeout expired. - * Returns 1 if timeout expired first. - * Returns <0 if wait fails for any other reason. - */ -int -condvarTimedWait(condvar_t *condvar, mutex_t *mutex, - jlong millis, thread_state_t wtype) -{ -#ifdef __linux__ - jmp_buf jmpbuf; -#else - sigjmp_buf jmpbuf; -#endif - int err; - struct timespec timeout; - sys_thread_t *self; - jlong end_time; - - if (millis < 0) - return SYS_ERR; - - if (millis > (jlong)INT_MAX) { - return condvarWait(condvar, mutex, wtype); - } - - end_time = sysTimeMillis() + millis; - - self = sysThreadSelf(); - self->state = wtype; - -#ifdef __linux__ - /* - * Register our intrHandler as a cleanup handler. If we get - * interrupted (i.e. canceled), we longjmp out of this handler. - */ - pthread_cleanup_push(intrHandler, NULL); - if (setjmp(jmpbuf) == 0) { - /* - * Set the jmp buf and enable cancellation. - */ - thr_setspecific(intrJmpbufkey, &jmpbuf); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - - /* - * Calculate an absolute timeout value. - */ - timeout.tv_sec = end_time / 1000; - timeout.tv_nsec = (end_time % 1000) * 1000000; - - again: -#else - thr_setspecific(sigusr1Jmpbufkey, &jmpbuf); - if (sigsetjmp(jmpbuf, 1) == 0) { - sigset_t osigset; - - thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &osigset); - - again: - timeout.tv_sec = end_time / 1000; - timeout.tv_nsec = (end_time % 1000) * 1000000; -#endif - err = cond_timedwait((cond_t *)condvar, (mutex_t *)mutex, &timeout); - switch(err) { - case 0: - err = SYS_OK; - break; - case EINTR: /* Signals other than USR1 were received. */ - if (sysTimeMillis() < end_time) { - goto again; - } - /*FALLTHRU*/ -#ifdef USE_PTHREADS - case ETIMEDOUT: -#else - case ETIME: -#endif - err = SYS_TIMEOUT; - break; - default: - err = SYS_ERR; - } -#ifdef __linux__ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - thr_setspecific(intrJmpbufkey, NULL); -#else - thr_sigsetmask(SIG_SETMASK, &osigset, NULL); -#endif - } else { - /* - * we've received a SIGUSR1 to interrupt our wait. We just return - * and something above use notices the change. - * clear the jump buf just to be paranoid. - */ -#ifndef __linux__ - thr_setspecific(sigusr1Jmpbufkey, NULL); -#endif - err = SYS_INTRPT; - } -#ifdef __linux__ - /* Remove intrHandler without calling it. */ - pthread_cleanup_pop(0); - - sysAssert(pthread_mutex_trylock(mutex) == EBUSY); - - /* - * After having woken up, change the thread state to RUNNABLE, since - * it is now runnable. - */ -#endif - self->state = RUNNABLE; - return err; -} - -int -condvarSignal(condvar_t *condvar) -{ - int err; - - err = cond_signal((cond_t *) condvar); - condvar->counter++; - return (err == 0 ? SYS_OK : SYS_ERR); -} - -int -condvarBroadcast(condvar_t *condvar) -{ - int err; - - err = cond_broadcast((cond_t *) condvar); - condvar->counter++; - return (err == 0 ? SYS_OK : SYS_ERR); -} diff --git a/jdk/src/solaris/hpi/native_threads/src/interrupt_md.c b/jdk/src/solaris/hpi/native_threads/src/interrupt_md.c deleted file mode 100644 index eea1c977aea..00000000000 --- a/jdk/src/solaris/hpi/native_threads/src/interrupt_md.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 1994, 2006, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Solaris 2.X dependant interrupt handling code. - */ - -/* - * Header files. - */ -#include -#include -#include -#include -#include - -#include "hpi_impl.h" - -#include "mutex_md.h" -#include "condvar_md.h" -#include "monitor_md.h" -#include "threads_md.h" -#include "interrupt.h" - -static int pending_signals[N_INTERRUPTS]; - -/* Stubs used from interrupt.c: they are nontrivial on Green */ -void intrLock() {} -void intrUnlock() {} -#ifdef __linux__ -extern int sr_sigsusp; -extern int sr_sigresu; -#endif - -/* We need a special monitor implementation for signals because - * signal handlers are not necessarily called in a Java thread. - */ -struct { - thread_t owner; - unsigned int count; - mutex_t mutex; - condvar_t condvar; -} userSigMon; - -static void sigMonitorInit() -{ - userSigMon.owner = 0; - userSigMon.count = 0; - mutexInit(&userSigMon.mutex); - condvarInit(&userSigMon.condvar); -} - -static void sigMonitorEnter() -{ - thread_t self = thr_self(); - - if (userSigMon.owner == self) { - userSigMon.count++; - } else { - mutex_lock(&userSigMon.mutex); - userSigMon.owner = self; - userSigMon.count = 1; - } -} - -static void sigMonitorExit() -{ - thread_t self = thr_self(); - - sysAssert(userSigMon.owner == self); - sysAssert(userSigMon.count > 0); - if (--userSigMon.count == 0) { - userSigMon.owner = 0; - mutex_unlock(&userSigMon.mutex); - } -} - -static void sigMonitorNotify() -{ - thread_t self = thr_self(); - - sysAssert(userSigMon.owner == self); - sysAssert(userSigMon.count > 0); - condvarSignal(&userSigMon.condvar); -} - -static void sigMonitorWait() -{ - thread_t self = thr_self(); - - unsigned int saved_count = userSigMon.count; - - sysAssert(userSigMon.owner == self); - sysAssert(userSigMon.count > 0); - - userSigMon.count = 0; - userSigMon.owner = 0; - - condvarWait(&userSigMon.condvar, &userSigMon.mutex, CONDVAR_WAIT); - - sysAssert(userSigMon.owner == 0); - sysAssert(userSigMon.count == 0); - - userSigMon.count = saved_count; - userSigMon.owner = self; -} - -static int -my_sigignore(int sig) -{ -#ifndef HAVE_SIGIGNORE - struct sigaction action; - sigset_t set; - - action.sa_handler = SIG_IGN; - action.sa_flags = 0; - sigemptyset(&action.sa_mask); - - if (sigaction(sig, &action, (struct sigaction *)0) < 0) - return -1; - sigemptyset(&set); - if (sigaddset(&set, sig) < 0) - return -1; - return sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0); -#else - return sigignore(sig); -#endif /* HAVE_SIGIGNORE */ -} - - -/* - * intrInitMD() -- Target-specific initialization. - */ -extern void -intrInitMD() -{ - memset(pending_signals, 0, sizeof(pending_signals)); - (void)my_sigignore(SIGPIPE); - sigMonitorInit(); -} - -/*- - * intrDispatchMD() -- Turn our signal into an intrDispatch(). - */ -void -#ifdef SA_SIGINFO -intrDispatchMD(int sig, siginfo_t *info, void *uc) -#else -intrDispatchMD(int sig) -#endif /* SA_SIGINFO */ -{ - Log1(1, "signalHandlerDispatch(sig=%d)\n", sig); - - sigMonitorEnter(); -#ifdef SA_SIGINFO -#if defined(__linux__) && defined(__sparc__) - uc = (((char *)&sig) + 4 + 0x20); - info = (siginfo_t *)(((char *)uc) + 0x60); -#endif - intrDispatch(sig, info, uc); -#else - intrDispatch(sig, 0, 0); -#endif /* SA_SIGINFO */ - - sigMonitorExit(); -} - -bool_t intrInUse(int sig) -{ - /* Signals used in native threads implementation. */ -#ifdef __linux__ - return sig == SIGPIPE || sig == sr_sigsusp || sig == sr_sigresu; -#else - return sig == SIGPIPE || sig == SIGUSR1; -#endif -} - -void sysSignalNotify(int sig) -{ - sigMonitorEnter(); - pending_signals[sig]++; - sigMonitorNotify(); - sigMonitorExit(); -} - -static int lookupSignal() -{ - int i; - for (i = 0; i < N_INTERRUPTS; i++) { - if (pending_signals[i]) { - pending_signals[i]--; - return i; - } - } - return -1; -} - -int sysSignalWait() -{ - int sig; - sigMonitorEnter(); - while ((sig = lookupSignal()) == -1) { - sigMonitorWait(); - } - sigMonitorExit(); - return sig; -} diff --git a/jdk/src/solaris/hpi/native_threads/src/monitor_md.c b/jdk/src/solaris/hpi/native_threads/src/monitor_md.c deleted file mode 100644 index 577888b5141..00000000000 --- a/jdk/src/solaris/hpi/native_threads/src/monitor_md.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Monitor implementation for Native Solaris threads - * - * Java Monitors are implemented using one solaris mutex and two - * condition variables. Because solaris mutex is not re-entrant we - * cannot simply have a monitor map to a mutex as re-entering a monitor - * would deadlock an application. - * - * Monitor is implemented using: - * mutex_t mutex; - * condvar_t cv_monitor; - * condvar_t cv_waiters; - * - * mutex protects the monitor state. - * cv_monitor is the condtion variable used along with mutex for - * supporting wait and notify on the monitor. - * cv_waiters is used for all the threads waiting to acquire the monitor - * lock. - * - * All of the sysMonitorXXX() functions that are passed a sys_mon_t - * assume that they get something nonnull, and only check when debugging. - */ - -#include "hpi_impl.h" - -#include "threads_md.h" -#include "monitor_md.h" - -#include -#include - -static mutex_t contention_count_mutex; - -void initializeContentionCountMutex() -{ - mutexInit(&contention_count_mutex); -} - -/* - * Operations on monitors - */ -/* - * Return the size of the lib-dependent portion of monitors. This - * is done this way so that monitors can be all of one piece, - * without paying the penalty of an extra level of indirection on - * each sys_mon reference. This is not how it is done for threads - * and it might be a good idea to use a pointer the same way that - * threads do. - */ -size_t -sysMonitorSizeof() -{ - return sizeof(struct sys_mon); -} - -int -sysMonitorInit(sys_mon_t *mid) -{ - int ret; - - sysAssert(mid != SYS_MID_NULL); - ret = mutexInit(&mid->mutex); - ret = (ret == SYS_OK ? condvarInit(&mid->cv_monitor) : ret); - - mid->entry_count = 0; - mid->monitor_owner = SYS_THREAD_NULL; - mid->contention_count = 0; - INIT_MONITOR_WAIT_QUEUE( mid->mwait_queue ); - - return ret; -} - -/* - * Free any system-dependent resources held by monitors. There is - * nothing to be done for native Solaris mutexes or condition variables. - */ -int -sysMonitorDestroy(sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - return SYS_OK; -} - -static void -enqueue_me(monitor_waiter_t *mp, monitor_wait_queue_t *queue, - sys_thread_t *self) -{ - /* - * Order does not matter here. It is more convenient to - * enqueue ourselves at the head of the list, so we do so. - */ - mp->waiting_thread = self; - mp->next = queue->head; - mp->prev = &(queue->head); - if ( queue->head != NULL ){ - queue->head->prev = &(mp->next); - } - queue->head = mp; - queue->count++; -} - -static void -dequeue_me(monitor_waiter_t *mp, monitor_wait_queue_t *queue) -{ - queue->count--; - *(mp->prev) = mp->next; - if (mp->next != NULL ){ - mp->next->prev = mp->prev; - } - mp->next = NULL; -} - -int -sysMonitorEnter(sys_thread_t *self, sys_mon_t *mid) -{ - int err; - - sysAssert(mid != SYS_MID_NULL); - err = mutex_trylock(&mid->mutex); - if (err == 0) { /* no one owns it */ - mid->monitor_owner = self; - mid->entry_count = 1; - return SYS_OK; - } else if (err == EBUSY) { /* it's already locked */ - if (mid->monitor_owner == self) { - mid->entry_count++; - return SYS_OK; - } else { - self->mon_enter = mid; - /* block on it */ - if (profiler_on) { - VM_CALL(monitorContendedEnter)(self, mid); - mutexLock(&contention_count_mutex); - mid->contention_count++; - mutexUnlock(&contention_count_mutex); - } - mutex_lock(&mid->mutex); - mid->monitor_owner = self; - mid->entry_count = 1; - self->mon_enter = NULL; - if (profiler_on) { - mutexLock(&contention_count_mutex); - mid->contention_count--; - mutexUnlock(&contention_count_mutex); - VM_CALL(monitorContendedEntered)(self, mid); - } - return SYS_OK; - } - } else { - sysAssert(err == 0); - return SYS_ERR; - } -} - -/* - * Return true if we currently own this monitor (and threads have been - * initialized. - */ -bool_t -sysMonitorEntered(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - /* We can only have locked monitors if threads have been initialized */ - return (mid->monitor_owner == self); -} - -int -sysMonitorExit(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - if (mid->monitor_owner == self) { - sysAssert(mid->entry_count > 0); - if (--mid->entry_count == 0) { - mid->monitor_owner = SYS_THREAD_NULL; - if (!mid->contention_count || !profiler_on) { - mutex_unlock(&mid->mutex); - } else { - mutex_unlock(&mid->mutex); - VM_CALL(monitorContendedExit)(self, mid); - } - } - return SYS_OK; - } else { - return SYS_ERR; - } -} - -int -sysMonitorNotify(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - if (self == mid->monitor_owner) { - if (ANY_WAITING(mid->mwait_queue)) { - /* If there is someone doing a monitor wait */ - condvarSignal(&(mid->cv_monitor)); - } - return SYS_OK; - } else - return SYS_ERR; -} - -int -sysMonitorNotifyAll(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - if (self == mid->monitor_owner) { - if (ANY_WAITING(mid->mwait_queue)) { - /* If there is someone doing a monitor wait */ - condvarBroadcast(&(mid->cv_monitor)); - } - return SYS_OK; - } else - return SYS_ERR; -} - -int -sysMonitorWait(sys_thread_t *self, sys_mon_t *mid, jlong millis) -{ - int ret = SYS_OK; - monitor_waiter_t me; - sysAssert(mid != SYS_MID_NULL); - - if (self != mid->monitor_owner) { - return SYS_ERR; - } - if (sysThreadIsInterrupted(self, TRUE)) { - return SYS_INTRPT; - } - - /* Prepare to wait: drop mutex ownership */ - sysAssert(self->monitor_entry_count == 0); - sysAssert(self->mon_wait == 0); - self->mon_wait = (sys_mon_t *) mid; - self->monitor_entry_count = mid->entry_count; - mid->entry_count = 0; - mid->monitor_owner = SYS_THREAD_NULL; - - /* Add myself to the monitor waitq */ - enqueue_me(&me, &mid->mwait_queue, self); - if (millis == SYS_TIMEOUT_INFINITY) { - ret = condvarWait(&mid->cv_monitor, &mid->mutex, CONDVAR_WAIT); - } else { - ret = condvarTimedWait(&mid->cv_monitor, &mid->mutex, millis, - CONDVAR_WAIT); - } - dequeue_me(&me, &mid->mwait_queue); - - sysAssert(mid->monitor_owner == NULL); - sysAssert(mid->entry_count == 0); - mid->monitor_owner = self; - mid->entry_count = self->monitor_entry_count; - self->monitor_entry_count = 0; - self->mon_wait = 0; - - /* Did we get interrupted in mid-wait? (IS THIS THE RIGHT PLACE?) */ - if (sysThreadIsInterrupted(self, TRUE)) { - return SYS_INTRPT; - } - - return ret; -} - -static int -dumpWaitingQueue(monitor_wait_queue_t *queue, sys_thread_t **waiters, int sz) -{ - int n; - monitor_waiter_t * waiter; - if (queue == NULL || ( waiter = queue->head ) == NULL ) { - return 0; - } - for (n = 0; waiter != 0; waiter = waiter->next, n++, sz--) { - if (sz > 0) { - waiters[n] = waiter->waiting_thread; - } - } - return n; -} - -typedef struct { - sys_mon_t *mid; - sys_thread_t **waiters; - int sz; - int nwaiters; -} wait_info; - -static int -findWaitersHelper(sys_thread_t *t, void *arg) -{ - wait_info * winfo = (wait_info *) arg; - if (t->mon_enter == winfo->mid) { - if (winfo->sz > 0) { - winfo->waiters[winfo->nwaiters] = t; - } - winfo->sz--; - winfo->nwaiters++; - } - return SYS_OK; -} - -int -sysMonitorGetInfo(sys_mon_t *mid, sys_mon_info *info) -{ - wait_info winfo; - - sysAssert(mid != SYS_MID_NULL); - info->owner = mid->monitor_owner; - if (mid->monitor_owner) { - info->entry_count = mid->entry_count; - } - - winfo.mid = mid; - winfo.nwaiters = 0; - winfo.waiters = info->monitor_waiters; - winfo.sz = info->sz_monitor_waiters; - sysThreadEnumerateOver(findWaitersHelper, (void *) &winfo); - info->n_monitor_waiters = winfo.nwaiters; - - info->n_condvar_waiters = dumpWaitingQueue(&mid->mwait_queue, - info->condvar_waiters, - info->sz_condvar_waiters); - - return SYS_OK; -} - - -bool_t -sysMonitorInUse(sys_mon_t * mon) -{ - return mon->monitor_owner != 0 || - mon->mwait_queue.count != 0; -} - -sys_thread_t * -sysMonitorOwner(sys_mon_t *mon) -{ - return mon->monitor_owner; -} diff --git a/jdk/src/solaris/hpi/native_threads/src/mutex_md.c b/jdk/src/solaris/hpi/native_threads/src/mutex_md.c deleted file mode 100644 index 852dc67b0d2..00000000000 --- a/jdk/src/solaris/hpi/native_threads/src/mutex_md.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Mutex HPI implementation for Solaris - * - * Mutexes are used both by the system-independent monitor implementation and - * to implement critical regions elsewhere within the runtime. - */ - -#include - -#include "hpi_impl.h" - -#include "mutex_md.h" -#include "threads_md.h" - -/* - * Return true of the mutex in question is already locked. note: - * this does not tell if the mutex is already locked by *this* - * thread, only that is is locked by *some* thread. - */ -bool_t -mutexLocked(mutex_t *mutex) -{ - if (mutex_trylock(mutex) == 0) { - mutex_unlock(mutex); - return FALSE; - } - return TRUE; -} diff --git a/jdk/src/solaris/hpi/native_threads/src/sys_api_td.c b/jdk/src/solaris/hpi/native_threads/src/sys_api_td.c deleted file mode 100644 index 54da289e1d2..00000000000 --- a/jdk/src/solaris/hpi/native_threads/src/sys_api_td.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright (c) 1997, 2008, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Solaris-dependent I/O Note: Routines here are just place holders - - * eventually we need to put in a solution that involves using - * setjmp/longjmp to avoid io races. Look at green_threads/io_md.c for - * more detailed comments on the architechture of the io modules. - */ -#include -#include -#include - -#ifdef HAVE_FILIOH -#include -#else -#include -#endif - -#include -#include -#include -#ifndef USE_SELECT -#include -#endif - -#include "hpi_impl.h" - -#include "threads_md.h" -#include "io_md.h" -#include "largefile.h" -#include "mutex_md.h" - -#if defined(__solaris__) && defined(NO_INTERRUPTIBLE_IO) -#error If there was no policy change, this could be a makefile error. -#endif - -#ifdef NO_INTERRUPTIBLE_IO -#undef CLOSEIO -#else -#define CLOSEIO -#endif /* NO_INTERRUPTIBLE_IO */ - -/* Get typedef for rlim_t */ -#include - -#ifdef CLOSEIO - -/* - * Structure for file control block, used by closable IO. - * We should NOT add more field into the data structure. - * Otherwise, the sysRead() will only work with sysOpen, - * and may NOT work with a fd return by open() - */ -typedef struct -{ - mutex_t lock; /* lock against the entry */ - sys_thread_t* list; /* blocking list on the fd */ -} file_t; - -/* - * Global data structure for interruptable io. - * It must be initialized before any IO access. - */ -static file_t * fd_table = 0; -static int fd_limit = 0; - -/* - * Initialize global data structure for non-blocking - * close semantics for Solaris 2.6 and ealier. - */ -int InitializeIO(rlim_t limit) -{ - int i; - - fd_limit = (int) limit; - - fd_table = (file_t *) sysCalloc(fd_limit, sizeof(file_t)); - if (fd_table == 0) { - return SYS_ERR; - } - - for (i = 0; i < fd_limit; i++) { - mutexInit(&(fd_table[i].lock)); - } - - return SYS_OK; -} - -/* - * Cleanup the data structure allocated as above. - * For JDK 1.2, this function is not called ... - */ -void FinalizeIO() { - int i; - for (i = 0; i < fd_limit; i++) { - mutexDestroy(&fd_table[i].lock); - } - sysFree(fd_table); - fd_table = 0; -} - -/* - * Non-blocking close semantics on Solaris native thread. - */ -int sysClose(int fd) -{ - int ret; - - /* Check if it is valid fd. */ - if (fd >= 0 && fd < fd_limit) { - file_t* file = &fd_table[fd]; - sys_thread_t *thread; - sys_thread_t *next; - - /* Lock the corresponding fd. */ - mutexLock(&file->lock); - - /* Read the blocking list. */ - thread = file->list; - - /* Iterates the list and interrupt every thread in there. */ - while (thread) { - /* This is the classic double-linked list operation. */ - if (thread->nextBlocked != thread) { - next = thread->nextBlocked; - - next->prevBlocked = thread->prevBlocked; - thread->prevBlocked->nextBlocked = next; - } else { - next = 0; - } - - thread->nextBlocked = 0; - thread->prevBlocked = 0; - - /* - * Use current interruptable IO mechanism to - * implement non-blocking closable IO. - */ - sysThreadInterrupt(thread); - - thread = next; - } - - file->list = 0; - - ret = close(fd); - - mutexUnlock(&file->lock); - } else { - /* It is not a valid fd. */ - errno = EBADF; - ret = SYS_ERR; - } - - return ret; -} - -/* - * Called before entering blocking IO. Enqueue the current - * thread to the fd blocking list. Need fd lock. - */ -static void BeginIO(sys_thread_t* self, file_t* file) { - mutexLock(&file->lock); - - if (!file->list) { - file->list = self->nextBlocked = self->prevBlocked = self; - } else { - sys_thread_t* head = file->list; - - self->prevBlocked = head->prevBlocked; - self->nextBlocked = head; - head->prevBlocked->nextBlocked = self; - head->prevBlocked = self; - } - mutexUnlock(&file->lock); -} - -/* - * Called after finishing blocking IO. Dequeue the current - * thread from the blocking list. Note: It may be waken up - * by thread interrupt or fd close operation. - */ -static ssize_t EndIO(sys_thread_t* self, file_t* file, ssize_t ret) { - mutexLock(&file->lock); - - /* - * Dequeue the current thread. It is classic double - * linked list operation. - */ -#ifdef __linux__ - if (!sysThreadIsInterrupted(self, 1) && self->prevBlocked) { -#else - if (self->prevBlocked) { -#endif - if (self->nextBlocked != self) { - self->prevBlocked->nextBlocked = self->nextBlocked; - self->nextBlocked->prevBlocked = self->prevBlocked; - file->list = self->nextBlocked; - } else { - file->list = 0; - } - self->nextBlocked = 0; - self->prevBlocked = 0; - } else { -#ifdef __linux__ - if (self->nextBlocked && self->prevBlocked) { - if (self->nextBlocked != self) { - self->prevBlocked->nextBlocked = self->nextBlocked; - self->nextBlocked->prevBlocked = self->prevBlocked; - file->list = self->nextBlocked; - } else { - file->list = 0; - } - } - self->nextBlocked = 0; - self->prevBlocked = 0; -#endif - /* file got closed during blocking call */ - errno = EBADF; - ret = SYS_ERR; - } - - mutexUnlock(&file->lock); - - return ret; -} - -/* - * The following is a big macro used to implement the closable IO. - * Note: It is also used by interruptable IO. If later we need to - * deprecate interruptable IO, all we need to change the return - * value and errno to EBADF instead of EINTR. The high level - * routine will interpret it as IOException instead of - * InterruptedIOException. No other change is needed. - * The underlying mechanism is using the SIGUSR1 signal to wake up the - * blocking thread. This may cause severe conflicts with any other - * libraries that also use SIGUSR1. - */ -#ifdef __linux__ -#define INTERRUPT_IO(cmd) \ -{\ - ssize_t ret = 0;\ - file_t* file;\ - sys_thread_t* self = sysThreadSelf();\ -\ - if (fd < 0 || fd >= fd_limit) {\ - errno = EBADF;\ - return SYS_ERR;\ - }\ -\ - file = &fd_table[fd];\ - BeginIO(self, file);\ -\ - {\ - jmp_buf jmpbuf;\ -\ - /*\ - * Register our intrHandler as a cleanup handler. If we get\ - * interrupted (i.e. canceled), we longjmp out of this handler.\ - */\ - pthread_cleanup_push(intrHandler, NULL);\ - if (setjmp(jmpbuf) == 0) {\ - thr_setspecific(intrJmpbufkey, &jmpbuf);\ - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);\ - ret = cmd;\ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);\ - thr_setspecific(intrJmpbufkey, NULL);\ - } else {\ - /* [jk] should/can we call sysThreadIsInterrupted(self, 1) here */ - - self->interrupted = FALSE;\ - errno = EINTR;\ - ret = SYS_INTRPT;\ - }\ - /* Remove intrHandler without calling it. */\ - pthread_cleanup_pop(0);\ - }\ -\ - return EndIO(self, file, ret);\ -} -#else -#define INTERRUPT_IO(cmd) \ -{\ - int ret = 0;\ - file_t* file;\ - sys_thread_t* self = sysThreadSelf();\ -\ - if (fd < 0 || fd >= fd_limit) {\ - errno = EBADF;\ - return SYS_ERR;\ - }\ -\ - file = &fd_table[fd];\ - BeginIO(self, file);\ -\ - {\ - sigjmp_buf jmpbuf;\ - sigset_t omask;\ -\ - thr_setspecific(sigusr1Jmpbufkey, &jmpbuf);\ - if (sigsetjmp(jmpbuf, 1) == 0) {\ - thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &omask);\ - ret = cmd;\ - thr_sigsetmask(SIG_SETMASK, &omask, NULL);\ - } else {\ - sysThreadIsInterrupted(self, TRUE);\ - errno = EINTR;\ - ret = SYS_INTRPT;\ - }\ - }\ -\ - return EndIO(self, file, ret);\ -} -#endif - -#else /* CLOSEIO */ - -#define INTERRUPT_IO(cmd) \ - return cmd; - -int sysClose(int fd) { - return close(fd); -} - -int InitializeIO(rlim_t limit) -{ - return SYS_OK; -} -#endif /* CLOSEIO */ - -/* - * sys API for I/O - */ - -size_t -sysRead(int fd, void *buf, unsigned int nBytes) { - INTERRUPT_IO(read(fd, buf, nBytes)) -} - -size_t -sysWrite(int fd, const void *buf, unsigned int nBytes) { - INTERRUPT_IO(write(fd, buf, nBytes)) -} - -int -sysSocket(int domain, int type, int protocol) { - return socket(domain, type, protocol); -} - -ssize_t -sysRecv(int fd, char *buf, int nBytes, int flags) { - INTERRUPT_IO(recv(fd, buf, nBytes, flags)) -} - -ssize_t -sysSend(int fd, char *buf, int nBytes, int flags) { - INTERRUPT_IO(send(fd, buf, nBytes, flags)) -} -/* -int -sysClose(int fd) { - INTERRUPT_IO(close(fd)) -} -*/ -jlong -sysSeek(int fd, jlong offset, int whence) { - return lseek64_w(fd, offset, whence); -} - -int -sysSetLength(int fd, jlong length) { - return ftruncate64_w(fd, length); -} - -int -sysSync(int fd) { - /* - * XXX: Is fsync() interruptible by the interrupt method? - * Is so, add the TSD, sigsetjmp()/longjmp() code here. - * - * This probably shouldn't be throwing an error and should - * be a macro. - */ - int ret; - if ((ret = fsync(fd)) == -1) { - } - return ret; -} - -int -sysAvailable(int fd, jlong *pbytes) { - jlong cur, end; - int mode; - - if (sysFfileMode(fd, &mode) >= 0) { - if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { - /* - * XXX: is the following call interruptible? If so, this might - * need to go through the INTERRUPT_IO() wrapper as for other - * blocking, interruptible calls in this file. - */ - int n; - if (ioctl(fd, FIONREAD, &n) >= 0) { - *pbytes = n; - return 1; - } - } - } - if ((cur = lseek64_w(fd, 0L, SEEK_CUR)) == -1) { - return 0; - } else if ((end = lseek64_w(fd, 0L, SEEK_END)) == -1) { - return 0; - } else if (lseek64_w(fd, cur, SEEK_SET) == -1) { - return 0; - } - *pbytes = end - cur; - return 1; -} - -/* IO routines that take in a FD object */ - -int -sysTimeout(int fd, long timeout) { -#ifndef USE_SELECT - struct pollfd pfd; - -#ifdef __linux__ - jlong end_time = sysTimeMillis() + (jlong) timeout; - volatile jlong to = (jlong) timeout; -#endif - - pfd.fd = fd; - pfd.events = POLLIN; - -#ifdef __linux__ - INTERRUPT_IO(__extension__ ({ - int __result; - do { - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); - __result = poll(&pfd, 1, ((int)to)); - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); - } while (__result == -1 && errno == EINTR && - (to = end_time - sysTimeMillis()) > 0 && - ((pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) == 0)); - if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) { - __result = -1; - errno = EBADF; - } - (__result == -1 && errno == EINTR) ? 0 : __result; - })) -#else - INTERRUPT_IO(poll(&pfd, 1, (int)timeout)) -#endif -#else - fd_set tbl; - struct timeval t; - - t.tv_sec = timeout / 1000; - t.tv_usec = (timeout % 1000) * 1000; - - FD_ZERO(&tbl); - FD_SET(fd, &tbl); - -#ifdef __linux__ - INTERRUPT_IO(TEMP_FAILURE_RETRY(select(fd + 1, &tbl, 0, 0, &t))) -#else - INTERRUPT_IO(select(fd + 1, &tbl, 0, 0, &t)) -#endif -#endif -} - - -/* - * sys API for networking - */ - -long -sysSocketAvailable(int fd, jint *pbytes) { - long ret = 1; - /* - * An ILP64 port of this code should pass the address of a local int - * to the ioctl and then convert that to jint with any error handling - * required for overflows, if overflow is possible. - */ - - /* - * XXX: is the following call interruptible? If so, this might - * need to go through the INTERRUPT_IO() wrapper as for other - * blocking, interruptible calls in this file. - */ - if (fd < 0 || ioctl(fd, FIONREAD, pbytes) < 0) { - ret = 0; - } - return ret; -} - -int -sysListen(int fd, int count) { - return listen(fd, count); -} - -int -sysConnect(int fd, struct sockaddr *addr, int size) { - INTERRUPT_IO(connect(fd, addr, size)) -} - -int -sysBind(int fd, struct sockaddr *addr, int size) { - INTERRUPT_IO(bind(fd, addr, size)) -} - -int -sysAccept(int fd, struct sockaddr *him, int *len) { - INTERRUPT_IO(accept(fd, him, (uint *)len)) -} - -int -sysGetSockName(int fd, struct sockaddr *him, int *len) { - return getsockname(fd, him, (uint *)len); -} - -int -sysSocketClose(int fd) { - return sysClose(fd); -} - -int -sysSocketShutdown(int fd, int howto) { - return shutdown(fd, howto); -} - -int -sysGetSockOpt(int fd, int level, int optname, char *optval, int *optlen) { - return getsockopt(fd, level, optname, optval, optlen); -} - -int -sysSetSockOpt(int fd, int level, int optname, const char *optval, int optlen) { - return setsockopt(fd, level, optname, optval, optlen); -} - -int -sysGetHostName(char *hostname, int namelen) { - return gethostname(hostname, namelen); -} - -struct hostent * -sysGetHostByAddr(const char *hostname, int len, int type) { - return gethostbyaddr(hostname, len, type); -} - -struct hostent * -sysGetHostByName(char *hostname) { - return gethostbyname(hostname); -} - -struct protoent * -sysGetProtoByName(char* name) { - return getprotobyname(name); -} - -/* - * Routines to do datagrams - */ -ssize_t -sysSendTo(int fd, char *buf, int len, - int flags, struct sockaddr *to, int tolen) { - INTERRUPT_IO(sendto(fd, buf, len, flags, to, tolen)) -} - -ssize_t -sysRecvFrom(int fd, char *buf, int nBytes, - int flags, struct sockaddr *from, int *fromlen) { - INTERRUPT_IO(recvfrom(fd, buf, nBytes, flags, from, (uint *)fromlen)) -} diff --git a/jdk/src/solaris/hpi/native_threads/src/threads_linux.c b/jdk/src/solaris/hpi/native_threads/src/threads_linux.c deleted file mode 100644 index dddc2cc8b52..00000000000 --- a/jdk/src/solaris/hpi/native_threads/src/threads_linux.c +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright (c) 1999, 2000, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Implementation of notposix.h on Linux. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "hpi_impl.h" -#include "monitor_md.h" -#include "threads_md.h" -#include "np.h" - -#undef LOG_THREADS - -/* Global lock used when calling np_suspend and np_resume */ -static pthread_mutex_t sr_lock; - -/* Semaphore used to acknowledge when the handler has received HANDLER_SIG */ -static sem_t sr_sem; - -/* The tid of the thread being suspended/resumed */ -static sys_thread_t *sr_tid; - -int sr_sigsusp; -int sr_sigresu; - -static void prtsigset(char *s, sigset_t *set) -{ - int sig; - dprintf(2, "%s:", s); - for (sig = 1; sig < _NSIG; sig++) { - if (sigismember(set, sig)) { - dprintf(2, " %d", sig); - } - } - dprintf(2, "\n"); -} - -/* - * Handler function invoked when a thread's execution is suspended - * We have to be careful that only async-safe functions are - * called here. I'm not even sure if calling sysThreadSelf is safe so - * we temporarily stash SP in a global variable instead. - */ -static void -#ifdef SA_SIGINFO -susp_handler(int sig, siginfo_t* info, void* arg) -#else -susp_handler(int sig) -#endif -{ - sys_thread_t *tid = sr_tid; - sigset_t set; - /* Save the current SP */ - tid->sp = &tid; - sem_post(&sr_sem); - sigfillset(&set); - sigdelset(&set,(sr_sigresu)); - /* block until we receive resume signal. */ - sigsuspend(&set); -} - -static void -#ifdef SA_SIGINFO -resu_handler(int sig, siginfo_t* info, void* arg) -#else -resu_handler(int sig) -#endif -{ - return; -} - -/* - * Initialize signal handlers for suspend and resume}. - */ -int -np_initialize() -{ - struct sigaction act; - char *s; - int err; - - /* Signal numbers used to suspend and resume */ -#if __GLIBC__ == 2 && __GLIBC_MINOR__ == 0 -#ifdef SIGUNUSED - sr_sigsusp = SIGUNUSED; -#else - sr_sigsusp = SIGLOST; -#endif -#ifdef SIGPWR - sr_sigresu = SIGPWR; -#else - sr_sigresu = SIGXFSZ; -#endif -#else - /* use real time signals */ - /* currently __SIGRTMIN, +1, +2 are all used by LinuxThreads */ - sr_sigsusp = SIGRTMIN + 3; - sr_sigresu = SIGRTMIN + 4; -#endif - - /* Set up signal handler for suspend and resume */ -#if defined(SA_SIGINFO) && !defined(__sparc__) - act.sa_handler = 0; - act.sa_sigaction = susp_handler; -#else - act.sa_handler = (__sighandler_t) susp_handler; -#endif -#ifdef SA_SIGINFO - act.sa_flags = SA_RESTART | SA_SIGINFO; -#else - act.sa_flags = SA_RESTART; -#endif - sigfillset(&act.sa_mask); - if (sigaction(sr_sigsusp, &act, 0) == -1) { - return -1; - } -#if defined(SA_SIGINFO) && !defined(__sparc__) - act.sa_handler = 0; - act.sa_sigaction = resu_handler; -#else - act.sa_handler = (__sighandler_t) resu_handler; -#endif -#ifdef SA_SIGINFO - act.sa_flags = SA_SIGINFO; -#else - act.sa_flags = 0; -#endif - sigfillset(&act.sa_mask); - if (sigaction(sr_sigresu, &act, 0) == -1) { - return -1; - } - - /* Initialize semaphore used by np_{suspend/resume} */ - if (sem_init(&sr_sem, 0, 0) == -1) { - return SYS_ERR; - } - - /* Initialize mutex used by np_{suspend/resume} */ - err = mutexInit(&sr_lock); - sysAssert(err == 0); - - return SYS_OK; -} - -int -np_initial_suspend(sys_thread_t* tid) -{ - int count; - - tid->selfsuspended = (tid == sysThreadSelf()); - sysAssert(tid->selfsuspended); - - count = tid->suspend_count++; - sysAssert(count == 0); - -#ifdef LOG_THREADS - dprintf(2, - "[Initial self-suspend [tid = %ld, sys_thread = %ld]\n", - pthread_self(), tid->sys_thread); -#endif - - /* Order should not matter but doing the post first should be faster */ - sem_post(&tid->sem_suspended); - do { - sem_wait(&tid->sem_selfsuspend); - } while (tid->selfsuspended); /* paranoid */ - return 0; -} - - -int -np_suspend(sys_thread_t *tid) -{ - int count, ret = 0; - - int err = mutexLock(&sr_lock); - sysAssert(err == 0); - - tid->selfsuspended = (tid == sysThreadSelf()); - - count = tid->suspend_count++; -#ifdef LOG_THREADS - dprintf(2, "[Suspending fromtid = %ld, tid = %ld, pid = %d, count = %d]\n", - pthread_self(), tid->sys_thread, tid->lwp_id, count); -#endif - if (count == 0) { - if (tid->selfsuspended) { -#ifdef LOG_THREADS - dprintf(2, - "[Self-suspending [tid = %ld, sys_thread = %ld]\n", - pthread_self(), tid->sys_thread); -#endif - mutexUnlock(&sr_lock); - do { - sem_wait(&tid->sem_selfsuspend); - } while (tid->selfsuspended); - /* [jk] What is the correct return value here? - There was no error, but when we return the thread - has already been resumed. */ - return SYS_OK; - - } else { - sr_tid = tid; - ret = pthread_kill(tid->sys_thread, sr_sigsusp); - if (ret == 0) { - sem_wait(&sr_sem); - } -#ifdef LOG_THREADS - dprintf(2, - "[Suspended fromtid = %ld, pthread_kill(%ld, %d) = %d]\n", - pthread_self(), tid->sys_thread, sr_sigsusp, ret); -#endif - } - } - - err = mutexUnlock(&sr_lock); - sysAssert(err == 0); - - return ret == 0 ? SYS_OK : SYS_ERR; -} - -int -np_continue(sys_thread_t *tid) -{ - int count, ret = 0; - - int err = mutexLock(&sr_lock); - sysAssert(err == 0); - - count = --tid->suspend_count; -#ifdef LOG_THREADS - dprintf(2, "[Resuming fromtid = %ld, tid = %ld, pid = %d, count = %d]\n", - pthread_self(), tid->sys_thread, tid->lwp_id, count); -#endif - if (count == 0) { - if (tid->selfsuspended) { - tid->selfsuspended = 0; - sem_post(&tid->sem_selfsuspend); - } else { - sr_tid = tid; - ret = pthread_kill(tid->sys_thread, sr_sigresu); - } -#ifdef LOG_THREADS - dprintf(2, "[Resumed fromtid = %ld, pthread_kill(%ld, %d) = %d]\n", - pthread_self(), tid->sys_thread, sr_sigresu, ret); -#endif - } else if (count < 0) { - /* Ignore attempts to resume a thread that has not been suspended */ - tid->suspend_count = 0; - } - - err = mutexUnlock(&sr_lock); - sysAssert(err == 0); - - return ret == 0 ? SYS_OK : SYS_ERR; -} - -/* - * Get the stack base and size. - */ -int -np_stackinfo(void **addr, long *size) -{ - /* For now assume stack is 2 meg, from internals.h. */ -#define STACK_SIZE (2 * 1024 * 1024) - void *p; - char *sp = (char *)&p; /* rougly %esp */ - - *addr = (void *)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1; - *size = STACK_SIZE; - - return SYS_OK; -} - -typedef unsigned long ulong_t; -#define VALID_SP(sp, bottom, top) \ - (((ulong_t)(sp)) < ((ulong_t)(bottom)) && ((ulong_t)(sp)) > ((ulong_t)(top))) - -/* - * Go into single threaded mode for GC. - */ -int -np_single() -{ - sys_thread_t *tid; - pthread_t me = pthread_self(); - int i; - -#ifdef LOG_THREADS - dprintf(2, "[Entering np_single: thread count = %d]\n", ActiveThreadCount); -#endif - /* Stop all other threads. */ - tid = ThreadQueue; - for (i = 0; i < ActiveThreadCount && tid != 0; i++) { - if ((tid->sys_thread != me) && (tid->state != SUSPENDED)) { - np_suspend(tid); - sysAssert(VALID_SP(tid->sp, tid->stack_bottom, tid->stack_top)); - tid->onproc = FALSE; /* REMIND: Might not need this */ - } - tid = tid->next; - } -#ifdef LOG_THREADS - dprintf(2, "[Leaving np_single]\n"); -#endif - return SYS_OK; -} - -/* - * Per thread initialization. - */ -void -np_initialize_thread(sys_thread_t *tid) -{ - sigset_t set; - - /* Block SIGQUIT so that it can be handled by the SIGQUIT handler thread */ - sigemptyset(&set); - sigaddset(&set, SIGQUIT); - pthread_sigmask(SIG_BLOCK, &set, 0); - /* Set process id */ - tid->lwp_id = getpid(); - tid->suspend_count = 0; - - /* Semaphore used for self-suspension */ - sem_init(&tid->sem_selfsuspend, 0, 0); - tid->selfsuspended = 0; - -#ifdef LOG_THREADS - dprintf(2, "[Init thread, tid = %ld, pid = %d, base = %p, size = %lu]\n", - pthread_self(), tid->lwp_id, tid->stack_bottom, tid->stack_size); -#endif -} - -void -np_free_thread(sys_thread_t *tid) -{ - sem_destroy(&tid->sem_selfsuspend); -} - -/* - * Recover from single threaded mode after GC. - */ -void -np_multi() -{ - int i; - sys_thread_t *tid; - pthread_t me = pthread_self(); - - tid = ThreadQueue; - for (i = 0; i < ActiveThreadCount && tid != 0; i++) { - if ((tid->sys_thread != me) && (tid->state != SUSPENDED)) { - np_continue(tid); - } - tid = tid->next; - } -} - -void -np_profiler_init(sys_thread_t *tid) -{ -} - -int -np_profiler_suspend(sys_thread_t *tid) -{ - return np_suspend(tid); -} - -int -np_profiler_continue(sys_thread_t *tid) -{ - return np_continue(tid); -} - -bool_t -np_profiler_thread_is_running(sys_thread_t *tid) -{ - return TRUE; -} diff --git a/jdk/src/solaris/hpi/native_threads/src/threads_md.c b/jdk/src/solaris/hpi/native_threads/src/threads_md.c deleted file mode 100644 index f3aab1aad14..00000000000 --- a/jdk/src/solaris/hpi/native_threads/src/threads_md.c +++ /dev/null @@ -1,1133 +0,0 @@ -/* - * Copyright (c) 1994, 2002, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Implementation of Java threads HPI on top of native Solaris threads - * - * [Sheng 1/18/97] Do not include any JVM-specific header file (such - * as interpreter.h) here! This file implements the thread-related - * APIs sys_api.h. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hpi_impl.h" - -#include "threads_md.h" -#include "monitor_md.h" - -#include "np.h" - -extern int InitializeIO(rlim_t limit); - -#if defined(__solaris__) && !defined(SA_SIGINFO) -#error That can NOT possibly be right. -#endif - -#ifdef SA_SIGINFO -static void sigusr1Handler(int sig, siginfo_t *info, void *uc); -#else -static void sigusr1Handler(int sig); -#endif /* SA_SIGINFO */ - -static void removeFromActiveQ(sys_thread_t *p); -static void clear_onproc_flags(void); - -sys_thread_t *ThreadQueue; -int ActiveThreadCount = 0; /* All threads */ -sys_mon_t *_sys_queue_lock; - -/* This is explained in linker_md.c. */ -#ifdef __GLIBC__ -#define NEED_DL_LOCK -#endif /* __GLIBC__ */ - -#ifdef NEED_DL_LOCK -extern sys_mon_t _dl_lock; -#endif /* NEED_DL_LOCK */ - -/* - * threads_initialized simplifies the check that has to be done in - * sysThreadCheckStack(). Otherwise, before sysThreadInit() is called - * on the primordial thread, we need to handle there being no current - * thread at all, and there being one with a 0 stack_base. - */ -static int threads_initialized = 0; - -/* The tid_key is a global key to *native* thread-specific data. That is, - * each native thread has a back pointer to the Java TID associated with it. - */ -static thread_key_t tid_key = (thread_key_t) -1; - -/* - * The sigusr1Jmpbufkey is used to get at the jmp buffer to longjmp to in a - * SIGUSR1 handler - used to implement stop(). The jmp buffer - * should have been allocated off the thread's stack. - */ -#ifdef __linux__ -thread_key_t intrJmpbufkey; -static sigset_t squm = {{sigmask(SIGUSR1), 0, 0, 0}}; -#else -thread_key_t sigusr1Jmpbufkey; -sigset_t sigusr1Mask = {{sigmask(SIGUSR1), 0, 0, 0}}; -#endif - -/* - * Thread C stack overflow check - * - * sysThreadCheckStack() being a function call is unfortunate, as it - * takes stack space to do, but that is weakly accounted for by the - * previous stack redzone. In general, where we can't predict stack - * use by C, thread stack overflow checking doesn't really work. - */ - -#define STACK_REDZONE 4096 - -#ifdef __linux__ -int jdk_waitpid(pid_t pid, int* status, int options); -int fork1(void); -int jdk_sem_init(sem_t*, int, unsigned int); -int jdk_sem_post(sem_t*); -int jdk_sem_wait(sem_t*); -int jdk_pthread_sigmask(int, const sigset_t*, sigset_t*); -pid_t waitpid(pid_t, int*, int); - -int jdk_waitpid(pid_t pid, int* status, int options) { - return waitpid(pid, status, options); -} - -int fork1() { - return fork(); -} - -int -jdk_sem_init(sem_t *sem, int pshared, unsigned int value) { - return sem_init(sem, pshared, value); -} - -int -jdk_sem_post(sem_t *sem) { - return sem_post(sem); -} - -int -jdk_sem_wait(sem_t *sem) { - return sem_wait(sem); -} - -int -jdk_pthread_sigmask(int how , const sigset_t* newmask, sigset_t* oldmask) { - return pthread_sigmask(how , newmask, oldmask); -} - -#endif - -/* REMIND: port _CurrentThread changes to make process - of getting the tid more efficient */ - -int -sysThreadCheckStack() -{ - sys_thread_t *tid = sysThreadSelf(); - - /* Stacks grow toward lower addresses on Solaris... */ - if (!threads_initialized || - (char *)(tid)->stack_bottom - (char *)&(tid) + STACK_REDZONE < - tid->stack_size) { - return 1; - } else { - return 0; - } -} - -#ifndef __linux__ -static sigset_t squm = {{sigmask(SIGUSR1), 0, 0, 0}}; -#endif - - -/* - * Allocate and initialize the sys_thread_t structure for an arbitary - * native thread. - */ -int -sysThreadAlloc(sys_thread_t **tidP) -{ - int err; - sys_thread_t *tid = allocThreadBlock(); - if (tid == NULL) { - return SYS_NOMEM; - } -#ifdef __linux__ - memset((char *)tid, 0, sizeof(sys_thread_t)); -#endif - - if (profiler_on) { - np_profiler_init(tid); - } - - if (np_stackinfo(&tid->stack_bottom, &tid->stack_size) == SYS_ERR) { - return SYS_ERR; - } -#ifdef __linux__ - tid->stack_top = tid->stack_bottom - tid->stack_size; -#else - tid->stack_top = (void *)((char *)(tid->stack_bottom) - tid->stack_size); -#endif - - tid->primordial_thread = 0; -#ifdef __linux__ - tid->interrupted = tid->pending_interrupt = FALSE; -#else - tid->interrupted = FALSE; -#endif - tid->onproc = FALSE; - tid->sys_thread = thr_self(); -#ifdef __linux__ - /* - * Disable cancellation. The default cancel type is - * PTHREAD_CANCEL_DEFERRED, so if we set the cancel state to - * PTHREAD_CANCEL_ENABLE again, we'll get deferred cancellation. - */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); -#endif - np_initialize_thread(tid); - - /* - * For the Invocation API: - * We update the thread-specific storage before locking the - * queue because sysMonitorEnter will access sysThreadSelf. - */ - err = thr_setspecific(tid_key, tid); - /* sys_thread_t * back pointer from native */ -#ifdef __linux__ - thr_setspecific(intrJmpbufkey, NULL); /* paranoid */ -#endif - assert (err == 0); - - if (threads_initialized) - SYS_QUEUE_LOCK(sysThreadSelf()); - ActiveThreadCount++; /* Count the thread */ - tid->next = ThreadQueue; /* Chain all threads */ - ThreadQueue = tid; - if (threads_initialized) - SYS_QUEUE_UNLOCK(sysThreadSelf()); - else - threads_initialized = TRUE; - - /* - * Ensure that SIGUSR1 is masked for interruptable IO - * Signal mask inheritance ensures all child threads are masked too. - */ -#ifndef __linux__ - thr_sigsetmask(SIG_BLOCK, &squm, NULL); -#endif - - setFPMode(); - - *tidP = tid; - return SYS_OK; -} - -/* - * threadBootstrapMD() bootstraps the UNIX process running from main() - * into a first primordial thread. This thread is distinguishable because - * it uniquely has the primordial_thread flag on in its private data. - * However, so that we have to special-case it as little as possible, we - * set it up to look as closely as possible to a thread that we created. - * One difference is that its stack is *not* known to us. - */ -int -threadBootstrapMD(sys_thread_t **tidP, sys_mon_t **lockP, int nb) -{ - /* We are running out of file descriptors in fonts. As a temporary - * fix, bump up the number of open file descriptors to OPEN_MAX. - */ - struct rlimit nbr_files; - - getrlimit(RLIMIT_NOFILE, &nbr_files); - nbr_files.rlim_cur = nbr_files.rlim_max; - setrlimit(RLIMIT_NOFILE, &nbr_files); - - /* - * Use the above setting for initialize (closable) IO package. - */ - if (InitializeIO(nbr_files.rlim_cur) != SYS_OK) { - return SYS_ERR; - } - - /* Create a thread-private key for a pointer back to the sys_thread_t *. - * Note that we don't need to worry about the destructor, as that's taken - * care of elsewhere. - */ - thr_keycreate(&tid_key, NULL); - -#ifdef __linux__ - thr_keycreate(&intrJmpbufkey, NULL); -#else - thr_keycreate(&sigusr1Jmpbufkey, NULL); -#endif - -#ifndef NO_INTERRUPTIBLE_IO - { - /* initialize SIGUSR1 handler for interruptable IO */ - struct sigaction sigAct; - -#ifdef SA_SIGINFO - sigAct.sa_handler = NULL; - sigAct.sa_sigaction = sigusr1Handler; -#else - sigAct.sa_handler = sigusr1Handler; -#endif /* SA_SIGINFO */ - memset((char *)&(sigAct.sa_mask), 0, sizeof (sigset_t)); - /* we do not want the restart flag for SIGUSR1 */ - sigAct.sa_flags = 0; - sigaction(SIGUSR1, &sigAct, (struct sigaction *)0); - } -#endif /* NO_INTERRUPTIBLE_IO */ - - nReservedBytes = (nb + 7) & (~7); - if (sysThreadAlloc(tidP) < 0) { - return SYS_NOMEM; - } - - /* profiler_on may have not been setup yet. */ - np_profiler_init(*tidP); - -#ifdef NEED_DL_LOCK - VM_CALL(monitorRegister)(&_dl_lock, "Dynamic loading lock"); -#endif /* NEED_DL_LOCK */ - - /* Initialize the queue lock monitor */ - _sys_queue_lock = (sys_mon_t *)sysMalloc(sysMonitorSizeof()); - if (_sys_queue_lock == NULL) { - return SYS_ERR; - } - VM_CALL(monitorRegister)(_sys_queue_lock, "Thread queue lock"); - *lockP = _sys_queue_lock; - - (*tidP)->primordial_thread = 1; - - if (np_initialize() == SYS_ERR) { - return SYS_ERR; - } - - return SYS_OK; -} - -/* - * Access to the thread stack pointer of an arbitrary thread (for GC). - * This information should be legitimately available in Solaris 2.5. - */ -void * -sysThreadStackPointer(sys_thread_t * tid) -{ - char *thread_info; - - if (tid == sysThreadSelf()) { - /* - * doing this assigment gets around a warning about returning - * the address of a local variable - */ - void *aStackAddress = &thread_info; - return aStackAddress; - } else { - return (void *) tid->sp; - } -} - -/* - * Get the end of stack (if you step beyond (above or below depending - * on your architecture) you can die. We refer to the logical top of - * stack. - * - * NOTE! There are restrictions about when you can call this method. If - * you did a sysThreadAlloc, then you can call this method as soon as - * sysThreadAlloc returns. If you called sysThreadCreate(start_function), - * then you must call sysThreadStackTop only inside start_function and not - * as soon as sysThreadCreate returns. - */ -void * -sysThreadStackTop(sys_thread_t *tid) -{ - return tid->stack_top; -} - -long * -sysThreadRegs(sys_thread_t * tid, int *nregs) -{ - *nregs = N_TRACED_REGS; - return tid->regs; -} - -static void * -_start(void *tid_) -{ - sys_thread_t *tid = (sys_thread_t *)tid_; - - np_initialize_thread(tid); - -#ifdef __linux__ - /* - * Disable cancellation. The default cancel type is - * PTHREAD_CANCEL_DEFERRED, so if we set the cancel state to - * PTHREAD_CANCEL_ENABLE again, we'll get deferred cancellation. - */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - - tid->sp = 0; - thr_setspecific(tid_key, tid); - thr_setspecific(intrJmpbufkey, NULL); /* paranoid */ - np_stackinfo(&tid->stack_bottom, &tid->stack_size); - tid->stack_top = (void *)((char *)(tid->stack_bottom) - tid->stack_size); - - /* Wait for resume signal */ - np_initial_suspend(tid); -#else -#ifdef USE_PTHREADS -#ifndef USE_MUTEX_HANDSHAKE - /* Wait for semaphore to be posted once thread has been suspended */ - sem_wait(&tid->sem); - sem_destroy(&tid->sem); -#else - /* I'm a new thread, and I must co-operate so I can be suspended. */ - pthread_mutex_lock(&tid->ntcond.m); - tid->ntcond.state = NEW_THREAD_REQUESTED_SUSPEND; - pthread_cond_signal(&tid->ntcond.c); - while (tid->ntcond.state != NEW_THREAD_SUSPENDED) - pthread_cond_wait(&tid->ntcond.c, &tid->ntcond.m); - pthread_mutex_unlock(&tid->ntcond.m); -#endif /* USE_MUTEX_HANDSHAKE */ -#endif /* USE_PTHREADS */ -#endif /* !linux */ - if (profiler_on) { - np_profiler_init(tid); - } - -#ifndef __linux__ - tid->sp = 0; - thr_setspecific(tid_key, tid); -#endif - - tid->state = RUNNABLE; - -#ifndef __linux__ - np_stackinfo(&tid->stack_bottom, &tid->stack_size); - tid->stack_top = (void *)((char *)(tid->stack_bottom) - tid->stack_size); -#endif - - setFPMode(); - tid->start_proc(tid->start_parm); -#ifdef __linux__ - /* Paranoid: We don't want to be canceled now, it would have - unpredictable consequences */ - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); -#endif - - sysThreadFree(); - thr_exit(0); - /* NOT REACHED */ - return 0; -} - -int -sysThreadCreate(sys_thread_t **tidP, long ss, void (*start)(void *), void *arg) -{ - size_t stack_size = ss; - int err; - sys_thread_t *tid = allocThreadBlock(); -#ifdef USE_PTHREADS - pthread_attr_t attr; -#endif - - if (tid == NULL) { - return SYS_NOMEM; - } - *tidP = tid; - -#ifdef __linux__ - memset((char *)tid, 0, sizeof(sys_thread_t)); -#endif - /* Install the backpointer to the Thread object */ - -#ifdef __linux__ - tid->interrupted = tid->pending_interrupt = FALSE; -#else - tid->interrupted = FALSE; -#endif - tid->onproc = FALSE; - -#ifndef __linux__ - SYS_QUEUE_LOCK(sysThreadSelf()); - ActiveThreadCount++; /* Global thread count */ - tid->next = ThreadQueue; /* Chain all threads */ - ThreadQueue = tid; - SYS_QUEUE_UNLOCK(sysThreadSelf()); -#endif - - tid->start_proc = start; - tid->start_parm = arg; -#ifdef __linux__ - tid->state = SUSPENDED; -#endif - -#ifdef __linux__ - tid->primordial_thread = 0; - - /* Semaphore used to block thread until np_suspend() is called */ - err = sem_init(&tid->sem_suspended, 0, 0); - sysAssert(err == 0); - /* Thread attributes */ - pthread_attr_init(&attr); -#ifdef _POSIX_THREAD_ATTR_STACKSIZE - pthread_attr_setstacksize(&attr, stack_size); -#endif - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (profiler_on) { - pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); - } - /* Create the thread. The thread will block waiting to be suspended */ - err = pthread_create(&tid->sys_thread, &attr, _start, (void *)tid); - sysAssert(err == 0); - if (err == 0) { - err = sem_wait(&tid->sem_suspended); - if (err == 0) { - sem_destroy(&tid->sem_suspended); - } - } - sysAssert(err == 0); - - SYS_QUEUE_LOCK(sysThreadSelf()); - ActiveThreadCount++; /* Global thread count */ - tid->next = ThreadQueue; /* Chain all threads */ - ThreadQueue = tid; - SYS_QUEUE_UNLOCK(sysThreadSelf()); -#else -#ifdef USE_PTHREADS - -#ifndef USE_MUTEX_HANDSHAKE - /* Semaphore used to block thread until np_suspend() is called */ - err = sem_init(&tid->sem, 0, 0); - sysAssert(err == 0); - /* Thread attributes */ -#else - /* Setup condition required to suspend the newly created thread. */ - pthread_mutex_init(&tid->ntcond.m, NULL); - pthread_cond_init(&tid->ntcond.c, NULL); - tid->ntcond.state = NEW_THREAD_MUST_REQUEST_SUSPEND; - pthread_mutex_lock(&tid->ntcond.m); -#endif /* USE_MUTEX_HANDSHAKE */ - - /* Create the new thread. */ - pthread_attr_init(&attr); -#ifdef _POSIX_THREAD_ATTR_STACKSIZE - pthread_attr_setstacksize(&attr, stack_size); -#endif - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (profiler_on) - pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); - err = pthread_create(&tid->sys_thread, &attr, _start, (void *)tid); - -#ifndef USE_MUTEX_HANDSHAKE - if (err == 0) { - /* Suspend the thread */ - err = np_suspend(tid); - if (err == SYS_OK) { - /* Unblock the thread now that it has been suspended */ - err = sem_post(&tid->sem); - sysAssert(err == 0); - } - } -#else - /* Wait for the newly created thread to block. */ - while (tid->ntcond.state != NEW_THREAD_REQUESTED_SUSPEND) - pthread_cond_wait(&tid->ntcond.c, &tid->ntcond.m); - - /* So it blocked. Now suspend it and _then_ get it out of the block. */ - np_suspend(tid->sys_thread); - tid->ntcond.state = NEW_THREAD_SUSPENDED; - pthread_cond_signal(&tid->ntcond.c); - pthread_mutex_unlock(&tid->ntcond.m); -#endif /* USE_MUTEX_HANDSHAKE */ - -#else - /* Create the thread */ - err = thr_create(NULL, stack_size, _start, (void *)tid, - THR_SUSPENDED|THR_DETACHED| - (profiler_on ? THR_BOUND : 0), - &tid->sys_thread); -#endif /* USE_PTHREADS */ -#endif /* !linux */ - - tid->state = SUSPENDED; - sysAssert(err != EINVAL); /* Invalid argument: shouldn't happen */ - if (err == EAGAIN) { - err = SYS_NORESOURCE; /* Will be treated as though SYS_NOMEM */ - } else if (err == ENOMEM) { - err = SYS_NOMEM; - } else { - err = SYS_OK; - } - - return err; -} - -/* - * Free a system thread block. - * Remove from the thread queue. - */ -int -sysThreadFree() -{ - sys_thread_t *tid = sysThreadSelf(); - /* - * remove ourselves from the thread queue. This must be done after - * the notify above since monitor operations aren't really safe if - * your thread isn't on the thread queue. (This isn't true of - * the sysMonitor* functions, only monitor*) - */ - SYS_QUEUE_LOCK(tid); - removeFromActiveQ(tid); - SYS_QUEUE_UNLOCK(tid); - - /* For invocation API: later sysThreadSelf() calls will return 0 */ - thr_setspecific(tid_key, 0); - -#ifdef __linux__ - np_free_thread(tid); -#endif - - freeThreadBlock(tid); - return SYS_OK; -} - -/* - * Current thread yield control - * - * Green threads originally supported forcing another thread to yield... - */ -void -sysThreadYield() -{ -#ifndef __linux__ - thr_yield(); -#endif -} - -#ifdef USE_PTHREADS -/* - * For POSIX threads, we don't want to use real-time policies SCHED_FIFO or - * SCHED_RR. That leaves SCHED_OTHER which is implementation defined. We - * assume Solaris-pthreads like behavior for SCHED_OTHER, and if it doesn't - * work on your platform, then maybe you want to do turn off thread - * priorities by setting -DMOOT_PRIORITIES. - */ -#ifndef MOOT_PRIORITIES -#define USE_SCHED_OTHER -#endif /* MOOT_PRIORITIES */ -#endif /* USE_PTHREADS */ - -/* - * Get the scheduling priority of a specified thread - */ -int -sysThreadGetPriority(sys_thread_t * tid, int *pri) -{ -#ifdef USE_PTHREADS -#ifdef USE_SCHED_OTHER - struct sched_param param; - int policy = SCHED_OTHER; - param.sched_priority = *pri; - return pthread_getschedparam(tid->sys_thread, &policy, ¶m); -#else - return 0; -#endif /* USE_SCHED_OTHER */ -#else - return thr_getprio(tid->sys_thread, pri); -#endif /* USE_PTHREADS */ -} - - -/* - * Set the scheduling priority of a specified thread - */ -int -sysThreadSetPriority(sys_thread_t * tid, int pri) -{ - int err; -#ifdef USE_PTHREADS -#ifdef USE_SCHED_OTHER - struct sched_param param; - param.sched_priority = pri; - err = pthread_setschedparam(tid->sys_thread, SCHED_OTHER, ¶m); -#else - err = 0; -#endif /* USE_SCHED_OTHER */ -#else - err = thr_setprio(tid->sys_thread, pri); -#endif /* USE_PTHREADS */ - sysAssert(err != ESRCH); /* No such thread: shouldn't happen */ - sysAssert(err != EINVAL); /* Invalid arguments: shouldn't happen */ - return SYS_OK; -} - -/* - * Suspend execution of the specified thread - */ -int -sysThreadSuspend(sys_thread_t * tid) -{ - int err1 = 0; - int err2 = 0; - sys_thread_t *self = sysThreadSelf(); - - if (tid == self) { - self->state = SUSPENDED; - } else { -#ifndef __linux__ - mutexLock(&tid->mutex); -#endif - switch(tid->state) { - case RUNNABLE: - tid->state = SUSPENDED; - break; - case CONDVAR_WAIT: - tid->state = SUSPENDED; - tid->cpending_suspend = 1; - break; - case SUSPENDED: - default: - err1 = -1; /* Thread in inconsistent state */ - break; - } -#ifndef __linux__ - mutexUnlock(&tid->mutex); -#endif - } - if (err1 == 0) { - err2 = np_suspend(tid); - } - - return ((err1 == 0 && err2 == 0) ? SYS_OK : SYS_ERR); -} - -/* - * Resume execution of the specified thread - */ -int -sysThreadResume(sys_thread_t * tid) -{ - int err1 = 0; - int err2 = 0; - -#ifndef __linux__ - mutexLock(&tid->mutex); -#endif - if (tid->cpending_suspend) { - tid->cpending_suspend = 0; - tid->state = CONDVAR_WAIT; - } else { - switch(tid->state) { - case SUSPENDED: - tid->state = RUNNABLE; - break; - case RUNNABLE: - case CONDVAR_WAIT: - default: - err1 = -1; /* Thread in inconsistent state */ - break; - } - } -#ifndef __linux__ - mutexUnlock(&tid->mutex); -#endif - if (err1 == 0) { - err2 = np_continue(tid); - } - - return ((err1 == 0 && err2 == 0) ? SYS_OK : SYS_ERR); -} - -/* - * Return the sys_thread_t * of the calling thread - */ -sys_thread_t * -sysThreadSelf() -{ -#ifdef USE_PTHREADS - return pthread_getspecific(tid_key); -#else - sys_thread_t * tid=NULL; - int err = thr_getspecific(tid_key, (void *) &tid); - - if (err == 0) { - return tid; - } - - sysAssert(tid_key == -1 || err != 0); - - return NULL; -#endif -} - -/* - * Enumerate over all threads, calling a function for each one. A - * paranoid helper function would be prepared to deal with threads - * that have not been created by Java. - */ - -int -sysThreadEnumerateOver(int (*func)(sys_thread_t *, void *), void *arg) -{ - sys_thread_t *tid; - int err = SYS_OK; - int i; - - sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf())); - - tid = ThreadQueue; - for (i = 0; i < ActiveThreadCount && tid != 0; i++) { - if ((err = (*func)(tid, arg)) != SYS_OK) { - break; - } - tid = tid->next; - } - - return err; -} - -void * -sysThreadNativeID(sys_thread_t *tid) -{ - return (void *) tid->sys_thread; -} - -/* - * Remove this thread from the list of Active threads. - */ -static void -removeFromActiveQ(sys_thread_t * t) -{ - sys_thread_t *prev; - sys_thread_t *tid; - - sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf())); - - ActiveThreadCount--; - - prev = 0; - tid = ThreadQueue; - while (tid) { - if (tid == t) { - if (prev) { - prev->next = tid->next; - } else { - ThreadQueue = tid->next; - } - tid->next = 0; - break; - } - prev = tid; - tid = tid->next; - } -} - -/* - * The mechanics of actually signalling an exception (in the future, - * and Alarm or Interrupt) depend upon what thread implementation you - * are using. - */ -void -sysThreadPostException(sys_thread_t *tid, void *exc) -{ - /* Thread.stop is deprecated */ - /* No longer wake up the thread if it is sleeping */ - /* thr_kill(tid->sys_thread, SIGUSR1); */ -} - -/* - * Support for (Java-level) interrupts. - */ -void -sysThreadInterrupt(sys_thread_t *tid) -{ -#ifdef __linux__ - tid->pending_interrupt = TRUE; - pthread_cancel(tid->sys_thread); -#else - mutexLock(&tid->mutex); - tid->interrupted = TRUE; - mutexUnlock(&tid->mutex); - thr_kill(tid->sys_thread, SIGUSR1); -#endif -} - -/* This doesn't need to aquire any locks */ -int -sysThreadIsInterrupted(sys_thread_t *tid, int ClearInterrupted) -{ - bool_t interrupted; - -#ifndef __linux__ - mutexLock(&tid->mutex); -#endif -#ifdef __linux__ - interrupted = tid->pending_interrupt || tid->interrupted; - - if (ClearInterrupted == 1 && tid->pending_interrupt) { - sys_thread_t* self = sysThreadSelf(); - - if (self == tid && pthread_getspecific(intrJmpbufkey) == NULL) { - jmp_buf jmpbuf; - - /* - * Register our intrHandler as a cleanup handler. If we get - * interrupted (i.e. canceled), we longjmp out of this handler. - */ - pthread_cleanup_push(intrHandler, NULL); - if (setjmp(jmpbuf) == 0) { - thr_setspecific(intrJmpbufkey, &jmpbuf); - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - while (1) { pthread_testcancel(); } - } - /* Remove intrHandler without calling it. */ - pthread_cleanup_pop(0); - } - } - - if (ClearInterrupted == 1 && interrupted) { - /* we have do to this last, otherwise we really would cancel the - thread */ - tid->interrupted = FALSE; - } -#else - interrupted = tid->interrupted; - if (ClearInterrupted == 1) { - tid->interrupted = FALSE; - mutexUnlock(&tid->mutex); - if (interrupted) { - sigset_t osigset; - /* - * we were interrupted so we may have a signal pending that - * we need to clear. We can just temporarily unmask SIGUSR1 - * and the sigusr1Handler to catch and notice that the - * interrupted flag is not set. - */ - - thr_setspecific(sigusr1Jmpbufkey, NULL); /* paranoid */ - thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &osigset); - thr_sigsetmask(SIG_SETMASK, &osigset, NULL); - } - } else { /* Otherwise leave it alone */ - mutexUnlock(&tid->mutex); - } -#endif - return interrupted; -} - - - -/* - * Stop all threads other than the current one. The stopped threads - * may be restarted with sysThreadMulti(); the operation of this - * routine is atomic; it either stops all java threads or it stops - * none of them. Upon success (all threads stopped) this routine - * returns SYS_OK, otherwise SYS_ERR. - * - * In general, sysThreadSingle() should take care of anything below - * the HPI that needs to be done to safely run single-threaded. - */ -int -sysThreadSingle() -{ - return np_single(); -} - -/* - * Allow multi threaded execution to resume after a - * sysThreadSingle() call. - * - * Note: When this routine is called the scheduler should already - * have been locked by sysThreadSingle(). - */ -void -sysThreadMulti() -{ - np_multi(); -} - -#ifdef __linux__ -/* - * We abuse thread cancellation to interrupt the threads, i.e when an - * exception is posted against the thread, pthread_cancel(3) is sent to the - * thread and the canceled thread executes the following cleanup handler - */ -void -intrHandler(void* arg) -{ - jmp_buf* jmpbufp = pthread_getspecific(intrJmpbufkey); - if (jmpbufp != NULL) { - volatile sys_thread_t* self = sysThreadSelf(); - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); - self->interrupted = TRUE; - self->pending_interrupt = FALSE; - thr_setspecific(intrJmpbufkey, NULL); - longjmp(*jmpbufp, 1); - } else { -#ifdef PARANOID_DEBUG - sysAssert(0); -#endif - } -} - -#else -/* - * SIGUSR1 is used to interrupt the threads, i.e when an exception - * is posted against the thread, SIGUSR1 is sent to the thread and the - * thread gets the signal, executes the following handler - */ - -static void -#ifdef SA_SIGINFO -sigusr1Handler(int sig, siginfo_t *info, void *uc) -#else -sigusr1Handler(int sig) -#endif -{ - sys_thread_t *tid = sysThreadSelf(); - - if (tid->interrupted) { - sigjmp_buf *jmpbufp; -#ifdef USE_PTHREADS - jmpbufp = pthread_getspecific(sigusr1Jmpbufkey); -#else - thr_getspecific(sigusr1Jmpbufkey, (void **)&jmpbufp); -#endif - if (jmpbufp != NULL) - siglongjmp(*jmpbufp, 1); - } -} -#endif - -HPI_SysInfo * -sysGetSysInfo() -{ - static HPI_SysInfo info = {0, 0}; - - if (info.name == NULL) { - /* - * we want the number of processors configured not the number online - * since processors may be turned on and off dynamically. - */ - int cpus = (int) sysconf(_SC_NPROCESSORS_CONF); - - info.isMP = (cpus < 0) ? 1 : (cpus > 1); - info.name = "native threads"; - } - return &info; -} - - -jlong -sysThreadCPUTime() -{ -#ifdef HAVE_GETHRVTIME - return gethrvtime(); -#else - return 0; -#endif -} - -int -sysThreadGetStatus(sys_thread_t *tid, sys_mon_t **monitorPtr) -{ - int status; - switch (tid->state) { - case RUNNABLE: - if (tid->mon_enter) { - status = SYS_THREAD_MONITOR_WAIT; - } else { - status = SYS_THREAD_RUNNABLE; - } - break; - case SUSPENDED: - if (tid->mon_enter) - status = SYS_THREAD_SUSPENDED | SYS_THREAD_MONITOR_WAIT; - else if (tid->cpending_suspend) - status = SYS_THREAD_SUSPENDED | SYS_THREAD_CONDVAR_WAIT; - else - status = SYS_THREAD_SUSPENDED; - break; - case CONDVAR_WAIT: - status = SYS_THREAD_CONDVAR_WAIT; - break; - default: - return SYS_ERR; - } - if (monitorPtr) { - if (status & SYS_THREAD_MONITOR_WAIT) { - *monitorPtr = tid->mon_enter; - } else if (status & SYS_THREAD_CONDVAR_WAIT) { - *monitorPtr = tid->mon_wait; - } else { - *monitorPtr = NULL; - } - } - return status; -} - -int sysAdjustTimeSlice(int new) -{ - return SYS_ERR; -} - -void sysThreadProfSuspend(sys_thread_t *tid) -{ - np_profiler_suspend(tid); -} - -void sysThreadProfResume(sys_thread_t *tid) -{ - np_profiler_continue(tid); -} - -bool_t sysThreadIsRunning(sys_thread_t *tid) -{ - return np_profiler_thread_is_running(tid); -} - -void * -sysThreadInterruptEvent() -{ - return NULL; -} diff --git a/jdk/src/solaris/hpi/native_threads/src/threads_solaris.c b/jdk/src/solaris/hpi/native_threads/src/threads_solaris.c deleted file mode 100644 index 33606d3b2bd..00000000000 --- a/jdk/src/solaris/hpi/native_threads/src/threads_solaris.c +++ /dev/null @@ -1,666 +0,0 @@ -/* - * Copyright (c) 1998, 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Implementation of HPI that can not be expressed with POSIX threads. - * Note that even if you are building with USE_PTHREADS, we have to - * explicitly undef it here because pthread.h and thread.h can not be - * included in the same file, and this file needs only thread.h. - */ -#undef USE_PTHREADS - -#include "hpi_impl.h" -#include "monitor_md.h" -#include "threads_md.h" -#include "np.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -extern int syscall(int, ...); - - -/* - * Forward declarations. - */ -static int procfd; -static void stop_lwps(); -static void clear_onproc_flags(); -static void restart_lwps(); -static void MakeProcName(register char *procname, register pid_t pid); -static void GC_msec_sleep(int n); - - -/* - * Make sure that we link against a verion of libthread that has at least - * the bug fixes and the interface for getting the stack from threads that - * aren't on LWPs. Otherwise we should exit with some informative message. - */ -extern ulong_t __gettsp(thread_t); - -static const char * gettspMessage = -"You must install a Solaris patch to run the native threads version of the\n" -"Java runtime. The green threads version will work without this patch.\n" -"Please check the native threads release notes for more information.\n" -"\n" -"If you are embedding the VM in a native application, please make sure that\n" -"the native application is linked with libthread.so (-lthread).\n" -"\n" -"Exiting.\n"; - -static void -checkForCorrectLibthread() -{ - if (&__gettsp == 0) { - fprintf(stderr, gettspMessage); - exit(1); - } -} -#ifdef __GNUC__ -static void checkForCorrectLibthread() __attribute__((constructor)); -#else -#pragma init(checkForCorrectLibthread) -#endif - -#pragma weak __gettsp - - -/* - * Suspend said thread. Used to implement java.lang.Thread.suspend(), - * which is deprecated. - */ -int -np_suspend(sys_thread_t *tid) -{ - return thr_suspend(tid->sys_thread); -} - - -/* - * Resume a suspended thread. Used to implement java.lang.Thread.resume(), - * which is deprecated. - */ -int -np_continue(sys_thread_t *tid) -{ - return thr_continue(tid->sys_thread); -} - -/* - * If there is any initialization is required by the non-POSIX parts. - */ -void np_initialize_thread(sys_thread_t *tid) -{ - return; -} - - -/* - * Get the stack start address, and max stack size for the current thread. - */ -int -np_stackinfo(void **addr, long *size) -{ - stack_t stkseg; - - if (thr_stksegment(&stkseg) == 0) { - *addr = (void *)(stkseg.ss_sp); - if (thr_main()) { - struct rlimit r; - getrlimit(RLIMIT_STACK, &r); - *size = (long)r.rlim_cur; - } else { - *size = (long)(stkseg.ss_size); - } - return SYS_OK; - } else { - return SYS_ERR; /* thr_stksegment failed. */ - } -} - -/* - * On Solaris when doing CPU profiling, the threads are bound. - */ -void -np_profiler_init(sys_thread_t *tid) -{ - tid->lwp_id = _lwp_self(); -} - -int -np_profiler_suspend(sys_thread_t *tid) -{ - return _lwp_suspend(tid->lwp_id); -} - -int -np_profiler_continue(sys_thread_t *tid) -{ - return _lwp_continue(tid->lwp_id); -} - -bool_t -np_profiler_thread_is_running(sys_thread_t *tid) -{ - unsigned long sum = 0; - int i; - prstatus_t lwpstatus; - int lwpfd; - int res; - - lwpfd = syscall(SYS_ioctl, procfd, PIOCOPENLWP, &(tid->lwp_id)); - sysAssert(lwpfd >= 0); - - retry: - res = syscall(SYS_ioctl, lwpfd, PIOCSTATUS, &lwpstatus); - sysAssert(res >= 0); - - if (!(lwpstatus.pr_flags & PR_STOPPED)) { - GC_msec_sleep(1); - goto retry; - } - - close(lwpfd); - -#if defined(sparc) - sum += lwpstatus.pr_reg[R_SP]; - sum += lwpstatus.pr_reg[R_PC]; - - sum += lwpstatus.pr_reg[R_G1]; - sum += lwpstatus.pr_reg[R_G2]; - sum += lwpstatus.pr_reg[R_G3]; - sum += lwpstatus.pr_reg[R_G4]; - - sum += lwpstatus.pr_reg[R_O0]; - sum += lwpstatus.pr_reg[R_O1]; - sum += lwpstatus.pr_reg[R_O2]; - sum += lwpstatus.pr_reg[R_O3]; - sum += lwpstatus.pr_reg[R_O4]; - sum += lwpstatus.pr_reg[R_O5]; - - sum += lwpstatus.pr_reg[R_I0]; - sum += lwpstatus.pr_reg[R_I1]; - sum += lwpstatus.pr_reg[R_I2]; - sum += lwpstatus.pr_reg[R_I3]; - sum += lwpstatus.pr_reg[R_I4]; - sum += lwpstatus.pr_reg[R_I5]; - sum += lwpstatus.pr_reg[R_I6]; - sum += lwpstatus.pr_reg[R_I7]; - - sum += lwpstatus.pr_reg[R_L0]; - sum += lwpstatus.pr_reg[R_L1]; - sum += lwpstatus.pr_reg[R_L2]; - sum += lwpstatus.pr_reg[R_L3]; - sum += lwpstatus.pr_reg[R_L4]; - sum += lwpstatus.pr_reg[R_L5]; - sum += lwpstatus.pr_reg[R_L6]; - sum += lwpstatus.pr_reg[R_L7]; -#elif defined(amd64) - sum += lwpstatus.pr_reg[REG_RIP]; - sum += lwpstatus.pr_reg[REG_RSP]; - - sum += lwpstatus.pr_reg[REG_RAX]; - sum += lwpstatus.pr_reg[REG_RCX]; - sum += lwpstatus.pr_reg[REG_RDX]; - sum += lwpstatus.pr_reg[REG_RBX]; - sum += lwpstatus.pr_reg[REG_RBP]; - sum += lwpstatus.pr_reg[REG_RSI]; - sum += lwpstatus.pr_reg[REG_RDI]; - - sum += lwpstatus.pr_reg[REG_R8]; - sum += lwpstatus.pr_reg[REG_R9]; - sum += lwpstatus.pr_reg[REG_R10]; - sum += lwpstatus.pr_reg[REG_R11]; - sum += lwpstatus.pr_reg[REG_R12]; - sum += lwpstatus.pr_reg[REG_R13]; - sum += lwpstatus.pr_reg[REG_R14]; - sum += lwpstatus.pr_reg[REG_R15]; -#elif defined(i386) - sum += lwpstatus.pr_reg[EIP]; - sum += lwpstatus.pr_reg[UESP]; - - sum += lwpstatus.pr_reg[EAX]; - sum += lwpstatus.pr_reg[ECX]; - sum += lwpstatus.pr_reg[EDX]; - sum += lwpstatus.pr_reg[EBX]; - sum += lwpstatus.pr_reg[EBP]; - sum += lwpstatus.pr_reg[ESI]; - sum += lwpstatus.pr_reg[EDI]; -#endif - - if (tid->last_sum == sum) { - return FALSE; - } - tid->last_sum = sum; - - return TRUE; -} - - -/* - * If building for Solaris native threads, open up the /proc file - * descriptor to be used when doing GC. The open is done at JVM start-up so - * as to reserve this fd, to prevent GC stall due to exhausted fds. This fd - * will never be closed, and will alwyas be present. - */ -int -np_initialize() -{ - char procname[32]; - MakeProcName(procname, getpid()); - if ((procfd = open(procname, O_RDONLY, 0)) < 0) { - VM_CALL(jio_fprintf)(stderr, "Cannot open %s for GC", procname); - return SYS_ERR; - } - return SYS_OK; -} - -static void -MakeProcName(register char *procname, register pid_t pid) -{ - register char * s; - - (void) strcpy(procname, "/proc/00000"); - s = procname + strlen(procname); - while (pid) { - *--s = pid%10 + '0'; - pid /= 10; - } -} - -/* - * Suspend all other threads, and record their contexts (register - * set or stack pointer) into the sys_thread structure, so that a - * garbage collect can be run. - */ -int -np_single(void) -{ - int ret; - - sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf())); - - stop_lwps(); - ret = SYS_OK; - return ret; -} - -/* - * Continue threads suspended earlier. But clear their context - * recorded in sys_thread structure first. - */ -void -np_multi(void) -{ - sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf())); - clear_onproc_flags(); - restart_lwps(); -} - -/* /proc solution to stop and restrt lwps */ -/* make sure gc is run as a bound thread */ -/* make sure signals are turned off for gc thread */ -/* what about new lwps getting created in the meantime? */ - -#define MAX_LWPS 1024 - -static prstatus_t Mystatus; -static id_t lwpid_list_buf[MAX_LWPS]; -static id_t oldlwpid_list_buf[MAX_LWPS]; -static sys_thread_t *onproct_list_buf[MAX_LWPS]; -static id_t *lwpid_list = lwpid_list_buf; -static id_t *oldlwpid_list = oldlwpid_list_buf; -static sys_thread_t **onproct_list = onproct_list_buf; -static int lwpid_list_len; -static int oldlwpid_list_len; -static int onproct_ix = 0; -static int gcprio; -static sigset_t gcmask; - -static void -clear_onproc_flags() -{ - int i; - - for (i = 0; i < onproct_ix; i++) { - ((sys_thread_t *)(onproct_list[i]))->onproc = FALSE; - } - onproct_ix = 0; -} - - -/* Sleep for n milliseconds, n < 1000 */ -static void -GC_msec_sleep(int n) -{ - struct timespec ts; - - ts.tv_sec = 0; - ts.tv_nsec = 1000000*n; - if (syscall(SYS_nanosleep, &ts, 0) < 0) { - VM_CALL(jio_fprintf)(stderr, "%d\n", errno); - } -} - -/* - * Assumes stacks grow down from high to low memory. True on sparc and Intel. - */ -#define VALID_SP(sp, bottom, top) \ - (((uintptr_t)(sp)) < ((uintptr_t)(bottom)) && ((uintptr_t)(sp)) > ((uintptr_t)(top))) - -static void -record_lwp_regs(prstatus_t lwpstatus) -{ - sys_thread_t *tid; - int i; -#if defined(sparc) - register uintptr_t sp = lwpstatus.pr_reg[R_SP]; -#elif defined(amd64) - register uintptr_t sp = lwpstatus.pr_reg[REG_RSP]; -#elif defined(i386) - register uintptr_t sp = lwpstatus.pr_reg[UESP]; -#endif - - tid = ThreadQueue; - for (i = 0; i < ActiveThreadCount && tid != 0; i++) { - if (VALID_SP(sp, tid->stack_bottom, tid->stack_top)) { - long *regs = tid->regs; - tid->sp = sp; - /* - * The code below relies on N_TRACED_REGS being set - * correctly for each platform. If you change the - * number of registers being watched, you should update - * the define for N_TRACED_REGS - */ -#if defined(sparc) - regs[0] = lwpstatus.pr_reg[R_G1]; - regs[1] = lwpstatus.pr_reg[R_G2]; - regs[2] = lwpstatus.pr_reg[R_G3]; - regs[3] = lwpstatus.pr_reg[R_G4]; - - regs[4] = lwpstatus.pr_reg[R_O0]; - regs[5] = lwpstatus.pr_reg[R_O1]; - regs[6] = lwpstatus.pr_reg[R_O2]; - regs[7] = lwpstatus.pr_reg[R_O3]; - regs[8] = lwpstatus.pr_reg[R_O4]; - regs[9] = lwpstatus.pr_reg[R_O5]; - regs[10] = lwpstatus.pr_reg[R_O6]; - regs[11] = lwpstatus.pr_reg[R_O7]; -#elif defined(amd64) - regs[0] = lwpstatus.pr_reg[REG_RAX]; - regs[1] = lwpstatus.pr_reg[REG_RCX]; - regs[2] = lwpstatus.pr_reg[REG_RDX]; - regs[3] = lwpstatus.pr_reg[REG_RBX]; - regs[4] = lwpstatus.pr_reg[REG_RBP]; - regs[5] = lwpstatus.pr_reg[REG_RSI]; - regs[6] = lwpstatus.pr_reg[REG_RDI]; - regs[7] = lwpstatus.pr_reg[REG_R8]; - regs[8] = lwpstatus.pr_reg[REG_R9]; - regs[9] = lwpstatus.pr_reg[REG_R10]; - regs[10]= lwpstatus.pr_reg[REG_R11]; - regs[11]= lwpstatus.pr_reg[REG_R12]; - regs[12]= lwpstatus.pr_reg[REG_R13]; - regs[13]= lwpstatus.pr_reg[REG_R14]; - regs[14]= lwpstatus.pr_reg[REG_R15]; -#elif defined(i386) - regs[0] = lwpstatus.pr_reg[EAX]; - regs[1] = lwpstatus.pr_reg[ECX]; - regs[2] = lwpstatus.pr_reg[EDX]; - regs[3] = lwpstatus.pr_reg[EBX]; - regs[4] = lwpstatus.pr_reg[EBP]; - regs[5] = lwpstatus.pr_reg[ESI]; - regs[6] = lwpstatus.pr_reg[EDI]; -#endif - - if (tid->onproc != TRUE) { - tid->onproc = TRUE; - onproct_list[onproct_ix++] = tid; - } - break; - } - tid = tid->next; - } -} - -static void -record_thread_regs() -{ - sys_thread_t *tid; - int i; - - tid = ThreadQueue; - for (i = 0; i < ActiveThreadCount && tid != 0; i++) { - if (tid->onproc != TRUE) { - int i; - - if (tid->sys_thread != 0) { - /* if thread has already been initialized */ - tid->sp = __gettsp(tid->sys_thread); - } else { - /* - * thread is still in the process of being initalized. - * So GC should not care about this thread. Just - * set its sp to 0, and this will force GC to ignore it. - */ - tid->sp = 0; - } - - /* - * Clear out the registers since they are no longer live - * and we don't want to garbage collector to think they are. - */ - - for (i = 0; i < N_TRACED_REGS; i++) - tid->regs[i] = 0; - } - tid = tid->next; - } -} - -static void -wait_stopped_lwps(void) -{ - int i, lwpfd; - prstatus_t lwpstatus; - - for (i = 0; i < (int) Mystatus.pr_nlwp; i++) { - /* if its not me */ - if (lwpid_list[i] != _lwp_self()) { - - /* open the lwp and check the status */ - if ((lwpfd = syscall(SYS_ioctl, procfd, PIOCOPENLWP, - &lwpid_list[i])) < 0) { -#ifdef MY_DEBUG - VM_CALL(jio_fprintf)(stderr, "lwpid %d was not found in process\n", - lwpid_list[i]); -#endif - continue; - } - memset(&lwpstatus, 0, sizeof(lwpstatus)); - while (1) { - if (syscall(SYS_ioctl,lwpfd, PIOCSTATUS, &lwpstatus)<0) { - sysAssert(0); -#ifdef MY_DEBUG - VM_CALL(jio_fprintf)(stderr, "PIOCSTATUS failed for lwp %d", - lwpid_list[i]); -#endif - break; - } - if (lwpstatus.pr_flags & PR_STOPPED) { - record_lwp_regs(lwpstatus); - break; - } - GC_msec_sleep(1); - } - - close (lwpfd); - } /* end of if-me */ - } /* end of for */ -} - -static void -suspend_lwps() -{ - int i; - /* pioopen all the lwps and stop them - except the one I am running on */ - for (i = 0; i < (int) Mystatus.pr_nlwp; i++) { - - /* open and stop the lwp if its not me */ - if (lwpid_list[i] != _lwp_self()) { - - /* PIOCSTOP doesn't work without a writable */ - /* descriptor. And that makes the process */ - /* undebuggable. */ - if (_lwp_suspend(lwpid_list[i]) < 0) { - /* Could happen if the lwp exited */ - lwpid_list[i] = _lwp_self(); - continue; - } - } - } -} - -static void -print_lwps() -{ -#ifdef MY_DEBUG - /* print all the lwps in the process */ - VM_CALL(jio_fprintf)(stdout, "lwpids "); - for (i = 0; i < (int) Mystatus.pr_nlwp; i++) { - if (i == 0) { - VM_CALL(jio_fprintf)(stdout, "%d", lwpid_list[0]); - } else if (i != Mystatus.pr_nlwp - 1) { - VM_CALL(jio_fprintf)(stdout, ", %d", lwpid_list[i]); - } else { - VM_CALL(jio_fprintf)(stdout, " and %d", lwpid_list[i]); - } - } -#endif -} - -/* routine to iteratively stop all lwps */ -static void -stop_lwps() -{ - int i; - sigset_t set; - boolean_t changed; - - /* mask all signals */ - (void) sigfillset(&set); - syscall(SYS_sigprocmask, SIG_SETMASK, &set, &gcmask); - - /* run at highest prio so I cannot be preempted */ - thr_getprio(thr_self(), &gcprio); - thr_setprio(thr_self(), 2147483647); /* #define INT_MAX 2147483647 */ - - oldlwpid_list_len = 0; - - while(1) { - changed = B_FALSE; - - /* Get the # of lwps in the process */ - memset(&Mystatus, 0, sizeof(Mystatus)); - syscall(SYS_ioctl, procfd, PIOCSTATUS, &Mystatus); - -#ifdef MY_DEBUG - VM_CALL(jio_fprintf)(stdout, "Number of lwps in the process is %d\n", - Mystatus.pr_nlwp); - VM_CALL(jio_fprintf)(stdout, "My lwp id is %d\n", _lwp_self()); -#endif - lwpid_list_len = Mystatus.pr_nlwp; - if (syscall(SYS_ioctl, procfd, PIOCLWPIDS, lwpid_list) == -1) { -#ifdef MY_DEBUG - VM_CALL(jio_fprintf)(stderr, "Can't read proc's lwpid list"); -#endif - return; - } - - print_lwps(); - - /* suspend all the lwps */ - suspend_lwps(); - - /* make sure all the lwps have actually stopped */ - wait_stopped_lwps(); - - /* make sure the list has not changed while you were not looking - else start all over again */ - if (lwpid_list_len != oldlwpid_list_len) changed = B_TRUE; - else { - for (i=0; i -#include -#include -#include - -#include "hpi_impl.h" - -#include "interrupt.h" - -/* handler_entry_t is used to keep track of the registered handlers. */ -typedef struct handler_entry { - intr_handler_t handler; - void *handlerArg; -} handler_entry_t; - -static handler_entry_t handlerList[N_INTERRUPTS]; - -/* Initialize the interrupt system */ -void -intrInit() -{ - memset(handlerList, 0, sizeof(handlerList)); - /* - * Target-dependent initialization. - */ - intrInitMD(); -} - -/* Add/Remove a handler for a particular interrupt */ - -signal_handler_t -intrRegister(int interrupt, intr_handler_t handler, void *handlerArg) -{ - struct sigaction sigAct, sigActOld; - - intrLock(); - - if (handler == (intr_handler_t)SYS_SIG_IGN || - handler == (intr_handler_t)SYS_SIG_DFL) { - /* If we get IGN or DFL, register that as the process signal handler, - * and clear the handlerList entry. - */ - sigAct.sa_handler = (void (*)(int))handler; - sigAct.sa_flags = 0; - sigaction(interrupt, &sigAct, &sigActOld); - handlerList[interrupt].handler = NULL; - } else { - /* Otherwise, we register intrDispatchMD as the common signal handler, - * and set the real handler in handlerList[interrupt].handler. - */ -#ifdef SA_SIGINFO - sigAct.sa_handler = 0; - sigAct.sa_sigaction = intrDispatchMD; - sigAct.sa_flags = SA_SIGINFO | SA_RESTART; -#else - sigAct.sa_handler = intrDispatchMD; - sigAct.sa_flags = SA_RESTART; -#endif - sigfillset(&sigAct.sa_mask); - sigaction(interrupt, &sigAct, &sigActOld); - handlerList[interrupt].handler = handler; - handlerList[interrupt].handlerArg = handlerArg; - } - - intrUnlock(); - - /* If SA_SIGINFO is set, sa_sigaction is valid, otherwise sa_handler is. */ -#ifdef SA_SIGINFO - return (sigActOld.sa_flags & SA_SIGINFO) ? - (signal_handler_t)sigActOld.sa_sigaction : - (signal_handler_t)sigActOld.sa_handler; -#else - return (signal_handler_t)sigActOld.sa_handler; -#endif -} - -/* - * intrDispatch -- Dispatch an interrupt. - * - * This routine is called from the low-level handlers - * at interrupt time. - */ -void -intrDispatch(int interrupt, void *siginfo, void *context) -{ - /* - * Assumptions: - * - Each interrupt only has one priority level associated with - * it. - * - Each handler will do enough work so that when it returns - * the source of the interrupt is masked. - */ - handler_entry_t *entry = &handlerList[interrupt]; - intr_handler_t handler = entry->handler; - - if (handler) { - (*handler)(interrupt, siginfo, context, entry->handlerArg); - return; - } - - /* No handler for this interrupt, log the error */ - Log1(0, "spurious interrupt %d\n", interrupt); - return; -} - -static void userSignalHandler(int sig, void *info, void *uc, void *arg) -{ - signal_handler_t handler = (signal_handler_t)arg; - /* for now we don't change the disposition of the signal in this case */ - /* sysSignal(sig, SYS_SIG_DFL); */ - handler(sig, info, uc); -} - -signal_handler_t sysSignal(int sig, signal_handler_t newHandler) -{ - handler_entry_t *entry = &handlerList[sig]; - void *oldHandlerArg = entry->handlerArg; - signal_handler_t oldHandler; - - if (intrInUse(sig)) { - return SYS_SIG_ERR; - } - -#ifdef __linux__ - oldHandler = intrRegister(sig, (intr_handler_t)userSignalHandler, (void *)newHandler); -#else - oldHandler = intrRegister(sig, userSignalHandler, (void *)newHandler); -#endif - /* If the old handler is intrDispatchMD, we get the real handler from - * entry->handlerArg. - */ - if (oldHandler == (signal_handler_t)intrDispatchMD) { - oldHandler = (signal_handler_t)oldHandlerArg; - } - - return oldHandler; -} - -void sysRaise(int sig) -{ - raise(sig); -} diff --git a/jdk/src/solaris/hpi/src/linker_md.c b/jdk/src/solaris/hpi/src/linker_md.c deleted file mode 100644 index 5f4e09692ea..00000000000 --- a/jdk/src/solaris/hpi/src/linker_md.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 1994, 2008, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Machine Dependent implementation of the dynamic linking support - * for java. This routine is Solaris specific. - */ - -#include "hpi_impl.h" - -#include -#include -#include -#include -#include - -#include "path_md.h" -#include "monitor_md.h" - -#ifndef NATIVE -#include "iomgr.h" -#include "threads_md.h" -#endif - -/* - * This lock protects the dl wrappers, assuring that two threads aren't - * in libdl at the same time. - */ -sys_mon_t _dl_lock; - -/* - * Solaris green threads needs to lock around libdl.so. - */ -#if defined(__solaris__) && !defined(NATIVE) - #define NEED_DL_LOCK -#endif - -/* - * create a string for the JNI native function name by adding the - * appropriate decorations. - */ -int -sysBuildFunName(char *name, int nameLen, int args_size, int encodingIndex) -{ - /* On Solaris, there is only one encoding method. */ - if (encodingIndex == 0) - return 1; - return 0; -} - -/* - * create a string for the dynamic lib open call by adding the - * appropriate pre and extensions to a filename and the path - */ -void -sysBuildLibName(char *holder, int holderlen, char *pname, char *fname) -{ - const size_t pnamelen = pname ? strlen(pname) : 0; - - /* Quietly truncate on buffer overflow. Should be an error. */ - if (pnamelen + strlen(fname) + 10 > (size_t) holderlen) { - *holder = '\0'; - return; - } - - if (pnamelen == 0) { - sprintf(holder, "lib%s.so", fname); - } else { - sprintf(holder, "%s/lib%s.so", pname, fname); - } -} - - -#ifdef __linux__ - static int thr_main(void) - { - return -1; - } -#else - #ifndef NATIVE - extern int thr_main(void); - #endif -#endif - -void * -sysLoadLibrary(const char *name, char *err_buf, int err_buflen) -{ - void * result; - -#ifdef NEED_DL_LOCK - sysMonitorEnter(sysThreadSelf(), &_dl_lock); - result = dlopen(name, RTLD_NOW); - sysMonitorExit(sysThreadSelf(), &_dl_lock); -#else - result = dlopen(name, RTLD_LAZY); -#endif - /* - * This is a bit of bulletproofing to catch the commonly occurring - * problem of people loading a library which depends on libthread into - * the VM. thr_main() should always return -1 which means that libthread - * isn't loaded. - */ -#ifndef NATIVE - if (thr_main() != -1) { - VM_CALL(panic)("libthread loaded into green threads"); - } -#endif - if (result == NULL) { - strncpy(err_buf, dlerror(), err_buflen-2); - err_buf[err_buflen-1] = '\0'; - } - return result; -} - -void -sysUnloadLibrary(void *handle) -{ -#ifdef NEED_DL_LOCK - sysMonitorEnter(sysThreadSelf(), &_dl_lock); - dlclose(handle); - sysMonitorExit(sysThreadSelf(), &_dl_lock); -#else - dlclose(handle); -#endif -} - -void * -sysFindLibraryEntry(void *handle, const char *name) -{ - void *sym; -#ifdef NEED_DL_LOCK - sysMonitorEnter(sysThreadSelf(), &_dl_lock); - sym = dlsym(handle, name); - sysMonitorExit(sysThreadSelf(), &_dl_lock); -#else - sym = dlsym(handle, name); -#endif - return sym; -} diff --git a/jdk/src/solaris/hpi/src/memory_md.c b/jdk/src/solaris/hpi/src/memory_md.c deleted file mode 100644 index 7650f254f6b..00000000000 --- a/jdk/src/solaris/hpi/src/memory_md.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (c) 1995, 2000, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Implementation of primitive memory allocation. - * - * The only thing machine dependent about this allocator is how it - * initially finds all of the possible memory, and how it implements - * mapChunk() and unmapChunk(). - * - * This is all pretty simple stuff. It is not likely to be banged on - * frequently enough to be a performance issue, unless the underlying - * primitives are. Implementing things: - * - * HPI function Solaris "malloc" Win32 - * -------------------------------------------------------------------- - * sysMapMem() mmap() malloc() VirtualAlloc(...MEM_RESERVE...) - * sysUnMapMem() munmap() free() VirtualFree(...MEM_RESERVE...) - * sysCommitMem() no-op no-op VirtualAlloc(...MEM_COMMIT...) - * sysDecommitMem() no-op no-op VirtualFree(...MEM_COMMIT...) - * - * Memory mapping is the default, but compiling with -DUSE_MALLOC gives - * a system based on malloc(). - */ - -#include -#include -#include -#include /* For perror() */ -#include -#include - -#include "hpi_impl.h" - -#ifndef USE_MALLOC - -#include -#include -#ifdef __linux__ -#ifndef MAP_ANONYMOUS -static int devZeroFD; -#endif -#else -static int devZeroFD; -#endif - -#endif /* !USE_MALLOC */ - -#ifdef __linux__ -#ifndef MAP_FAILED -#define MAP_FAILED ((caddr_t)-1) -#endif -static size_t memGrainSize; /* A page for Linux */ -#else -static unsigned int memGrainSize; /* A page for Solaris */ -#endif - -/* - * Mem size rounding is done at this level. The calling code asks - * these routines for literally what it thinks it wants. The size is - * rounded up to the first multiple of memGrainSize that contains - * requestedSize bytes. - */ - -static long -roundUpToGrain(long value) -{ - return (value + memGrainSize - 1) & ~(memGrainSize - 1); -} - -static long -roundDownToGrain(long value) -{ - return value & ~(memGrainSize - 1); -} - -void -InitializeMem(void) -{ - static int init = 0; - - if (init) { - return; /* Subsequent calls are no-ops */ - } - - /* - * Set system-specific variables used by mem allocator - */ - if (memGrainSize == 0) { - memGrainSize = (int) sysconf(_SC_PAGESIZE); - } - -#ifdef __linux__ -#if !defined(USE_MALLOC) && !defined(MAP_ANONYMOUS) - devZeroFD = open("/dev/zero", O_RDWR); - if (devZeroFD == -1) { - perror("devzero"); - exit(1); - } -#endif /* !USE_MALLOC MAP_ANONYMOUS*/ -#else -#ifndef USE_MALLOC - devZeroFD = open("/dev/zero", O_RDWR); - if (devZeroFD == -1) { - perror("devzero"); - exit(1); - } -#endif /* !USE_MALLOC */ -#endif - - init = 1; /* We're initialized now */ -} - - -#ifndef USE_MALLOC - -#define PROT_ALL (PROT_READ|PROT_WRITE|PROT_EXEC) - -#ifndef MAP_NORESERVE -#define MAP_NORESERVE 0 -#endif - -/* - * Map a chunk of memory. Return the address of the base if successful, - * 0 otherwise. We do not care where the mapped memory is, and can't - * even express a preference in the current HPI. If any platforms - * require us to manage addresses of mapped chunks explicitly, that - * must be done below the HPI. - */ -static char * -mapChunk(long length) -{ - char *ret; - -#if defined(__linux__) && defined(MAP_ANONYMOUS) - ret = (char *) mmap(0, length, PROT_ALL, - MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, - -1, (off_t) 0); -#else - ret = (char *) mmap(0, length, PROT_ALL, MAP_NORESERVE|MAP_PRIVATE, - devZeroFD, (off_t) 0); -#endif - return (ret == MAP_FAILED ? 0 : ret); -} - -/* - * Map a chunk of memory at a specific address and reserve swap space - * for it. This is currently only used to remap space previously mapped - * MAP_NORESERVE, reserving swap and getting native error handling. We - * assume that all alignment and rounding has been done by the caller. - * Return 1 if successful and 0 otherwise. - */ -static char * -mapChunkReserve(char *addr, long length) -{ - char *ret; -#if defined(__linux__) && defined(MAP_ANONYMOUS) - ret = (char *) mmap(addr, length, PROT_ALL, - MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, - -1, (off_t) 0); -#else - ret = (char *) mmap(addr, length, PROT_ALL, MAP_FIXED|MAP_PRIVATE, - devZeroFD, (off_t) 0); -#endif - return (ret == MAP_FAILED ? 0 : ret); -} - -/* - * Map a chunk of memory at a specific address and reserve swap space - * for it. This is currently only used to remap space previously mapped - * MAP_RESERVE, unreserving swap and getting native error handling. We - * assume that all alignment and rounding has been done by the caller. - * Return 1 if successful and 0 otherwise. - */ -static char * -mapChunkNoreserve(char *addr, long length) -{ - char *ret; - -#if defined(__linux__) && defined(MAP_ANONYMOUS) - ret = (char *) mmap(addr, length, PROT_ALL, - MAP_FIXED | MAP_PRIVATE | - MAP_NORESERVE | MAP_ANONYMOUS, - -1, (off_t) 0); -#else - ret = (char *) mmap(addr, length, PROT_ALL, - MAP_FIXED|MAP_PRIVATE|MAP_NORESERVE, - devZeroFD, (off_t) 0); -#endif - return (ret == MAP_FAILED ? 0 : ret); -} - -/* - * Unmap a chunk of memory. Return 1 if successful, 0 otherwise. We - * currently don't do any alignment or rounding, assuming that we only - * will unmap chunks that have previously been returned by mapChunk(). - */ -static int -unmapChunk(void *addr, long length) -{ - return (munmap(addr, length) == 0); -} - -#endif /* !USE_MALLOC */ - - -/* HPI Functions: */ - -/* - * Map a range of virtual memory. Note that the size asked for here - * is literally what the upper level has asked for. We need to do - * any rounding, etc. here. If mapping fails return 0, otherwise - * return the address of the base of the mapped memory. - */ -void * -sysMapMem(size_t requestedSize, size_t *mappedSize) -{ - void *mappedAddr; - - *mappedSize = roundUpToGrain(requestedSize); -#ifdef USE_MALLOC - mappedAddr = (void *) sysMalloc(*mappedSize); /* Returns 0 on failure */ -#ifdef __linux__ - if (mappedAddr) { - memset(mappedAddr, 0, *mappedSize); - mappedAddr = (void *) roundUpToGrain(mappedAddr); - } -#endif -#else - mappedAddr = mapChunk(*mappedSize); /* Returns 0 on failure */ -#endif /* USE_MALLOC */ - if (mappedAddr) { - Log3(2, "sysMapMem: 0x%x bytes at 0x%x (request: 0x%x bytes)\n", - *mappedSize, mappedAddr, requestedSize); - } else { - Log1(2, "sysMapMem failed: (request: 0x%x bytes)\n", requestedSize); - } - return mappedAddr; -} - -/* - * Unmap a range of virtual memory. Note that the size asked for here - * is literally what the upper level has asked for. We need to do any - * rounding, etc. here. If unmapping fails return 0, otherwise return - * the address of the base of the unmapped memory. - */ -void * -sysUnmapMem(void *requestedAddr, size_t requestedSize, size_t *unmappedSize) -{ - void *unmappedAddr; - int ret; - - *unmappedSize = roundUpToGrain(requestedSize); -#ifdef USE_MALLOC - sysFree(requestedAddr); - ret = 1; -#else - ret = unmapChunk(requestedAddr, *unmappedSize); -#endif /* USE_MALLOC */ - if (ret) { - unmappedAddr = requestedAddr; - Log4(2, - "sysUnmapMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *unmappedSize, unmappedAddr, requestedSize, requestedAddr); - } else { - unmappedAddr = 0; - Log2(2, "sysUnmapMem failed: (request: 0x%x bytes at 0x%x)\n", - requestedSize, requestedAddr); - } - return unmappedAddr; -} - -/* - * Commit/decommit backing store to a range of virtual memory. This range - * needs not be identical to a mapped range, but must be a subset of one. - * On Solaris, we remap the range to reserve swap for the space on - * commit. We don't strictly need to do this, as Solaris will demand - * page pages that we've mapped when we want to access them. But by - * reserving swap we get reasonable error handling for free where we'd - * otherwise end up getting a SIGBUS on a random write when we run out - * of swap. It also emphasizes the general need for shared code to - * postpone committing to mapped memory for as long as is feasible. - * When Java really needs space (the thread stacks excepted), it will - * soon write over it (heap, markbits), so we don't really get much from - * demand paging. - * - * We do not validate that commitment requests cover already-mapped - * memory, although in principle we could. The size asked for here - * is what the upper level has asked for. We need to do any platform- - * dependent rounding here. - * - * When you commit, you commit to the entire page (or whatever quantum - * your O/S requires) containing the pointer, and return the beginning of - * that page. When you decommit, you decommit starting at the next page - * *up* from that containing the pointer, except that decommitting from - * a pointer to the beginning of the page operates on that page. - */ - -/* - * Return the address of the base of the newly committed memory, or 0 - * if committing failed. - */ -void * -sysCommitMem(void *requestedAddr, size_t requestedSize, size_t *committedSize) -{ - void *committedAddr; - char *ret; - - *committedSize = roundUpToGrain(requestedSize); - committedAddr = (void *) roundDownToGrain((long) requestedAddr); -#ifdef USE_MALLOC -#ifdef __linux__ - ret = committedAddr; -#else - ret = requestedAddr; -#endif -#else - ret = mapChunkReserve(committedAddr, *committedSize); -#endif - if (ret) { - committedAddr = ret; - Log4(2, - "sysCommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *committedSize, committedAddr, requestedSize, requestedAddr); - } else { - committedAddr = 0; - Log2(2, "sysCommitMem failed: (request: 0x%x bytes at 0x%x)\n", - requestedSize, requestedAddr); - } - - return committedAddr; -} - -/* - * Return the address of the base of the newly decommitted memory, or 0 - * if decommitting failed. - */ -void * -sysDecommitMem(void *requestedAddr, size_t requestedSize, - size_t *decommittedSize) -{ - void *decommittedAddr; - char *ret; - - *decommittedSize = roundDownToGrain(requestedSize); - decommittedAddr = (void *) roundUpToGrain((long) requestedAddr); -#ifdef USE_MALLOC - ret = 0; -#else - ret = mapChunkNoreserve(decommittedAddr, *decommittedSize); -#endif - Log4(2, - "sysDecommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *decommittedSize, decommittedAddr, requestedSize, requestedAddr); - - return ret; -} - -/* - * Allocate memory on an alignment boundary. Returns aligned - * pointer to new memory. Use sysFreeBlock to free the block. - * - * sysAllocBlock() is similar to memalign(), except that it also - * returns a pointer to the beginning of the block returned by the - * OS, which must be used to deallocate the block. (On some OSes, - * these two won't be the same.) sysAllocBlock() is also more - * limited than memalign in that it can only be used to allocate - * on particular alignments (PAGE_ALIGNMENT) and should be assumed - * to round the sizes of allocated blocks up to multiples of the - * alignment value (PAGE_ALIGNMENT*n bytes). - */ -void * -sysAllocBlock(size_t size, void** allocHead) -{ - void* alignedPtr = memalign(PAGE_ALIGNMENT, size); - *allocHead = alignedPtr; - return alignedPtr; -} - -/* - * Wrapper to free block allocated by sysMemAlign. - */ -void -sysFreeBlock(void *allocHead) -{ - free(allocHead); -} - -void * sysMalloc(size_t s) -{ - if (s == 0) - return malloc(1); - return malloc(s); -} - -void * sysRealloc(void *p, size_t s) -{ - return realloc(p, s); -} - -void sysFree(void *p) -{ - if (p != NULL) - free(p); -} - -void * sysCalloc(size_t s1, size_t s2) -{ - if (s1 == 0 || s2 == 0) - return calloc(1, 1); - return calloc(s1, s2); -} - -char * sysStrdup(const char * string) -{ - return strdup(string); -} diff --git a/jdk/src/solaris/hpi/src/system_md.c b/jdk/src/solaris/hpi/src/system_md.c deleted file mode 100644 index e4823021053..00000000000 --- a/jdk/src/solaris/hpi/src/system_md.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 1994, 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "hpi_impl.h" - -#include -#include -#include -#include /* timeval */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "jni_md.h" -#include "mutex_md.h" - -#include "hpi_init.h" - -#include "interrupt.h" -#include "threads_md.h" -#include "monitor_md.h" -#include "largefile.h" - - -#define O_DELETE 0x10000 - -int sysThreadBootstrap(sys_thread_t **tidP, sys_mon_t **lockP, int nb) -{ - threadBootstrapMD(tidP, lockP, nb); - - intrInit(); - -#ifndef NATIVE - /* Initialize the special case for sbrk on Solaris (see synch.c) */ - InitializeSbrk(); - /* Initialize the async io */ - InitializeAsyncIO(); - InitializeMem(); - /* Initialize Clock and Idle threads */ - InitializeHelperThreads(); -#else /* if NATIVE */ - initializeContentionCountMutex(); - InitializeMem(); -#endif /* NATIVE */ - - return SYS_OK; -} - -int sysShutdown() -{ - return SYS_OK; -} - -long -sysGetMilliTicks() -{ - struct timeval tv; - - (void) gettimeofday(&tv, (void *) 0); - return((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); -} - -jlong -sysTimeMillis() -{ - struct timeval t; - gettimeofday(&t, 0); - return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000); -} - -int -sysGetLastErrorString(char *buf, int len) -{ - if (errno == 0) { - return 0; - } else { - const char *s = strerror(errno); - int n = strlen(s); - if (n >= len) n = len - 1; - strncpy(buf, s, n); - buf[n] = '\0'; - return n; - } -} - -/* - * File system - * - * These are all the sys API which implement the straight POSIX - * API. Those that do not are defined by thread-specific files - * (i.e. io_md.c) - */ - -/* - * Open a file. Unlink the file immediately after open returns - * if the specified oflag has the O_DELETE flag set. - */ -int sysOpen(const char *path, int oflag, int mode) -{ - int fd; - int delete = (oflag & O_DELETE); - oflag = oflag & ~O_DELETE; - fd = open64_w(path, oflag, mode); - if (delete != 0) { - unlink(path); - } - return fd; -} - -char *sysNativePath(char *path) -{ - return path; -} - -int -sysFileSizeFD(int fd, jlong *size) -{ - struct stat64 buf64; - int ret = fstat64(fd, &buf64); - *size = buf64.st_size; - return ret; -} - -int -sysFfileMode(int fd, int *mode) -{ - struct stat64 buf64; - int ret = fstat64(fd, &buf64); - (*mode) = buf64.st_mode; - return ret; -} - -int -sysFileType(const char *path) -{ - int ret; - struct stat buf; - - if ((ret = stat(path, &buf)) == 0) { - mode_t mode = buf.st_mode & S_IFMT; - if (mode == S_IFREG) return SYS_FILETYPE_REGULAR; - if (mode == S_IFDIR) return SYS_FILETYPE_DIRECTORY; - return SYS_FILETYPE_OTHER; - } - return ret; -} - -/* - * Wrapper functions for low-level I/O routines - use the 64 bit - * version if available, else revert to the 32 bit versions. - */ - -off64_t -lseek64_w(int fd, off64_t offset, int whence) -{ - return lseek64(fd, offset, whence); -} - -int -ftruncate64_w(int fd, off64_t length) -{ - return ftruncate64(fd, length); -} - -int -open64_w(const char *path, int oflag, int mode) -{ - int fd = open64(path, oflag, mode); - if (fd == -1) return -1; - - /* If the open succeeded, the file might still be a directory */ - { - int st_mode; - if (sysFfileMode(fd, &st_mode) != -1) { - if ((st_mode & S_IFMT) == S_IFDIR) { - errno = EISDIR; - close(fd); - return -1; - } - } else { - close(fd); - return -1; - } - } - - /* - * 32-bit Solaris systems suffer from: - * - * - an historical default soft limit of 256 per-process file - * descriptors that is too low for many Java programs. - * - * - a design flaw where file descriptors created using stdio - * fopen must be less than 256, _even_ when the first limit above - * has been raised. This can cause calls to fopen (but not calls to - * open, for example) to fail mysteriously, perhaps in 3rd party - * native code (although the JDK itself uses fopen). One can hardly - * criticize them for using this most standard of all functions. - * - * We attempt to make everything work anyways by: - * - * - raising the soft limit on per-process file descriptors beyond - * 256 (done by hotspot) - * - * - As of Solaris 10u4, we can request that Solaris raise the 256 - * stdio fopen limit by calling function enable_extended_FILE_stdio, - * (also done by hotspot). We check for its availability. - * - * - If we are stuck on an old (pre 10u4) Solaris system, we can - * workaround the bug by remapping non-stdio file descriptors below - * 256 to ones beyond 256, which is done below. - * - * See: - * 1085341: 32-bit stdio routines should support file descriptors >255 - * 6533291: Work around 32-bit Solaris stdio limit of 256 open files - * 6431278: Netbeans crash on 32 bit Solaris: need to call - * enable_extended_FILE_stdio() in VM initialisation - * Giri Mandalika's blog - * http://technopark02.blogspot.com/2005_05_01_archive.html - */ -#if defined(__solaris__) && defined(_ILP32) - { - static int needToWorkAroundBug1085341 = -1; - if (needToWorkAroundBug1085341) { - if (needToWorkAroundBug1085341 == -1) - needToWorkAroundBug1085341 = - (dlsym(RTLD_DEFAULT, "enable_extended_FILE_stdio") == NULL); - if (needToWorkAroundBug1085341 && fd < 256) { - int newfd = fcntl(fd, F_DUPFD, 256); - if (newfd != -1) { - close(fd); - fd = newfd; - } - } - } - } -#endif /* 32-bit Solaris */ - - /* - * All file descriptors that are opened in the JVM and not - * specifically destined for a subprocess should have the - * close-on-exec flag set. If we don't set it, then careless 3rd - * party native code might fork and exec without closing all - * appropriate file descriptors (e.g. as we do in closeDescriptors in - * UNIXProcess.c), and this in turn might: - * - * - cause end-of-file to fail to be detected on some file - * descriptors, resulting in mysterious hangs, or - * - * - might cause an fopen in the subprocess to fail on a system - * suffering from bug 1085341. - * - * (Yes, the default setting of the close-on-exec flag is a Unix - * design flaw) - * - * See: - * 1085341: 32-bit stdio routines should support file descriptors >255 - * 4843136: (process) pipe file descriptor from Runtime.exec not being closed - * 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9 - */ -#ifdef FD_CLOEXEC - { - int flags = fcntl(fd, F_GETFD); - if (flags != -1) - fcntl(fd, F_SETFD, flags | FD_CLOEXEC); - } -#endif - return fd; -} - -void setFPMode(void) -{ -#if defined(__amd64) - asm(" pushq $0x1F80"); - /* ldmxcsr (%rsp) */ - asm(" .byte 0x0f,0xae,0x14,0x24"); - asm(" popq %rax"); -#elif defined(i386) - asm(" pushl $575"); - asm(" fldcw (%esp)"); - asm(" popl %eax"); -#endif -#if defined(__linux__) && defined(__mc68000__) - asm(" fmovel #0x80,%fpcr"); -#endif -} diff --git a/jdk/src/windows/hpi/export/byteorder_md.h b/jdk/src/windows/hpi/export/byteorder_md.h deleted file mode 100644 index 3ff9e162362..00000000000 --- a/jdk/src/windows/hpi/export/byteorder_md.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/*- - * Win32 dependent machine byte ordering (actually intel ordering) - */ - -#ifndef _JAVASOFT_WIN32_BYTEORDER_MD_H_ -#define _JAVASOFT_WIN32_BYTEORDER_MD_H_ - -#ifdef x86 -#define ntohl(x) ((x << 24) | \ - ((x & 0x0000ff00) << 8) | \ - ((x & 0x00ff0000) >> 8) | \ - (((unsigned long)(x & 0xff000000)) >> 24)) -#define ntohs(x) (((x & 0xff) << 8) | ((x >> 8) & (0xff))) -#define htonl(x) ntohl(x) -#define htons(x) ntohs(x) -#else /* x86 */ -#define ntohl(x) (x) -#define ntohs(x) (x) -#define htonl(x) (x) -#define htons(x) (x) -#endif /* x86 */ - -#endif /* !_JAVASOFT_WIN32_BYTEORDER_MD_H_ */ diff --git a/jdk/src/windows/hpi/export/hpi_md.h b/jdk/src/windows/hpi/export/hpi_md.h deleted file mode 100644 index 92b96f50fc3..00000000000 --- a/jdk/src/windows/hpi/export/hpi_md.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#ifndef _JAVASOFT_HPI_MD_H_ -#define _JAVASOFT_HPI_MD_H_ - -#include "timeval_md.h" -#include "io_md.h" -#include "path_md.h" -#include "byteorder_md.h" - -#define HPI_TIMEOUT_INFINITY ((jlong)(-1)) - -#endif /* !_JAVASOFT_HPI_MD_H_ */ diff --git a/jdk/src/windows/hpi/export/io_md.h b/jdk/src/windows/hpi/export/io_md.h deleted file mode 100644 index 620533e26f4..00000000000 --- a/jdk/src/windows/hpi/export/io_md.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Win32 system dependent low level io definitions - */ - -#ifndef _JAVASOFT_WIN32_IO_MD_H_ -#define _JAVASOFT_WIN32_IO_MD_H_ - -#include -#include /* For read(), lseek() etc. */ -#include /* For mkdir() */ -#include -#include -#include -#include -#include - -#include "jvm_md.h" - -#define R_OK 4 -#define W_OK 2 -#define X_OK 1 -#define F_OK 0 - -#define MAXPATHLEN _MAX_PATH - -#define S_ISFIFO(mode) (((mode) & _S_IFIFO) == _S_IFIFO) -#define S_ISCHR(mode) (((mode) & _S_IFCHR) == _S_IFCHR) -#define S_ISDIR(mode) (((mode) & _S_IFDIR) == _S_IFDIR) -#define S_ISREG(mode) (((mode) & _S_IFREG) == _S_IFREG) - -#define LINE_SEPARATOR "\r\n" - -#endif /* !_JAVASOFT_WIN32_IO_MD_H_ */ diff --git a/jdk/src/windows/hpi/export/path_md.h b/jdk/src/windows/hpi/export/path_md.h deleted file mode 100644 index fc801d80a9c..00000000000 --- a/jdk/src/windows/hpi/export/path_md.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/*- - * Win32 dependent search path definitions and API - */ - -#ifndef _JAVASOFT_WIN32_PATH_MD_H_ -#define _JAVASOFT_WIN32_PATH_MD_H_ - -#define PATH_SEPARATOR ";" -#define PATH_CURDIR "." - -#define DIR_SEPARATOR '/' -#define LOCAL_DIR_SEPARATOR '\\' - -#endif /* !_JAVASOFT_WIN32_PATH_MD_H_ */ diff --git a/jdk/src/windows/hpi/export/timeval_md.h b/jdk/src/windows/hpi/export/timeval_md.h deleted file mode 100644 index 98392b1d9f0..00000000000 --- a/jdk/src/windows/hpi/export/timeval_md.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -#ifndef _JAVASOFT_WIN32_TIMEVAL_H_ -#define _JAVASOFT_WIN32_TIMEVAL_H_ - -typedef struct { - long tv_sec; - long tv_usec; -} timeval_t; - -/* - * Operations on timevals. - * - * NB: timercmp does not work for >=, <= or ==. - */ -#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) -#define timercmp(tvp, uvp, cmp) \ - ((tvp)->tv_sec cmp (uvp)->tv_sec || \ - (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec) -#define timereq(tvp, uvp) \ - ((tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec == (uvp)->tv_usec) -#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0 - -void timeradd(timeval_t*, timeval_t*); -void timersub(timeval_t*, timeval_t*); - -#endif /* !_JAVASOFT_WIN32_TIMEVAL_H_ */ diff --git a/jdk/src/windows/hpi/include/monitor_md.h b/jdk/src/windows/hpi/include/monitor_md.h deleted file mode 100644 index dc74c4c3b0c..00000000000 --- a/jdk/src/windows/hpi/include/monitor_md.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Win32 implementation of Java monitors - */ - -#ifndef _JAVASOFT_WIN32_MONITOR_MD_H_ -#define _JAVASOFT_WIN32_MONITOR_MD_H_ - -#include - -#include "threads_md.h" -#include "mutex_md.h" - -#define SYS_MID_NULL ((sys_mon_t *) 0) - -typedef struct sys_mon { - long atomic_count; /* Variable for atomic compare swap */ - HANDLE semaphore; /* Semaphore used for the contention */ - sys_thread_t *monitor_owner; /* Current owner of this monitor */ - long entry_count; /* Recursion depth */ - sys_thread_t *monitor_waiter; /* Monitor waiting queue head */ - long waiter_count; /* For debugging purpose */ -} sys_mon_t; - -#endif /* !_JAVASOFT_WIN32_MONITOR_MD_H_ */ diff --git a/jdk/src/windows/hpi/include/mutex_md.h b/jdk/src/windows/hpi/include/mutex_md.h deleted file mode 100644 index f927bd0a08f..00000000000 --- a/jdk/src/windows/hpi/include/mutex_md.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 1994, 1998, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Win32 implementation of mutexes. Here we use critical sections as - * our mutexes. We could have used mutexes, but mutexes are heavier - * weight than critical sections. Mutexes and critical sections are - * semantically identical, the only difference being that mutexes - * can operate between processes (i.e. address spaces). - * - * It's worth noting that the Win32 functions supporting critical - * sections do not provide any error information whatsoever (i.e. - * all critical section routines return (void)). - */ - -#ifndef _JAVASOFT_WIN32_MUTEX_MD_H_ -#define _JAVASOFT_WIN32_MUTEX_MD_H_ - -#include - -typedef CRITICAL_SECTION mutex_t; - -#define mutexInit(m) InitializeCriticalSection(m) -#define mutexDestroy(m) DeleteCriticalSection(m) -#define mutexLock(m) EnterCriticalSection(m) -#define mutexUnlock(m) LeaveCriticalSection(m) - -#endif /* !_JAVASOFT_WIN32_MUTEX_MD_H_ */ diff --git a/jdk/src/windows/hpi/include/threads_md.h b/jdk/src/windows/hpi/include/threads_md.h deleted file mode 100644 index 166a880c58f..00000000000 --- a/jdk/src/windows/hpi/include/threads_md.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 1994, 1999, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Win32 implementation of Java threads - */ - -#ifndef _JAVASOFT_WIN32_THREADS_MD_H_ -#define _JAVASOFT_WIN32_THREADS_MD_H_ - -#include - -#define N_TRACED_REGS 7 - -#define SYS_THREAD_NULL ((sys_thread_t *) 0) - -/* - * Machine dependent info in a sys_thread_t: Keep these values in - * sync with the string array used by sysThreadDumpInfo() in threads_md.c! - */ -typedef enum { - FIRST_THREAD_STATE, - RUNNABLE = FIRST_THREAD_STATE, - SUSPENDED, - MONITOR_WAIT, - CONDVAR_WAIT, - MONITOR_SUSPENDED, - NUM_THREAD_STATES -} thread_state_t; - -struct sys_mon; - -/* - * Machine dependent thread data structure - */ -typedef struct sys_thread { - HANDLE handle; /* Win32 thread handle */ - unsigned long id; /* Win32 thread id */ - long regs[N_TRACED_REGS]; /* Registers */ - thread_state_t state; /* Current thread state */ - bool_t system_thread; /* TRUE if this is a system thread */ - bool_t interrupted; /* Shadow thread interruption */ - short suspend_flags; - HANDLE interrupt_event; /* Event signaled on thread interrupt */ - struct sys_mon *wait_monitor; /* Monitor the thread is waiting for */ - struct sys_thread *next_waiter; /* Next thread in the waiting queue */ - struct sys_mon *enter_monitor; /* Monitor thread is waiting to enter */ - void (*start_proc)(void *); /* Thread start routine address */ - void *start_parm; /* Thread start routine parameter */ - struct sys_thread *next; /* Next thread in active thread queue */ - void *stack_ptr; /* Pointer into the stack segment */ - unsigned int last_sum; - PNT_TIB nt_tib; /* Pointer to NT thread-local block */ -} sys_thread_t; - -#define MONITOR_WAIT_SUSPENDED 0x0001 -#define CONDVAR_WAIT_SUSPENDED 0x0002 - -extern bool_t ThreadsInitialized; - -extern sys_mon_t *_sys_queue_lock; - -#define SYS_QUEUE_LOCK(self) sysMonitorEnter(self, _sys_queue_lock) -#define SYS_QUEUE_LOCKED(self) sysMonitorEntered(self, _sys_queue_lock) -#define SYS_QUEUE_UNLOCK(self) sysMonitorExit(self, _sys_queue_lock) -#define SYS_QUEUE_NOTIFYALL(self) sysMonitorNotifyAll(self, _sys_queue_lock) -#define SYS_QUEUE_WAIT(self) sysMonitorWait(self, _sys_queue_lock, \ - SYS_TIMEOUT_INFINITY) - -#endif /* !_JAVASOFT_WIN32_THREADS_MD_H_ */ diff --git a/jdk/src/windows/hpi/src/linker_md.c b/jdk/src/windows/hpi/src/linker_md.c deleted file mode 100644 index f14109a1f66..00000000000 --- a/jdk/src/windows/hpi/src/linker_md.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 1994, 2005, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Maintains a list of currently loaded DLLs (Dynamic Link Libraries) - * and their associated handles. Library names are case-insensitive. - */ - -#include -#include -#include - -#include "hpi_impl.h" - -#include "path_md.h" - -/* - * create a string for the JNI native function name by adding the - * appropriate decorations. - * - * On Win32, "__stdcall" functions are exported differently, depending - * on the compiler. In MSVC 4.0, they are decorated with a "_" in the - * beginning, and @nnn in the end, where nnn is the number of bytes in - * the arguments (in decimal). Borland C++ exports undecorated names. - * - * sysBuildFunName handles different encodings depending on the value - * of encodingIndex. It returns 0 when handed an out-of-range - * encodingIndex. - */ -int -sysBuildFunName(char *name, int nameMax, int args_size, int encodingIndex) -{ - if (encodingIndex == 0) { - /* For Microsoft MSVC 4.0 */ - char suffix[6]; /* This is enough since Java never has more than - 256 words of arguments. */ - int nameLen; - int i; - - sprintf(suffix, "@%d", args_size * 4); - - nameLen = strlen(name); - if (nameLen >= nameMax - 7) - return 1; - for(i = nameLen; i > 0; i--) - name[i] = name[i-1]; - name[0] = '_'; - - sprintf(name + nameLen + 1, "%s", suffix); - return 1; - } else if (encodingIndex == 1) - /* For Borland, etc. */ - return 1; - else - return 0; -} - -/* - * Build a machine dependent library name out of a path and file name. - */ -void -sysBuildLibName(char *holder, int holderlen, char *pname, char *fname) -{ - const int pnamelen = pname ? strlen(pname) : 0; - const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0; - - /* Quietly truncates on buffer overflow. Should be an error. */ - if (pnamelen + strlen(fname) + 10 > holderlen) { - *holder = '\0'; - return; - } - - if (pnamelen == 0) { - sprintf(holder, "%s.dll", fname); - } else if (c == ':' || c == '\\') { - sprintf(holder, "%s%s.dll", pname, fname); - } else { - sprintf(holder, "%s\\%s.dll", pname, fname); - } -} - -void * -sysLoadLibrary(const char * name, char *err_buf, int err_buflen) -{ - void *result = LoadLibrary(name); - if (result == NULL) { - /* Error message is pretty lame, try to make a better guess. */ - long errcode = GetLastError(); - if (errcode == ERROR_MOD_NOT_FOUND) { - strncpy(err_buf, "Can't find dependent libraries", err_buflen-2); - err_buf[err_buflen-1] = '\0'; - } else { - sysGetLastErrorString(err_buf, err_buflen); - } - } - return result; -} - -void sysUnloadLibrary(void *handle) -{ - FreeLibrary(handle); -} - -void * sysFindLibraryEntry(void *handle, const char *name) -{ - return GetProcAddress(handle, name); -} diff --git a/jdk/src/windows/hpi/src/memory_md.c b/jdk/src/windows/hpi/src/memory_md.c deleted file mode 100644 index 982a93f2707..00000000000 --- a/jdk/src/windows/hpi/src/memory_md.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 1995, 2002, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Implementation of primitive memory allocation. - * - * The only thing machine dependent about this allocator is how it - * initially finds all of the possible memory, and how it implements - * mapChunk() and unmapChunk(). - * - * This is all pretty simple stuff. It is not likely to be banged on - * frequently enough to be a performance issue, unless the underlying - * primitives are. Implementing things: - * - * HPI function Solaris "malloc" Win32 - * -------------------------------------------------------------------- - * sysMapMem() mmap() malloc() VirtualAlloc(...MEM_RESERVE...) - * sysUnMapMem() munmap() free() VirtualFree(...MEM_RESERVE...) - * sysCommitMem() no-op no-op VirtualAlloc(...MEM_COMMIT...) - * sysDecommitMem() no-op no-op VirtualFree(...MEM_COMMIT...) - * - * Memory mapping is the default, but compiling with -DUSE_MALLOC gives - * a system based on malloc(). - */ - -#include -#include - -#include "hpi_impl.h" - -static size_t -roundUp(size_t n, size_t m) -{ - return (n + m - 1) & ~(m - 1); -} - -static size_t -roundDown(size_t n, size_t m) -{ - return n & ~(m - 1); -} - -#define RESERVE_SIZE 65536 /* Memory is reserved in 64KB chunks */ - -static size_t pageSize; /* Machine page size */ - -void -InitializeMem() -{ - SYSTEM_INFO si; - - GetSystemInfo(&si); - pageSize = si.dwPageSize; -} - -/* HPI Functions: */ - -/* - * Map a range of virtual memory. Note that the size asked for here - * is literally what the upper level has asked for. We need to do - * any rounding, etc. here. If mapping fails return 0, otherwise - * return the address of the base of the mapped memory. - */ -void * -sysMapMem(size_t requestedSize, size_t *mappedSize) -{ - void *mappedAddr; - -#ifdef USE_MALLOC - *mappedSize = roundUp(requestedSize, pageSize); - mappedAddr = (void *)malloc(*mappedSize); -#else - *mappedSize = roundUp(requestedSize, RESERVE_SIZE); - mappedAddr = VirtualAlloc(NULL, *mappedSize, MEM_RESERVE, PAGE_READWRITE); -#endif - if (mappedAddr != NULL) { - Log3(2, "sysMapMem: 0x%x bytes at 0x%x (request: 0x%x bytes)\n", - *mappedSize, mappedAddr, requestedSize); - } else { - Log1(2, "sysMapMem failed: (request: 0x%x bytes)\n", requestedSize); - } - return mappedAddr; -} - -/* - * Unmap a range of virtual memory. Note that the size asked for here - * is literally what the upper level has asked for. We need to do any - * rounding, etc. here. If unmapping fails return 0, otherwise return - * the address of the base of the unmapped memory. - */ -void * -sysUnmapMem(void *requestedAddr, size_t requestedSize, size_t *unmappedSize) -{ - void *unmappedAddr; - int ret; - -#ifdef USE_MALLOC - *unmappedSize = roundUp(requestedSize, pageSize); - free(requestedAddr); - ret = TRUE; -#else - *unmappedSize = roundUp(requestedSize, RESERVE_SIZE); - ret = VirtualFree(requestedAddr, 0, MEM_RELEASE); -#endif - if (ret) { - unmappedAddr = requestedAddr; - Log4(2, - "sysUnmapMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *unmappedSize, unmappedAddr, requestedSize, requestedAddr); - } else { - unmappedAddr = NULL; - Log2(2, "sysUnmapMem failed: (request: 0x%x bytes at 0x%x)\n", - requestedSize, requestedAddr); - } - return unmappedAddr; -} - -/* - * Commit/decommit backing store to a range of virtual memory. This range - * needs not be identical to a mapped range, but must be a subset of one. - * On Solaris, we remap the range to reserve swap for the space on - * commit. We don't strictly need to do this, as Solaris will demand - * page pages that we've mapped when we want to access them. But by - * reserving swap we get reasonable error handling for free where we'd - * otherwise end up getting a SIGBUS on a random write when we run out - * of swap. It also emphasizes the general need for shared code to - * postpone committing to mapped memory for as long as is feasible. - * When Java really needs space (the thread stacks excepted), it will - * soon write over it (heap, markbits), so we don't really get much from - * demand paging. - * - * We do not validate that commitment requests cover already-mapped - * memory, although in principle we could. The size asked for here - * is what the upper level has asked for. We need to do any platform- - * dependent rounding here. - * - * When you commit, you commit to the entire page (or whatever quantum - * your O/S requires) containing the pointer, and return the beginning of - * that page. When you decommit, you decommit starting at the next page - * *up* from that containing the pointer, except that decommitting from - * a pointer to the beginning of the page operates on that page. - */ - -/* - * Return the address of the base of the newly committed memory, or 0 - * if committing failed. - */ -void * -sysCommitMem(void *requestedAddr, size_t requestedSize, size_t *committedSize) -{ - void *committedAddr; - - *committedSize = roundUp(requestedSize, pageSize); - committedAddr = VirtualAlloc(requestedAddr, *committedSize, MEM_COMMIT, - PAGE_READWRITE); - if (committedAddr != NULL) { - Log4(2, - "sysCommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *committedSize, committedAddr, requestedSize, requestedAddr); - } else { - Log2(2, "sysCommitMem failed: (request: 0x%x bytes at 0x%x)\n", - requestedSize, requestedAddr); - } - return committedAddr; -} - -/* - * Return the address of the base of the newly decommitted memory, or 0 - * if decommitting failed. - */ -void * -sysDecommitMem(void *requestedAddr, size_t requestedSize, - size_t *decommittedSize) -{ - void *decommittedAddr; - - /* - * We round the size down to a multiple of the page size and - * round the address up. This ensures that we never decommit - * more that we intend to. - */ - *decommittedSize = roundDown(requestedSize, pageSize); - decommittedAddr = (void *)roundUp((size_t)requestedAddr, pageSize); - - /* - * If the rounded size is equal to zero we simply fail. Passing - * 0 to VirtualFree seems to cause the entire region to be released, - * which is definitely not what we want, since that probably means - * that decommittedAddr is at the end of the current mapping which - * may be the beginning of the next mapping. - */ - if (*decommittedSize != 0 && - VirtualFree(decommittedAddr, *decommittedSize, MEM_DECOMMIT)) { - Log4(2, - "sysDecommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *decommittedSize, decommittedAddr, requestedSize, requestedAddr); - } else { - Log4(2, - "sysDecommitMem: failed 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", - *decommittedSize, decommittedAddr, requestedSize, requestedAddr); - decommittedAddr = NULL; - } - return decommittedAddr; -} - -#define PAGED_HEAPS - -#ifdef PAGED_HEAPS - -/* - * Allocate memory on an alignment boundary. Returns aligned - * pointer to new memory. Use sysFreeBlock to free the block. - * - * sysAllocBlock() is similar to memalign(), except that it also - * returns a pointer to the beginning of the block returned by the - * OS, which must be used to deallocate the block. (On some OSes, - * these two won't be the same.) sysAllocBlock() is also more - * limited than memalign in that it can only be used to allocate - * on particular alignments (PAGE_ALIGNMENT) and should be assumed - * to round the sizes of allocated blocks up to multiples of the - * alignment value (PAGE_ALIGNMENT*n bytes). - * - * Note that the use of VirtualAlloc on Win32 is closely tied in to - * the decision for paged heap pages on Win32 to be 64K (that is, - * PAGE_ALIGNMENT is 64K), a reasonable choice in any case. - */ -void * -sysAllocBlock(size_t size, void** allocHead) -{ - void* alignedPtr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); - *allocHead = alignedPtr; - return alignedPtr; -} - -/* - * Wrapper to free block allocated by sysMemAlign. - */ -void -sysFreeBlock(void *allocHead) -{ - VirtualFree(allocHead, 0, MEM_RELEASE); -} - -#endif /* PAGED_HEAPS */ - -void * sysMalloc(size_t s) -{ - if (s == 0) - return malloc(1); - return malloc(s); -} - -void * sysRealloc(void *p, size_t s) -{ - return realloc(p, s); -} - -void sysFree(void *p) -{ - if (p != NULL) - free(p); -} - -void * sysCalloc(size_t s1, size_t s2) -{ - if (s1 == 0 || s2 == 0) - return calloc(1, 1); - return calloc(s1, s2); -} - -char * sysStrdup(const char * string) -{ - return strdup(string); -} diff --git a/jdk/src/windows/hpi/src/monitor_md.c b/jdk/src/windows/hpi/src/monitor_md.c deleted file mode 100644 index 9765f0a51ac..00000000000 --- a/jdk/src/windows/hpi/src/monitor_md.c +++ /dev/null @@ -1,517 +0,0 @@ -/* - * Copyright (c) 1994, 2002, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Win32 implementation of Java monitors - */ - -#include - -#include "hpi_impl.h" - -#include "threads_md.h" -#include "monitor_md.h" - -/* - * Use this information to improve performance for single CPU machine. - */ -static int systemIsMP; - -static mutex_t semaphore_init_mutex; -static mutex_t *semaphore_init_mutex_p = NULL; -/* - * Create and initialize monitor. This can be called before threads have - * been initialized. - */ -int -sysMonitorInit(sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - if (semaphore_init_mutex_p == NULL) { - systemIsMP = sysGetSysInfo()->isMP; - mutexInit(&semaphore_init_mutex); - semaphore_init_mutex_p = &semaphore_init_mutex; - } - - mid->atomic_count = -1; /* -1 for no thread, 0 means 1 thread */ - mid->semaphore = NULL; /* No semaphore until needed */ - mid->monitor_owner = SYS_THREAD_NULL; - mid->entry_count = 0; /* Recursion count */ - mid->monitor_waiter = 0; /* First waiting thread */ - mid->waiter_count = 0; /* Count of waiting and wake-up thread */ - - return SYS_OK; -} - -/* - * Free any system-dependent resources held by monitors. On Win32 this - * means releasing the critical section (mutex) and condition variable - * that are part of each monitor. - */ -int -sysMonitorDestroy(sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - CloseHandle(mid->semaphore); - - return SYS_OK; -} - -static void initializeSemaphore(HANDLE *pSema) -{ - mutexLock(semaphore_init_mutex_p); - if (*pSema == NULL) { - *pSema = CreateSemaphore(0,0,1,0); - } - mutexUnlock(semaphore_init_mutex_p); -} - -/* - * Take ownership of monitor. This can be called before threads have - * been initialized, in which case we do nothing since locked monitors - * are not yet needed. - - * The actual code is split into two functions, the assembler routine - * handles the fast path, while the C routine handle the slow path, - * including the lazy initialization of monitor semaphore. - * - * REMIND: It is EXTREMELY RISKY to change any of the code without - * thorough understanding of the system, compiler and call convention. - */ - -static int __fastcall sysMonitorEnter2(sys_thread_t *self, sys_mon_t *mid) -{ - if (mid->semaphore == NULL) { - initializeSemaphore(&(mid->semaphore)); - if (mid->semaphore == NULL) { - return SYS_NORESOURCE; - } - } - - self->enter_monitor = mid; - if (profiler_on) { - VM_CALL(monitorContendedEnter)(self, mid); - } - WaitForSingleObject(mid->semaphore, INFINITE); - self->enter_monitor = NULL; - - mid->monitor_owner = self; - mid->entry_count = 1; - - if (profiler_on) { - VM_CALL(monitorContendedEntered)(self, mid); - } - return SYS_OK; -} - -/* - * The following assembler routine is highly compiler specific. - * Because of the complexity, there is no debug error check. - */ - -#ifndef _WIN64 -int __cdecl -sysMonitorEnter(sys_thread_t *self, sys_mon_t *mid) -{ - __asm - { - mov edx, dword ptr [esp+8]; // load mid - mov ecx, dword ptr [esp+4]; // load self - mov eax, dword ptr [edx+8]; // load mid->monitor_owner - - cmp eax, ecx; // if ( self == mid->monitor_owner ) - je RECURSION; // goto RECURSION; - - mov eax, dword ptr [systemIsMP]; - test eax, eax; - jne MPM; - - inc dword ptr [edx]; /* atomic increment mid->atomic_count */ - jne ACQUIRE_SEMAPHORE; /* if there is an owner already */ - - mov dword ptr [edx+8], ecx; /* mid->monitor_owner = self */ - mov dword ptr [edx+12], 1; /* mid->entry_count = 1 */ - xor eax, eax; /* return SYS_OK */ - ret; - -MPM: - lock inc dword ptr [edx]; /* atomic increment mid->atomic_count */ - jne ACQUIRE_SEMAPHORE; /* if there is an owner already */ - - mov dword ptr [edx+8], ecx; /* mid->monitor_owner = self */ - mov dword ptr [edx+12], 1; /* mid->entry_count = 1 */ - xor eax, eax; /* return SYS_OK */ - ret; - -RECURSION: - inc dword ptr [edx+12]; /* Increment mid->entry_count */ - xor eax, eax; /* return SYS_OK */ - ret; - -ACQUIRE_SEMAPHORE: - /* The self is passed by ECX, mid is passed by EDX */ - jmp sysMonitorEnter2; - } -} -#else -int __cdecl -sysMonitorEnter(sys_thread_t *self, sys_mon_t *mid) -{ -return (SYS_NORESOURCE); -} -#endif - -/* - * Return TRUE if this thread currently owns the monitor. This can be - * called before threads have been initialized, in which case we always - * return TRUE. - */ -bool_t -sysMonitorEntered(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - sysAssert(self != 0); - sysAssert(ThreadsInitialized); - - return (mid->monitor_owner == self); -} - -/* - * Release ownership of monitor. This can be called before threads have - * been initialized, in which case we do nothing as locked monitors are - * not yet needed. - * - * The actual code is split into two functions, the assembler routine - * handles the fast path, while the C routine handle the slow path. - * - * REMIND: It is EXTREMELY RISKY to change any of the code without - * thorough understanding of the system, compiler and call convention. - */ - -static int __fastcall -sysMonitorExit2(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid->entry_count == 0); - sysAssert(mid->atomic_count >= 0); - sysAssert(mid->monitor_owner == 0); - - if (mid->semaphore == NULL) { - initializeSemaphore(&(mid->semaphore)); - if (mid->semaphore == NULL) { - return SYS_NORESOURCE; - } - } - - ReleaseSemaphore(mid->semaphore, 1, 0); - - if (profiler_on) { - VM_CALL(monitorContendedExit)(self, mid); - } - - return SYS_OK; -} - -#ifndef _WIN64 -__declspec(naked) int __cdecl -sysMonitorExit(sys_thread_t *self, sys_mon_t *mid) -{ - __asm - { - mov edx, dword ptr [esp+8]; /* load mid */ - mov ecx, dword ptr [esp+4]; /* load self */ - mov eax, dword ptr [edx+8]; /* load mid->monitor_owner */ - - cmp eax, ecx; /* if ( self != mid->monitor_owner ) */ - jne ERR_RET; /* goto ERROR_RET */ - - dec dword ptr [edx+12]; /* dec mid->entry_count */ - jne OK_RET; /* entry_count != 0 */ - - mov dword ptr [edx+8], 0; /* mid->monitor_owner = 0 */ - - mov eax, dword ptr [systemIsMP]; - test eax, eax; - jne MPM; - - dec dword ptr [edx]; /* atomic decrement mid->atomic_count */ - jge RELEASE_SEMAPHORE; /* if ( atomic_variable < 0 ) */ - xor eax, eax; /* return SYS_OK */ - ret; - -MPM: - lock dec dword ptr [edx]; /* atomic decrement mid->atomic_count */ - jge RELEASE_SEMAPHORE; /* if ( atomic_variable < 0 ) */ -OK_RET: - xor eax, eax; - ret; - -ERR_RET: - mov eax, 0FFFFFFFFH; - ret; - -RELEASE_SEMAPHORE: - jmp sysMonitorExit2; /* forwading call */ - } -} -#else -int __cdecl -sysMonitorExit(sys_thread_t *self, sys_mon_t *mid) -{ -return (-1); -} -#endif - -/* - * Notify single thread waiting on condition variable. - */ -int -sysMonitorNotify(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - if (mid->monitor_owner != self) { - return SYS_ERR; - } - - if (mid->monitor_waiter != SYS_THREAD_NULL) - { - sys_thread_t *thread = mid->monitor_waiter; - mid->monitor_waiter = thread->next_waiter; - - thread->next_waiter = SYS_THREAD_NULL; - thread->wait_monitor = SYS_MID_NULL; - - SetEvent(thread->interrupt_event); - } - - return SYS_OK; -} - -/* - * Notify all threads waiting on condition variable. - */ -int -sysMonitorNotifyAll(sys_thread_t *self, sys_mon_t *mid) -{ - sysAssert(mid != SYS_MID_NULL); - - if (mid->monitor_owner != self) { - return SYS_ERR; - } - - while (mid->monitor_waiter != SYS_THREAD_NULL) - { - sys_thread_t *thread = mid->monitor_waiter; - mid->monitor_waiter = thread->next_waiter; - - thread->next_waiter = SYS_THREAD_NULL; - thread->wait_monitor = SYS_MID_NULL; - - SetEvent(thread->interrupt_event); - } - - return SYS_OK; -} - -/* - * Atomically drop mutex and wait for notification. - */ -int -sysMonitorWait(sys_thread_t *self, sys_mon_t *mid, jlong millis) -{ - long entry_count; - DWORD timeout; - - sysAssert(mid != SYS_MID_NULL); - - if (mid->monitor_owner != self) { - return SYS_ERR; - } - - if ( sysThreadIsInterrupted(self, 1) ) { - return SYS_INTRPT; - } - - entry_count = mid->entry_count; - mid->entry_count = 1; - - self->wait_monitor = mid; - self->next_waiter = 0; - - if (mid->monitor_waiter == 0) { - mid->monitor_waiter = self; - } else { - sys_thread_t *thread = mid->monitor_waiter; - while (thread->next_waiter != 0) { - thread = thread->next_waiter; - } - thread->next_waiter = self; - } - - if ( millis == SYS_TIMEOUT_INFINITY || - millis > (jlong)((unsigned int)0xffffffff) ) { - timeout = INFINITE; - } else { - timeout = (long) millis; - } - - mid->waiter_count++; - - sysMonitorExit(self, mid); - - self->state = CONDVAR_WAIT; - - WaitForSingleObject(self->interrupt_event, timeout); - - self->state = RUNNABLE; - - sysMonitorEnter(self, mid); - - mid->waiter_count--; - - mid->entry_count = entry_count; - /* Reset event anyway, prevent racing the timeout */ - ResetEvent(self->interrupt_event); - - if (self->wait_monitor != SYS_MID_NULL) { - sys_thread_t *head; - - sysAssert( self->wait_monitor == mid ); - sysAssert( mid->monitor_waiter != SYS_THREAD_NULL ); - - head = mid->monitor_waiter; - - if (head == self) { - mid->monitor_waiter = self->next_waiter; - } else { - while (head != SYS_THREAD_NULL) { - if (head->next_waiter == self) { - head->next_waiter = self->next_waiter; - break; - } else { - head = head->next_waiter; - } - } - } - - self->next_waiter = SYS_THREAD_NULL; - self->wait_monitor = SYS_MID_NULL; - } - - if ( sysThreadIsInterrupted(self, 1) ) { - return SYS_INTRPT; - } - - return SYS_OK; -} - -static int -dumpWaitingQueue(sys_thread_t *tid, sys_thread_t **waiters, int sz) -{ - int n; - for (n = 0; tid != 0; tid = tid->next_waiter, n++, sz--) { - if (sz > 0) { - waiters[n] = tid; - } - } - return n; -} - -typedef struct { - sys_mon_t *mid; - sys_thread_t **waiters; - int sz; - int nwaiters; -} wait_info; - -static int -findWaitersHelper(sys_thread_t *t, void *arg) -{ - wait_info * winfo = (wait_info *) arg; - if (t->enter_monitor == winfo->mid) { - if (winfo->sz > 0) { - winfo->waiters[winfo->nwaiters] = t; - } - winfo->sz--; - winfo->nwaiters++; - } - return SYS_OK; -} - -int -sysMonitorGetInfo(sys_mon_t *mid, sys_mon_info *info) -{ - wait_info winfo; - - sysAssert(mid != SYS_MID_NULL); - info->owner = mid->monitor_owner; - if (mid->monitor_owner) { - info->entry_count = mid->entry_count; - } - - winfo.mid = mid; - winfo.nwaiters = 0; - winfo.waiters = info->monitor_waiters; - winfo.sz = info->sz_monitor_waiters; - sysThreadEnumerateOver(findWaitersHelper, (void *) &winfo); - info->n_monitor_waiters = winfo.nwaiters; - - info->n_condvar_waiters = dumpWaitingQueue(mid->monitor_waiter, - info->condvar_waiters, - info->sz_condvar_waiters); - - return SYS_OK; -} - -/* - * Return size of system-dependent monitor structure. - */ -size_t -sysMonitorSizeof(void) -{ - return sizeof(struct sys_mon); -} - - -/* - * Return true if there are any threads inside this monitor. - */ -bool_t -sysMonitorInUse(sys_mon_t *mid) -{ - return (mid->atomic_count != -1 - || mid->waiter_count != 0 - || mid->monitor_owner != SYS_THREAD_NULL - || mid->monitor_waiter != SYS_THREAD_NULL); -} - - -sys_thread_t * -sysMonitorOwner(sys_mon_t *mon) -{ - return mon->monitor_owner; -} diff --git a/jdk/src/windows/hpi/src/path_md.c b/jdk/src/windows/hpi/src/path_md.c deleted file mode 100644 index 2f86ceabeb4..00000000000 --- a/jdk/src/windows/hpi/src/path_md.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 1994, 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Machine dependent path name and file name manipulation code - */ - -#include -#include -#include -#include -#include - -#include -#include - -#include "hpi_impl.h" - -#undef DEBUG_PATH /* Define this to debug path code */ - -#define isfilesep(c) ((c) == '/' || (c) == '\\') -#define islb(c) (IsDBCSLeadByte((BYTE)(c))) - - -/* Convert a pathname to native format. On win32, this involves forcing all - separators to be '\\' rather than '/' (both are legal inputs, but Win95 - sometimes rejects '/') and removing redundant separators. The input path is - assumed to have been converted into the character encoding used by the local - system. Because this might be a double-byte encoding, care is taken to - treat double-byte lead characters correctly. - - This procedure modifies the given path in place, as the result is never - longer than the original. There is no error return; this operation always - succeeds. */ - -char * -sysNativePath(char *path) -{ - char *src = path, *dst = path, *end = path; - char *colon = NULL; /* If a drive specifier is found, this will - point to the colon following the drive - letter */ - - /* Assumption: '/', '\\', ':', and drive letters are never lead bytes */ - sysAssert(!islb('/') && !islb('\\') && !islb(':')); - - /* Check for leading separators */ - while (isfilesep(*src)) src++; - if (isalpha(*src) && !islb(*src) && src[1] == ':') { - /* Remove leading separators if followed by drive specifier. This - hack is necessary to support file URLs containing drive - specifiers (e.g., "file://c:/path"). As a side effect, - "/c:/path" can be used as an alternative to "c:/path". */ - *dst++ = *src++; - colon = dst; - *dst++ = ':'; src++; - } else { - src = path; - if (isfilesep(src[0]) && isfilesep(src[1])) { - /* UNC pathname: Retain first separator; leave src pointed at - second separator so that further separators will be collapsed - into the second separator. The result will be a pathname - beginning with "\\\\" followed (most likely) by a host name. */ - src = dst = path + 1; - path[0] = '\\'; /* Force first separator to '\\' */ - } - } - - end = dst; - - /* Remove redundant separators from remainder of path, forcing all - separators to be '\\' rather than '/'. Also, single byte space - characters are removed from the end of the path because those - are not legal ending characters on this operating system. - */ - while (*src != '\0') { - if (isfilesep(*src)) { - *dst++ = '\\'; src++; - while (isfilesep(*src)) src++; - if (*src == '\0') { /* Check for trailing separator */ - end = dst; - if (colon == dst - 2) break; /* "z:\\" */ - if (dst == path + 1) break; /* "\\" */ - if (dst == path + 2 && isfilesep(path[0])) { - /* "\\\\" is not collapsed to "\\" because "\\\\" marks the - beginning of a UNC pathname. Even though it is not, by - itself, a valid UNC pathname, we leave it as is in order - to be consistent with the path canonicalizer as well - as the win32 APIs, which treat this case as an invalid - UNC pathname rather than as an alias for the root - directory of the current drive. */ - break; - } - end = --dst; /* Path does not denote a root directory, so - remove trailing separator */ - break; - } - end = dst; - } else { - if (islb(*src)) { /* Copy a double-byte character */ - *dst++ = *src++; - if (*src) { - *dst++ = *src++; - } - end = dst; - } else { /* Copy a single-byte character */ - char c = *src++; - *dst++ = c; - /* Space is not a legal ending character */ - if (c != ' ') - end = dst; - } - } - } - - *end = '\0'; - - /* For "z:", add "." to work around a bug in the C runtime library */ - if (colon == dst - 1) { - path[2] = '.'; - path[3] = '\0'; - } - -#ifdef DEBUG_PATH - jio_fprintf(stderr, "sysNativePath: %s\n", path); -#endif DEBUG_PATH - return path; -} diff --git a/jdk/src/windows/hpi/src/socket_md.c b/jdk/src/windows/hpi/src/socket_md.c deleted file mode 100644 index 1641650dd4f..00000000000 --- a/jdk/src/windows/hpi/src/socket_md.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright (c) 1997, 2008, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include -#include - -#include "hpi_impl.h" - -#include "mutex_md.h" - -struct sockaddr; - -#define FN_RECV 0 -#define FN_SEND 1 -#define FN_LISTEN 2 -#define FN_BIND 3 -#define FN_ACCEPT 4 -#define FN_RECVFROM 5 -#define FN_SENDTO 6 -#define FN_SELECT 7 -#define FN_CONNECT 8 -#define FN_CLOSESOCKET 9 -#define FN_SHUTDOWN 10 -#define FN_GETHOSTNAME 11 -#define FN_GETHOSTBYADDR 12 -#define FN_GETHOSTBYNAME 13 -#define FN_HTONS 14 -#define FN_HTONL 15 -#define FN_NTOHS 16 -#define FN_NTOHL 17 -#define FN_GETSOCKOPT 18 -#define FN_SETSOCKOPT 19 -#define FN_GETPROTOBYNAME 20 -#define FN_GETSOCKNAME 21 -#define FN_SOCKET 22 -#define FN_WSASENDDISCONNECT 23 -#define FN_SOCKETAVAILABLE 24 - -static int (PASCAL FAR *sockfnptrs[])() = - {NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, - }; - -static bool_t sockfnptrs_initialized = FALSE; -static mutex_t sockFnTableMutex; - -/* is Winsock2 loaded? better to be explicit than to rely on sockfnptrs */ -static bool_t winsock2Available = FALSE; - -/* Winsock2 options at the IPPROTO_IP level - We need the following translation in order to deal with the multiple - definitions for IPPROTO_IP level options in different winsock versions. - -in winsock.h vs. ws2tcpip.h -#define IP_OPTIONS 1 1 -#define IP_MULTICAST_IF 2 9 -#define IP_MULTICAST_TTL 3 10 -#define IP_MULTICAST_LOOP 4 11 -#define IP_ADD_MEMBERSHIP 5 12 -#define IP_DROP_MEMBERSHIP 6 13 -#define IP_TTL 7 4 -#define IP_TOS 8 3 -#define IP_DONTFRAGMENT 9 14 -*/ -static int IPPROTO_OPTIONS[] = {-1, 1, 9, 10, 11, 12, 13, 4, 3, 14}; - -/* IMPORTANT: whenever possible, we want to use Winsock2 (ws2_32.dll) - * instead of Winsock (wsock32.dll). Other than the fact that it is - * newer, less buggy and faster than Winsock, Winsock2 lets us to work - * around the following problem: - * - * Generally speaking, it is important to shutdown a socket before - * closing it, since failing to do so can sometimes result in a TCP - * RST (abortive close) which is disturbing to the peer of the - * connection. - * - * The Winsock way to shutdown a socket is the Berkeley call - * shutdown(). We do not want to call it on Win95, since it - * sporadically leads to an OS crash in IFS_MGR.VXD. Complete hull - * breach. Blue screen. Ugly. - * - * So, in initSockTable we look for Winsock 2, and if we find it we - * assign wsassendisconnectfn function pointer. When we close, we - * first check to see if it's bound, and if it is, we call it. Winsock - * 2 will always be there on NT, and we recommend that win95 user - * install it. - * - * - br 10/11/97 - */ - -static void -initSockFnTable() { - int (PASCAL FAR* WSAStartupPtr)(WORD, LPWSADATA); - WSADATA wsadata; - OSVERSIONINFO info; - - mutexInit(&sockFnTableMutex); - mutexLock(&sockFnTableMutex); - if (sockfnptrs_initialized == FALSE) { - HANDLE hWinsock; - - /* try to load Winsock2, and if that fails, load Winsock */ - hWinsock = LoadLibrary("ws2_32.dll"); - if (hWinsock == NULL) { - hWinsock = LoadLibrary("wsock32.dll"); - winsock2Available = FALSE; - } else { - winsock2Available = TRUE; - } - - if (hWinsock == NULL) { - VM_CALL(jio_fprintf)(stderr, "Could not load Winsock 1 or 2 (error: %d)\n", - GetLastError()); - } - - /* If we loaded a DLL, then we might as well initialize it. */ - WSAStartupPtr = (int (PASCAL FAR *)(WORD, LPWSADATA)) - GetProcAddress(hWinsock, "WSAStartup"); - if (WSAStartupPtr(MAKEWORD(1,1), &wsadata) != 0) { - VM_CALL(jio_fprintf)(stderr, "Could not initialize Winsock\n"); - } - - sockfnptrs[FN_RECV] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "recv"); - sockfnptrs[FN_SEND] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "send"); - sockfnptrs[FN_LISTEN] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "listen"); - sockfnptrs[FN_BIND] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "bind"); - sockfnptrs[FN_ACCEPT] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "accept"); - sockfnptrs[FN_RECVFROM] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "recvfrom"); - sockfnptrs[FN_SENDTO] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "sendto"); - sockfnptrs[FN_SELECT] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "select"); - sockfnptrs[FN_CONNECT] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "connect"); - sockfnptrs[FN_CLOSESOCKET] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "closesocket"); - /* we don't use this */ - sockfnptrs[FN_SHUTDOWN] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "shutdown"); - sockfnptrs[FN_GETHOSTNAME] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "gethostname"); - sockfnptrs[FN_GETHOSTBYADDR] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "gethostbyaddr"); - sockfnptrs[FN_GETHOSTBYNAME] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "gethostbyname"); - sockfnptrs[FN_HTONS] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "htons"); - sockfnptrs[FN_HTONL] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "htonl"); - sockfnptrs[FN_NTOHS] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "ntohs"); - sockfnptrs[FN_NTOHL] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "ntohl"); - sockfnptrs[FN_GETSOCKOPT] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "getsockopt"); - sockfnptrs[FN_SETSOCKOPT] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "setsockopt"); - sockfnptrs[FN_GETPROTOBYNAME] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "getprotobyname"); - sockfnptrs[FN_GETSOCKNAME] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "getsockname"); - - sockfnptrs[FN_SOCKET] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "socket"); - /* in winsock 1, this will simply be 0 */ - sockfnptrs[FN_WSASENDDISCONNECT] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, - "WSASendDisconnect"); - sockfnptrs[FN_SOCKETAVAILABLE] - = (int (PASCAL FAR *)())GetProcAddress(hWinsock, - "ioctlsocket"); - } - - sysAssert(sockfnptrs[FN_RECV] != NULL); - sysAssert(sockfnptrs[FN_SEND] != NULL); - sysAssert(sockfnptrs[FN_LISTEN] != NULL); - sysAssert(sockfnptrs[FN_BIND] != NULL); - sysAssert(sockfnptrs[FN_ACCEPT] != NULL); - sysAssert(sockfnptrs[FN_RECVFROM] != NULL); - sysAssert(sockfnptrs[FN_SENDTO] != NULL); - sysAssert(sockfnptrs[FN_SELECT] != NULL); - sysAssert(sockfnptrs[FN_CONNECT] != NULL); - sysAssert(sockfnptrs[FN_CLOSESOCKET] != NULL); - sysAssert(sockfnptrs[FN_SHUTDOWN] != NULL); - sysAssert(sockfnptrs[FN_GETHOSTNAME] != NULL); - sysAssert(sockfnptrs[FN_GETHOSTBYADDR] != NULL); - sysAssert(sockfnptrs[FN_GETHOSTBYNAME] != NULL); - sysAssert(sockfnptrs[FN_HTONS] != NULL); - sysAssert(sockfnptrs[FN_HTONL] != NULL); - sysAssert(sockfnptrs[FN_NTOHS] != NULL); - sysAssert(sockfnptrs[FN_NTOHL] != NULL); - sysAssert(sockfnptrs[FN_GETSOCKOPT] != NULL); - sysAssert(sockfnptrs[FN_SETSOCKOPT] != NULL); - sysAssert(sockfnptrs[FN_GETPROTOBYNAME] != NULL); - sysAssert(sockfnptrs[FN_GETSOCKNAME] != NULL); - sysAssert(sockfnptrs[FN_SOCKET] != NULL); - - if (winsock2Available) { - sysAssert(sockfnptrs[FN_WSASENDDISCONNECT] != NULL); - } - - sysAssert(sockfnptrs[FN_SOCKETAVAILABLE] != NULL); - - sockfnptrs_initialized = TRUE; - mutexUnlock(&sockFnTableMutex); -} - -/* - * If we get a nonnull function pointer it might still be the case - * that some other thread is in the process of initializing the socket - * function pointer table, but our pointer should still be good. - */ -int -sysListen(int fd, int count) { - int (PASCAL FAR *listenfn)(); - if ((listenfn = sockfnptrs[FN_LISTEN]) == NULL) { - initSockFnTable(); - listenfn = sockfnptrs[FN_LISTEN]; - } - sysAssert(sockfnptrs_initialized == TRUE && listenfn != NULL); - return (*listenfn)(fd, (long)count); -} - -int -sysConnect(int fd, struct sockaddr *name, int namelen) { - int (PASCAL FAR *connectfn)(); - if ((connectfn = sockfnptrs[FN_CONNECT]) == NULL) { - initSockFnTable(); - connectfn = sockfnptrs[FN_CONNECT]; - } - sysAssert(sockfnptrs_initialized == TRUE); - sysAssert(connectfn != NULL); - return (*connectfn)(fd, name, namelen); -} - -int -sysBind(int fd, struct sockaddr *name, int namelen) { - int (PASCAL FAR *bindfn)(); - if ((bindfn = sockfnptrs[FN_BIND]) == NULL) { - initSockFnTable(); - bindfn = sockfnptrs[FN_BIND]; - } - sysAssert(sockfnptrs_initialized == TRUE); - sysAssert(bindfn != NULL); - return (*bindfn)(fd, name, namelen); -} - -int -sysAccept(int fd, struct sockaddr *name, int *namelen) { - int (PASCAL FAR *acceptfn)(); - if ((acceptfn = sockfnptrs[FN_ACCEPT]) == NULL) { - initSockFnTable(); - acceptfn = sockfnptrs[FN_ACCEPT]; - } - sysAssert(sockfnptrs_initialized == TRUE && acceptfn != NULL); - return (*acceptfn)(fd, name, namelen); -} - -int -sysRecvFrom(int fd, char *buf, int nBytes, - int flags, struct sockaddr *from, int *fromlen) { - int (PASCAL FAR *recvfromfn)(); - if ((recvfromfn = sockfnptrs[FN_RECVFROM]) == NULL) { - initSockFnTable(); - recvfromfn = sockfnptrs[FN_RECVFROM]; - } - sysAssert(sockfnptrs_initialized == TRUE && recvfromfn != NULL); - return (*recvfromfn)(fd, buf, nBytes, flags, from, fromlen); -} - -int -sysSendTo(int fd, char *buf, int len, - int flags, struct sockaddr *to, int tolen) { - int (PASCAL FAR *sendtofn)(); - if ((sendtofn = sockfnptrs[FN_SENDTO]) == NULL) { - initSockFnTable(); - sendtofn = sockfnptrs[FN_SENDTO]; - } - sysAssert(sockfnptrs_initialized == TRUE && sendtofn != NULL); - return (*sendtofn)(fd, buf, len, flags, to, tolen); -} - -int -sysRecv(int fd, char *buf, int nBytes, int flags) { - int (PASCAL FAR *recvfn)(); - if ((recvfn = sockfnptrs[FN_RECV]) == NULL) { - initSockFnTable(); - recvfn = sockfnptrs[FN_RECV]; - } - sysAssert(sockfnptrs_initialized == TRUE && recvfn != NULL); - return (*recvfn)(fd, buf, nBytes, flags); -} - -int -sysSend(int fd, char *buf, int nBytes, int flags) { - int (PASCAL FAR *sendfn)(); - if ((sendfn = sockfnptrs[FN_SEND]) == NULL) { - initSockFnTable(); - sendfn = sockfnptrs[FN_SEND]; - } - sysAssert(sockfnptrs_initialized == TRUE && sendfn != NULL); - return (*sendfn)(fd, buf, nBytes, flags); -} - - -int -sysGetHostName(char *hostname, int namelen) { - int (PASCAL FAR *fn)(); - if ((fn = sockfnptrs[FN_GETHOSTNAME]) == NULL) { - initSockFnTable(); - fn = sockfnptrs[FN_GETHOSTNAME]; - } - sysAssert(sockfnptrs_initialized == TRUE && fn != NULL); - return (*fn)(hostname, namelen); -} - -struct hostent * -sysGetHostByAddr(const char *hostname, int len, int type) { - struct hostent * (PASCAL FAR *fn)(); - if ((fn = (struct hostent * (PASCAL FAR *)()) sockfnptrs[FN_GETHOSTBYADDR]) == NULL) { - initSockFnTable(); - fn = (struct hostent * (PASCAL FAR *)()) sockfnptrs[FN_GETHOSTBYADDR]; - } - sysAssert(sockfnptrs_initialized == TRUE && fn != NULL); - return (*fn)(hostname, len, type); -} - -struct hostent * -sysGetHostByName(char *hostname) { - struct hostent * (PASCAL FAR *fn)(); - if ((fn = (struct hostent * (PASCAL FAR *)()) sockfnptrs[FN_GETHOSTBYNAME]) == NULL) { - initSockFnTable(); - fn = (struct hostent * (PASCAL FAR *)()) sockfnptrs[FN_GETHOSTBYNAME]; - } - sysAssert(sockfnptrs_initialized == TRUE && fn != NULL); - return (*fn)(hostname); -} - -int -sysSocket(int domain, int type, int protocol) { - int sock; - int (PASCAL FAR *socketfn)(); - if ((socketfn = sockfnptrs[FN_SOCKET]) == NULL) { - initSockFnTable(); - socketfn = sockfnptrs[FN_SOCKET]; - } - sysAssert(sockfnptrs_initialized == TRUE && socketfn != NULL); - sock = (*socketfn)(domain, type, protocol); - if (sock != INVALID_SOCKET) { - SetHandleInformation((HANDLE)(uintptr_t)sock, HANDLE_FLAG_INHERIT, FALSE); - } - return sock; -} - -int sysSocketShutdown(int fd, int how) { - if (fd > 0) { - int (PASCAL FAR *shutdownfn)(); - if ((shutdownfn = sockfnptrs[FN_SHUTDOWN]) == NULL) { - initSockFnTable(); - shutdownfn = sockfnptrs[FN_SHUTDOWN]; - } - /* At this point we are guaranteed the sockfnptrs are initialized */ - sysAssert(sockfnptrs_initialized == TRUE && shutdownfn != NULL); - (void) (*shutdownfn)(fd, how); - } -return TRUE; -} - -/* - * This function is carefully designed to work around a bug in Windows - * 95's networking winsock. Please see the beginning of this file for - * a complete description of the problem. - */ -int sysSocketClose(int fd) { - - if (fd > 0) { - int (PASCAL FAR *closesocketfn)(); - int (PASCAL FAR *wsasenddisconnectfn)(); - int dynamic_ref = -1; - - if ((closesocketfn = sockfnptrs[FN_CLOSESOCKET]) == NULL) { - initSockFnTable(); - } - /* At this point we are guaranteed the sockfnptrs are initialized */ - sysAssert(sockfnptrs_initialized == TRUE); - - closesocketfn = sockfnptrs[FN_CLOSESOCKET]; - sysAssert(closesocketfn != NULL); - - if (winsock2Available) { - struct linger l; - int len = sizeof(l); - - if (sysGetSockOpt(fd, SOL_SOCKET, SO_LINGER, (char *)&l, &len) == 0) { - if (l.l_onoff == 0) { - wsasenddisconnectfn = sockfnptrs[FN_WSASENDDISCONNECT]; - (*wsasenddisconnectfn)(fd, NULL); - } - } - } - (void) (*closesocketfn)(fd); - } - return TRUE; -} - -/* - * Poll the fd for reading for timeout ms. Returns 1 if something's - * ready, 0 if it timed out, -1 on error, -2 if interrupted (although - * interruption isn't implemented yet). Timeout in milliseconds. */ -int -sysTimeout(int fd, long timeout) { - int res; - fd_set tbl; - struct timeval t; - int (PASCAL FAR *selectfn)(); - - t.tv_sec = timeout / 1000; - t.tv_usec = (timeout % 1000) * 1000; - FD_ZERO(&tbl); - FD_SET(fd, &tbl); - - if ((selectfn = sockfnptrs[FN_SELECT]) == NULL) { - initSockFnTable(); - selectfn = sockfnptrs[FN_SELECT]; - } - sysAssert(sockfnptrs_initialized == TRUE && selectfn != NULL); - res = (*selectfn)(fd + 1, &tbl, 0, 0, &t); - return res; -} - -long -sysSocketAvailable(int fd, jint *pbytes) -{ - int (PASCAL FAR *socketfn)(); - if ((socketfn = sockfnptrs[FN_SOCKETAVAILABLE]) == NULL) { - initSockFnTable(); - socketfn = sockfnptrs[FN_SOCKETAVAILABLE]; - } - sysAssert(sockfnptrs_initialized == TRUE && socketfn != NULL); - return (*socketfn)(fd, FIONREAD, pbytes); -} - -int -sysGetSockName(int fd, struct sockaddr *name, int *namelen) { - int (PASCAL FAR *getsocknamefn)(); - if ((getsocknamefn = sockfnptrs[FN_GETSOCKNAME]) == NULL) { - initSockFnTable(); - getsocknamefn = sockfnptrs[FN_GETSOCKNAME]; - } - sysAssert(sockfnptrs_initialized == TRUE); - sysAssert(getsocknamefn != NULL); - return (*getsocknamefn)(fd, name, namelen); -} - -int -sysGetSockOpt(int fd, int level, int optname, char *optval, int *optlen ) { - int (PASCAL FAR *getsockoptfn)(); - if ((getsockoptfn = sockfnptrs[FN_GETSOCKOPT]) == NULL) { - initSockFnTable(); - getsockoptfn = sockfnptrs[FN_GETSOCKOPT]; - } - sysAssert(sockfnptrs_initialized == TRUE); - sysAssert(getsockoptfn != NULL); - - /* We need the following translation in order to deal with the multiple - definitions for IPPROTO_IP level options in different winsock versions - */ - if (winsock2Available && level == IPPROTO_IP && - optname >= IP_OPTIONS && optname <= IP_DONTFRAGMENT) { - optname = IPPROTO_OPTIONS[optname]; - } - return (*getsockoptfn)(fd, level, optname, optval, optlen); -} - -int -sysSetSockOpt(int fd, int level, int optname, const char *optval, int optlen ) { - int (PASCAL FAR *setsockoptfn)(); - if ((setsockoptfn = sockfnptrs[FN_SETSOCKOPT]) == NULL) { - initSockFnTable(); - setsockoptfn = sockfnptrs[FN_SETSOCKOPT]; - } - sysAssert(sockfnptrs_initialized == TRUE); - sysAssert(setsockoptfn != NULL); - - /* We need the following translation in order to deal with the multiple - definitions for IPPROTO_IP level options in different winsock versions - */ - if (winsock2Available && level == IPPROTO_IP && - optname >= IP_OPTIONS && optname <= IP_DONTFRAGMENT) { - optname = IPPROTO_OPTIONS[optname]; - } - - return (*setsockoptfn)(fd, level, optname, optval, optlen); -} - -struct protoent * -sysGetProtoByName(char *name) { - struct protoent * (PASCAL FAR *getprotobynamefn)(); - if ((getprotobynamefn = (struct protoent * (PASCAL FAR *)()) sockfnptrs[FN_GETPROTOBYNAME]) == NULL) { - initSockFnTable(); - getprotobynamefn = (struct protoent * (PASCAL FAR *)()) sockfnptrs[FN_GETPROTOBYNAME]; - } - sysAssert(sockfnptrs_initialized == TRUE); - sysAssert(getprotobynamefn != NULL); - return (*getprotobynamefn)(name); -} diff --git a/jdk/src/windows/hpi/src/sys_api_md.c b/jdk/src/windows/hpi/src/sys_api_md.c deleted file mode 100644 index 514b3c5529f..00000000000 --- a/jdk/src/windows/hpi/src/sys_api_md.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 1997, 2004, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "hpi_impl.h" - -#include "path_md.h" - -static int MAX_INPUT_EVENTS = 2000; - -int -sysOpen(const char *path, int oflag, int mode) -{ - char pathbuf[MAX_PATH]; - - if (strlen(path) > MAX_PATH - 1) { - errno = ENAMETOOLONG; - return -1; - } - return open(sysNativePath(strcpy(pathbuf, path)), - oflag | O_BINARY | O_NOINHERIT, mode); -} - - -static int -nonSeekAvailable(int, long *); -static int -stdinAvailable(int, long *); - -int -sysAvailable(int fd, jlong *pbytes) { - jlong cur, end; - struct _stati64 stbuf64; - - if (_fstati64(fd, &stbuf64) >= 0) { - int mode = stbuf64.st_mode; - if (S_ISCHR(mode) || S_ISFIFO(mode)) { - int ret; - long lpbytes; - if (fd == 0) { - ret = stdinAvailable(fd, &lpbytes); - } else { - ret = nonSeekAvailable(fd, &lpbytes); - } - (*pbytes) = (jlong)(lpbytes); - return ret; - } - if ((cur = _lseeki64(fd, 0L, SEEK_CUR)) == -1) { - return FALSE; - } else if ((end = _lseeki64(fd, 0L, SEEK_END)) == -1) { - return FALSE; - } else if (_lseeki64(fd, cur, SEEK_SET) == -1) { - return FALSE; - } - *pbytes = end - cur; - return TRUE; - } else { - return FALSE; - } -} - -static int -nonSeekAvailable(int fd, long *pbytes) { - /* This is used for available on non-seekable devices - * (like both named and anonymous pipes, such as pipes - * connected to an exec'd process). - * Standard Input is a special case. - * - */ - HANDLE han; - - if ((han = (HANDLE) _get_osfhandle(fd)) == (HANDLE)(-1)) { - return FALSE; - } - - if (! PeekNamedPipe(han, NULL, 0, NULL, pbytes, NULL)) { - /* PeekNamedPipe fails when at EOF. In that case we - * simply make *pbytes = 0 which is consistent with the - * behavior we get on Solaris when an fd is at EOF. - * The only alternative is to raise an Exception, - * which isn't really warranted. - */ - if (GetLastError() != ERROR_BROKEN_PIPE) { - return FALSE; - } - *pbytes = 0; - } - return TRUE; -} - -static int -stdinAvailable(int fd, long *pbytes) { - HANDLE han; - DWORD numEventsRead = 0; /* Number of events read from buffer */ - DWORD numEvents = 0; /* Number of events in buffer */ - DWORD i = 0; /* Loop index */ - DWORD curLength = 0; /* Position marker */ - DWORD actualLength = 0; /* Number of bytes readable */ - BOOL error = FALSE; /* Error holder */ - INPUT_RECORD *lpBuffer; /* Pointer to records of input events */ - - if ((han = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { - return FALSE; - } - - /* Construct an array of input records in the console buffer */ - error = GetNumberOfConsoleInputEvents(han, &numEvents); - if (error == 0) { - return nonSeekAvailable(fd, pbytes); - } - - /* lpBuffer must fit into 64K or else PeekConsoleInput fails */ - if (numEvents > MAX_INPUT_EVENTS) { - numEvents = MAX_INPUT_EVENTS; - } - - lpBuffer = sysMalloc(numEvents * sizeof(INPUT_RECORD)); - if (lpBuffer == NULL) { - return FALSE; - } - - error = PeekConsoleInput(han, lpBuffer, numEvents, &numEventsRead); - if (error == 0) { - sysFree(lpBuffer); - return FALSE; - } - - /* Examine input records for the number of bytes available */ - for(i=0; ibKeyDown == TRUE) { - CHAR *keyPressed = (CHAR *) &(keyRecord->uChar); - curLength++; - if (*keyPressed == '\r') - actualLength = curLength; - } - } - } - if(lpBuffer != NULL) - sysFree(lpBuffer); - *pbytes = (long) actualLength; - return TRUE; -} - -/* - * This is documented to succeed on read-only files, but Win32's - * FlushFileBuffers functions fails with "access denied" in such a - * case. So we only signal an error if the error is *not* "access - * denied". - */ - -int -sysSync(int fd) { - /* - * From the documentation: - * - * On Windows NT, the function FlushFileBuffers fails if hFile - * is a handle to console output. That is because console - * output is not buffered. The function returns FALSE, and - * GetLastError returns ERROR_INVALID_HANDLE. - * - * On the other hand, on Win95, it returns without error. I cannot - * assume that 0, 1, and 2 are console, because if someone closes - * System.out and then opens a file, they might get file descriptor - * 1. An error on *that* version of 1 should be reported, whereas - * an error on System.out (which was the original 1) should be - * ignored. So I use isatty() to ensure that such an error was due - * to this bogosity, and if it was, I ignore the error. - */ - - HANDLE handle = (HANDLE)_get_osfhandle(fd); - - if (!FlushFileBuffers(handle)) { - if (GetLastError() != ERROR_ACCESS_DENIED) { /* from winerror.h */ - return -1; - } - } - return 0; -} - - -int -sysSetLength(int fd, jlong length) { - HANDLE h = (HANDLE)_get_osfhandle(fd); - long high = (long)(length >> 32); - DWORD ret; - - if (h == (HANDLE)(-1)) return -1; - ret = SetFilePointer(h, (long)(length), &high, FILE_BEGIN); - if (ret == 0xFFFFFFFF && GetLastError() != NO_ERROR) { - return -1; - } - if (SetEndOfFile(h) == FALSE) return -1; - return 0; -} - -int -sysFileSizeFD(int fd, jlong *size) -{ - struct _stati64 buf64; - - if(_fstati64(fd, &buf64) < 0) { - return -1; - } - (*size) = buf64.st_size; - - if (*size & 0xFFFFFFFF00000000) { - /* - * On Win98 accessing a non-local file we have observed a - * bogus file size of 0x100000000. So if upper 32 bits - * are non-zero we re-calculate the size using lseek. This - * should work for any file size, but it might have a - * performance impact relative to fstati64. Note: Hotspot - * doesn't have this problem because it uses stat rather - * than fstat or fstati64. - */ - - jlong curpos; - jlong endpos; - jlong newpos; - - curpos = _lseeki64(fd, 0, SEEK_CUR); - if (curpos < 0) { - return -1; - } - endpos = _lseeki64(fd, 0, SEEK_END); - if (endpos < 0) { - return -1; - } - newpos = _lseeki64(fd, curpos, SEEK_SET); - if (newpos != curpos) { - return -1; - } - (*size) = endpos; - - } - return 0; -} - -int -sysFfileMode(int fd, int *mode) -{ - int ret; - struct _stati64 buf64; - ret = _fstati64(fd, &buf64); - (*mode) = buf64.st_mode; - return ret; -} - -int -sysFileType(const char *path) -{ - int ret; - struct _stati64 buf; - - if ((ret = _stati64(path, &buf)) == 0) { - int mode = buf.st_mode & S_IFMT; - if (mode == S_IFREG) return SYS_FILETYPE_REGULAR; - if (mode == S_IFDIR) return SYS_FILETYPE_DIRECTORY; - return SYS_FILETYPE_OTHER; - } - return ret; -} - -size_t sysRead(int fd, void *buf, unsigned int nBytes) -{ - return read(fd, buf, nBytes); -} - -size_t sysWrite(int fd, const void *buf, unsigned int nBytes) -{ - return write(fd, buf, nBytes); -} - -int sysClose(int fd) -{ - return close(fd); -} - -jlong sysSeek(int fd, jlong offset, int whence) -{ - return _lseeki64(fd, offset, whence); -} diff --git a/jdk/src/windows/hpi/src/system_md.c b/jdk/src/windows/hpi/src/system_md.c deleted file mode 100644 index d45c8d657a0..00000000000 --- a/jdk/src/windows/hpi/src/system_md.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 1994, 2002, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include -#include /* For constants for _control87() */ -#include -#include /* For _tzset() and _ftime() */ -#include - -#include "hpi_impl.h" - -#include "jni_md.h" -#include "monitor_md.h" - - -static int pending_signals[NSIG]; -static HANDLE sigEvent; -static CRITICAL_SECTION userSigMon; - - -void sysSignalNotify(int sig) -{ - sys_thread_t *self = sysThreadSelf(); - EnterCriticalSection(&userSigMon); - pending_signals[sig]++; - LeaveCriticalSection(&userSigMon); - SetEvent(sigEvent); -} - -static int lookupSignal() -{ - int i; - EnterCriticalSection(&userSigMon); - for (i = 0; i < NSIG; i++) { - if (pending_signals[i]) { - pending_signals[i]--; - LeaveCriticalSection(&userSigMon); - return i; - } - } - LeaveCriticalSection(&userSigMon); - return -1; -} - -int sysSignalWait() -{ - int sig; - while ((sig = lookupSignal()) == -1) { - WaitForSingleObject(sigEvent, INFINITE); - } - return sig; -} - -signal_handler_t sysSignal(int sig, signal_handler_t newHandler) -{ - return (signal_handler_t)signal(sig, (void (*)(int))newHandler); -} - -void sysRaise(int sig) -{ - raise(sig); -} - -int sysThreadBootstrap(sys_thread_t **tidP, sys_mon_t **lockP, int nb) -{ - extern void InitializeMem(void); - - threadBootstrapMD(tidP, lockP, nb); - - sigEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - InitializeCriticalSection(&userSigMon); - memset(pending_signals, 0, sizeof(pending_signals)); - - /* - * Change default for std. streams stdout, stderr, - * stdin to be O_BINARY not O_TEXT. The `\r` characters - * corrupt binary files. - */ - - _setmode(0, O_BINARY); - _setmode(1, O_BINARY); - _setmode(2, O_BINARY); - - /* - * Set floating point processor to no floating point exceptions. - * See bug 4027374. Should be the same values VC++ would set them - * to, but by doing this here we ensure other dll's don't override. - */ - _control87(_MCW_EM | _RC_NEAR | _PC_53, _MCW_EM | _MCW_RC | _MCW_PC); - - InitializeMem(); - - return SYS_OK; -} - -long -sysGetMilliTicks(void) -{ - return(GetTickCount()); -} - -#define FT2INT64(ft) \ - ((jlong)(ft).dwHighDateTime << 32 | (jlong)(ft).dwLowDateTime) - -jlong -sysTimeMillis(void) -{ - static jlong fileTime_1_1_70 = 0; - SYSTEMTIME st0; - FILETIME ft0; - - if (fileTime_1_1_70 == 0) { - /* Initialize fileTime_1_1_70 -- the Win32 file time of midnight - * 1/1/70. - */ - - memset(&st0, 0, sizeof(st0)); - st0.wYear = 1970; - st0.wMonth = 1; - st0.wDay = 1; - SystemTimeToFileTime(&st0, &ft0); - fileTime_1_1_70 = FT2INT64(ft0); - } - - GetSystemTime(&st0); - SystemTimeToFileTime(&st0, &ft0); - - return (FT2INT64(ft0) - fileTime_1_1_70) / 10000; -} - -void * -sysAllocateMem(long size) -{ - return malloc(size); -} - -int sysShutdown() -{ - return SYS_OK; -} - -unsigned -sleep(unsigned seconds) -{ - Sleep(seconds * 1000); - return 0; -} - -int -sysGetLastErrorString(char *buf, int len) -{ - long errval; - - if ((errval = GetLastError()) != 0) { - /* DOS error */ - int n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, errval, - 0, buf, len, NULL); - if (n > 3) { - /* Drop final '.', CR, LF */ - if (buf[n - 1] == '\n') n--; - if (buf[n - 1] == '\r') n--; - if (buf[n - 1] == '.') n--; - buf[n] = '\0'; - } - return n; - } - - if (errno != 0) { - /* C runtime error that has no corresponding DOS error code */ - const char *s = strerror(errno); - int n = strlen(s); - if (n >= len) n = len - 1; - strncpy(buf, s, n); - buf[n] = '\0'; - return n; - } - - return 0; -} diff --git a/jdk/src/windows/hpi/src/threads_md.c b/jdk/src/windows/hpi/src/threads_md.c deleted file mode 100644 index 7bc98038b44..00000000000 --- a/jdk/src/windows/hpi/src/threads_md.c +++ /dev/null @@ -1,831 +0,0 @@ -/* - * Copyright (c) 1994, 2008, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -/* - * Win32 implementation of Java threads - */ - -#include "hpi_impl.h" - -#include -#include /* for _beginthreadex(), _endthreadex() */ -#include - -#include "threads_md.h" -#include "monitor_md.h" - - -/* - * Queue of active Java threads - */ -static sys_thread_t *ThreadQueue; -sys_mon_t *_sys_queue_lock; - -static int ActiveThreadCount = 0; /* All threads */ - -/* - * Set to TRUE once threads have been bootstrapped - */ -bool_t ThreadsInitialized = FALSE; - -/* - * Are we running under Window NT - */ -static bool_t windowsNT = FALSE; - -/* - * Thread local storage index used for looking up sys_thread_t struct - * (tid) associated with the current thread. - */ -#define TLS_INVALID_INDEX 0xffffffffUL -static unsigned long tls_index = TLS_INVALID_INDEX; - -static void RecordNTTIB(sys_thread_t *tid) -{ -#ifndef _WIN64 - PNT_TIB nt_tib; - __asm { - mov eax, dword ptr fs:[18h]; - mov nt_tib, eax; - } - tid->nt_tib = nt_tib; -#else - tid->nt_tib = 0; -#endif -} - -/* - * Add thread to queue of active threads. - */ -static void -queueInsert(sys_thread_t *tid) -{ - if (ThreadsInitialized) - SYS_QUEUE_LOCK(sysThreadSelf()); - ActiveThreadCount++; - tid->next = ThreadQueue; - ThreadQueue = tid; - if (ThreadsInitialized) - SYS_QUEUE_UNLOCK(sysThreadSelf()); - else - ThreadsInitialized = TRUE; -} - -/* - * Remove thread from queue of active threads. - */ -static void -removefromActiveQ(sys_thread_t *tid) -{ - sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf())); - --ActiveThreadCount; - - if (ThreadQueue == tid) { - ThreadQueue = tid->next; - } else { - sys_thread_t *p; - for (p = ThreadQueue; p->next != 0; p = p->next) { - if (p->next == tid) { - p->next = tid->next; - break; - } - } - } -} - -/* - * Allocate and initialize the sys_thread_t structure for an arbitary - * native thread. - */ -int -sysThreadAlloc(sys_thread_t **tidP) -{ - HANDLE hnd = GetCurrentProcess(); - sys_thread_t *tid = allocThreadBlock(); - if (tid == NULL) { - return SYS_NOMEM; - } - - tid->state = RUNNABLE; - tid->interrupted = FALSE; - tid->interrupt_event = CreateEvent(NULL, TRUE, FALSE, NULL); - tid->id = GetCurrentThreadId(); - DuplicateHandle(hnd, GetCurrentThread(), hnd, &tid->handle, 0, FALSE, - DUPLICATE_SAME_ACCESS); - - RecordNTTIB(tid); - /* For the Invocation API: - We update the thread-specific storage before locking the - queue because sysMonitorEnter will access sysThreadSelf. - */ - TlsSetValue(tls_index, tid); - - queueInsert(tid); - tid->stack_ptr = &tid; - *tidP = tid; - return SYS_OK; -} - -/* - * Bootstrap the Java thread system by making the current thread the - * "primordial" thread. - */ -int threadBootstrapMD(sys_thread_t **tidP, sys_mon_t **lockP, int nb) -{ - OSVERSIONINFO windowsVersion; - HANDLE hnd = GetCurrentProcess(); - - nReservedBytes = (nb + 7) & (~7); - /* - * Allocate TLS index for thread-specific data. - */ - tls_index = TlsAlloc(); - if (tls_index == TLS_INVALID_INDEX) { - VM_CALL(jio_fprintf)(stderr, "TlsAlloc failed (errcode = %x)\n", - GetLastError()); - return SYS_NOMEM; - } - - /* OS properties */ - windowsVersion.dwOSVersionInfoSize = sizeof(windowsVersion); - GetVersionEx(&windowsVersion); - windowsNT = windowsVersion.dwPlatformId == VER_PLATFORM_WIN32_NT; - - /* Initialize the queue lock monitor */ - _sys_queue_lock = (sys_mon_t *)sysMalloc(sysMonitorSizeof()); - if (_sys_queue_lock == NULL) { - return SYS_ERR; - } - VM_CALL(monitorRegister)(_sys_queue_lock, "Thread queue lock"); - *lockP = _sys_queue_lock; - - return sysThreadAlloc(tidP); -} - -/* - * Return current stack pointer of specified thread. - */ -void * -sysThreadStackPointer(sys_thread_t *tid) -{ -#ifndef _WIN64 - CONTEXT context; - WORD __current_SS; - - /* REMIND: Need to fix this for Win95 */ - context.ContextFlags = CONTEXT_CONTROL; - if (!GetThreadContext(tid->handle, &context)) { - VM_CALL(jio_fprintf)(stderr, "GetThreadContext failed (errcode = %x)\n", - GetLastError()); - return 0; - } - - /* With the NT TIB stuff that Hong came up with, I don't think we - * need any of the complicated VirtualQuery calls anymore. If - * context.Esp is within the stack limit and base, we return - * context.Esp, otherwise, we can simply return nt_tib->StackLimit. - * To minimize code changes, though, I'm keeping the code the way - * it was. - */ - if (tid->nt_tib == NULL) { - /* thread hasn't started yet. */ - return 0; - } - - __asm { - mov ax, ss; - mov __current_SS, ax; - } - - if (context.SegSs == __current_SS && - context.Esp >= (uintptr_t)(tid->nt_tib->StackLimit) && - context.Esp < (uintptr_t)(tid->nt_tib->StackBase)) { - MEMORY_BASIC_INFORMATION mbi; - - VirtualQuery((PBYTE) context.Esp, &mbi, sizeof(mbi)); - - if (!(mbi.Protect & PAGE_GUARD)) { - return (void *) context.Esp; - } else { - SYSTEM_INFO si; - char *Esp = (char*) context.Esp; - DWORD dwPageSize; - - GetSystemInfo(&si); - dwPageSize = si.dwPageSize; - Esp -= (((DWORD) Esp) % dwPageSize); - do { - Esp += dwPageSize; - VirtualQuery((PBYTE) Esp, &mbi, sizeof(mbi)); - } while (mbi.Protect & PAGE_GUARD); - return Esp; - } - } else { - /* segment selectors don't match - thread is in some weird context */ - MEMORY_BASIC_INFORMATION mbi; - PBYTE pbStackHwm, pbStackBase; - SYSTEM_INFO si; - DWORD dwPageSize; - stackp_t stack_ptr = tid->stack_ptr; - - if (stack_ptr == 0) { - return 0; - } - GetSystemInfo(&si); - dwPageSize = si.dwPageSize; - VirtualQuery((PBYTE)stack_ptr - 1, &mbi, sizeof(mbi)); - pbStackBase = (PBYTE)mbi.AllocationBase; - /* step backwards till beginning of segment, non-RW page, or guard - page (guard pages only on WinNT) */ - do { - pbStackHwm = (PBYTE)mbi.BaseAddress; - if (pbStackHwm <= pbStackBase) { - break; - } - VirtualQuery(pbStackHwm - dwPageSize, &mbi, sizeof(mbi)); - } - while ((mbi.Protect & PAGE_READWRITE) && - !(mbi.Protect & PAGE_GUARD)); - /* the best we can do for now is the first page of stack - storage - it should be a stack high-water mark, anyway */ - return (void *)pbStackHwm; - } -#else - return 0; -#endif -} - -/* - * Get the end of stack (if you step beyond (above or below depending - * on your architecture) you can die. We refer to the logical top of - * stack. - * - * NOTE! There are restrictions about when you can call this method. If - * you did a sysThreadAlloc, then you can call this method as soon as - * sysThreadAlloc returns. If you called sysThreadCreate(start_function), - * then you must call sysThreadStackTop only inside start_function and not - * as soon as sysThreadCreate returns. - */ -void * -sysThreadStackTop(sys_thread_t *tid) -{ - return 0; /* FIXME: Unimplemented. */ -} - -long * -sysThreadRegs(sys_thread_t *tid, int *nregs) -{ - *nregs = N_TRACED_REGS; - return tid->regs; -} - -/* - * Thread start routine for new Java threads - */ -static unsigned __stdcall -_start(sys_thread_t *tid) -{ - /* Should thread suspend itself at this point? */ - - tid->state = RUNNABLE; - RecordNTTIB(tid); - TlsSetValue(tls_index, tid); - tid->stack_ptr = &tid; - tid->start_proc(tid->start_parm); - sysThreadFree(); - _endthreadex(0); - /* not reached */ - return 0; -} - -/* - * Create a new Java thread. The thread is initially suspended. - */ -int -sysThreadCreate(sys_thread_t **tidP, long stack_size, - void (*proc)(void *), void *arg) -{ - sys_thread_t *tid = allocThreadBlock(); - if (tid == NULL) { - return SYS_NOMEM; - } - tid->state = SUSPENDED; - tid->start_proc = proc; - tid->start_parm = arg; - - tid->interrupt_event = CreateEvent(NULL, TRUE, FALSE, NULL); - - /* - * Start the new thread. - */ - tid->handle = (HANDLE)_beginthreadex(NULL, stack_size, _start, tid, - CREATE_SUSPENDED, &tid->id); - if (tid->handle == 0) { - return SYS_NORESOURCE; /* Will be treated as though SYS_NOMEM */ - } - - queueInsert(tid); - *tidP = tid; - return SYS_OK; -} - -/* - * Free a system thread block. - * Remove from the thread queue. - */ -int -sysThreadFree() -{ - sys_thread_t *tid = sysThreadSelf(); - - /* - * remove ourselves from the thread queue. This must be done after - * the notify above since monitor operations aren't really safe if - * your thread isn't on the thread queue. (This isn't true of - * the sysMonitor* functions, only monitor*) - */ - SYS_QUEUE_LOCK(tid); - removefromActiveQ(tid); - SYS_QUEUE_UNLOCK(tid); - - /* For invocation API: later sysThreadSelf() calls will return 0 */ - TlsSetValue(tls_index, 0); - - /* - * Close the thread and interrupt event handles, and free the - * sys_thread_t structure. - */ - CloseHandle(tid->handle); - CloseHandle(tid->interrupt_event); - freeThreadBlock(tid); - return SYS_OK; -} - -/* - * Yield control to another thread. - */ -void -sysThreadYield(void) -{ - Sleep(0); -} - -/* - * Suspend execution of the specified thread. - */ -int -sysThreadSuspend(sys_thread_t *tid) -{ - /* REMIND: Fix for Win95 */ - /* Set state first so state is reflected before this thread */ - /* returns. Fix suggested by ARB of SAS */ - thread_state_t oldstate = tid->state; - sys_thread_t *self = sysThreadSelf(); - - if (tid == self) { - self->state = SUSPENDED; - } else { - switch(tid->state) { - case RUNNABLE: - tid->state = SUSPENDED; - break; - case MONITOR_WAIT: - tid->state = SUSPENDED; - tid->suspend_flags |= MONITOR_WAIT_SUSPENDED; - break; - case CONDVAR_WAIT: - tid->state = SUSPENDED; - tid->suspend_flags |= CONDVAR_WAIT_SUSPENDED; - break; - case SUSPENDED: - case MONITOR_SUSPENDED: - default: - return SYS_ERR; - } - } - if (SuspendThread(tid->handle) == 0xffffffffUL) { - tid->state = oldstate; - tid->suspend_flags = 0; - return SYS_ERR; - } - return SYS_OK; -} - -/* - * Continue execution of the specified thread. - */ -int -sysThreadResume(sys_thread_t *tid) -{ - unsigned long n; - - if (tid->suspend_flags & MONITOR_WAIT_SUSPENDED) { - tid->suspend_flags = 0; - tid->state = MONITOR_WAIT; - } else if (tid->suspend_flags & CONDVAR_WAIT_SUSPENDED) { - tid->suspend_flags = 0; - tid->state = CONDVAR_WAIT; - } else { - switch(tid->state) { - case SUSPENDED: - tid->state = RUNNABLE; - break; - case MONITOR_SUSPENDED: - tid->state = MONITOR_WAIT; - break; - case RUNNABLE: - case MONITOR_WAIT: - case CONDVAR_WAIT: - default: - return SYS_ERR; - break; - } - } - - /* Decrement thread's suspend count until no longer suspended */ - while ((n = ResumeThread(tid->handle)) > 1) { - if (n == 0xffffffffUL) { - return SYS_ERR; - } - } - return SYS_OK; -} - -/* - * Return priority of specified thread. - */ -int -sysThreadGetPriority(sys_thread_t *tid, int *pp) -{ - switch (GetThreadPriority(tid->handle)) { - case THREAD_PRIORITY_IDLE: - *pp = 0; break; - case THREAD_PRIORITY_LOWEST: - *pp = 2; break; - case THREAD_PRIORITY_BELOW_NORMAL: - *pp = 4; break; - case THREAD_PRIORITY_NORMAL: - *pp = 5; break; - case THREAD_PRIORITY_ABOVE_NORMAL: - *pp = 6; break; - case THREAD_PRIORITY_HIGHEST: - *pp = 8; break; - case THREAD_PRIORITY_TIME_CRITICAL: - *pp = 10; break; - case THREAD_PRIORITY_ERROR_RETURN: - return SYS_ERR; - } - return SYS_OK; -} - -/* - * Set priority of specified thread. - */ -int -sysThreadSetPriority(sys_thread_t *tid, int p) -{ - int priority; - - switch (p) { - case 0: - priority = THREAD_PRIORITY_IDLE; - break; - case 1: case 2: - priority = THREAD_PRIORITY_LOWEST; - break; - case 3: case 4: - priority = THREAD_PRIORITY_BELOW_NORMAL; - break; - case 5: - priority = THREAD_PRIORITY_NORMAL; - break; - case 6: case 7: - priority = THREAD_PRIORITY_ABOVE_NORMAL; - break; - case 8: case 9: - priority = THREAD_PRIORITY_HIGHEST; - break; - case 10: - priority = THREAD_PRIORITY_TIME_CRITICAL; - break; - default: - return SYS_ERR; - } - return SetThreadPriority(tid->handle, priority) ? SYS_OK : SYS_ERR; -} - -/* - * Return the thread information block of the calling thread. - */ -sys_thread_t * -sysThreadSelf(void) -{ - return tls_index == 0xffffffffUL ? 0 : TlsGetValue(tls_index); -} - -/* - * Enumerate over all threads in active queue calling a function for - * each one. Expects the caller to lock _queue_lock - */ -int -sysThreadEnumerateOver(int (*func)(sys_thread_t *, void *), void *arg) -{ - sys_thread_t *tid; - int ret = SYS_OK; - sys_thread_t *self = sysThreadSelf(); - - sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf())); - - for (tid = ThreadQueue; tid != 0; tid = tid->next) { - if ((ret = (*func)(tid, arg)) != SYS_OK) { - break; - } - } - return ret; -} - -/* - * Helper function for sysThreadSingle() - */ -static int -threadSingleHelper(sys_thread_t *tid, void *self) -{ - if (tid == self) { - return SYS_OK; - } - if (SuspendThread(tid->handle) == 0xffffffffUL) { - return SYS_ERR; - } - { - CONTEXT context; - DWORD *esp = (DWORD *)tid->regs; - - context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; - if (!GetThreadContext(tid->handle, &context)) { - VM_CALL(jio_fprintf) - (stderr, "GetThreadContext failed (errcode = %x)\n", - GetLastError()); - return SYS_ERR; - } -#ifdef _M_AMD64 - *esp++ = context.Rax; - *esp++ = context.Rbx; - *esp++ = context.Rcx; - *esp++ = context.Rdx; - *esp++ = context.Rsi; - *esp++ = context.Rdi; - *esp = context.Rbp; -#else - *esp++ = context.Eax; - *esp++ = context.Ebx; - *esp++ = context.Ecx; - *esp++ = context.Edx; - *esp++ = context.Esi; - *esp++ = context.Edi; - *esp = context.Ebp; -#endif - } - return SYS_OK; -} - -/* - * Puts each thread in the active thread queue to sleep except for the - * calling thread. The threads must be later woken up with a corresponding - * call to 'sysThreadMulti'. Returns SYS_OK on success, or SYS_ERR if any - * of the threads could not be suspended. - */ -int -sysThreadSingle(void) -{ - return sysThreadEnumerateOver(threadSingleHelper, sysThreadSelf()); -} - -/* - * Helper function for sysThreadMulti(): Only ResumeThread once, unlike - * sysThreadResume(), which will repeatedly call ResumeThread until the - * thread is really resumed. That is, Thread.resume will unwind any - * number of Thread.suspend invocations, but sysThreadMulti() calls must - * be strictly matched with sysThreadSingle() calls. Doing this keeps - * the garbage collector, which uses thread suspension to stop threads - * while it operates, from waking up threads that were already suspended - * when GC was invoked. - */ -static int -threadMultiHelper(sys_thread_t *tid, void *self) -{ - if (tid == self || ResumeThread(tid->handle) != 0xffffffffUL) { - return SYS_OK; - } else { - return SYS_ERR; - } -} - -/* - * Wakes up each thread in active thread queue except for the calling - * thread. The mechanism uses thread suspension, and will not wake a - * thread that was already suspended. Must be matched 1-1 with calls - * to sysThreadSingle(). Returns SYS_ERR if not all threads could be - * woken up. - */ -void -sysThreadMulti(void) -{ - sysThreadEnumerateOver(threadMultiHelper, sysThreadSelf()); -} - -/* - * Dump system-specific information about threads. - */ -void * -sysThreadNativeID(sys_thread_t *tid) -{ - return (void *)(uintptr_t)tid->id; -} - -int -sysThreadCheckStack(void) -{ - return 1; -} - -/* - * The mechanics of actually signalling an exception (in the future, - * and Alarm or Interrupt) depend upon what thread implementation you - * are using. - */ -void -sysThreadPostException(sys_thread_t *tid, void *exc) -{ - /* Interrupt the thread if it's waiting; REMIND: race??? */ - SetEvent(tid->interrupt_event); -} - -/* - * Support for (Java-level) interrupts. - */ -void -sysThreadInterrupt(sys_thread_t *tid) -{ - if (tid->interrupted == FALSE) { - tid->interrupted = TRUE; - SetEvent(tid->interrupt_event); - } -} - -int -sysThreadIsInterrupted(sys_thread_t *tid, int ClearInterrupted) -{ - bool_t interrupted = tid->interrupted; - if (interrupted && ClearInterrupted) { - tid->interrupted = FALSE; - ResetEvent(tid->interrupt_event); - } - return interrupted; -} - -HPI_SysInfo * -sysGetSysInfo() -{ - static HPI_SysInfo info = {0, 0}; - - if (info.name == NULL) { - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - info.isMP = sysinfo.dwNumberOfProcessors > 1; - info.name = "native threads"; - } - return &info; -} - -#define FT2INT64(ft) \ - ((jlong)(ft).dwHighDateTime << 32 | (jlong)(ft).dwLowDateTime) - -jlong -sysThreadCPUTime() -{ - if (windowsNT) { - FILETIME CreationTime; - FILETIME ExitTime; - FILETIME KernelTime; - FILETIME UserTime; - - GetThreadTimes(GetCurrentThread(), - &CreationTime, &ExitTime, &KernelTime, &UserTime); - return FT2INT64(UserTime) * 100; - } else { - return (jlong)sysGetMilliTicks() * 1000000; - } -} - -int -sysThreadGetStatus(sys_thread_t *tid, sys_mon_t **monitorPtr) -{ - int status; - switch (tid->state) { - case RUNNABLE: - if (tid->enter_monitor) - status = SYS_THREAD_MONITOR_WAIT; - else - status = SYS_THREAD_RUNNABLE; - break; - case SUSPENDED: - if (tid->enter_monitor) - status = SYS_THREAD_SUSPENDED | SYS_THREAD_MONITOR_WAIT; - else if (tid->suspend_flags & CONDVAR_WAIT_SUSPENDED) - status = SYS_THREAD_SUSPENDED | SYS_THREAD_CONDVAR_WAIT; - else - status = SYS_THREAD_SUSPENDED; - break; - case MONITOR_SUSPENDED: - status = SYS_THREAD_SUSPENDED | SYS_THREAD_MONITOR_WAIT; - break; - case CONDVAR_WAIT: - status = SYS_THREAD_CONDVAR_WAIT; - break; - case MONITOR_WAIT: - /* - * this flag should never be in used on win32 since the - * state is actually signalled by setting self->enter_monitor - * to point at the monitor the thread is waiting to enter - */ - sysAssert(FALSE); - default: - return SYS_ERR; - } - if (monitorPtr) { - if (status & SYS_THREAD_MONITOR_WAIT) { - *monitorPtr = tid->enter_monitor; - } else if (status & SYS_THREAD_CONDVAR_WAIT) { - *monitorPtr = tid->wait_monitor; - } else { - *monitorPtr = NULL; - } - } - return status; -} - -int sysAdjustTimeSlice(int i) -{ - return JNI_ERR; -} - -void sysThreadProfSuspend(sys_thread_t *tid) -{ - SuspendThread(tid->handle); -} - -void sysThreadProfResume(sys_thread_t *tid) -{ - ResumeThread(tid->handle); -} - -bool_t sysThreadIsRunning(sys_thread_t *tid) -{ -#ifndef _M_AMD64 - unsigned int sum = 0; - unsigned int *p; - CONTEXT context; - - context.ContextFlags = CONTEXT_FULL; - GetThreadContext(tid->handle, &context); - p = &context.SegGs; - while (p <= &context.SegSs) { - sum += *p; - p++; - } - - if (sum == tid->last_sum) { - return FALSE; - } - tid->last_sum = sum; -#endif - return TRUE; -} - -void * -sysThreadInterruptEvent() -{ - return sysThreadSelf()->interrupt_event; -} From afbf71368caf0ceb223b56976f568877443d5472 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 7 Jan 2011 10:16:57 -0800 Subject: [PATCH 009/152] 7009756: volatile variables could be broken throw reflection API Use Atomic::load() and Atomic::store() to access a volatile long. Reviewed-by: iveresov, jrose, dholmes, never --- .../vm/atomic_linux_sparc.inline.hpp | 4 +- .../linux_x86/vm/atomic_linux_x86.inline.hpp | 34 +++++++--- .../src/os_cpu/linux_x86/vm/linux_x86_32.s | 15 +++- .../vm/orderAccess_linux_x86.inline.hpp | 13 ++-- .../vm/atomic_solaris_x86.inline.hpp | 14 +++- .../vm/orderAccess_solaris_x86.inline.hpp | 15 ++-- .../os_cpu/solaris_x86/vm/solaris_x86_32.il | 7 +- .../vm/atomic_windows_x86.inline.hpp | 33 ++++++++- .../vm/orderAccess_windows_x86.inline.hpp | 13 ++-- hotspot/src/share/vm/prims/unsafe.cpp | 68 ++++++++++++------- 10 files changed, 154 insertions(+), 62 deletions(-) diff --git a/hotspot/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp b/hotspot/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp index 648543eadb8..a409f27b422 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -54,6 +54,8 @@ inline void Atomic::dec (volatile jint* dest) { (void)add (-1, dest); inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); } inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); } +inline jlong Atomic::load(volatile jlong* src) { return *src; } + inline jint Atomic::add (jint add_value, volatile jint* dest) { intptr_t rv; __asm__ volatile( diff --git a/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp b/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp index 7a89e56e107..7ec3dace4b1 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp +++ b/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -100,11 +100,6 @@ inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* return exchange_value; } -extern "C" { - // defined in linux_x86.s - jlong _Atomic_cmpxchg_long(jlong, volatile jlong*, jlong, bool); -} - #ifdef AMD64 inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; } inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; } @@ -164,9 +159,9 @@ inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); } -#else -//inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; } -//inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; } +inline jlong Atomic::load(volatile jlong* src) { return *src; } + +#else // !AMD64 inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { return (intptr_t)Atomic::add((jint)add_value, (volatile jint*)dest); @@ -189,6 +184,12 @@ inline intptr_t Atomic::xchg_ptr(intptr_t exchange_value, volatile intptr_t* des return (intptr_t)xchg((jint)exchange_value, (volatile jint*)dest); } +extern "C" { + // defined in linux_x86.s + jlong _Atomic_cmpxchg_long(jlong, volatile jlong*, jlong, bool); + void _Atomic_move_long(volatile jlong* src, volatile jlong* dst); +} + inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) { return _Atomic_cmpxchg_long(exchange_value, dest, compare_value, os::is_MP()); } @@ -200,6 +201,21 @@ inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); } + +inline jlong Atomic::load(volatile jlong* src) { + volatile jlong dest; + _Atomic_move_long(src, &dest); + return dest; +} + +inline void Atomic::store(jlong store_value, jlong* dest) { + _Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest); +} + +inline void Atomic::store(jlong store_value, volatile jlong* dest) { + _Atomic_move_long((volatile jlong*)&store_value, dest); +} + #endif // AMD64 #endif // OS_CPU_LINUX_X86_VM_ATOMIC_LINUX_X86_INLINE_HPP diff --git a/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s b/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s index ff315197949..08c6391c4cb 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s +++ b/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2011, 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 @@ -38,6 +38,7 @@ .globl _mmx_Copy_arrayof_conjoint_jshorts .globl _Atomic_cmpxchg_long + .globl _Atomic_move_long .text @@ -653,3 +654,15 @@ _Atomic_cmpxchg_long: popl %ebx ret + + # Support for jlong Atomic::load and Atomic::store. + # void _Atomic_move_long(volatile jlong* src, volatile jlong* dst) + .p2align 4,,15 + .type _Atomic_move_long,@function +_Atomic_move_long: + movl 4(%esp), %eax # src + fildll (%eax) + movl 8(%esp), %eax # dest + fistpll (%eax) + ret + diff --git a/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp b/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp index 9adf947ad37..8c6e566e270 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp +++ b/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -25,6 +25,7 @@ #ifndef OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP #define OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP +#include "runtime/atomic.hpp" #include "runtime/orderAccess.hpp" #include "vm_version_x86.hpp" @@ -64,11 +65,11 @@ inline void OrderAccess::fence() { inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; } +inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); } inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; } +inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); } inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; } @@ -79,11 +80,11 @@ inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return * inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; } +inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); } inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; } +inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); } inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; } @@ -178,7 +179,7 @@ inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) : "0" (v), "r" (p) : "memory"); #else - *p = v; fence(); + release_store(p, v); fence(); #endif // AMD64 } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp b/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp index a4b04606b9a..d91812db9c6 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -151,14 +151,22 @@ inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); } -extern "C" void _Atomic_load_long(volatile jlong* src, volatile jlong* dst); +extern "C" void _Atomic_move_long(volatile jlong* src, volatile jlong* dst); inline jlong Atomic::load(volatile jlong* src) { volatile jlong dest; - _Atomic_load_long(src, &dest); + _Atomic_move_long(src, &dest); return dest; } +inline void Atomic::store(jlong store_value, jlong* dest) { + _Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest); +} + +inline void Atomic::store(jlong store_value, volatile jlong* dest) { + _Atomic_move_long((volatile jlong*)&store_value, dest); +} + #endif // AMD64 #ifdef _GNU_SOURCE diff --git a/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp b/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp index a4894c8f89a..223e69e5cde 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -25,6 +25,7 @@ #ifndef OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP #define OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP +#include "runtime/atomic.hpp" #include "runtime/orderAccess.hpp" #include "vm_version_x86.hpp" @@ -80,11 +81,11 @@ extern "C" { inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; } +inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); } inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; } +inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); } inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; } @@ -95,11 +96,11 @@ inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return * inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; } +inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); } inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; } +inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); } inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; } @@ -123,11 +124,11 @@ inline void OrderAccess::store_ptr_fence(void** p, void* v) { *p = v; inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { *p = v; fence(); } inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { *p = v; fence(); } inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); } inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { *p = v; fence(); } inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); } inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { *p = v; fence(); } -inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store(p, v); fence(); } inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); } inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il index 99b19a313ad..056cb140293 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il +++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2011, 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 @@ -104,8 +104,9 @@ popl %ebx .end - // Support for void Atomic::load(volatile jlong* src, volatile jlong* dest). - .inline _Atomic_load_long,2 + // Support for jlong Atomic::load and Atomic::store. + // void _Atomic_move_long(volatile jlong* src, volatile jlong* dst) + .inline _Atomic_move_long,2 movl 0(%esp), %eax // src fildll (%eax) movl 4(%esp), %eax // dest diff --git a/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp b/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp index 7c26cb61051..37d2879662e 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp +++ b/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -137,10 +137,10 @@ inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value); } +inline jlong Atomic::load(volatile jlong* src) { return *src; } + #else // !AMD64 -//inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; } -//inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; } inline jint Atomic::add (jint add_value, volatile jint* dest) { int mp = os::is_MP(); __asm { @@ -254,6 +254,33 @@ inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); } + +inline jlong Atomic::load(volatile jlong* src) { + volatile jlong dest; + volatile jlong* pdest = &dest; + __asm { + mov eax, src + fild qword ptr [eax] + mov eax, pdest + fistp qword ptr [eax] + } + return dest; +} + +inline void Atomic::store(jlong store_value, volatile jlong* dest) { + volatile jlong* src = &store_value; + __asm { + mov eax, src + fild qword ptr [eax] + mov eax, dest + fistp qword ptr [eax] + } +} + +inline void Atomic::store(jlong store_value, jlong* dest) { + Atomic::store(store_value, (volatile jlong*)dest); +} + #endif // AMD64 #pragma warning(default: 4035) // Enables warnings reporting missing return statement diff --git a/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp b/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp index b47753bf656..682990dc6b7 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp +++ b/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -25,6 +25,7 @@ #ifndef OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP #define OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP +#include "runtime/atomic.hpp" #include "runtime/orderAccess.hpp" #include "vm_version_x86.hpp" @@ -65,11 +66,11 @@ inline void OrderAccess::fence() { inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; } inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; } inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; } -inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; } +inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); } inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; } inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; } inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; } -inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; } +inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); } inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; } inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; } @@ -80,11 +81,11 @@ inline void* OrderAccess::load_ptr_acquire(const volatile void* p) { return * inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; } inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; } inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; } -inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; } +inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); } inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; } inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; } inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; } -inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; } +inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); } inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; } inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; } @@ -188,7 +189,7 @@ inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { #endif // AMD64 } -inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { *p = v; fence(); } +inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); } inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store_fence((volatile jbyte*)p, (jbyte)v); } inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store_fence((volatile jshort*)p, (jshort)v); } diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index 4444fc67a25..7c64262d86f 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, 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 @@ -154,12 +154,11 @@ jint Unsafe_invocation_key_to_method_slot(jint key) { #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \ oop p = JNIHandles::resolve(obj); \ - volatile type_name v = *(volatile type_name*)index_oop_from_field_offset_long(p, offset) + volatile type_name v = OrderAccess::load_acquire((volatile type_name*)index_oop_from_field_offset_long(p, offset)); #define SET_FIELD_VOLATILE(obj, offset, type_name, x) \ oop p = JNIHandles::resolve(obj); \ - *(volatile type_name*)index_oop_from_field_offset_long(p, offset) = x; \ - OrderAccess::fence(); + OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x); // Macros for oops that check UseCompressedOops @@ -181,7 +180,8 @@ jint Unsafe_invocation_key_to_method_slot(jint key) { v = oopDesc::decode_heap_oop(n); \ } else { \ v = *(volatile oop*)index_oop_from_field_offset_long(p, offset); \ - } + } \ + OrderAccess::acquire(); // Get/SetObject must be special-cased, since it works with handles. @@ -248,14 +248,22 @@ UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject UnsafeWrapper("Unsafe_SetObjectVolatile"); oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); + void* addr = index_oop_from_field_offset_long(p, offset); + OrderAccess::release(); if (UseCompressedOops) { - oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x); + oop_store((narrowOop*)addr, x); } else { - oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); + oop_store((oop*)addr, x); } OrderAccess::fence(); UNSAFE_END +#if defined(SPARC) || defined(X86) +// Sparc and X86 have atomic jlong (8 bytes) instructions + +#else +// Keep old code for platforms which may not have atomic jlong (8 bytes) instructions + // Volatile long versions must use locks if !VM_Version::supports_cx8(). // support_cx8 is a surrogate for 'supports atomic long memory ops'. @@ -291,6 +299,7 @@ UNSAFE_ENTRY(void, Unsafe_SetLongVolatile(JNIEnv *env, jobject unsafe, jobject o } UNSAFE_END +#endif // not SPARC and not X86 #define DEFINE_GETSETOOP(jboolean, Boolean) \ \ @@ -320,6 +329,16 @@ UNSAFE_END \ \ // END DEFINE_GETSETOOP. +DEFINE_GETSETOOP(jboolean, Boolean) +DEFINE_GETSETOOP(jbyte, Byte) +DEFINE_GETSETOOP(jshort, Short); +DEFINE_GETSETOOP(jchar, Char); +DEFINE_GETSETOOP(jint, Int); +DEFINE_GETSETOOP(jlong, Long); +DEFINE_GETSETOOP(jfloat, Float); +DEFINE_GETSETOOP(jdouble, Double); + +#undef DEFINE_GETSETOOP #define DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) \ \ @@ -336,47 +355,49 @@ UNSAFE_END \ \ // END DEFINE_GETSETOOP_VOLATILE. -DEFINE_GETSETOOP(jboolean, Boolean) -DEFINE_GETSETOOP(jbyte, Byte) -DEFINE_GETSETOOP(jshort, Short); -DEFINE_GETSETOOP(jchar, Char); -DEFINE_GETSETOOP(jint, Int); -DEFINE_GETSETOOP(jlong, Long); -DEFINE_GETSETOOP(jfloat, Float); -DEFINE_GETSETOOP(jdouble, Double); - DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) DEFINE_GETSETOOP_VOLATILE(jbyte, Byte) DEFINE_GETSETOOP_VOLATILE(jshort, Short); DEFINE_GETSETOOP_VOLATILE(jchar, Char); DEFINE_GETSETOOP_VOLATILE(jint, Int); -// no long -- handled specially DEFINE_GETSETOOP_VOLATILE(jfloat, Float); DEFINE_GETSETOOP_VOLATILE(jdouble, Double); -#undef DEFINE_GETSETOOP +#if defined(SPARC) || defined(X86) +// Sparc and X86 have atomic jlong (8 bytes) instructions +DEFINE_GETSETOOP_VOLATILE(jlong, Long); +#endif + +#undef DEFINE_GETSETOOP_VOLATILE // The non-intrinsified versions of setOrdered just use setVolatile -UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x)) \ - UnsafeWrapper("Unsafe_SetOrderedInt"); \ - SET_FIELD_VOLATILE(obj, offset, jint, x); \ +UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x)) + UnsafeWrapper("Unsafe_SetOrderedInt"); + SET_FIELD_VOLATILE(obj, offset, jint, x); UNSAFE_END UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) UnsafeWrapper("Unsafe_SetOrderedObject"); oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); + void* addr = index_oop_from_field_offset_long(p, offset); + OrderAccess::release(); if (UseCompressedOops) { - oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x); + oop_store((narrowOop*)addr, x); } else { - oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); + oop_store((oop*)addr, x); } OrderAccess::fence(); UNSAFE_END UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) UnsafeWrapper("Unsafe_SetOrderedLong"); +#if defined(SPARC) || defined(X86) + // Sparc and X86 have atomic jlong (8 bytes) instructions + SET_FIELD_VOLATILE(obj, offset, jlong, x); +#else + // Keep old code for platforms which may not have atomic long (8 bytes) instructions { if (VM_Version::supports_cx8()) { SET_FIELD_VOLATILE(obj, offset, jlong, x); @@ -388,6 +409,7 @@ UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject ob *addr = x; } } +#endif UNSAFE_END ////// Data in the C heap. From 5bce844ff639c2f8c6eded9cd3b36e25d729117f Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 7 Jan 2011 11:53:24 -0800 Subject: [PATCH 010/152] 6876037: CTW fails jdk7/hotspot/src/share/vm/opto/type.cpp:2055. assert(bits,"Use TypePtr for NULL") Add missing 0 value check in TypeRawPtr::add_offset(). Reviewed-by: never --- hotspot/src/share/vm/opto/type.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index ac09b95c974..5f6550a6795 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -2187,8 +2187,11 @@ const TypePtr *TypeRawPtr::add_offset( intptr_t offset ) const { case TypePtr::NotNull: return this; case TypePtr::Null: - case TypePtr::Constant: - return make( _bits+offset ); + case TypePtr::Constant: { + address bits = _bits+offset; + if ( bits == 0 ) return TypePtr::NULL_PTR; + return make( bits ); + } default: ShouldNotReachHere(); } return NULL; // Lint noise From c816ca10db2d88936e5811763a0bf4d92896c409 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Fri, 7 Jan 2011 21:02:58 +0000 Subject: [PATCH 011/152] 7009760: Possible stack corruption in Java_java_net_TwoStacksPlainSocketImpl_socketGetOption SOCKET_ADDRESS -> SOCKETADDRESS Reviewed-by: alanb --- jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c b/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c index 792fc251d35..71e2b2b124e 100644 --- a/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c +++ b/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c @@ -1032,21 +1032,20 @@ Java_java_net_TwoStacksPlainSocketImpl_socketGetOption(JNIEnv *env, jobject this * SO_BINDADDR isn't a socket option */ if (opt == java_net_SocketOptions_SO_BINDADDR) { - SOCKET_ADDRESS him; + SOCKETADDRESS him; int len; int port; jobject iaObj; jclass iaCntrClass; jfieldID iaFieldID; - len = sizeof(struct sockaddr_in); + len = sizeof(him); if (fd == -1) { /* must be an IPV6 only socket. Case where both sockets are != -1 * is handled in java */ fd = getFD1 (env, this); - len = sizeof(struct SOCKADDR_IN6); } if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) { From b2ef93e7d4e6bca8760fc576bee8bceb336ad06a Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Fri, 7 Jan 2011 15:39:58 -0800 Subject: [PATCH 012/152] 7008728: diamond conversion of basic security, permissions, authentication Reviewed-by: mullan --- .../classes/com/sun/security/auth/PolicyFile.java | 2 +- .../auth/callback/DialogCallbackHandler.java | 4 ++-- .../com/sun/security/auth/login/ConfigFile.java | 7 +++---- .../sun/security/auth/module/JndiLoginModule.java | 2 +- .../security/auth/module/KeyStoreLoginModule.java | 3 +-- .../security/auth/module/SolarisLoginModule.java | 2 +- .../sun/security/auth/module/UnixLoginModule.java | 2 +- .../java/security/AccessControlContext.java | 2 +- .../classes/java/security/BasicPermission.java | 2 +- .../share/classes/java/security/CodeSource.java | 6 +++--- .../share/classes/java/security/Permissions.java | 4 ++-- .../classes/java/security/ProtectionDomain.java | 4 ++-- jdk/src/share/classes/java/security/Provider.java | 6 +++--- .../classes/java/security/SecureClassLoader.java | 2 +- jdk/src/share/classes/java/security/Security.java | 12 +++++------- .../java/security/UnresolvedPermission.java | 2 +- .../security/UnresolvedPermissionCollection.java | 10 ++++------ .../security/auth/PrivateCredentialPermission.java | 2 +- .../javax/security/auth/SubjectDomainCombiner.java | 2 +- .../auth/kerberos/DelegationPermission.java | 2 +- .../security/auth/kerberos/ServicePermission.java | 2 +- .../classes/sun/security/acl/AclEntryImpl.java | 2 +- .../share/classes/sun/security/acl/AclImpl.java | 14 +++++++------- .../share/classes/sun/security/acl/GroupImpl.java | 4 ++-- .../auth/module/LdapLoginModule/CheckConfigs.java | 6 +++--- .../auth/module/LdapLoginModule/CheckOptions.java | 6 +++--- 26 files changed, 53 insertions(+), 59 deletions(-) diff --git a/jdk/src/share/classes/com/sun/security/auth/PolicyFile.java b/jdk/src/share/classes/com/sun/security/auth/PolicyFile.java index fa9caf79e53..2005f044052 100644 --- a/jdk/src/share/classes/com/sun/security/auth/PolicyFile.java +++ b/jdk/src/share/classes/com/sun/security/auth/PolicyFile.java @@ -1180,7 +1180,7 @@ public class PolicyFile extends javax.security.auth.Policy { // Done return certs; - ArrayList userCertList = new ArrayList(); + ArrayList userCertList = new ArrayList<>(); i = 0; while (i < certs.length) { userCertList.add(certs[i]); diff --git a/jdk/src/share/classes/com/sun/security/auth/callback/DialogCallbackHandler.java b/jdk/src/share/classes/com/sun/security/auth/callback/DialogCallbackHandler.java index 63212fafb87..5f217190417 100644 --- a/jdk/src/share/classes/com/sun/security/auth/callback/DialogCallbackHandler.java +++ b/jdk/src/share/classes/com/sun/security/auth/callback/DialogCallbackHandler.java @@ -99,10 +99,10 @@ public class DialogCallbackHandler implements CallbackHandler { throws UnsupportedCallbackException { /* Collect messages to display in the dialog */ - final List messages = new ArrayList(3); + final List messages = new ArrayList<>(3); /* Collection actions to perform if the user clicks OK */ - final List okActions = new ArrayList(2); + final List okActions = new ArrayList<>(2); ConfirmationInfo confirmation = new ConfirmationInfo(); diff --git a/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java b/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java index ad186566fee..b3689ff21a0 100644 --- a/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java +++ b/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java @@ -152,7 +152,7 @@ public class ConfigFile extends javax.security.auth.login.Configuration { // new configuration HashMap> newConfig = - new HashMap>(); + new HashMap<>(); if (url != null) { @@ -392,8 +392,7 @@ public class ConfigFile extends javax.security.auth.login.Configuration { String moduleClass; String sflag; AppConfigurationEntry.LoginModuleControlFlag controlFlag; - LinkedList configEntries = - new LinkedList(); + LinkedList configEntries = new LinkedList<>(); // application name appName = st.sval; @@ -433,7 +432,7 @@ public class ConfigFile extends javax.security.auth.login.Configuration { } // get the args - HashMap options = new HashMap(); + HashMap options = new HashMap<>(); String key; String value; while (peek(";") == false) { diff --git a/jdk/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java b/jdk/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java index 59a19849df4..cede6b64062 100644 --- a/jdk/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java +++ b/jdk/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java @@ -184,7 +184,7 @@ public class JndiLoginModule implements LoginModule { private UnixNumericUserPrincipal UIDPrincipal; private UnixNumericGroupPrincipal GIDPrincipal; private LinkedList supplementaryGroups = - new LinkedList(); + new LinkedList<>(); // initial state private Subject subject; diff --git a/jdk/src/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java b/jdk/src/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java index ff6185e3877..f2199ed890c 100644 --- a/jdk/src/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java +++ b/jdk/src/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java @@ -658,8 +658,7 @@ public class KeyStoreLoginModule implements LoginModule { throw new FailedLoginException( "Unable to find X.509 certificate chain in keystore"); } else { - LinkedList certList = - new LinkedList(); + LinkedList certList = new LinkedList<>(); for (int i=0; i < fromKeyStore.length; i++) { certList.add(fromKeyStore[i]); } diff --git a/jdk/src/share/classes/com/sun/security/auth/module/SolarisLoginModule.java b/jdk/src/share/classes/com/sun/security/auth/module/SolarisLoginModule.java index 2767b9a4a22..cca9be6564d 100644 --- a/jdk/src/share/classes/com/sun/security/auth/module/SolarisLoginModule.java +++ b/jdk/src/share/classes/com/sun/security/auth/module/SolarisLoginModule.java @@ -76,7 +76,7 @@ public class SolarisLoginModule implements LoginModule { private SolarisNumericUserPrincipal UIDPrincipal; private SolarisNumericGroupPrincipal GIDPrincipal; private LinkedList supplementaryGroups = - new LinkedList(); + new LinkedList<>(); /** * Initialize this LoginModule. diff --git a/jdk/src/share/classes/com/sun/security/auth/module/UnixLoginModule.java b/jdk/src/share/classes/com/sun/security/auth/module/UnixLoginModule.java index a29153fb6a9..6f9a443f30a 100644 --- a/jdk/src/share/classes/com/sun/security/auth/module/UnixLoginModule.java +++ b/jdk/src/share/classes/com/sun/security/auth/module/UnixLoginModule.java @@ -70,7 +70,7 @@ public class UnixLoginModule implements LoginModule { private UnixNumericUserPrincipal UIDPrincipal; private UnixNumericGroupPrincipal GIDPrincipal; private LinkedList supplementaryGroups = - new LinkedList(); + new LinkedList<>(); /** * Initialize this LoginModule. diff --git a/jdk/src/share/classes/java/security/AccessControlContext.java b/jdk/src/share/classes/java/security/AccessControlContext.java index d4f167b6480..e80953b6696 100644 --- a/jdk/src/share/classes/java/security/AccessControlContext.java +++ b/jdk/src/share/classes/java/security/AccessControlContext.java @@ -121,7 +121,7 @@ public final class AccessControlContext { this.context = null; } } else { - List v = new ArrayList(context.length); + List v = new ArrayList<>(context.length); for (int i =0; i< context.length; i++) { if ((context[i] != null) && (!v.contains(context[i]))) v.add(context[i]); diff --git a/jdk/src/share/classes/java/security/BasicPermission.java b/jdk/src/share/classes/java/security/BasicPermission.java index 7f3b9479d1f..f22e4c755d2 100644 --- a/jdk/src/share/classes/java/security/BasicPermission.java +++ b/jdk/src/share/classes/java/security/BasicPermission.java @@ -515,7 +515,7 @@ implements java.io.Serializable // Copy perms into a Hashtable Hashtable permissions = - new Hashtable(perms.size()*2); + new Hashtable<>(perms.size()*2); synchronized (this) { permissions.putAll(perms); diff --git a/jdk/src/share/classes/java/security/CodeSource.java b/jdk/src/share/classes/java/security/CodeSource.java index d762b2dda40..5ec8cebc028 100644 --- a/jdk/src/share/classes/java/security/CodeSource.java +++ b/jdk/src/share/classes/java/security/CodeSource.java @@ -188,7 +188,7 @@ public class CodeSource implements java.io.Serializable { } else if (signers != null) { // Convert the code signers to certs ArrayList certChains = - new ArrayList(); + new ArrayList<>(); for (int i = 0; i < signers.length; i++) { certChains.addAll( signers[i].getSignerCertPath().getCertificates()); @@ -606,10 +606,10 @@ public class CodeSource implements java.io.Serializable { // Iterate through all the certificates int i = 0; - List signers = new ArrayList(); + List signers = new ArrayList<>(); while (i < certs.length) { List certChain = - new ArrayList(); + new ArrayList<>(); certChain.add(certs[i++]); // first cert is an end-entity cert int j = i; diff --git a/jdk/src/share/classes/java/security/Permissions.java b/jdk/src/share/classes/java/security/Permissions.java index 3f41ac408cf..e480db0fda8 100644 --- a/jdk/src/share/classes/java/security/Permissions.java +++ b/jdk/src/share/classes/java/security/Permissions.java @@ -362,7 +362,7 @@ implements Serializable // Copy perms into a Hashtable Hashtable, PermissionCollection> perms = - new Hashtable, PermissionCollection>(permsMap.size()*2); // no sync; estimate + new Hashtable<>(permsMap.size()*2); // no sync; estimate synchronized (this) { perms.putAll(permsMap); } @@ -567,7 +567,7 @@ implements Serializable // Copy perms into a Hashtable Hashtable perms = - new Hashtable(permsMap.size()*2); + new Hashtable<>(permsMap.size()*2); synchronized (this) { perms.putAll(permsMap); } diff --git a/jdk/src/share/classes/java/security/ProtectionDomain.java b/jdk/src/share/classes/java/security/ProtectionDomain.java index 6079436a585..43a39028e3d 100644 --- a/jdk/src/share/classes/java/security/ProtectionDomain.java +++ b/jdk/src/share/classes/java/security/ProtectionDomain.java @@ -336,8 +336,8 @@ public class ProtectionDomain { int swag = 32; int vcap = 8; Enumeration e; - List pdVector = new ArrayList(vcap); - List plVector = new ArrayList(swag); + List pdVector = new ArrayList<>(vcap); + List plVector = new ArrayList<>(swag); // // Build a vector of domain permissions for subsequent merge diff --git a/jdk/src/share/classes/java/security/Provider.java b/jdk/src/share/classes/java/security/Provider.java index 11dc07ae4f0..e13303526d3 100644 --- a/jdk/src/share/classes/java/security/Provider.java +++ b/jdk/src/share/classes/java/security/Provider.java @@ -437,7 +437,7 @@ public abstract class Provider extends Properties { private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - Map copy = new HashMap(); + Map copy = new HashMap<>(); for (Map.Entry entry : super.entrySet()) { copy.put(entry.getKey(), entry.getValue()); } @@ -719,7 +719,7 @@ public abstract class Provider extends Properties { } if (serviceSet == null) { ensureLegacyParsed(); - Set set = new LinkedHashSet(); + Set set = new LinkedHashSet<>(); if (serviceMap != null) { set.addAll(serviceMap.values()); } @@ -1395,7 +1395,7 @@ public abstract class Provider extends Properties { if (s != null) { String[] classNames = s.split("\\|"); List classList = - new ArrayList(classNames.length); + new ArrayList<>(classNames.length); for (String className : classNames) { Class clazz = getKeyClass(className); if (clazz != null) { diff --git a/jdk/src/share/classes/java/security/SecureClassLoader.java b/jdk/src/share/classes/java/security/SecureClassLoader.java index 3d53dffe1e7..4f774ca8f7d 100644 --- a/jdk/src/share/classes/java/security/SecureClassLoader.java +++ b/jdk/src/share/classes/java/security/SecureClassLoader.java @@ -50,7 +50,7 @@ public class SecureClassLoader extends ClassLoader { // HashMap that maps CodeSource to ProtectionDomain // @GuardedBy("pdcache") private final HashMap pdcache = - new HashMap(11); + new HashMap<>(11); private static final Debug debug = Debug.getInstance("scl"); diff --git a/jdk/src/share/classes/java/security/Security.java b/jdk/src/share/classes/java/security/Security.java index 28bc22e58ab..72d0b0b8778 100644 --- a/jdk/src/share/classes/java/security/Security.java +++ b/jdk/src/share/classes/java/security/Security.java @@ -545,8 +545,7 @@ public final class Security { value = filter.substring(index + 1); } - Hashtable hashtableFilter = - new Hashtable(1); + Hashtable hashtableFilter = new Hashtable<>(1); hashtableFilter.put(key, value); return (getProviders(hashtableFilter)); @@ -606,7 +605,7 @@ public final class Security { // Then only return those providers who satisfy the selection criteria. Provider[] allProviders = Security.getProviders(); Set keySet = filter.keySet(); - LinkedHashSet candidates = new LinkedHashSet(5); + LinkedHashSet candidates = new LinkedHashSet<>(5); // Returns all installed providers // if the selection criteria is null. @@ -660,8 +659,7 @@ public final class Security { } // Map containing cached Spi Class objects of the specified type - private static final Map spiMap = - new ConcurrentHashMap(); + private static final Map spiMap = new ConcurrentHashMap<>(); /** * Return the Class object for the given engine type @@ -885,7 +883,7 @@ public final class Security { String attrName, String filterValue, Provider[] allProviders) { - LinkedHashSet candidates = new LinkedHashSet(5); + LinkedHashSet candidates = new LinkedHashSet<>(5); for (int i = 0; i < allProviders.length; i++) { if (isCriterionSatisfied(allProviders[i], serviceName, algName, @@ -1082,7 +1080,7 @@ public final class Security { return Collections.EMPTY_SET; } - HashSet result = new HashSet(); + HashSet result = new HashSet<>(); Provider[] providers = Security.getProviders(); for (int i = 0; i < providers.length; i++) { diff --git a/jdk/src/share/classes/java/security/UnresolvedPermission.java b/jdk/src/share/classes/java/security/UnresolvedPermission.java index eeeccebca88..9e4e1aed053 100644 --- a/jdk/src/share/classes/java/security/UnresolvedPermission.java +++ b/jdk/src/share/classes/java/security/UnresolvedPermission.java @@ -198,7 +198,7 @@ implements java.io.Serializable if (this.certs == null) { // extract the signer certs ArrayList signerCerts = - new ArrayList(); + new ArrayList<>(); i = 0; while (i < certs.length) { signerCerts.add(certs[i]); diff --git a/jdk/src/share/classes/java/security/UnresolvedPermissionCollection.java b/jdk/src/share/classes/java/security/UnresolvedPermissionCollection.java index c186596ee31..01cf9f7edef 100644 --- a/jdk/src/share/classes/java/security/UnresolvedPermissionCollection.java +++ b/jdk/src/share/classes/java/security/UnresolvedPermissionCollection.java @@ -119,7 +119,7 @@ implements java.io.Serializable public Enumeration elements() { List results = - new ArrayList(); // where results are stored + new ArrayList<>(); // where results are stored // Get iterator of Map values (which are lists of permissions) synchronized (this) { @@ -161,7 +161,7 @@ implements java.io.Serializable // Copy perms into a Hashtable Hashtable> permissions = - new Hashtable>(perms.size()*2); + new Hashtable<>(perms.size()*2); // Convert each entry (List) into a Vector synchronized (this) { @@ -169,8 +169,7 @@ implements java.io.Serializable for (Map.Entry> e : set) { // Convert list into Vector List list = e.getValue(); - Vector vec = - new Vector(list.size()); + Vector vec = new Vector<>(list.size()); synchronized (list) { vec.addAll(list); } @@ -207,8 +206,7 @@ implements java.io.Serializable for (Map.Entry> e : set) { // Convert Vector into ArrayList Vector vec = e.getValue(); - List list = - new ArrayList(vec.size()); + List list = new ArrayList<>(vec.size()); list.addAll(vec); // Add to Hashtable being serialized diff --git a/jdk/src/share/classes/javax/security/auth/PrivateCredentialPermission.java b/jdk/src/share/classes/javax/security/auth/PrivateCredentialPermission.java index e78df3fdb5b..22cb6ef2d2f 100644 --- a/jdk/src/share/classes/javax/security/auth/PrivateCredentialPermission.java +++ b/jdk/src/share/classes/javax/security/auth/PrivateCredentialPermission.java @@ -329,7 +329,7 @@ public final class PrivateCredentialPermission extends Permission { throw new IllegalArgumentException("invalid empty name"); } - ArrayList pList = new ArrayList(); + ArrayList pList = new ArrayList<>(); StringTokenizer tokenizer = new StringTokenizer(name, " ", true); String principalClass = null; String principalName = null; diff --git a/jdk/src/share/classes/javax/security/auth/SubjectDomainCombiner.java b/jdk/src/share/classes/javax/security/auth/SubjectDomainCombiner.java index 9dc82fc0153..6ac38515e1c 100644 --- a/jdk/src/share/classes/javax/security/auth/SubjectDomainCombiner.java +++ b/jdk/src/share/classes/javax/security/auth/SubjectDomainCombiner.java @@ -48,7 +48,7 @@ public class SubjectDomainCombiner implements java.security.DomainCombiner { private Subject subject; private WeakKeyValueMap cachedPDs = - new WeakKeyValueMap(); + new WeakKeyValueMap<>(); private Set principalSet; private Principal[] principals; diff --git a/jdk/src/share/classes/javax/security/auth/kerberos/DelegationPermission.java b/jdk/src/share/classes/javax/security/auth/kerberos/DelegationPermission.java index 09387897d2e..76dbf65afe0 100644 --- a/jdk/src/share/classes/javax/security/auth/kerberos/DelegationPermission.java +++ b/jdk/src/share/classes/javax/security/auth/kerberos/DelegationPermission.java @@ -361,7 +361,7 @@ final class KrbDelegationPermissionCollection extends PermissionCollection // Don't call out.defaultWriteObject() // Write out Vector - Vector permissions = new Vector(perms.size()); + Vector permissions = new Vector<>(perms.size()); synchronized (this) { permissions.addAll(perms); diff --git a/jdk/src/share/classes/javax/security/auth/kerberos/ServicePermission.java b/jdk/src/share/classes/javax/security/auth/kerberos/ServicePermission.java index 98d2878154b..e9aedd09bc6 100644 --- a/jdk/src/share/classes/javax/security/auth/kerberos/ServicePermission.java +++ b/jdk/src/share/classes/javax/security/auth/kerberos/ServicePermission.java @@ -569,7 +569,7 @@ final class KrbServicePermissionCollection extends PermissionCollection // Don't call out.defaultWriteObject() // Write out Vector - Vector permissions = new Vector(perms.size()); + Vector permissions = new Vector<>(perms.size()); synchronized (this) { permissions.addAll(perms); diff --git a/jdk/src/share/classes/sun/security/acl/AclEntryImpl.java b/jdk/src/share/classes/sun/security/acl/AclEntryImpl.java index 521e73b8f9c..2bc035469b8 100644 --- a/jdk/src/share/classes/sun/security/acl/AclEntryImpl.java +++ b/jdk/src/share/classes/sun/security/acl/AclEntryImpl.java @@ -37,7 +37,7 @@ import java.security.acl.*; */ public class AclEntryImpl implements AclEntry { private Principal user = null; - private Vector permissionSet = new Vector(10, 10); + private Vector permissionSet = new Vector<>(10, 10); private boolean negative = false; /** diff --git a/jdk/src/share/classes/sun/security/acl/AclImpl.java b/jdk/src/share/classes/sun/security/acl/AclImpl.java index 6a6da4bea85..d8ea50d3fb9 100644 --- a/jdk/src/share/classes/sun/security/acl/AclImpl.java +++ b/jdk/src/share/classes/sun/security/acl/AclImpl.java @@ -41,15 +41,15 @@ public class AclImpl extends OwnerImpl implements Acl { // or principal. // private Hashtable allowedUsersTable = - new Hashtable(23); + new Hashtable<>(23); private Hashtable allowedGroupsTable = - new Hashtable(23); + new Hashtable<>(23); private Hashtable deniedUsersTable = - new Hashtable(23); + new Hashtable<>(23); private Hashtable deniedGroupsTable = - new Hashtable(23); + new Hashtable<>(23); private String aclName = null; - private Vector zeroSet = new Vector(1,1); + private Vector zeroSet = new Vector<>(1,1); /** @@ -294,7 +294,7 @@ public class AclImpl extends OwnerImpl implements Acl { // private static Enumeration union(Enumeration e1, Enumeration e2) { - Vector v = new Vector(20, 20); + Vector v = new Vector<>(20, 20); while (e1.hasMoreElements()) v.addElement(e1.nextElement()); @@ -313,7 +313,7 @@ public class AclImpl extends OwnerImpl implements Acl { // private Enumeration subtract(Enumeration e1, Enumeration e2) { - Vector v = new Vector(20, 20); + Vector v = new Vector<>(20, 20); while (e1.hasMoreElements()) v.addElement(e1.nextElement()); diff --git a/jdk/src/share/classes/sun/security/acl/GroupImpl.java b/jdk/src/share/classes/sun/security/acl/GroupImpl.java index e475b795c7d..586c705bc0c 100644 --- a/jdk/src/share/classes/sun/security/acl/GroupImpl.java +++ b/jdk/src/share/classes/sun/security/acl/GroupImpl.java @@ -34,7 +34,7 @@ import java.security.acl.*; * @author Satish Dharmaraj */ public class GroupImpl implements Group { - private Vector groupMembers = new Vector(50, 100); + private Vector groupMembers = new Vector<>(50, 100); private String group; /** @@ -131,7 +131,7 @@ public class GroupImpl implements Group { if (groupMembers.contains(member)) { return true; } else { - Vector alreadySeen = new Vector(10); + Vector alreadySeen = new Vector<>(10); return isMemberRecurse(member, alreadySeen); } } diff --git a/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.java b/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.java index 12c1db497da..f74e69079ed 100644 --- a/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.java +++ b/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.java @@ -178,7 +178,7 @@ class SearchFirstMode extends LdapConfiguration { public SearchFirstMode() { super(); - Map options = new HashMap(4); + Map options = new HashMap<>(4); options.put("userProvider", "ldap://localhost:23456/dc=example,dc=com"); options.put("userFilter", "(&(uid={USERNAME})(objectClass=inetOrgPerson))"); @@ -213,7 +213,7 @@ class AuthFirstMode extends LdapConfiguration { public AuthFirstMode() { super(); - Map options = new HashMap(5); + Map options = new HashMap<>(5); options.put("userProvider", "ldap://localhost:23456/dc=example,dc=com"); options.put("authIdentity", "{USERNAME}"); options.put("userFilter", @@ -248,7 +248,7 @@ class AuthOnlyMode extends LdapConfiguration { public AuthOnlyMode() { super(); - Map options = new HashMap(4); + Map options = new HashMap<>(4); options.put("userProvider", "ldap://localhost:23456 ldap://localhost:23457"); options.put("authIdentity", diff --git a/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckOptions.java b/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckOptions.java index fb175ca717a..3f7d8e3bac2 100644 --- a/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckOptions.java +++ b/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckOptions.java @@ -73,7 +73,7 @@ public class CheckOptions { // bad value for userProvider option - Map options = new HashMap(); + Map options = new HashMap<>(); options.put(USER_PROVIDER_OPTION, "ldap://localhost:23456"); ldap.initialize(subject, null, null, options); @@ -93,7 +93,7 @@ public class CheckOptions { LdapLoginModule ldap = new LdapLoginModule(); Subject subject = new Subject(); - Map options = new HashMap(); + Map options = new HashMap<>(); ldap.initialize(subject, null, null, options); try { @@ -110,7 +110,7 @@ public class CheckOptions { LdapLoginModule ldap = new LdapLoginModule(); Subject subject = new Subject(); - Map options = new HashMap(); + Map options = new HashMap<>(); CallbackHandler goodHandler = new MyCallbackHandler(true); ldap.initialize(subject, goodHandler, null, options); From c5d2b222a94bfdaee705c8f578e3d2e59a3d23c0 Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Fri, 7 Jan 2011 21:52:35 -0800 Subject: [PATCH 013/152] 6980024: Rebranding jre7/jdk7 License, Copyright, Readme 6912291: Third party license agreement should be present in all bundles Reviewed-by: katleman --- jdk/make/common/Modules.gmk | 45 +++----------- jdk/make/common/Release.gmk | 80 +++++-------------------- jdk/make/common/shared/Defs-control.gmk | 3 - 3 files changed, 22 insertions(+), 106 deletions(-) diff --git a/jdk/make/common/Modules.gmk b/jdk/make/common/Modules.gmk index 0bca87467f0..9eedcbcb5ab 100644 --- a/jdk/make/common/Modules.gmk +++ b/jdk/make/common/Modules.gmk @@ -73,47 +73,20 @@ module-image-jdk:: initial-module-image-jdk trim-module-image-jdk process-module # # Paths to these files we need -JDK_MODULE_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%) -JDK_MODULE_64_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%64) -JDK_MODULE_DOCFILES = $(OTHER_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%) - -JRE_MODULE_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%) -JRE_MODULE_64_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%64) -JRE_MODULE_DOCFILES = $(OTHER_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%) -JRE_MODULE_DOCFILES += $(JRE_NAMECHANGE_DOCLIST:%=$(JRE_MODULE_IMAGE_DIR)/%$(TEXT_SUFFIX)) +JDK_MODULE_DOCFILES = $(IMAGE_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%) +JRE_MODULE_DOCFILES = $(IMAGE_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%) ###### RULES # JDK files $(JDK_MODULE_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/% $(process-doc-file) -# Removes LICENSE_VERSION or not -ifdef LICENSE_VERSION -$(JDK_MODULE_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -$(JDK_MODULE_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -else -$(JDK_MODULE_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/% - $(process-doc-file) -endif # JRE files $(JRE_MODULE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/% $(process-doc-file) -# Add $(TEXT_SUFFIX) suffix -ifdef TEXT_SUFFIX -$(JRE_MODULE_IMAGE_DIR)/%$(TEXT_SUFFIX): $(SHARE_JRE_DOC_SRC)/% - $(process-doc-file) -endif -# Removes LICENSE_VERSION or not -ifdef LICENSE_VERSION -$(JRE_MODULE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -$(JRE_MODULE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -else -$(JRE_MODULE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/% +ifeq ($(PLATFORM), windows) +$(JRE_MODULE_IMAGE_DIR)/README.txt: $(SHARE_JRE_DOC_SRC)/README $(process-doc-file) endif @@ -157,8 +130,7 @@ initial-module-image-jre-setup: $(MKDIR) -p $(JRE_MODULE_IMAGE_DIR) # 64-bit solaris jre image contains only the 64-bit add-on files. -initial-module-image-jre-sol64:: initial-module-image-jre-setup \ - $(JRE_MODULE_LICENSES) $(JRE_MODULE_64_LICENSES) +initial-module-image-jre-sol64:: initial-module-image-jre-setup @# Use tar instead of cp to preserve the symbolic links for dir in bin lib ; do \ ( $(CD) $(OUTPUTDIR) && \ @@ -174,7 +146,7 @@ initial-module-image-jre-sol64:: initial-module-image-jre-setup \ # Construct an initial jre image (initial jdk jre) no trimming or stripping initial-module-image-jre:: initial-module-image-jre-setup \ - $(JRE_LICENSES) $(JRE_MODULE_DOCFILES) \ + $(JRE_MODULE_DOCFILES) \ $(BUILDMETAINDEX_JARFILE) @# Copy in bin directory $(CD) $(OUTPUTDIR) && $(FIND) bin -depth | $(CPIO) -pdum $(JRE_MODULE_IMAGE_DIR) @@ -310,8 +282,7 @@ initial-module-image-jdk64-bindemos: # Solaris 64 bit image is special initial-module-image-jdk-sol64:: initial-module-image-jdk-setup \ - initial-module-image-jdk64-bindemos \ - $(JDK_MODULE_LICENSES) $(JDK_MODULARLIZED_64_LICENSES) + initial-module-image-jdk64-bindemos # DB files to add ifeq ($(OPENJDK),true) @@ -335,7 +306,7 @@ endif # Standard jdk image initial-module-image-jdk:: initial-module-image-jdk-setup \ initial-module-image-jdk-db \ - $(JDK_MODULE_LICENSES) $(JDK_MODULE_DOCFILES) + $(JDK_MODULE_DOCFILES) $(MKDIR) $(JDK_MODULE_IMAGE_DIR)/lib @# @# copy jdk modules to jdk/lib diff --git a/jdk/make/common/Release.gmk b/jdk/make/common/Release.gmk index 9d83ae748b1..271f74695b3 100644 --- a/jdk/make/common/Release.gmk +++ b/jdk/make/common/Release.gmk @@ -75,11 +75,6 @@ JTG_DOCS = $(JDK_TOPDIR)/src/solaris/doc #We use this for man page header jdkversion := $(JDK_MAJOR_VERSION).$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION) -# Text documents on windows use this suffix -ifeq ($(PLATFORM), windows) - TEXT_SUFFIX = .txt -endif - # The base names of all the license and document files for the jdk and jre # (These files get placed in the jdk and jre install images) ifdef OPENJDK @@ -87,48 +82,24 @@ ifdef OPENJDK SHARE_JDK_DOC_SRC = $(JDK_TOPDIR) SHARE_JRE_DOC_SRC = $(JDK_TOPDIR) # Same files for jdk and jre, no name changes - LICENSE_DOCLIST_JDK = LICENSE ASSEMBLY_EXCEPTION - LICENSE_DOCLIST_JRE = LICENSE ASSEMBLY_EXCEPTION - OTHER_DOCLIST_JDK = THIRD_PARTY_README - OTHER_DOCLIST_JRE = THIRD_PARTY_README + IMAGE_DOCLIST_JDK = LICENSE ASSEMBLY_EXCEPTION THIRD_PARTY_README + IMAGE_DOCLIST_JRE = LICENSE ASSEMBLY_EXCEPTION THIRD_PARTY_README else # Where to find these files SHARE_JDK_DOC_SRC = $(CLOSED_SHARE_SRC)/doc/jdk SHARE_JRE_DOC_SRC = $(CLOSED_SHARE_SRC)/doc/jre - # Select the pre-release or FCS license version based on the build milestone. - LICENSE_VERSION=.pre - ifeq ($(MILESTONE), fcs) - LICENSE_VERSION=.fcs - endif + IMAGE_DOCLIST_JDK = COPYRIGHT README.html THIRDPARTYLICENSEREADME.txt + IMAGE_DOCLIST_JRE = COPYRIGHT Welcome.html THIRDPARTYLICENSEREADME.txt ifeq ($(PLATFORM), windows) - LICENSE_DOCLIST_JDK = $(subst $(LICENSE_VERSION),,\ - $(shell $(CD) $(SHARE_JDK_DOC_SRC) && \ - $(LS) *LICENSE*$(LICENSE_VERSION))) - LICENSE_DOCLIST_JRE = $(subst $(LICENSE_VERSION),,\ - $(shell $(CD) $(SHARE_JRE_DOC_SRC) && \ - $(LS) *LICENSE*$(LICENSE_VERSION))) + IMAGE_DOCLIST_JRE += README.txt else - LICENSE_DOCLIST_JDK = $(subst $(LICENSE_VERSION),,\ - $(shell $(CD) $(SHARE_JDK_DOC_SRC) && \ - $(LS) *LICENSE*$(LICENSE_VERSION) | $(GREP) -v rtf)) - LICENSE_DOCLIST_JRE = $(subst $(LICENSE_VERSION),,\ - $(shell $(CD) $(SHARE_JRE_DOC_SRC) && \ - $(LS) *LICENSE*$(LICENSE_VERSION) | $(GREP) -v rtf)) + IMAGE_DOCLIST_JRE += README endif - OTHER_DOCLIST_JDK = COPYRIGHT README.html README_ja.html README_zh_CN.html - OTHER_DOCLIST_JRE = COPYRIGHT Welcome.html - JRE_NAMECHANGE_DOCLIST = README endif # Paths to these files we need -JDK_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_IMAGE_DIR)/%) -JDK64_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_IMAGE_DIR)/%64) -JDK_DOCFILES = $(OTHER_DOCLIST_JDK:%=$(JDK_IMAGE_DIR)/%) - -JRE_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_IMAGE_DIR)/%) -JRE64_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_IMAGE_DIR)/%64) -JRE_DOCFILES = $(OTHER_DOCLIST_JRE:%=$(JRE_IMAGE_DIR)/%) -JRE_DOCFILES += $(JRE_NAMECHANGE_DOCLIST:%=$(JRE_IMAGE_DIR)/%$(TEXT_SUFFIX)) +JDK_DOCFILES = $(IMAGE_DOCLIST_JDK:%=$(JDK_IMAGE_DIR)/%) +JRE_DOCFILES = $(IMAGE_DOCLIST_JRE:%=$(JRE_IMAGE_DIR)/%) # absolute directory names: note, these must exist prior to build # time - they are created in the main Makefile. @@ -504,33 +475,12 @@ endef # JDK files $(JDK_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/% $(process-doc-file) -# Removes LICENSE_VERSION or not -ifdef LICENSE_VERSION -$(JDK_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -$(JDK_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -else -$(JDK_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/% - $(process-doc-file) -endif # JRE files $(JRE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/% $(process-doc-file) -# Add $(TEXT_SUFFIX) suffix -ifdef TEXT_SUFFIX -$(JRE_IMAGE_DIR)/%$(TEXT_SUFFIX): $(SHARE_JRE_DOC_SRC)/% - $(process-doc-file) -endif -# Removes LICENSE_VERSION or not -ifdef LICENSE_VERSION -$(JRE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -$(JRE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION) - $(process-doc-file) -else -$(JRE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/% +ifeq ($(PLATFORM), windows) +$(JRE_IMAGE_DIR)/README.txt: $(SHARE_JRE_DOC_SRC)/README $(process-doc-file) endif @@ -738,8 +688,7 @@ initial-image-jre-setup: $(MKDIR) -p $(JRE_IMAGE_DIR) # 64-bit solaris jre image contains only the 64-bit add-on files. -initial-image-jre-sol64:: initial-image-jre-setup \ - $(JRE_LICENSES) $(JRE64_LICENSES) +initial-image-jre-sol64:: initial-image-jre-setup @# Use tar instead of cp to preserve the symbolic links for dir in bin lib ; do \ ( $(CD) $(OUTPUTDIR) && \ @@ -760,7 +709,7 @@ initial-image-jre-sol64:: initial-image-jre-setup \ # See "initial-image-jdk-setup" for an explanation of the rm of # drive names like C: initial-image-jre:: initial-image-jre-setup \ - $(JRE_LICENSES) $(JRE_DOCFILES) \ + $(JRE_DOCFILES) \ $(RT_JAR) $(RESOURCES_JAR) $(JSSE_JAR) \ $(BUILDMETAINDEX_JARFILE) @# Copy in bin directory @@ -911,8 +860,7 @@ initial-image-jdk64-bindemos: # Solaris 64 bit image is special initial-image-jdk-sol64:: initial-image-jdk-setup \ - initial-image-jdk64-bindemos \ - $(JDK_LICENSES) $(JDK64_LICENSES) + initial-image-jdk64-bindemos # DB files to add ifdef OPENJDK @@ -936,7 +884,7 @@ endif # Standard jdk image initial-image-jdk:: initial-image-jdk-setup \ initial-image-jdk-db \ - $(JDK_LICENSES) $(JDK_DOCFILES) + $(JDK_DOCFILES) $(MKDIR) $(JDK_IMAGE_DIR)/lib @# @# Copy in the jars in lib that only belong in the JDK diff --git a/jdk/make/common/shared/Defs-control.gmk b/jdk/make/common/shared/Defs-control.gmk index 13eb20b1da4..288eb83e01c 100644 --- a/jdk/make/common/shared/Defs-control.gmk +++ b/jdk/make/common/shared/Defs-control.gmk @@ -76,12 +76,9 @@ SRC_BUNDLEDIR = $(OUTPUTDIR)/source-bundles ABS_SRC_BUNDLEDIR = $(ABS_OUTPUTDIR)/source-bundles BIN_BUNDLEDIR = $(OUTPUTDIR)/bundles ABS_BIN_BUNDLEDIR = $(ABS_OUTPUTDIR)/bundles -JRL_BUNDLEDIR = $(OUTPUTDIR)/java.net -ABS_JRL_BUNDLEDIR = $(ABS_OUTPUTDIR)/java.net dummy := $(shell $(MKDIR) -p $(BIN_BUNDLEDIR)) dummy := $(shell $(MKDIR) -p $(SRC_BUNDLEDIR) ) -dummy := $(shell $(MKDIR) -p $(JRL_BUNDLEDIR) ) TEMP_DIR = $(OUTPUTDIR)/tmp ABS_TEMP_DIR = $(ABS_OUTPUTDIR)/tmp From 5d2936a29ceaec23a51606fd5ded66a0c71b3a92 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Sun, 9 Jan 2011 17:16:16 -0500 Subject: [PATCH 014/152] 7010665: Misplaced membar in C1 implementation of Unsafe.get/putXXX Modify membars to match regular volatile variable handling Reviewed-by: iveresov, kvn, never --- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 56b22f686f1..9a7850d69bb 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -1990,9 +1990,8 @@ void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) { LIR_Opr reg = reg = rlock_result(x, x->basic_type()); - if (x->is_volatile() && os::is_MP()) __ membar_acquire(); get_Object_unsafe(reg, src.result(), off.result(), type, x->is_volatile()); - if (x->is_volatile() && os::is_MP()) __ membar(); + if (x->is_volatile() && os::is_MP()) __ membar_acquire(); } @@ -2014,6 +2013,7 @@ void LIRGenerator::do_UnsafePutObject(UnsafePutObject* x) { if (x->is_volatile() && os::is_MP()) __ membar_release(); put_Object_unsafe(src.result(), off.result(), data.result(), type, x->is_volatile()); + if (x->is_volatile() && os::is_MP()) __ membar(); } From b2f607fcb608105c0793b250470339c4cdf1973e Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Mon, 10 Jan 2011 00:56:39 -0800 Subject: [PATCH 015/152] 7010180: JSR 292 InvokeDynamicPrintArgs fails with: assert(_adapter == NULL) failed: init'd to NULL Reviewed-by: never --- .../src/cpu/sparc/vm/methodHandles_sparc.cpp | 9 ++++--- hotspot/src/cpu/x86/vm/methodHandles_x86.cpp | 9 ++++--- hotspot/src/share/vm/prims/methodHandles.cpp | 25 +++++++++++-------- hotspot/src/share/vm/prims/methodHandles.hpp | 8 +++--- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index 2fb2e56d8b3..4fc102fa480 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2011, 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 @@ -395,7 +395,7 @@ int MethodHandles::adapter_conversion_ops_supported_mask() { // // Generate an "entry" field for a method handle. // This determines how the method handle will respond to calls. -void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) { +void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) { // Here is the register state during an interpreted call, // as set up by generate_method_handle_interpreter_entry(): // - G5: garbage temp (was MethodHandle.invoke methodOop, unused) @@ -447,8 +447,9 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // exception. Since we use a C2I adapter to set up the // interpreter state, arguments are expected in compiler // argument registers. - methodHandle mh(raise_exception_method()); - address c2i_entry = methodOopDesc::make_adapters(mh, CATCH); + assert(raise_exception_method(), "must be set"); + address c2i_entry = raise_exception_method()->get_c2i_entry(); + assert(c2i_entry, "method must be linked"); __ mov(O5_savedSP, SP); // Cut the stack back to where the caller started. diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index f92beb4839f..bbbc29d6408 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -390,7 +390,7 @@ int MethodHandles::adapter_conversion_ops_supported_mask() { // // Generate an "entry" field for a method handle. // This determines how the method handle will respond to calls. -void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) { +void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) { // Here is the register state during an interpreted call, // as set up by generate_method_handle_interpreter_entry(): // - rbx: garbage temp (was MethodHandle.invoke methodOop, unused) @@ -451,8 +451,9 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan // exception. Since we use a C2I adapter to set up the // interpreter state, arguments are expected in compiler // argument registers. - methodHandle mh(raise_exception_method()); - address c2i_entry = methodOopDesc::make_adapters(mh, CHECK); + assert(raise_exception_method(), "must be set"); + address c2i_entry = raise_exception_method()->get_c2i_entry(); + assert(c2i_entry, "method must be linked"); const Register rdi_pc = rax; __ pop(rdi_pc); // caller PC diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index 1b2c3c60d4a..f77f0b625d5 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2011, 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 @@ -111,7 +111,7 @@ bool MethodHandles::spot_check_entry_names() { //------------------------------------------------------------------------------ // MethodHandles::generate_adapters // -void MethodHandles::generate_adapters(TRAPS) { +void MethodHandles::generate_adapters() { if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL) return; assert(_adapter_code == NULL, "generate only once"); @@ -123,20 +123,20 @@ void MethodHandles::generate_adapters(TRAPS) { vm_exit_out_of_memory(_adapter_code_size, "CodeCache: no room for MethodHandles adapters"); CodeBuffer code(_adapter_code); MethodHandlesAdapterGenerator g(&code); - g.generate(CHECK); + g.generate(); } //------------------------------------------------------------------------------ // MethodHandlesAdapterGenerator::generate // -void MethodHandlesAdapterGenerator::generate(TRAPS) { +void MethodHandlesAdapterGenerator::generate() { // Generate generic method handle adapters. for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST; ek < MethodHandles::_EK_LIMIT; ek = MethodHandles::EntryKind(1 + (int)ek)) { StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek)); - MethodHandles::generate_method_handle_stub(_masm, ek, CHECK); + MethodHandles::generate_method_handle_stub(_masm, ek); } } @@ -2621,10 +2621,20 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) warning("JSR 292 method handle code is mismatched to this JVM. Disabling support."); enable_MH = false; } + } else { + enable_MH = false; } } if (enable_MH) { + // We need to link the MethodHandleImpl klass before we generate + // the method handle adapters as the _raise_exception adapter uses + // one of its methods (and its c2i-adapter). + KlassHandle k = SystemDictionaryHandles::MethodHandleImpl_klass(); + instanceKlass* ik = instanceKlass::cast(k()); + ik->link_class(CHECK); + + MethodHandles::generate_adapters(); MethodHandles::set_enabled(true); } @@ -2645,10 +2655,5 @@ JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) MethodHandles::set_enabled(true); } } - - // Generate method handles adapters if enabled. - if (MethodHandles::enabled()) { - MethodHandles::generate_adapters(CHECK); - } } JVM_END diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index f66f0e026d2..cf9c25a5ae9 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2011, 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 @@ -294,11 +294,11 @@ class MethodHandles: AllStatic { enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 }; // Generate MethodHandles adapters. - static void generate_adapters(TRAPS); + static void generate_adapters(); // Called from InterpreterGenerator and MethodHandlesAdapterGenerator. static address generate_method_handle_interpreter_entry(MacroAssembler* _masm); - static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek, TRAPS); + static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek); // argument list parsing static int argument_slot(oop method_type, int arg); @@ -530,7 +530,7 @@ class MethodHandlesAdapterGenerator : public StubCodeGenerator { public: MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {} - void generate(TRAPS); + void generate(); }; #endif // SHARE_VM_PRIMS_METHODHANDLES_HPP From a449cd08d7475215fe50218312a5d858068c694c Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Mon, 10 Jan 2011 09:32:32 +0000 Subject: [PATCH 016/152] 7002957: (fc) FileChannel.transferTo fails to load libsendfile on Solaris 64-bit Reviewed-by: chegar --- jdk/make/java/nio/Makefile | 2 +- .../native/sun/nio/ch/FileChannelImpl.c | 116 +++++------------- 2 files changed, 35 insertions(+), 83 deletions(-) diff --git a/jdk/make/java/nio/Makefile b/jdk/make/java/nio/Makefile index c0a03c23d42..af84a82b8ac 100644 --- a/jdk/make/java/nio/Makefile +++ b/jdk/make/java/nio/Makefile @@ -296,7 +296,7 @@ ifeq ($(PLATFORM), linux) OTHER_LDLIBS += -L$(LIBDIR)/$(LIBARCH) -ljava -lnet -lpthread -ldl endif ifeq ($(PLATFORM), solaris) -OTHER_LDLIBS += $(JVMLIB) $(LIBSOCKET) -lposix4 -ldl \ +OTHER_LDLIBS += $(JVMLIB) $(LIBSOCKET) -lposix4 -ldl -lsendfile \ -L$(LIBDIR)/$(LIBARCH) -ljava -lnet endif # PLATFORM diff --git a/jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c b/jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c index c570fe1bc3e..539013f0bd7 100644 --- a/jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c +++ b/jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c @@ -35,48 +35,17 @@ #include "nio_util.h" #include -static jfieldID chan_fd; /* jobject 'fd' in sun.io.FileChannelImpl */ - -#ifdef __solaris__ -typedef struct sendfilevec64 { - int sfv_fd; /* input fd */ - uint_t sfv_flag; /* Flags. see below */ - off64_t sfv_off; /* offset to start reading from */ - size_t sfv_len; /* amount of data */ -} sendfilevec_t; - -/* Function pointer for sendfilev on Solaris 8+ */ -typedef ssize_t sendfile_func(int fildes, const struct sendfilevec64 *vec, - int sfvcnt, size_t *xferred); - -sendfile_func* my_sendfile_func = NULL; -#endif - -#ifdef __linux__ +#if defined(__linux__) || defined(__solaris__) #include - -/* Function pointer for sendfile64 on Linux 2.6 (and newer 2.4 kernels) */ -typedef ssize_t sendfile64_func(int out_fd, int in_fd, off64_t *offset, size_t count); - -sendfile64_func* my_sendfile64_func = NULL; #endif +static jfieldID chan_fd; /* jobject 'fd' in sun.io.FileChannelImpl */ + JNIEXPORT jlong JNICALL Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz) { jlong pageSize = sysconf(_SC_PAGESIZE); chan_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;"); - -#ifdef __solaris__ - if (dlopen("/usr/lib/libsendfile.so.1", RTLD_GLOBAL | RTLD_LAZY) != NULL) { - my_sendfile_func = (sendfile_func*) dlsym(RTLD_DEFAULT, "sendfilev64"); - } -#endif - -#ifdef __linux__ - my_sendfile64_func = (sendfile64_func*) dlsym(RTLD_DEFAULT, "sendfile64"); -#endif - return pageSize; } @@ -178,22 +147,9 @@ Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, jlong position, jlong count, jint dstFD) { -#ifdef __linux__ - jlong max = (jlong)java_lang_Integer_MAX_VALUE; - jlong n; - - if (my_sendfile64_func == NULL) { - off_t offset; - if (position > max) - return IOS_UNSUPPORTED_CASE; - if (count > max) - count = max; - offset = (off_t)position; - n = sendfile(dstFD, srcFD, &offset, (size_t)count); - } else { - off64_t offset = (off64_t)position; - n = (*my_sendfile64_func)(dstFD, srcFD, &offset, (size_t)count); - } +#if defined(__linux__) + off64_t offset = (off64_t)position; + jlong n = sendfile64(dstFD, srcFD, &offset, (size_t)count); if (n < 0) { if (errno == EAGAIN) return IOS_UNAVAILABLE; @@ -206,41 +162,37 @@ Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, return IOS_THROWN; } return n; -#endif +#elif defined (__solaris__) + sendfilevec64_t sfv; + size_t numBytes = 0; + jlong result; -#ifdef __solaris__ - if (my_sendfile_func == NULL) { - return IOS_UNSUPPORTED; - } else { - sendfilevec_t sfv; - size_t numBytes = 0; - jlong result; + sfv.sfv_fd = srcFD; + sfv.sfv_flag = 0; + sfv.sfv_off = (off64_t)position; + sfv.sfv_len = count; - sfv.sfv_fd = srcFD; - sfv.sfv_flag = 0; - sfv.sfv_off = (off64_t)position; - sfv.sfv_len = count; + result = sendfilev64(dstFD, &sfv, 1, &numBytes); - result = (*my_sendfile_func)(dstFD, &sfv, 1, &numBytes); - - /* Solaris sendfilev() will return -1 even if some bytes have been - * transferred, so we check numBytes first. - */ - if (numBytes > 0) - return numBytes; - if (result < 0) { - if (errno == EAGAIN) - return IOS_UNAVAILABLE; - if (errno == EOPNOTSUPP) - return IOS_UNSUPPORTED_CASE; - if ((errno == EINVAL) && ((ssize_t)count >= 0)) - return IOS_UNSUPPORTED_CASE; - if (errno == EINTR) - return IOS_INTERRUPTED; - JNU_ThrowIOExceptionWithLastError(env, "Transfer failed"); - return IOS_THROWN; - } - return result; + /* Solaris sendfilev() will return -1 even if some bytes have been + * transferred, so we check numBytes first. + */ + if (numBytes > 0) + return numBytes; + if (result < 0) { + if (errno == EAGAIN) + return IOS_UNAVAILABLE; + if (errno == EOPNOTSUPP) + return IOS_UNSUPPORTED_CASE; + if ((errno == EINVAL) && ((ssize_t)count >= 0)) + return IOS_UNSUPPORTED_CASE; + if (errno == EINTR) + return IOS_INTERRUPTED; + JNU_ThrowIOExceptionWithLastError(env, "Transfer failed"); + return IOS_THROWN; } + return result; +#else + return IOS_UNSUPPORTED_CASE; #endif } From 595eda12a49ad434398496d8b759dd78802da9fb Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Mon, 10 Jan 2011 03:58:07 -0800 Subject: [PATCH 017/152] 7010913: JSR 292 ciMethodHandle does not handle MethodHandleCompiler exceptions properly Reviewed-by: kvn, never --- hotspot/src/share/vm/ci/ciMethodHandle.cpp | 9 +++++---- hotspot/src/share/vm/prims/methodHandleWalk.cpp | 3 +-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/ci/ciMethodHandle.cpp b/hotspot/src/share/vm/ci/ciMethodHandle.cpp index c8e7cf18142..1355b504c4c 100644 --- a/hotspot/src/share/vm/ci/ciMethodHandle.cpp +++ b/hotspot/src/share/vm/ci/ciMethodHandle.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, 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 @@ -38,11 +38,12 @@ // Return an adapter for this MethodHandle. ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const { VM_ENTRY_MARK; - Handle h(get_oop()); methodHandle callee(_callee->get_methodOop()); - MethodHandleCompiler mhc(h, callee, is_invokedynamic, THREAD); - methodHandle m = mhc.compile(CHECK_NULL); + // We catch all exceptions here that could happen in the method + // handle compiler and stop the VM. + MethodHandleCompiler mhc(h, callee, is_invokedynamic, CATCH); + methodHandle m = mhc.compile(CATCH); return CURRENT_ENV->get_object(m())->as_method(); } diff --git a/hotspot/src/share/vm/prims/methodHandleWalk.cpp b/hotspot/src/share/vm/prims/methodHandleWalk.cpp index f20859dac8c..4552410944f 100644 --- a/hotspot/src/share/vm/prims/methodHandleWalk.cpp +++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2011, 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 @@ -137,7 +137,6 @@ BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int void MethodHandleChain::lose(const char* msg, TRAPS) { - assert(false, "lose"); _lose_message = msg; if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) { // throw a preallocated exception From a137c29891a81509d5c528817ee5e01a5d07d319 Mon Sep 17 00:00:00 2001 From: Lance Andersen Date: Mon, 10 Jan 2011 14:43:50 -0500 Subject: [PATCH 018/152] 6544224: Remove the need of sun.reflect.misc Reviewed-by: alanb --- .../sql/rowset/serial/SerialJavaObject.java | 37 +++++-------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/jdk/src/share/classes/javax/sql/rowset/serial/SerialJavaObject.java b/jdk/src/share/classes/javax/sql/rowset/serial/SerialJavaObject.java index 0a05a01e031..5aa034f6854 100644 --- a/jdk/src/share/classes/javax/sql/rowset/serial/SerialJavaObject.java +++ b/jdk/src/share/classes/javax/sql/rowset/serial/SerialJavaObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -25,9 +25,7 @@ package javax.sql.rowset.serial; -import java.sql.*; import java.io.*; -import java.util.Map; import java.lang.reflect.*; import javax.sql.rowset.RowSetWarning; @@ -51,7 +49,7 @@ public class SerialJavaObject implements Serializable, Cloneable { /** * Placeholder for object to be serialized. */ - private Object obj; + private final Object obj; /** @@ -64,8 +62,7 @@ public class SerialJavaObject implements Serializable, Cloneable { *

* * @param obj the Java Object to be serialized - * @throws SerialException if the object is found - * to be unserializable + * @throws SerialException if the object is found not to be serializable */ public SerialJavaObject(Object obj) throws SerialException { @@ -74,16 +71,11 @@ public class SerialJavaObject implements Serializable, Cloneable { // get Class. Object instance should always be available - Class c = obj.getClass(); + Class c = obj.getClass(); // determine if object implements Serializable i/f - boolean serializableImpl = false; - Class[] theIf = c.getInterfaces(); - for (int i = 0; i < theIf.length; i++) { - String ifName = theIf[i].getName(); - if (ifName == "java.io.Serializable") { - serializableImpl = true; - } + if (!(obj instanceof java.io.Serializable)) { + setWarning(new RowSetWarning("Warning, the object passed to the constructor does not implement Serializable")); } // can only determine public fields (obviously). If @@ -93,22 +85,14 @@ public class SerialJavaObject implements Serializable, Cloneable { boolean anyStaticFields = false; fields = c.getFields(); - //fields = new Object[field.length]; for (int i = 0; i < fields.length; i++ ) { if ( fields[i].getModifiers() == Modifier.STATIC ) { anyStaticFields = true; } - //fields[i] = field[i].get(obj); - } - try { - if (!(serializableImpl)) { - throw new RowSetWarning("Test"); - } - } catch (RowSetWarning w) { - setWarning(w); } + if (anyStaticFields) { throw new SerialException("Located static fields in " + "object instance. Cannot serialize"); @@ -139,11 +123,8 @@ public class SerialJavaObject implements Serializable, Cloneable { */ public Field[] getFields() throws SerialException { if (fields != null) { - Class c = this.obj.getClass(); - //the following has to be commented before mustang integration - //return c.getFields(); - //the following has to be uncommented before mustang integration - return sun.reflect.misc.FieldUtil.getFields(c); + Class c = this.obj.getClass(); + return c.getFields(); } else { throw new SerialException("SerialJavaObject does not contain" + " a serialized object instance"); From ae65c6240f81238d7ee62252b1c0ce86689e231a Mon Sep 17 00:00:00 2001 From: Keith McGuigan Date: Mon, 10 Jan 2011 17:14:53 -0500 Subject: [PATCH 019/152] 6458402: 3 jvmti tests fail with CMS and +ExplicitGCInvokesConcurrent Make JvmtiGCMark safe to run non-safepoint and instrument CMS Reviewed-by: ysr, dcubed --- .../concurrentMarkSweepGeneration.cpp | 8 +- .../gc_implementation/g1/concurrentMark.cpp | 3 + .../gc_implementation/g1/g1CollectedHeap.cpp | 4 +- .../gc_implementation/g1/vm_operations_g1.cpp | 3 - .../parallelScavenge/vmPSOperations.cpp | 13 +- .../shared/vmGCOperations.cpp | 15 +- .../shared/vmGCOperations.hpp | 15 +- hotspot/src/share/vm/prims/jvmti.xml | 8 +- hotspot/src/share/vm/prims/jvmtiExport.cpp | 49 +-- hotspot/src/share/vm/prims/jvmtiExport.hpp | 51 +-- hotspot/src/share/vm/prims/jvmtiImpl.cpp | 20 +- hotspot/src/share/vm/prims/jvmtiImpl.hpp | 4 - hotspot/src/share/vm/prims/jvmtiTagMap.cpp | 383 +++++------------- hotspot/src/share/vm/prims/jvmtiTagMap.hpp | 27 +- hotspot/src/share/vm/runtime/globals.hpp | 3 - hotspot/src/share/vm/runtime/jniHandles.cpp | 7 + 16 files changed, 157 insertions(+), 456 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 36a070a1826..2ca6c6d0dd6 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -3478,6 +3478,7 @@ void CMSCollector::checkpointRootsInitial(bool asynch) { assert(_collectorState == InitialMarking, "Wrong collector state"); check_correct_thread_executing(); TraceCMSMemoryManagerStats tms(_collectorState); + ReferenceProcessor* rp = ref_processor(); SpecializationStats::clear(); assert(_restart_addr == NULL, "Control point invariant"); @@ -5940,11 +5941,6 @@ void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) { } rp->verify_no_references_recorded(); assert(!rp->discovery_enabled(), "should have been disabled"); - - // JVMTI object tagging is based on JNI weak refs. If any of these - // refs were cleared then JVMTI needs to update its maps and - // maybe post ObjectFrees to agents. - JvmtiExport::cms_ref_processing_epilogue(); } #ifndef PRODUCT @@ -6305,6 +6301,7 @@ void CMSCollector::do_CMS_operation(CMS_op_type op) { switch (op) { case CMS_op_checkpointRootsInitial: { + SvcGCMarker sgcm(SvcGCMarker::OTHER); checkpointRootsInitial(true); // asynch if (PrintGC) { _cmsGen->printOccupancy("initial-mark"); @@ -6312,6 +6309,7 @@ void CMSCollector::do_CMS_operation(CMS_op_type op) { break; } case CMS_op_checkpointRootsFinal: { + SvcGCMarker sgcm(SvcGCMarker::OTHER); checkpointRootsFinal(true, // asynch false, // !clear_all_soft_refs false); // !init_mark_was_synchronous diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index d1989d4a24e..994cc683ace 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -31,6 +31,7 @@ #include "gc_implementation/g1/g1RemSet.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" #include "gc_implementation/g1/heapRegionSeq.inline.hpp" +#include "gc_implementation/shared/vmGCOperations.hpp" #include "memory/genOopClosures.inline.hpp" #include "memory/referencePolicy.hpp" #include "memory/resourceArea.hpp" @@ -1142,6 +1143,8 @@ void ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { return; } + SvcGCMarker sgcm(SvcGCMarker::OTHER); + if (VerifyDuringGC) { HandleMark hm; // handle scope gclog_or_tty->print(" VerifyDuringGC:(before)"); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 030aecade77..7bc64ce3a25 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1192,7 +1192,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, return false; } - DTraceGCProbeMarker gc_probe_marker(true /* full */); + SvcGCMarker sgcm(SvcGCMarker::FULL); ResourceMark rm; if (PrintHeapAtGC) { @@ -3214,7 +3214,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { return false; } - DTraceGCProbeMarker gc_probe_marker(false /* full */); + SvcGCMarker sgcm(SvcGCMarker::MINOR); ResourceMark rm; if (PrintHeapAtGC) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp index 1ceeead58ff..aaf44b02d3f 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp @@ -38,7 +38,6 @@ VM_G1CollectForAllocation::VM_G1CollectForAllocation( } void VM_G1CollectForAllocation::doit() { - JvmtiGCForAllocationMarker jgcm; G1CollectedHeap* g1h = G1CollectedHeap::heap(); _result = g1h->satisfy_failed_allocation(_word_size, &_pause_succeeded); assert(_result == NULL || _pause_succeeded, @@ -46,7 +45,6 @@ void VM_G1CollectForAllocation::doit() { } void VM_G1CollectFull::doit() { - JvmtiGCFullMarker jgcm; G1CollectedHeap* g1h = G1CollectedHeap::heap(); GCCauseSetter x(g1h, _gc_cause); g1h->do_full_collection(false /* clear_all_soft_refs */); @@ -72,7 +70,6 @@ VM_G1IncCollectionPause::VM_G1IncCollectionPause( } void VM_G1IncCollectionPause::doit() { - JvmtiGCForAllocationMarker jgcm; G1CollectedHeap* g1h = G1CollectedHeap::heap(); assert(!_should_initiate_conc_mark || ((_gc_cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) || diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp index 453c791621b..0f122a97b57 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp @@ -42,8 +42,7 @@ VM_ParallelGCFailedAllocation::VM_ParallelGCFailedAllocation(size_t size, } void VM_ParallelGCFailedAllocation::doit() { - JvmtiGCForAllocationMarker jgcm; - notify_gc_begin(false); + SvcGCMarker sgcm(SvcGCMarker::MINOR); ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "must be a ParallelScavengeHeap"); @@ -54,8 +53,6 @@ void VM_ParallelGCFailedAllocation::doit() { if (_result == NULL && GC_locker::is_active_and_needs_gc()) { set_gc_locked(); } - - notify_gc_end(); } VM_ParallelGCFailedPermanentAllocation::VM_ParallelGCFailedPermanentAllocation(size_t size, @@ -67,8 +64,7 @@ VM_ParallelGCFailedPermanentAllocation::VM_ParallelGCFailedPermanentAllocation(s } void VM_ParallelGCFailedPermanentAllocation::doit() { - JvmtiGCFullMarker jgcm; - notify_gc_begin(true); + SvcGCMarker sgcm(SvcGCMarker::FULL); ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "must be a ParallelScavengeHeap"); @@ -78,7 +74,6 @@ void VM_ParallelGCFailedPermanentAllocation::doit() { if (_result == NULL && GC_locker::is_active_and_needs_gc()) { set_gc_locked(); } - notify_gc_end(); } // Only used for System.gc() calls @@ -91,8 +86,7 @@ VM_ParallelGCSystemGC::VM_ParallelGCSystemGC(unsigned int gc_count, } void VM_ParallelGCSystemGC::doit() { - JvmtiGCFullMarker jgcm; - notify_gc_begin(true); + SvcGCMarker sgcm(SvcGCMarker::FULL); ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap(); assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, @@ -106,5 +100,4 @@ void VM_ParallelGCSystemGC::doit() { } else { heap->invoke_full_gc(false); } - notify_gc_end(); } diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp index 350d6dbacb6..5799550d114 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp @@ -31,7 +31,6 @@ #include "memory/oopFactory.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceRefKlass.hpp" -#include "prims/jvmtiExport.hpp" #include "runtime/handles.inline.hpp" #include "runtime/init.hpp" #include "runtime/interfaceSupport.hpp" @@ -40,6 +39,7 @@ #ifndef SERIALGC #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #endif + HS_DTRACE_PROBE_DECL1(hotspot, gc__begin, bool); HS_DTRACE_PROBE_DECL(hotspot, gc__end); @@ -158,8 +158,7 @@ void VM_GC_HeapInspection::doit() { void VM_GenCollectForAllocation::doit() { - JvmtiGCForAllocationMarker jgcm; - notify_gc_begin(false); + SvcGCMarker sgcm(SvcGCMarker::MINOR); GenCollectedHeap* gch = GenCollectedHeap::heap(); GCCauseSetter gccs(gch, _gc_cause); @@ -169,22 +168,19 @@ void VM_GenCollectForAllocation::doit() { if (_res == NULL && GC_locker::is_active_and_needs_gc()) { set_gc_locked(); } - notify_gc_end(); } void VM_GenCollectFull::doit() { - JvmtiGCFullMarker jgcm; - notify_gc_begin(true); + SvcGCMarker sgcm(SvcGCMarker::FULL); GenCollectedHeap* gch = GenCollectedHeap::heap(); GCCauseSetter gccs(gch, _gc_cause); gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level); - notify_gc_end(); } void VM_GenCollectForPermanentAllocation::doit() { - JvmtiGCForAllocationMarker jgcm; - notify_gc_begin(true); + SvcGCMarker sgcm(SvcGCMarker::FULL); + SharedHeap* heap = (SharedHeap*)Universe::heap(); GCCauseSetter gccs(heap, _gc_cause); switch (heap->kind()) { @@ -209,5 +205,4 @@ void VM_GenCollectForPermanentAllocation::doit() { if (_res == NULL && GC_locker::is_active_and_needs_gc()) { set_gc_locked(); } - notify_gc_end(); } diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp index c7ee95f445b..1a828facadc 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp @@ -30,6 +30,7 @@ #include "runtime/jniHandles.hpp" #include "runtime/synchronizer.hpp" #include "runtime/vm_operations.hpp" +#include "prims/jvmtiExport.hpp" // The following class hierarchy represents // a set of operations (VM_Operation) related to GC. @@ -209,13 +210,17 @@ class VM_GenCollectForPermanentAllocation: public VM_GC_Operation { HeapWord* result() const { return _res; } }; -class DTraceGCProbeMarker : public StackObj { -public: - DTraceGCProbeMarker(bool full) { - VM_GC_Operation::notify_gc_begin(full); +class SvcGCMarker : public StackObj { + private: + JvmtiGCMarker _jgcm; + public: + typedef enum { MINOR, FULL, OTHER } reason_type; + + SvcGCMarker(reason_type reason ) { + VM_GC_Operation::notify_gc_begin(reason == FULL); } - ~DTraceGCProbeMarker() { + ~SvcGCMarker() { VM_GC_Operation::notify_gc_end(); } }; diff --git a/hotspot/src/share/vm/prims/jvmti.xml b/hotspot/src/share/vm/prims/jvmti.xml index 9e24fb64b1c..0d845050ac9 100644 --- a/hotspot/src/share/vm/prims/jvmti.xml +++ b/hotspot/src/share/vm/prims/jvmti.xml @@ -13048,8 +13048,8 @@ myInit() { - A Garbage Collection Start event is sent when a full cycle - garbage collection begins. + A Garbage Collection Start event is sent when a + garbage collection pause begins. Only stop-the-world collections are reported--that is, collections during which all threads cease to modify the state of the Java virtual machine. This means that some collectors will never generate these events. @@ -13075,8 +13075,8 @@ myInit() { - A Garbage Collection Finish event is sent when a full - garbage collection cycle ends. + A Garbage Collection Finish event is sent when a + garbage collection pause ends. This event is sent while the VM is still stopped, thus the event handler must not use JNI functions and must not use functions except those which diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index ab5ced93ba4..6e87bbc8c90 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -2358,15 +2358,6 @@ jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { } #endif // SERVICES_KERNEL -// CMS has completed referencing processing so may need to update -// tag maps. -void JvmtiExport::cms_ref_processing_epilogue() { - if (JvmtiEnv::environments_might_exist()) { - JvmtiTagMap::cms_ref_processing_epilogue(); - } -} - - //////////////////////////////////////////////////////////////////////////////////////////////// // Setup current current thread for event collection. @@ -2536,36 +2527,20 @@ NoJvmtiVMObjectAllocMark::~NoJvmtiVMObjectAllocMark() { } }; -JvmtiGCMarker::JvmtiGCMarker(bool full) : _full(full), _invocation_count(0) { - assert(Thread::current()->is_VM_thread(), "wrong thread"); - +JvmtiGCMarker::JvmtiGCMarker() { // if there aren't any JVMTI environments then nothing to do if (!JvmtiEnv::environments_might_exist()) { return; } - if (ForceFullGCJVMTIEpilogues) { - // force 'Full GC' was done semantics for JVMTI GC epilogues - _full = true; - } - - // GarbageCollectionStart event posted from VM thread - okay because - // JVMTI is clear that the "world is stopped" and callback shouldn't - // try to call into the VM. if (JvmtiExport::should_post_garbage_collection_start()) { JvmtiExport::post_garbage_collection_start(); } - // if "full" is false it probably means this is a scavenge of the young - // generation. However it could turn out that a "full" GC is required - // so we record the number of collections so that it can be checked in - // the destructor. - if (!_full) { - _invocation_count = Universe::heap()->total_full_collections(); + if (SafepointSynchronize::is_at_safepoint()) { + // Do clean up tasks that need to be done at a safepoint + JvmtiEnvBase::check_for_periodic_clean_up(); } - - // Do clean up tasks that need to be done at a safepoint - JvmtiEnvBase::check_for_periodic_clean_up(); } JvmtiGCMarker::~JvmtiGCMarker() { @@ -2578,21 +2553,5 @@ JvmtiGCMarker::~JvmtiGCMarker() { if (JvmtiExport::should_post_garbage_collection_finish()) { JvmtiExport::post_garbage_collection_finish(); } - - // we might have initially started out doing a scavenge of the young - // generation but could have ended up doing a "full" GC - check the - // GC count to see. - if (!_full) { - _full = (_invocation_count != Universe::heap()->total_full_collections()); - } - - // Full collection probably means the perm generation has been GC'ed - // so we clear the breakpoint cache. - if (_full) { - JvmtiCurrentBreakpoints::gc_epilogue(); - } - - // Notify heap/object tagging support - JvmtiTagMap::gc_epilogue(_full); } #endif // JVMTI_KERNEL diff --git a/hotspot/src/share/vm/prims/jvmtiExport.hpp b/hotspot/src/share/vm/prims/jvmtiExport.hpp index 88a23383116..b46c9c12622 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.hpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp @@ -356,9 +356,6 @@ class JvmtiExport : public AllStatic { // SetNativeMethodPrefix support static char** get_all_native_method_prefixes(int* count_ptr); - - // call after CMS has completed referencing processing - static void cms_ref_processing_epilogue() KERNEL_RETURN; }; // Support class used by JvmtiDynamicCodeEventCollector and others. It @@ -492,55 +489,11 @@ class NoJvmtiVMObjectAllocMark : public StackObj { // Base class for reporting GC events to JVMTI. class JvmtiGCMarker : public StackObj { - private: - bool _full; // marks a "full" GC - unsigned int _invocation_count; // GC invocation count - protected: - JvmtiGCMarker(bool full) KERNEL_RETURN; // protected - ~JvmtiGCMarker() KERNEL_RETURN; // protected -}; - - -// Support class used to report GC events to JVMTI. The class is stack -// allocated and should be placed in the doit() implementation of all -// vm operations that do a stop-the-world GC for failed allocation. -// -// Usage :- -// -// void VM_GenCollectForAllocation::doit() { -// JvmtiGCForAllocationMarker jgcm; -// : -// } -// -// If jvmti is not enabled the constructor and destructor is essentially -// a no-op (no overhead). -// -class JvmtiGCForAllocationMarker : public JvmtiGCMarker { public: - JvmtiGCForAllocationMarker() : JvmtiGCMarker(false) { - } + JvmtiGCMarker() KERNEL_RETURN; + ~JvmtiGCMarker() KERNEL_RETURN; }; -// Support class used to report GC events to JVMTI. The class is stack -// allocated and should be placed in the doit() implementation of all -// vm operations that do a "full" stop-the-world GC. This class differs -// from JvmtiGCForAllocationMarker in that this class assumes that a -// "full" GC will happen. -// -// Usage :- -// -// void VM_GenCollectFull::doit() { -// JvmtiGCFullMarker jgcm; -// : -// } -// -class JvmtiGCFullMarker : public JvmtiGCMarker { - public: - JvmtiGCFullMarker() : JvmtiGCMarker(true) { - } -}; - - // JvmtiHideSingleStepping is a helper class for hiding // internal single step events. class JvmtiHideSingleStepping : public StackObj { diff --git a/hotspot/src/share/vm/prims/jvmtiImpl.cpp b/hotspot/src/share/vm/prims/jvmtiImpl.cpp index 90864b68abe..2e6a7df0f65 100644 --- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp +++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp @@ -212,14 +212,7 @@ void GrowableCache::oops_do(OopClosure* f) { for (int i=0; iat(i); e->oops_do(f); - } -} - -void GrowableCache::gc_epilogue() { - int len = _elements->length(); - // recompute the new cache value after GC - for (int i=0; iat(i)->getCacheValue(); + _cache[i] = e->getCacheValue(); } } @@ -401,10 +394,6 @@ void JvmtiBreakpoints::oops_do(OopClosure* f) { _bps.oops_do(f); } -void JvmtiBreakpoints::gc_epilogue() { - _bps.gc_epilogue(); -} - void JvmtiBreakpoints::print() { #ifndef PRODUCT ResourceMark rm; @@ -534,13 +523,6 @@ void JvmtiCurrentBreakpoints::oops_do(OopClosure* f) { } } -void JvmtiCurrentBreakpoints::gc_epilogue() { - if (_jvmti_breakpoints != NULL) { - _jvmti_breakpoints->gc_epilogue(); - } -} - - /////////////////////////////////////////////////////////////// // // class VM_GetOrSetLocal diff --git a/hotspot/src/share/vm/prims/jvmtiImpl.hpp b/hotspot/src/share/vm/prims/jvmtiImpl.hpp index df28abf7d72..023fe93874d 100644 --- a/hotspot/src/share/vm/prims/jvmtiImpl.hpp +++ b/hotspot/src/share/vm/prims/jvmtiImpl.hpp @@ -117,7 +117,6 @@ public: void clear(); // apply f to every element and update the cache void oops_do(OopClosure* f); - void gc_epilogue(); }; @@ -149,7 +148,6 @@ public: void remove (int index) { _cache.remove(index); } void clear() { _cache.clear(); } void oops_do(OopClosure* f) { _cache.oops_do(f); } - void gc_epilogue() { _cache.gc_epilogue(); } }; @@ -278,7 +276,6 @@ public: int length(); void oops_do(OopClosure* f); - void gc_epilogue(); void print(); int set(JvmtiBreakpoint& bp); @@ -328,7 +325,6 @@ public: static inline bool is_breakpoint(address bcp); static void oops_do(OopClosure* f); - static void gc_epilogue(); }; // quickly test whether the bcp matches a cached breakpoint in the list diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp index 085952af565..bb556ca4886 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp @@ -50,7 +50,7 @@ // JvmtiTagHashmapEntry // -// Each entry encapsulates a JNI weak reference to the tagged object +// Each entry encapsulates a reference to the tagged object // and the tag value. In addition an entry includes a next pointer which // is used to chain entries together. @@ -58,24 +58,25 @@ class JvmtiTagHashmapEntry : public CHeapObj { private: friend class JvmtiTagMap; - jweak _object; // JNI weak ref to tagged object + oop _object; // tagged object jlong _tag; // the tag JvmtiTagHashmapEntry* _next; // next on the list - inline void init(jweak object, jlong tag) { + inline void init(oop object, jlong tag) { _object = object; _tag = tag; _next = NULL; } // constructor - JvmtiTagHashmapEntry(jweak object, jlong tag) { init(object, tag); } + JvmtiTagHashmapEntry(oop object, jlong tag) { init(object, tag); } public: // accessor methods - inline jweak object() const { return _object; } - inline jlong tag() const { return _tag; } + inline oop object() const { return _object; } + inline oop* object_addr() { return &_object; } + inline jlong tag() const { return _tag; } inline void set_tag(jlong tag) { assert(tag != 0, "can't be zero"); @@ -92,9 +93,7 @@ class JvmtiTagHashmapEntry : public CHeapObj { // A hashmap is essentially a table of pointers to entries. Entries // are hashed to a location, or position in the table, and then // chained from that location. The "key" for hashing is address of -// the object, or oop. The "value" is the JNI weak reference to the -// object and the tag value. Keys are not stored with the entry. -// Instead the weak reference is resolved to obtain the key. +// the object, or oop. The "value" is the tag value. // // A hashmap maintains a count of the number entries in the hashmap // and resizes if the number of entries exceeds a given threshold. @@ -206,7 +205,7 @@ class JvmtiTagHashmap : public CHeapObj { JvmtiTagHashmapEntry* entry = _table[i]; while (entry != NULL) { JvmtiTagHashmapEntry* next = entry->next(); - oop key = JNIHandles::resolve(entry->object()); + oop key = entry->object(); assert(key != NULL, "jni weak reference cleared!!"); unsigned int h = hash(key, new_size); JvmtiTagHashmapEntry* anchor = new_table[h]; @@ -299,14 +298,12 @@ class JvmtiTagHashmap : public CHeapObj { unsigned int h = hash(key); JvmtiTagHashmapEntry* entry = _table[h]; while (entry != NULL) { - oop orig_key = JNIHandles::resolve(entry->object()); - assert(orig_key != NULL, "jni weak reference cleared!!"); - if (key == orig_key) { - break; + if (entry->object() == key) { + return entry; } entry = entry->next(); } - return entry; + return NULL; } @@ -343,9 +340,7 @@ class JvmtiTagHashmap : public CHeapObj { JvmtiTagHashmapEntry* entry = _table[h]; JvmtiTagHashmapEntry* prev = NULL; while (entry != NULL) { - oop orig_key = JNIHandles::resolve(entry->object()); - assert(orig_key != NULL, "jni weak reference cleared!!"); - if (key == orig_key) { + if (key == entry->object()) { break; } prev = entry; @@ -418,54 +413,6 @@ void JvmtiTagHashmap::compute_next_trace_threshold() { } } -// memory region for young generation -MemRegion JvmtiTagMap::_young_gen; - -// get the memory region used for the young generation -void JvmtiTagMap::get_young_generation() { - CollectedHeap* ch = Universe::heap(); - switch (ch->kind()) { - case (CollectedHeap::GenCollectedHeap): { - _young_gen = ((GenCollectedHeap*)ch)->get_gen(0)->reserved(); - break; - } -#ifndef SERIALGC - case (CollectedHeap::ParallelScavengeHeap): { - _young_gen = ((ParallelScavengeHeap*)ch)->young_gen()->reserved(); - break; - } - case (CollectedHeap::G1CollectedHeap): { - // Until a more satisfactory solution is implemented, all - // oops in the tag map will require rehash at each gc. - // This is a correct, if extremely inefficient solution. - // See RFE 6621729 for related commentary. - _young_gen = ch->reserved_region(); - break; - } -#endif // !SERIALGC - default: - ShouldNotReachHere(); - } -} - -// returns true if oop is in the young generation -inline bool JvmtiTagMap::is_in_young(oop o) { - assert(_young_gen.start() != NULL, "checking"); - void* p = (void*)o; - bool in_young = _young_gen.contains(p); - return in_young; -} - -// returns the appropriate hashmap for a given object -inline JvmtiTagHashmap* JvmtiTagMap::hashmap_for(oop o) { - if (is_in_young(o)) { - return _hashmap[0]; - } else { - return _hashmap[1]; - } -} - - // create a JvmtiTagMap JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) : _env(env), @@ -476,13 +423,7 @@ JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) : assert(JvmtiThreadState_lock->is_locked(), "sanity check"); assert(((JvmtiEnvBase *)env)->tag_map() == NULL, "tag map already exists for environment"); - // create the hashmaps - for (int i=0; iset_tag_map(this); @@ -496,25 +437,20 @@ JvmtiTagMap::~JvmtiTagMap() { // also being destroryed. ((JvmtiEnvBase *)_env)->set_tag_map(NULL); - // iterate over the hashmaps and destroy each of the entries - for (int i=0; itable(); - for (int j=0; jsize(); j++) { - JvmtiTagHashmapEntry *entry = table[j]; - while (entry != NULL) { - JvmtiTagHashmapEntry* next = entry->next(); - jweak ref = entry->object(); - JNIHandles::destroy_weak_global(ref); - delete entry; - entry = next; - } + JvmtiTagHashmapEntry** table = _hashmap->table(); + for (int j = 0; j < _hashmap->size(); j++) { + JvmtiTagHashmapEntry* entry = table[j]; + while (entry != NULL) { + JvmtiTagHashmapEntry* next = entry->next(); + delete entry; + entry = next; } - - // finally destroy the hashmap - delete hashmap; } + // finally destroy the hashmap + delete _hashmap; + _hashmap = NULL; + // remove any entries on the free list JvmtiTagHashmapEntry* entry = _free_entries; while (entry != NULL) { @@ -522,12 +458,13 @@ JvmtiTagMap::~JvmtiTagMap() { delete entry; entry = next; } + _free_entries = NULL; } // create a hashmap entry // - if there's an entry on the (per-environment) free list then this // is returned. Otherwise an new entry is allocated. -JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(jweak ref, jlong tag) { +JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(oop ref, jlong tag) { assert(Thread::current()->is_VM_thread() || is_locked(), "checking"); JvmtiTagHashmapEntry* entry; if (_free_entries == NULL) { @@ -558,10 +495,10 @@ void JvmtiTagMap::destroy_entry(JvmtiTagHashmapEntry* entry) { // returns the tag map for the given environments. If the tag map // doesn't exist then it is created. JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) { - JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map(); + JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->tag_map(); if (tag_map == NULL) { MutexLocker mu(JvmtiThreadState_lock); - tag_map = ((JvmtiEnvBase *)env)->tag_map(); + tag_map = ((JvmtiEnvBase*)env)->tag_map(); if (tag_map == NULL) { tag_map = new JvmtiTagMap(env); } @@ -573,17 +510,13 @@ JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) { // iterate over all entries in the tag map. void JvmtiTagMap::entry_iterate(JvmtiTagHashmapEntryClosure* closure) { - for (int i=0; ientry_iterate(closure); - } + hashmap()->entry_iterate(closure); } // returns true if the hashmaps are empty bool JvmtiTagMap::is_empty() { assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking"); - assert(n_hashmaps == 2, "not implemented"); - return ((_hashmap[0]->entry_count() == 0) && (_hashmap[1]->entry_count() == 0)); + return hashmap()->entry_count() == 0; } @@ -591,7 +524,7 @@ bool JvmtiTagMap::is_empty() { // not tagged // static inline jlong tag_for(JvmtiTagMap* tag_map, oop o) { - JvmtiTagHashmapEntry* entry = tag_map->hashmap_for(o)->find(o); + JvmtiTagHashmapEntry* entry = tag_map->hashmap()->find(o); if (entry == NULL) { return 0; } else { @@ -655,7 +588,7 @@ class CallbackWrapper : public StackObj { // record the context _tag_map = tag_map; - _hashmap = tag_map->hashmap_for(_o); + _hashmap = tag_map->hashmap(); _entry = _hashmap->find(_o); // get object tag @@ -694,23 +627,18 @@ void inline CallbackWrapper::post_callback_tag_update(oop o, if (obj_tag != 0) { // callback has tagged the object assert(Thread::current()->is_VM_thread(), "must be VMThread"); - HandleMark hm; - Handle h(o); - jweak ref = JNIHandles::make_weak_global(h); - entry = tag_map()->create_entry(ref, obj_tag); + entry = tag_map()->create_entry(o, obj_tag); hashmap->add(o, entry); } } else { // object was previously tagged - the callback may have untagged // the object or changed the tag value if (obj_tag == 0) { - jweak ref = entry->object(); JvmtiTagHashmapEntry* entry_removed = hashmap->remove(o); assert(entry_removed == entry, "checking"); tag_map()->destroy_entry(entry); - JNIHandles::destroy_weak_global(ref); } else { if (obj_tag != entry->tag()) { entry->set_tag(obj_tag); @@ -760,7 +688,7 @@ class TwoOopCallbackWrapper : public CallbackWrapper { // for Classes the klassOop is tagged _referrer = klassOop_if_java_lang_Class(referrer); // record the context - _referrer_hashmap = tag_map->hashmap_for(_referrer); + _referrer_hashmap = tag_map->hashmap(); _referrer_entry = _referrer_hashmap->find(_referrer); // get object tag @@ -796,8 +724,7 @@ class TwoOopCallbackWrapper : public CallbackWrapper { // // This function is performance critical. If many threads attempt to tag objects // around the same time then it's possible that the Mutex associated with the -// tag map will be a hot lock. Eliminating this lock will not eliminate the issue -// because creating a JNI weak reference requires acquiring a global lock also. +// tag map will be a hot lock. void JvmtiTagMap::set_tag(jobject object, jlong tag) { MutexLocker ml(lock()); @@ -808,22 +735,14 @@ void JvmtiTagMap::set_tag(jobject object, jlong tag) { o = klassOop_if_java_lang_Class(o); // see if the object is already tagged - JvmtiTagHashmap* hashmap = hashmap_for(o); + JvmtiTagHashmap* hashmap = _hashmap; JvmtiTagHashmapEntry* entry = hashmap->find(o); // if the object is not already tagged then we tag it if (entry == NULL) { if (tag != 0) { - HandleMark hm; - Handle h(o); - jweak ref = JNIHandles::make_weak_global(h); - - // the object may have moved because make_weak_global may - // have blocked - thus it is necessary resolve the handle - // and re-hash the object. - o = h(); - entry = create_entry(ref, tag); - hashmap_for(o)->add(o, entry); + entry = create_entry(o, tag); + hashmap->add(o, entry); } else { // no-op } @@ -831,13 +750,9 @@ void JvmtiTagMap::set_tag(jobject object, jlong tag) { // if the object is already tagged then we either update // the tag (if a new tag value has been provided) // or remove the object if the new tag value is 0. - // Removing the object requires that we also delete the JNI - // weak ref to the object. if (tag == 0) { - jweak ref = entry->object(); hashmap->remove(o); destroy_entry(entry); - JNIHandles::destroy_weak_global(ref); } else { entry->set_tag(tag); } @@ -1626,8 +1541,8 @@ class TagObjectCollector : public JvmtiTagHashmapEntryClosure { void do_entry(JvmtiTagHashmapEntry* entry) { for (int i=0; i<_tag_count; i++) { if (_tags[i] == entry->tag()) { - oop o = JNIHandles::resolve(entry->object()); - assert(o != NULL && o != JNIHandles::deleted_handle(), "sanity check"); + oop o = entry->object(); + assert(o != NULL, "sanity check"); // the mirror is tagged if (o->is_klass()) { @@ -3374,62 +3289,21 @@ void JvmtiTagMap::follow_references(jint heap_filter, } -// called post-GC -// - for each JVMTI environment with an object tag map, call its rehash -// function to re-sync with the new object locations. -void JvmtiTagMap::gc_epilogue(bool full) { - assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint"); +void JvmtiTagMap::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) { + assert(SafepointSynchronize::is_at_safepoint(), + "must be executed at a safepoint"); if (JvmtiEnv::environments_might_exist()) { - // re-obtain the memory region for the young generation (might - // changed due to adaptive resizing policy) - get_young_generation(); - JvmtiEnvIterator it; for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) { JvmtiTagMap* tag_map = env->tag_map(); if (tag_map != NULL && !tag_map->is_empty()) { - TraceTime t(full ? "JVMTI Full Rehash " : "JVMTI Rehash ", TraceJVMTIObjectTagging); - if (full) { - tag_map->rehash(0, n_hashmaps); - } else { - tag_map->rehash(0, 0); // tag map for young gen only - } + tag_map->do_weak_oops(is_alive, f); } } } } -// CMS has completed referencing processing so we may have JNI weak refs -// to objects in the CMS generation that have been GC'ed. -void JvmtiTagMap::cms_ref_processing_epilogue() { - assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint"); - assert(UseConcMarkSweepGC, "should only be used with CMS"); - if (JvmtiEnv::environments_might_exist()) { - JvmtiEnvIterator it; - for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) { - JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map(); - if (tag_map != NULL && !tag_map->is_empty()) { - TraceTime t("JVMTI Rehash (CMS) ", TraceJVMTIObjectTagging); - tag_map->rehash(1, n_hashmaps); // assume CMS not used in young gen - } - } - } -} - - -// For each entry in the hashmaps 'start' to 'end' : -// -// 1. resolve the JNI weak reference -// -// 2. If it resolves to NULL it means the object has been freed so the entry -// is removed, the weak reference destroyed, and the object free event is -// posted (if enabled). -// -// 3. If the weak reference resolves to an object then we re-hash the object -// to see if it has moved or has been promoted (from the young to the old -// generation for example). -// -void JvmtiTagMap::rehash(int start, int end) { +void JvmtiTagMap::do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f) { // does this environment have the OBJECT_FREE event enabled bool post_object_free = env()->is_enabled(JVMTI_EVENT_OBJECT_FREE); @@ -3437,143 +3311,98 @@ void JvmtiTagMap::rehash(int start, int end) { // counters used for trace message int freed = 0; int moved = 0; - int promoted = 0; - // we assume there are two hashmaps - one for the young generation - // and the other for all other spaces. - assert(n_hashmaps == 2, "not implemented"); - JvmtiTagHashmap* young_hashmap = _hashmap[0]; - JvmtiTagHashmap* other_hashmap = _hashmap[1]; + JvmtiTagHashmap* hashmap = this->hashmap(); // reenable sizing (if disabled) - young_hashmap->set_resizing_enabled(true); - other_hashmap->set_resizing_enabled(true); + hashmap->set_resizing_enabled(true); - // when re-hashing the hashmap corresponding to the young generation we - // collect the entries corresponding to objects that have been promoted. - JvmtiTagHashmapEntry* promoted_entries = NULL; - - if (end >= n_hashmaps) { - end = n_hashmaps - 1; + // if the hashmap is empty then we can skip it + if (hashmap->_entry_count == 0) { + return; } - for (int i=start; i <= end; i++) { - JvmtiTagHashmap* hashmap = _hashmap[i]; + // now iterate through each entry in the table - // if the hashmap is empty then we can skip it - if (hashmap->_entry_count == 0) { - continue; - } + JvmtiTagHashmapEntry** table = hashmap->table(); + int size = hashmap->size(); - // now iterate through each entry in the table + JvmtiTagHashmapEntry* delayed_add = NULL; - JvmtiTagHashmapEntry** table = hashmap->table(); - int size = hashmap->size(); + for (int pos = 0; pos < size; ++pos) { + JvmtiTagHashmapEntry* entry = table[pos]; + JvmtiTagHashmapEntry* prev = NULL; - for (int pos=0; posnext(); - while (entry != NULL) { - JvmtiTagHashmapEntry* next = entry->next(); + oop* obj = entry->object_addr(); - jweak ref = entry->object(); - oop oop = JNIHandles::resolve(ref); + // has object been GC'ed + if (!is_alive->do_object_b(entry->object())) { + // grab the tag + jlong tag = entry->tag(); + guarantee(tag != 0, "checking"); - // has object been GC'ed - if (oop == NULL) { - // grab the tag - jlong tag = entry->tag(); - guarantee(tag != 0, "checking"); + // remove GC'ed entry from hashmap and return the + // entry to the free list + hashmap->remove(prev, pos, entry); + destroy_entry(entry); - // remove GC'ed entry from hashmap and return the - // entry to the free list - hashmap->remove(prev, pos, entry); - destroy_entry(entry); + // post the event to the profiler + if (post_object_free) { + JvmtiExport::post_object_free(env(), tag); + } - // destroy the weak ref - JNIHandles::destroy_weak_global(ref); + ++freed; + } else { + f->do_oop(entry->object_addr()); + oop new_oop = entry->object(); - // post the event to the profiler - if (post_object_free) { - JvmtiExport::post_object_free(env(), tag); + // if the object has moved then re-hash it and move its + // entry to its new location. + unsigned int new_pos = JvmtiTagHashmap::hash(new_oop, size); + if (new_pos != (unsigned int)pos) { + if (prev == NULL) { + table[pos] = next; + } else { + prev->set_next(next); } - - freed++; - entry = next; - continue; - } - - // if this is the young hashmap then the object is either promoted - // or moved. - // if this is the other hashmap then the object is moved. - - bool same_gen; - if (i == 0) { - assert(hashmap == young_hashmap, "checking"); - same_gen = is_in_young(oop); - } else { - same_gen = true; - } - - - if (same_gen) { - // if the object has moved then re-hash it and move its - // entry to its new location. - unsigned int new_pos = JvmtiTagHashmap::hash(oop, size); - if (new_pos != (unsigned int)pos) { - if (prev == NULL) { - table[pos] = next; - } else { - prev->set_next(next); - } + if (new_pos < (unsigned int)pos) { entry->set_next(table[new_pos]); table[new_pos] = entry; - moved++; } else { - // object didn't move - prev = entry; + // Delay adding this entry to it's new position as we'd end up + // hitting it again during this iteration. + entry->set_next(delayed_add); + delayed_add = entry; } + moved++; } else { - // object has been promoted so remove the entry from the - // young hashmap - assert(hashmap == young_hashmap, "checking"); - hashmap->remove(prev, pos, entry); - - // move the entry to the promoted list - entry->set_next(promoted_entries); - promoted_entries = entry; + // object didn't move + prev = entry; } - - entry = next; } + + entry = next; } } - - // add the entries, corresponding to the promoted objects, to the - // other hashmap. - JvmtiTagHashmapEntry* entry = promoted_entries; - while (entry != NULL) { - oop o = JNIHandles::resolve(entry->object()); - assert(hashmap_for(o) == other_hashmap, "checking"); - JvmtiTagHashmapEntry* next = entry->next(); - other_hashmap->add(o, entry); - entry = next; - promoted++; + // Re-add all the entries which were kept aside + while (delayed_add != NULL) { + JvmtiTagHashmapEntry* next = delayed_add->next(); + unsigned int pos = JvmtiTagHashmap::hash(delayed_add->object(), size); + delayed_add->set_next(table[pos]); + table[pos] = delayed_add; + delayed_add = next; } // stats if (TraceJVMTIObjectTagging) { - int total_moves = promoted + moved; - - int post_total = 0; - for (int i=0; i_entry_count; - } + int post_total = hashmap->_entry_count; int pre_total = post_total + freed; - tty->print("(%d->%d, %d freed, %d promoted, %d total moves)", - pre_total, post_total, freed, promoted, total_moves); + tty->print_cr("(%d->%d, %d freed, %d total moves)", + pre_total, post_total, freed, moved); } } diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.hpp b/hotspot/src/share/vm/prims/jvmtiTagMap.hpp index f94e74f71c2..9abdd9b37a1 100644 --- a/hotspot/src/share/vm/prims/jvmtiTagMap.hpp +++ b/hotspot/src/share/vm/prims/jvmtiTagMap.hpp @@ -45,17 +45,12 @@ class JvmtiTagMap : public CHeapObj { private: enum{ - n_hashmaps = 2, // encapsulates 2 hashmaps - max_free_entries = 4096 // maximum number of free entries per env + max_free_entries = 4096 // maximum number of free entries per env }; - // memory region for young generation - static MemRegion _young_gen; - static void get_young_generation(); - JvmtiEnv* _env; // the jvmti environment Mutex _lock; // lock for this tag map - JvmtiTagHashmap* _hashmap[n_hashmaps]; // the hashmaps + JvmtiTagHashmap* _hashmap; // the hashmap JvmtiTagHashmapEntry* _free_entries; // free list for this environment int _free_entries_count; // number of entries on the free list @@ -67,11 +62,7 @@ class JvmtiTagMap : public CHeapObj { inline Mutex* lock() { return &_lock; } inline JvmtiEnv* env() const { return _env; } - // rehash tags maps for generation start to end - void rehash(int start, int end); - - // indicates if the object is in the young generation - static bool is_in_young(oop o); + void do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f); // iterate over all entries in this tag map void entry_iterate(JvmtiTagHashmapEntryClosure* closure); @@ -81,11 +72,10 @@ class JvmtiTagMap : public CHeapObj { // indicates if this tag map is locked bool is_locked() { return lock()->is_locked(); } - // return the appropriate hashmap for a given object - JvmtiTagHashmap* hashmap_for(oop o); + JvmtiTagHashmap* hashmap() { return _hashmap; } // create/destroy entries - JvmtiTagHashmapEntry* create_entry(jweak ref, jlong tag); + JvmtiTagHashmapEntry* create_entry(oop ref, jlong tag); void destroy_entry(JvmtiTagHashmapEntry* entry); // returns true if the hashmaps are empty @@ -134,11 +124,8 @@ class JvmtiTagMap : public CHeapObj { jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr); - // call post-GC to rehash the tag maps. - static void gc_epilogue(bool full); - - // call after referencing processing has completed (CMS) - static void cms_ref_processing_epilogue(); + static void weak_oops_do( + BoolObjectClosure* is_alive, OopClosure* f) KERNEL_RETURN; }; #endif // SHARE_VM_PRIMS_JVMTITAGMAP_HPP diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 07bda32a07f..7024dacb9bc 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1198,9 +1198,6 @@ class CommandLineFlags { product(ccstr, TraceJVMTI, NULL, \ "Trace flags for JVMTI functions and events") \ \ - product(bool, ForceFullGCJVMTIEpilogues, false, \ - "Force 'Full GC' was done semantics for JVMTI GC epilogues") \ - \ /* This option can change an EMCP method into an obsolete method. */ \ /* This can affect tests that except specific methods to be EMCP. */ \ /* This option should be used with caution. */ \ diff --git a/hotspot/src/share/vm/runtime/jniHandles.cpp b/hotspot/src/share/vm/runtime/jniHandles.cpp index 357061f3ea0..40f82864423 100644 --- a/hotspot/src/share/vm/runtime/jniHandles.cpp +++ b/hotspot/src/share/vm/runtime/jniHandles.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" #include "oops/oop.inline.hpp" +#include "prims/jvmtiTagMap.hpp" #include "runtime/jniHandles.hpp" #include "runtime/mutexLocker.hpp" #ifdef TARGET_OS_FAMILY_linux @@ -428,6 +429,12 @@ void JNIHandleBlock::weak_oops_do(BoolObjectClosure* is_alive, break; } } + + /* + * JvmtiTagMap may also contain weak oops. The iteration of it is placed + * here so that we don't need to add it to each of the collectors. + */ + JvmtiTagMap::weak_oops_do(is_alive, f); } From 43e78a8d44fe9f6061231c5fffc8087e0920e235 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 10 Jan 2011 14:57:59 -0800 Subject: [PATCH 020/152] 6992999: fully remove JSR 308 from langtools Reviewed-by: mcimadamore --- .../com/sun/source/tree/MethodTree.java | 3 +- .../classes/com/sun/source/tree/Tree.java | 4 +- .../com/sun/source/tree/TreeVisitor.java | 3 +- .../sun/source/tree/TypeParameterTree.java | 3 +- .../sun/source/util/SimpleTreeVisitor.java | 6 +- .../com/sun/source/util/TreeScanner.java | 10 +- .../com/sun/tools/classfile/Attribute.java | 8 +- .../com/sun/tools/classfile/ClassWriter.java | 113 +--- .../tools/classfile/ExtendedAnnotation.java | 612 ------------------ ...imeInvisibleTypeAnnotations_attribute.java | 56 -- .../RuntimeTypeAnnotations_attribute.java | 61 -- ...ntimeVisibleTypeAnnotations_attribute.java | 56 -- .../com/sun/tools/javac/code/Attribute.java | 17 +- .../com/sun/tools/javac/code/Symbol.java | 14 +- .../sun/tools/javac/code/TypeAnnotations.java | 403 ------------ .../com/sun/tools/javac/comp/Attr.java | 38 +- .../com/sun/tools/javac/comp/Check.java | 43 +- .../com/sun/tools/javac/comp/Flow.java | 26 +- .../com/sun/tools/javac/comp/Lower.java | 7 +- .../com/sun/tools/javac/comp/MemberEnter.java | 86 +-- .../com/sun/tools/javac/comp/TransTypes.java | 6 +- .../com/sun/tools/javac/jvm/ClassReader.java | 186 +----- .../com/sun/tools/javac/jvm/ClassWriter.java | 147 +---- .../classes/com/sun/tools/javac/jvm/Code.java | 19 +- .../classes/com/sun/tools/javac/jvm/Gen.java | 51 +- .../JavacProcessingEnvironment.java | 4 +- .../tools/javac/resources/compiler.properties | 4 +- .../com/sun/tools/javac/tree/JCTree.java | 63 +- .../com/sun/tools/javac/tree/Pretty.java | 47 +- .../com/sun/tools/javac/tree/TreeCopier.java | 15 +- .../com/sun/tools/javac/tree/TreeInfo.java | 14 +- .../com/sun/tools/javac/tree/TreeMaker.java | 37 +- .../com/sun/tools/javac/tree/TreeScanner.java | 12 +- .../sun/tools/javac/tree/TreeTranslator.java | 14 +- .../com/sun/tools/javap/AnnotationWriter.java | 126 +--- .../com/sun/tools/javap/AttributeWriter.java | 28 +- .../com/sun/tools/javap/CodeWriter.java | 9 +- .../tools/javap/InstructionDetailWriter.java | 6 +- .../sun/tools/javap/TypeAnnotationWriter.java | 126 ---- .../tools/javac/diags/examples.not-yet.txt | 1 - 40 files changed, 44 insertions(+), 2440 deletions(-) delete mode 100644 langtools/src/share/classes/com/sun/tools/classfile/ExtendedAnnotation.java delete mode 100644 langtools/src/share/classes/com/sun/tools/classfile/RuntimeInvisibleTypeAnnotations_attribute.java delete mode 100644 langtools/src/share/classes/com/sun/tools/classfile/RuntimeTypeAnnotations_attribute.java delete mode 100644 langtools/src/share/classes/com/sun/tools/classfile/RuntimeVisibleTypeAnnotations_attribute.java delete mode 100644 langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java delete mode 100644 langtools/src/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java diff --git a/langtools/src/share/classes/com/sun/source/tree/MethodTree.java b/langtools/src/share/classes/com/sun/source/tree/MethodTree.java index 71eedc996bd..074c8c08329 100644 --- a/langtools/src/share/classes/com/sun/source/tree/MethodTree.java +++ b/langtools/src/share/classes/com/sun/source/tree/MethodTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, 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 @@ -53,7 +53,6 @@ public interface MethodTree extends Tree { Tree getReturnType(); List getTypeParameters(); List getParameters(); -//308 List getReceiverAnnotations(); List getThrows(); BlockTree getBody(); Tree getDefaultValue(); // for annotation types diff --git a/langtools/src/share/classes/com/sun/source/tree/Tree.java b/langtools/src/share/classes/com/sun/source/tree/Tree.java index 28e7ba8ac85..c271a0ca069 100644 --- a/langtools/src/share/classes/com/sun/source/tree/Tree.java +++ b/langtools/src/share/classes/com/sun/source/tree/Tree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, 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 @@ -46,8 +46,6 @@ public interface Tree { */ public enum Kind { -//308 ANNOTATED_TYPE(AnnotatedTypeTree.class), - /** * Used for instances of {@link AnnotationTree}. */ diff --git a/langtools/src/share/classes/com/sun/source/tree/TreeVisitor.java b/langtools/src/share/classes/com/sun/source/tree/TreeVisitor.java index 0f4e9259f00..ccdee51ca32 100644 --- a/langtools/src/share/classes/com/sun/source/tree/TreeVisitor.java +++ b/langtools/src/share/classes/com/sun/source/tree/TreeVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, 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 @@ -57,7 +57,6 @@ package com.sun.source.tree; * @since 1.6 */ public interface TreeVisitor { -//308 R visitAnnotatedType(AnnotatedTypeTree node, P p); R visitAnnotation(AnnotationTree node, P p); R visitMethodInvocation(MethodInvocationTree node, P p); R visitAssert(AssertTree node, P p); diff --git a/langtools/src/share/classes/com/sun/source/tree/TypeParameterTree.java b/langtools/src/share/classes/com/sun/source/tree/TypeParameterTree.java index 36d970e8c1e..66e8757e182 100644 --- a/langtools/src/share/classes/com/sun/source/tree/TypeParameterTree.java +++ b/langtools/src/share/classes/com/sun/source/tree/TypeParameterTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, 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 @@ -47,5 +47,4 @@ import javax.lang.model.element.Name; public interface TypeParameterTree extends Tree { Name getName(); List getBounds(); -//308 List getAnnotations(); } diff --git a/langtools/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java b/langtools/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java index f3c59fdfd91..9ff7be8ec85 100644 --- a/langtools/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java +++ b/langtools/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, 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 @@ -248,10 +248,6 @@ public class SimpleTreeVisitor implements TreeVisitor { return defaultAction(node, p); } -//308 public R visitAnnotatedType(AnnotatedTypeTree node, P p) { -//308 return defaultAction(node, p); -//308 } - public R visitErroneous(ErroneousTree node, P p) { return defaultAction(node, p); } diff --git a/langtools/src/share/classes/com/sun/source/util/TreeScanner.java b/langtools/src/share/classes/com/sun/source/util/TreeScanner.java index b8525b8008d..be0b0e8ee8a 100644 --- a/langtools/src/share/classes/com/sun/source/util/TreeScanner.java +++ b/langtools/src/share/classes/com/sun/source/util/TreeScanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, 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 @@ -138,7 +138,6 @@ public class TreeScanner implements TreeVisitor { r = scanAndReduce(node.getReturnType(), p, r); r = scanAndReduce(node.getTypeParameters(), p, r); r = scanAndReduce(node.getParameters(), p, r); -//308 r = scanAndReduce(node.getReceiverAnnotations(), p, r); r = scanAndReduce(node.getThrows(), p, r); r = scanAndReduce(node.getBody(), p, r); r = scanAndReduce(node.getDefaultValue(), p, r); @@ -362,7 +361,6 @@ public class TreeScanner implements TreeVisitor { public R visitTypeParameter(TypeParameterTree node, P p) { R r = scan(node.getBounds(), p); -//308 R r = scanAndReduce(node.getAnnotations(), p, r); return r; } @@ -380,12 +378,6 @@ public class TreeScanner implements TreeVisitor { return r; } -//308 public R visitAnnotatedType(AnnotatedTypeTree node, P p) { -//308 R r = scan(node.getAnnotations(), p); -//308 r = scanAndReduce(node.getUnderlyingType(), p, r); -//308 return r; -//308 } - public R visitOther(Tree node, P p) { return null; } diff --git a/langtools/src/share/classes/com/sun/tools/classfile/Attribute.java b/langtools/src/share/classes/com/sun/tools/classfile/Attribute.java index 0c6e43d6cd3..f09374c9e1e 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/Attribute.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/Attribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2011, 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 @@ -54,8 +54,6 @@ public abstract class Attribute { public static final String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations"; public static final String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations"; public static final String RuntimeInvisibleParameterAnnotations = "RuntimeInvisibleParameterAnnotations"; - public static final String RuntimeVisibleTypeAnnotations = "RuntimeVisibleTypeAnnotations"; - public static final String RuntimeInvisibleTypeAnnotations = "RuntimeInvisibleTypeAnnotations"; public static final String Signature = "Signature"; public static final String SourceDebugExtension = "SourceDebugExtension"; public static final String SourceFile = "SourceFile"; @@ -118,8 +116,6 @@ public abstract class Attribute { standardAttributes.put(RuntimeInvisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations_attribute.class); standardAttributes.put(RuntimeVisibleAnnotations, RuntimeVisibleAnnotations_attribute.class); standardAttributes.put(RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations_attribute.class); - standardAttributes.put(RuntimeVisibleTypeAnnotations, RuntimeVisibleTypeAnnotations_attribute.class); - standardAttributes.put(RuntimeInvisibleTypeAnnotations, RuntimeInvisibleTypeAnnotations_attribute.class); standardAttributes.put(Signature, Signature_attribute.class); standardAttributes.put(SourceID, SourceID_attribute.class); } @@ -176,8 +172,6 @@ public abstract class Attribute { R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p); R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p); R visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, P p); - R visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, P p); - R visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, P p); R visitSignature(Signature_attribute attr, P p); R visitSourceDebugExtension(SourceDebugExtension_attribute attr, P p); R visitSourceFile(SourceFile_attribute attr, P p); diff --git a/langtools/src/share/classes/com/sun/tools/classfile/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/classfile/ClassWriter.java index 13b3d48b900..00927b56b0e 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/ClassWriter.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2011, 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 @@ -459,16 +459,6 @@ public class ClassWriter { return null; } - public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, ClassOutputStream out) { - annotationWriter.write(attr.annotations, out); - return null; - } - - public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, ClassOutputStream out) { - annotationWriter.write(attr.annotations, out); - return null; - } - public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, ClassOutputStream out) { out.writeByte(attr.parameter_annotations.length); for (Annotation[] annos: attr.parameter_annotations) @@ -628,12 +618,6 @@ public class ClassWriter { write(anno, out); } - public void write(ExtendedAnnotation[] annos, ClassOutputStream out) { - out.writeShort(annos.length); - for (ExtendedAnnotation anno: annos) - write(anno, out); - } - public void write(Annotation anno, ClassOutputStream out) { out.writeShort(anno.type_index); out.writeShort(anno.element_value_pairs.length); @@ -641,11 +625,6 @@ public class ClassWriter { write(p, out); } - public void write(ExtendedAnnotation anno, ClassOutputStream out) { - write(anno.annotation, out); - write(anno.position, out); - } - public void write(element_value_pair pair, ClassOutputStream out) { out.writeShort(pair.element_name_index); write(pair.value, out); @@ -684,95 +663,5 @@ public class ClassWriter { return null; } - private void write(ExtendedAnnotation.Position p, ClassOutputStream out) { - out.writeByte(p.type.targetTypeValue()); - switch (p.type) { - // type case - case TYPECAST: - case TYPECAST_GENERIC_OR_ARRAY: - // object creation - case INSTANCEOF: - case INSTANCEOF_GENERIC_OR_ARRAY: - // new expression - case NEW: - case NEW_GENERIC_OR_ARRAY: - case NEW_TYPE_ARGUMENT: - case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - out.writeShort(p.offset); - break; - // local variable - case LOCAL_VARIABLE: - case LOCAL_VARIABLE_GENERIC_OR_ARRAY: - int table_length = p.lvarOffset.length; - out.writeShort(table_length); - for (int i = 0; i < table_length; ++i) { - out.writeShort(1); // for table length - out.writeShort(p.lvarOffset[i]); - out.writeShort(p.lvarLength[i]); - out.writeShort(p.lvarIndex[i]); - } - break; - // method receiver - case METHOD_RECEIVER: - // Do nothing - break; - // type parameters - case CLASS_TYPE_PARAMETER: - case METHOD_TYPE_PARAMETER: - out.writeByte(p.parameter_index); - break; - // type parameters bounds - case CLASS_TYPE_PARAMETER_BOUND: - case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - case METHOD_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - out.writeByte(p.parameter_index); - out.writeByte(p.bound_index); - break; - // wildcards - case WILDCARD_BOUND: - case WILDCARD_BOUND_GENERIC_OR_ARRAY: - write(p.wildcard_position, out); - break; - // Class extends and implements clauses - case CLASS_EXTENDS: - case CLASS_EXTENDS_GENERIC_OR_ARRAY: - out.writeByte(p.type_index); - break; - // throws - case THROWS: - out.writeByte(p.type_index); - break; - case CLASS_LITERAL: - case CLASS_LITERAL_GENERIC_OR_ARRAY: - out.writeShort(p.offset); - break; - // method parameter: not specified - case METHOD_PARAMETER_GENERIC_OR_ARRAY: - out.writeByte(p.parameter_index); - break; - // method type argument: wasn't specified - case METHOD_TYPE_ARGUMENT: - case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - out.writeShort(p.offset); - out.writeByte(p.type_index); - break; - // We don't need to worry abut these - case METHOD_RETURN_GENERIC_OR_ARRAY: - case FIELD_GENERIC_OR_ARRAY: - break; - case UNKNOWN: - break; - default: - throw new AssertionError("unknown type: " + p); - } - - // Append location data for generics/arrays. - if (p.type.hasLocation()) { - out.writeShort(p.location.size()); - for (int i : p.location) - out.writeByte((byte)i); - } - } } } diff --git a/langtools/src/share/classes/com/sun/tools/classfile/ExtendedAnnotation.java b/langtools/src/share/classes/com/sun/tools/classfile/ExtendedAnnotation.java deleted file mode 100644 index a007421d03a..00000000000 --- a/langtools/src/share/classes/com/sun/tools/classfile/ExtendedAnnotation.java +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package com.sun.tools.classfile; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; -import java.util.Set; - -import static com.sun.tools.classfile.ExtendedAnnotation.TargetAttribute.*; - -/** - * See JSR 308 specification, section 4.1 - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ExtendedAnnotation { - ExtendedAnnotation(ClassReader cr) throws IOException, Annotation.InvalidAnnotation { - annotation = new Annotation(cr); - position = read_position(cr); - } - - public ExtendedAnnotation(ConstantPool constant_pool, - Annotation annotation, Position position) { - this.annotation = annotation; - this.position = position; - } - - public int length() { - int n = annotation.length(); - n += position_length(position); - return n; - } - - public final Annotation annotation; - public final Position position; - - private static Position read_position(ClassReader cr) throws IOException, Annotation.InvalidAnnotation { - // Copied from ClassReader - int tag = (byte)cr.readUnsignedByte(); // cast to introduce signedness - if (!TargetType.isValidTargetTypeValue(tag)) - throw new Annotation.InvalidAnnotation("invalid type annotation target type value: " + tag); - - TargetType type = TargetType.fromTargetTypeValue(tag); - - Position position = new Position(); - position.type = type; - - switch (type) { - // type case - case TYPECAST: - case TYPECAST_GENERIC_OR_ARRAY: - // object creation - case INSTANCEOF: - case INSTANCEOF_GENERIC_OR_ARRAY: - // new expression - case NEW: - case NEW_GENERIC_OR_ARRAY: - position.offset = cr.readUnsignedShort(); - break; - // local variable - case LOCAL_VARIABLE: - case LOCAL_VARIABLE_GENERIC_OR_ARRAY: - int table_length = cr.readUnsignedShort(); - position.lvarOffset = new int[table_length]; - position.lvarLength = new int[table_length]; - position.lvarIndex = new int[table_length]; - for (int i = 0; i < table_length; ++i) { - position.lvarOffset[i] = cr.readUnsignedShort(); - position.lvarLength[i] = cr.readUnsignedShort(); - position.lvarIndex[i] = cr.readUnsignedShort(); - } - break; - // method receiver - case METHOD_RECEIVER: - // Do nothing - break; - // type parameters - case CLASS_TYPE_PARAMETER: - case METHOD_TYPE_PARAMETER: - position.parameter_index = cr.readUnsignedByte(); - break; - // type parameter bounds - case CLASS_TYPE_PARAMETER_BOUND: - case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - case METHOD_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - position.parameter_index = cr.readUnsignedByte(); - position.bound_index = cr.readUnsignedByte(); - break; - // wildcards - case WILDCARD_BOUND: - case WILDCARD_BOUND_GENERIC_OR_ARRAY: - position.wildcard_position = read_position(cr); - break; - // Class extends and implements clauses - case CLASS_EXTENDS: - case CLASS_EXTENDS_GENERIC_OR_ARRAY: - int in = cr.readUnsignedShort(); - if (in == 0xFFFF) - in = -1; - position.type_index = in; - break; - // throws - case THROWS: - position.type_index = cr.readUnsignedShort(); - break; - case CLASS_LITERAL: - case CLASS_LITERAL_GENERIC_OR_ARRAY: - position.offset = cr.readUnsignedShort(); - break; - // method parameter: not specified - case METHOD_PARAMETER_GENERIC_OR_ARRAY: - position.parameter_index = cr.readUnsignedByte(); - break; - // method type argument: wasn't specified - case NEW_TYPE_ARGUMENT: - case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - case METHOD_TYPE_ARGUMENT: - case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - position.offset = cr.readUnsignedShort(); - position.type_index = cr.readUnsignedByte(); - break; - // We don't need to worry abut these - case METHOD_RETURN_GENERIC_OR_ARRAY: - case FIELD_GENERIC_OR_ARRAY: - break; - case UNKNOWN: - break; - default: - throw new AssertionError("Cannot be here"); - } - - if (type.hasLocation()) { - int len = cr.readUnsignedShort(); - List loc = new ArrayList(len); - for (int i = 0; i < len; i++) - loc.add(cr.readUnsignedByte()); - position.location = loc; - } - return position; - } - - private static int position_length(Position pos) { - int n = 0; - n += 1; // target_type - switch (pos.type) { - // type case - case TYPECAST: - case TYPECAST_GENERIC_OR_ARRAY: - // object creation - case INSTANCEOF: - case INSTANCEOF_GENERIC_OR_ARRAY: - // new expression - case NEW: - case NEW_GENERIC_OR_ARRAY: - n += 2; - break; - // local variable - case LOCAL_VARIABLE: - case LOCAL_VARIABLE_GENERIC_OR_ARRAY: - n += 2; // table_length; - int table_length = pos.lvarOffset.length; - n += 2 * table_length; // offset - n += 2 * table_length; // length; - n += 2 * table_length; // index - break; - // method receiver - case METHOD_RECEIVER: - // Do nothing - break; - // type parameters - case CLASS_TYPE_PARAMETER: - case METHOD_TYPE_PARAMETER: - n += 1; // parameter_index; - break; - // type parameter bounds - case CLASS_TYPE_PARAMETER_BOUND: - case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - case METHOD_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - n += 1; // parameter_index - n += 1; // bound_index - break; - case WILDCARD_BOUND: - case WILDCARD_BOUND_GENERIC_OR_ARRAY: - n += position_length(pos.wildcard_position); - break; - // Class extends and implements clauses - case CLASS_EXTENDS: - case CLASS_EXTENDS_GENERIC_OR_ARRAY: - n += 2; // type_index - break; - // throws - case THROWS: - n += 2; // type_index - break; - case CLASS_LITERAL: - case CLASS_LITERAL_GENERIC_OR_ARRAY: - n += 1; // offset - break; - // method parameter: not specified - case METHOD_PARAMETER_GENERIC_OR_ARRAY: - n += 1; // parameter_index - break; - // method type argument: wasn't specified - case NEW_TYPE_ARGUMENT: - case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - case METHOD_TYPE_ARGUMENT: - case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - n += 2; // offset - n += 1; // type index - break; - // We don't need to worry abut these - case METHOD_RETURN_GENERIC_OR_ARRAY: - case FIELD_GENERIC_OR_ARRAY: - break; - case UNKNOWN: - break; - default: - } - - if (pos.type.hasLocation()) { - n += 2; // length - n += 1 * pos.location.size(); // actual array size - } - - return n; - } - - // Code duplicated from com.sun.tools.javac.code.TypeAnnotations.Position - public static class Position { - - public TargetType type = TargetType.UNKNOWN; - - // For generic/array types. - public List location = new ArrayList(); - - // For typecasts, type tests, new (and locals, as start_pc). - public int offset = -1; - - // For locals. - public int[] lvarOffset = null; - public int[] lvarLength = null; - public int[] lvarIndex = null; - - // For type parameter bound - public int bound_index = Integer.MIN_VALUE; - - // For type parameter and method parameter - public int parameter_index = Integer.MIN_VALUE; - - // For class extends, implements, and throws classes - public int type_index = Integer.MIN_VALUE; - - // For wildcards - public Position wildcard_position = null; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('['); - sb.append(type); - - switch (type) { - // type case - case TYPECAST: - case TYPECAST_GENERIC_OR_ARRAY: - // object creation - case INSTANCEOF: - case INSTANCEOF_GENERIC_OR_ARRAY: - // new expression - case NEW: - case NEW_GENERIC_OR_ARRAY: - case NEW_TYPE_ARGUMENT: - case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - sb.append(", offset = "); - sb.append(offset); - break; - // local variable - case LOCAL_VARIABLE: - case LOCAL_VARIABLE_GENERIC_OR_ARRAY: - sb.append(", {"); - for (int i = 0; i < lvarOffset.length; ++i) { - if (i != 0) sb.append("; "); - sb.append(", start_pc = "); - sb.append(lvarOffset[i]); - sb.append(", length = "); - sb.append(lvarLength[i]); - sb.append(", index = "); - sb.append(lvarIndex[i]); - } - sb.append("}"); - break; - // method receiver - case METHOD_RECEIVER: - // Do nothing - break; - // type parameters - case CLASS_TYPE_PARAMETER: - case METHOD_TYPE_PARAMETER: - sb.append(", param_index = "); - sb.append(parameter_index); - break; - // type parameters bound - case CLASS_TYPE_PARAMETER_BOUND: - case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - case METHOD_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - sb.append(", param_index = "); - sb.append(parameter_index); - sb.append(", bound_index = "); - sb.append(bound_index); - break; - // wildcard - case WILDCARD_BOUND: - case WILDCARD_BOUND_GENERIC_OR_ARRAY: - sb.append(", wild_card = "); - sb.append(wildcard_position); - break; - // Class extends and implements clauses - case CLASS_EXTENDS: - case CLASS_EXTENDS_GENERIC_OR_ARRAY: - sb.append(", type_index = "); - sb.append(type_index); - break; - // throws - case THROWS: - sb.append(", type_index = "); - sb.append(type_index); - break; - case CLASS_LITERAL: - case CLASS_LITERAL_GENERIC_OR_ARRAY: - sb.append(", offset = "); - sb.append(offset); - break; - // method parameter: not specified - case METHOD_PARAMETER_GENERIC_OR_ARRAY: - sb.append(", param_index = "); - sb.append(parameter_index); - break; - // method type argument: wasn't specified - case METHOD_TYPE_ARGUMENT: - case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - sb.append(", offset = "); - sb.append(offset); - sb.append(", type_index = "); - sb.append(type_index); - break; - // We don't need to worry abut these - case METHOD_RETURN_GENERIC_OR_ARRAY: - case FIELD_GENERIC_OR_ARRAY: - break; - case UNKNOWN: - break; - default: - throw new AssertionError("unknown type: " + type); - } - - // Append location data for generics/arrays. - if (type.hasLocation()) { - sb.append(", location = ("); - sb.append(location); - sb.append(")"); - } - - sb.append(']'); - return sb.toString(); - } - } - - // Code duplicated from com.sun.tools.javac.comp.TargetType - public enum TargetType { - - /** For annotations on typecasts. */ - TYPECAST(0x00), - - /** For annotations on a type argument or nested array of a typecast. */ - TYPECAST_GENERIC_OR_ARRAY(0x01, HasLocation), - - /** For annotations on type tests. */ - INSTANCEOF(0x02), - - /** For annotations on a type argument or nested array of a type test. */ - INSTANCEOF_GENERIC_OR_ARRAY(0x03, HasLocation), - - /** For annotations on object creation expressions. */ - NEW(0x04), - - /** - * For annotations on a type argument or nested array of an object creation - * expression. - */ - NEW_GENERIC_OR_ARRAY(0x05, HasLocation), - - - /** For annotations on the method receiver. */ - METHOD_RECEIVER(0x06), - - // invalid location - // METHOD_RECEIVER_GENERIC_OR_ARRAY(0x07, HasLocation), - - /** For annotations on local variables. */ - LOCAL_VARIABLE(0x08), - - /** For annotations on a type argument or nested array of a local. */ - LOCAL_VARIABLE_GENERIC_OR_ARRAY(0x09, HasLocation), - - // already handled by regular annotations - // METHOD_RETURN(0x0A), - - /** - * For annotations on a type argument or nested array of a method return - * type. - */ - METHOD_RETURN_GENERIC_OR_ARRAY(0x0B, HasLocation), - - // already handled by regular annotations - // METHOD_PARAMETER(0x0C), - - /** For annotations on a type argument or nested array of a method parameter. */ - METHOD_PARAMETER_GENERIC_OR_ARRAY(0x0D, HasLocation), - - // already handled by regular annotations - // FIELD(0x0E), - - /** For annotations on a type argument or nested array of a field. */ - FIELD_GENERIC_OR_ARRAY(0x0F, HasLocation), - - /** For annotations on a bound of a type parameter of a class. */ - CLASS_TYPE_PARAMETER_BOUND(0x10, HasBound, HasParameter), - - /** - * For annotations on a type argument or nested array of a bound of a type - * parameter of a class. - */ - CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY(0x11, HasBound, HasLocation, HasParameter), - - /** For annotations on a bound of a type parameter of a method. */ - METHOD_TYPE_PARAMETER_BOUND(0x12, HasBound, HasParameter), - - /** - * For annotations on a type argument or nested array of a bound of a type - * parameter of a method. - */ - METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY(0x13, HasBound, HasLocation, HasParameter), - - /** For annotations on the type of an "extends" or "implements" clause. */ - CLASS_EXTENDS(0x14), - - /** For annotations on the inner type of an "extends" or "implements" clause. */ - CLASS_EXTENDS_GENERIC_OR_ARRAY(0x15, HasLocation), - - /** For annotations on a throws clause in a method declaration. */ - THROWS(0x16), - - // invalid location - // THROWS_GENERIC_OR_ARRAY(0x17, HasLocation), - - /** For annotations in type arguments of object creation expressions. */ - NEW_TYPE_ARGUMENT(0x18), - NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x19, HasLocation), - - METHOD_TYPE_ARGUMENT(0x1A), - METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x1B, HasLocation), - - WILDCARD_BOUND(0x1C, HasBound), - WILDCARD_BOUND_GENERIC_OR_ARRAY(0x1D, HasBound, HasLocation), - - CLASS_LITERAL(0x1E), - CLASS_LITERAL_GENERIC_OR_ARRAY(0x1F, HasLocation), - - METHOD_TYPE_PARAMETER(0x20, HasParameter), - - // invalid location - // METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x21, HasLocation, HasParameter), - - CLASS_TYPE_PARAMETER(0x22, HasParameter), - - // invalid location - // CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x23, HasLocation, HasParameter), - - /** For annotations with an unknown target. */ - UNKNOWN(-1); - - static final int MAXIMUM_TARGET_TYPE_VALUE = 0x22; - - private final int targetTypeValue; - private Set flags; - - TargetType(int targetTypeValue, TargetAttribute... attrs) { - if (targetTypeValue < Byte.MIN_VALUE - || targetTypeValue > Byte.MAX_VALUE) - throw new AssertionError("attribute type value needs to be a byte: " + targetTypeValue); - this.targetTypeValue = (byte)targetTypeValue; - this.flags = EnumSet.noneOf(TargetAttribute.class); - for (TargetAttribute attr : attrs) - this.flags.add(attr); - } - - /** - * Returns whether or not this TargetType represents an annotation whose - * target is an inner type of a generic or array type. - * - * @return true if this TargetType represents an annotation on an inner - * type, false otherwise - */ - public boolean hasLocation() { - return flags.contains(HasLocation); - } - - public TargetType getGenericComplement() { - if (hasLocation()) - return this; - else - return fromTargetTypeValue(targetTypeValue() + 1); - } - - /** - * Returns whether or not this TargetType represents an annotation whose - * target has a parameter index. - * - * @return true if this TargetType has a parameter index, - * false otherwise - */ - public boolean hasParameter() { - return flags.contains(HasParameter); - } - - /** - * Returns whether or not this TargetType represents an annotation whose - * target is a type parameter bound. - * - * @return true if this TargetType represents an type parameter bound - * annotation, false otherwise - */ - public boolean hasBound() { - return flags.contains(HasBound); - } - - public int targetTypeValue() { - return this.targetTypeValue; - } - - private static TargetType[] targets = null; - - private static TargetType[] buildTargets() { - TargetType[] targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1]; - TargetType[] alltargets = values(); - for (TargetType target : alltargets) - if (target.targetTypeValue >= 0) - targets[target.targetTypeValue] = target; - for (int i = 0; i <= MAXIMUM_TARGET_TYPE_VALUE; ++i) - if (targets[i] == null) - targets[i] = UNKNOWN; - return targets; - } - - public static boolean isValidTargetTypeValue(int tag) { - if (targets == null) - targets = buildTargets(); - - if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue)) - return true; - - return (tag >= 0 && tag < targets.length); - } - - public static TargetType fromTargetTypeValue(int tag) { - if (targets == null) - targets = buildTargets(); - - if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue)) - return UNKNOWN; - - if (tag < 0 || tag >= targets.length) - throw new IllegalArgumentException("Unknown TargetType: " + tag); - return targets[tag]; - } - } - - static enum TargetAttribute { - HasLocation, HasParameter, HasBound; - } -} diff --git a/langtools/src/share/classes/com/sun/tools/classfile/RuntimeInvisibleTypeAnnotations_attribute.java b/langtools/src/share/classes/com/sun/tools/classfile/RuntimeInvisibleTypeAnnotations_attribute.java deleted file mode 100644 index 01b14a8d4cc..00000000000 --- a/langtools/src/share/classes/com/sun/tools/classfile/RuntimeInvisibleTypeAnnotations_attribute.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2007, 2008, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JSR 308 specification, section 4.1 - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class RuntimeInvisibleTypeAnnotations_attribute extends RuntimeTypeAnnotations_attribute { - RuntimeInvisibleTypeAnnotations_attribute(ClassReader cr, int name_index, int length) - throws IOException, Annotation.InvalidAnnotation { - super(cr, name_index, length); - } - - public RuntimeInvisibleTypeAnnotations_attribute(ConstantPool cp, ExtendedAnnotation[] annotations) - throws ConstantPoolException { - this(cp.getUTF8Index(Attribute.RuntimeInvisibleTypeAnnotations), annotations); - } - - public RuntimeInvisibleTypeAnnotations_attribute(int name_index, ExtendedAnnotation[] annotations) { - super(name_index, annotations); - } - - public R accept(Visitor visitor, P p) { - return visitor.visitRuntimeInvisibleTypeAnnotations(this, p); - } -} diff --git a/langtools/src/share/classes/com/sun/tools/classfile/RuntimeTypeAnnotations_attribute.java b/langtools/src/share/classes/com/sun/tools/classfile/RuntimeTypeAnnotations_attribute.java deleted file mode 100644 index 803fbd7f8bc..00000000000 --- a/langtools/src/share/classes/com/sun/tools/classfile/RuntimeTypeAnnotations_attribute.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2007, 2008, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JSR 308 specification, section 4 - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public abstract class RuntimeTypeAnnotations_attribute extends Attribute { - protected RuntimeTypeAnnotations_attribute(ClassReader cr, int name_index, int length) - throws IOException, Annotation.InvalidAnnotation { - super(name_index, length); - int num_annotations = cr.readUnsignedShort(); - annotations = new ExtendedAnnotation[num_annotations]; - for (int i = 0; i < annotations.length; i++) - annotations[i] = new ExtendedAnnotation(cr); - } - - protected RuntimeTypeAnnotations_attribute(int name_index, ExtendedAnnotation[] annotations) { - super(name_index, length(annotations)); - this.annotations = annotations; - } - - private static int length(ExtendedAnnotation[] annos) { - int n = 2; - for (ExtendedAnnotation anno: annos) - n += anno.length(); - return n; - } - - public final ExtendedAnnotation[] annotations; -} diff --git a/langtools/src/share/classes/com/sun/tools/classfile/RuntimeVisibleTypeAnnotations_attribute.java b/langtools/src/share/classes/com/sun/tools/classfile/RuntimeVisibleTypeAnnotations_attribute.java deleted file mode 100644 index 1cee8b5458e..00000000000 --- a/langtools/src/share/classes/com/sun/tools/classfile/RuntimeVisibleTypeAnnotations_attribute.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2007, 2008, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package com.sun.tools.classfile; - -import java.io.IOException; - -/** - * See JSR 308 specification, section 4.1 - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class RuntimeVisibleTypeAnnotations_attribute extends RuntimeTypeAnnotations_attribute { - RuntimeVisibleTypeAnnotations_attribute(ClassReader cr, int name_index, int length) - throws IOException, Annotation.InvalidAnnotation { - super(cr, name_index, length); - } - - public RuntimeVisibleTypeAnnotations_attribute(ConstantPool cp, ExtendedAnnotation[] annotations) - throws ConstantPoolException { - this(cp.getUTF8Index(Attribute.RuntimeVisibleTypeAnnotations), annotations); - } - - public RuntimeVisibleTypeAnnotations_attribute(int name_index, ExtendedAnnotation[] annotations) { - super(name_index, annotations); - } - - public R accept(Visitor visitor, P p) { - return visitor.visitRuntimeVisibleTypeAnnotations(this, p); - } -} diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java b/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java index 8e54e579c56..8f3c7ed1963 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -204,21 +204,6 @@ public abstract class Attribute implements AnnotationValue { } } - public static class TypeCompound extends Compound { - public TypeAnnotationPosition position; - public TypeCompound(Compound compound, - TypeAnnotationPosition position) { - this(compound.type, compound.values, position); - } - public TypeCompound(Type type, - List> values, - TypeAnnotationPosition position) { - super(type, values); - this.position = position; - } - - } - /** The value for an annotation element of an array type. */ public static class Array extends Attribute { diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java index da0d812da05..20c33d7365d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -100,17 +100,6 @@ public abstract class Symbol implements Element { */ public Type type; - /** The type annotations targeted to a tree directly owned by this symbol - */ - // type annotations are stored here for two purposes: - // - convenient location to store annotations for generation after erasure - // - a private interface for accessing type annotations parsed from - // classfiles - // the field is populated for the following declaration only - // class, field, variable and type parameters - // - public List typeAnnotations; - /** The owner of this symbol. */ public Symbol owner; @@ -133,7 +122,6 @@ public abstract class Symbol implements Element { this.completer = null; this.erasure_field = null; this.attributes_field = List.nil(); - this.typeAnnotations = List.nil(); this.name = name; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java deleted file mode 100644 index 8fc585cac6b..00000000000 --- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ - -package com.sun.tools.javac.code; - -import javax.lang.model.element.ElementKind; - -import com.sun.tools.javac.code.Symbol.VarSymbol; -import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.TreeInfo; -import com.sun.tools.javac.tree.TreeScanner; -import com.sun.tools.javac.tree.JCTree.*; -import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.List; -import com.sun.tools.javac.util.ListBuffer; - -/** - * Contains operations specific to processing type annotations - */ -public class TypeAnnotations { - private static final Context.Key key - = new Context.Key(); - - public static TypeAnnotations instance(Context context) { - TypeAnnotations instance = context.get(key); - if (instance == null) - instance = new TypeAnnotations(context); - return instance; - } - - protected TypeAnnotations(Context context) { - context.put(key, this); - } - - public void taFillAndLift(JCClassDecl tree, boolean visitBodies) { -//308 new TypeAnnotationPositions().scan(tree); -//308 new TypeAnnotationLift().scan(tree); - } - - private static class TypeAnnotationPositions extends TreeScanner { - - private ListBuffer frames = ListBuffer.lb(); - private void push(JCTree t) { frames = frames.prepend(t); } - private JCTree pop() { return frames.next(); } - private JCTree peek2() { return frames.toList().tail.head; } - - @Override - public void scan(JCTree tree) { - push(tree); - super.scan(tree); - pop(); - } - - private boolean inClass = false; - - @Override - public void visitClassDef(JCClassDecl tree) { - if (!inClass) { - // Do not recurse into nested and inner classes since - // TransTypes.visitClassDef makes an invocation for each class - // separately. - inClass = true; - try { - super.visitClassDef(tree); - } finally { - inClass = false; - } - } - } - - private TypeAnnotationPosition resolveFrame(JCTree tree, JCTree frame, - List path, TypeAnnotationPosition p) { - switch (frame.getKind()) { - case TYPE_CAST: - p.type = TargetType.TYPECAST; - p.pos = frame.pos; - return p; - - case INSTANCE_OF: - p.type = TargetType.INSTANCEOF; - p.pos = frame.pos; - return p; - - case NEW_CLASS: - p.type = TargetType.NEW; - p.pos = frame.pos; - return p; - - case NEW_ARRAY: - p.type = TargetType.NEW; - p.pos = frame.pos; - return p; - - case ANNOTATION_TYPE: - case CLASS: - case ENUM: - case INTERFACE: - p.pos = frame.pos; - if (((JCClassDecl)frame).extending == tree) { - p.type = TargetType.CLASS_EXTENDS; - p.type_index = -1; - } else if (((JCClassDecl)frame).implementing.contains(tree)) { - p.type = TargetType.CLASS_EXTENDS; - p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree); - } else if (((JCClassDecl)frame).typarams.contains(tree)) { - p.type = TargetType.CLASS_TYPE_PARAMETER; - p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree); - } else - throw new AssertionError(); - return p; - - case METHOD: { - JCMethodDecl frameMethod = (JCMethodDecl)frame; - p.pos = frame.pos; - if (frameMethod.receiverAnnotations.contains(tree)) - p.type = TargetType.METHOD_RECEIVER; - else if (frameMethod.thrown.contains(tree)) { - p.type = TargetType.THROWS; - p.type_index = frameMethod.thrown.indexOf(tree); - } else if (((JCMethodDecl)frame).restype == tree) { - p.type = TargetType.METHOD_RETURN_GENERIC_OR_ARRAY; - } else if (frameMethod.typarams.contains(tree)) { - p.type = TargetType.METHOD_TYPE_PARAMETER; - p.parameter_index = frameMethod.typarams.indexOf(tree); - } else - throw new AssertionError(); - return p; - } - case MEMBER_SELECT: { - JCFieldAccess fieldFrame = (JCFieldAccess)frame; - if ("class".contentEquals(fieldFrame.name)) { - p.type = TargetType.CLASS_LITERAL; - p.pos = TreeInfo.innermostType(fieldFrame.selected).pos; - } else - throw new AssertionError(); - return p; - } - case PARAMETERIZED_TYPE: { - TypeAnnotationPosition nextP; - if (((JCTypeApply)frame).clazz == tree) - nextP = p; // generic: RAW; noop - else if (((JCTypeApply)frame).arguments.contains(tree)) - p.location = p.location.prepend( - ((JCTypeApply)frame).arguments.indexOf(tree)); - else - throw new AssertionError(); - - List newPath = path.tail; - return resolveFrame(newPath.head, newPath.tail.head, newPath, p); - } - - case ARRAY_TYPE: { - p.location = p.location.prepend(0); - List newPath = path.tail; - return resolveFrame(newPath.head, newPath.tail.head, newPath, p); - } - - case TYPE_PARAMETER: - if (path.tail.tail.head.getTag() == JCTree.CLASSDEF) { - JCClassDecl clazz = (JCClassDecl)path.tail.tail.head; - p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND; - p.parameter_index = clazz.typarams.indexOf(path.tail.head); - p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree); - } else if (path.tail.tail.head.getTag() == JCTree.METHODDEF) { - JCMethodDecl method = (JCMethodDecl)path.tail.tail.head; - p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND; - p.parameter_index = method.typarams.indexOf(path.tail.head); - p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree); - } else - throw new AssertionError(); - p.pos = frame.pos; - return p; - - case VARIABLE: - VarSymbol v = ((JCVariableDecl)frame).sym; - p.pos = frame.pos; - switch (v.getKind()) { - case LOCAL_VARIABLE: - p.type = TargetType.LOCAL_VARIABLE; break; - case FIELD: - p.type = TargetType.FIELD_GENERIC_OR_ARRAY; break; - case PARAMETER: - p.type = TargetType.METHOD_PARAMETER_GENERIC_OR_ARRAY; - p.parameter_index = methodParamIndex(path, frame); - break; - default: throw new AssertionError(); - } - return p; - -//308 case ANNOTATED_TYPE: { -//308 List newPath = path.tail; -//308 return resolveFrame(newPath.head, newPath.tail.head, -//308 newPath, p); -//308 } - - case METHOD_INVOCATION: { - JCMethodInvocation invocation = (JCMethodInvocation)frame; - if (!invocation.typeargs.contains(tree)) - throw new AssertionError("{" + tree + "} is not an argument in the invocation: " + invocation); - p.type = TargetType.METHOD_TYPE_ARGUMENT; - p.pos = invocation.pos; - p.type_index = invocation.typeargs.indexOf(tree); - return p; - } - - case EXTENDS_WILDCARD: - case SUPER_WILDCARD: { - p.type = TargetType.WILDCARD_BOUND; - List newPath = path.tail; - - TypeAnnotationPosition wildcard = - resolveFrame(newPath.head, newPath.tail.head, newPath, - new TypeAnnotationPosition()); - if (!wildcard.location.isEmpty()) - wildcard.type = wildcard.type.getGenericComplement(); - p.wildcard_position = wildcard; - p.pos = frame.pos; - return p; - } - } - return p; - } - - private void setTypeAnnotationPos(List annotations, TypeAnnotationPosition position) { - for (JCTypeAnnotation anno : annotations) { - anno.annotation_position = position; - anno.attribute_field.position = position; - } - } - - @Override - public void visitNewArray(JCNewArray tree) { - findPosition(tree, tree, tree.annotations); - int dimAnnosCount = tree.dimAnnotations.size(); - - // handle annotations associated with dimentions - for (int i = 0; i < dimAnnosCount; ++i) { - TypeAnnotationPosition p = new TypeAnnotationPosition(); - p.type = TargetType.NEW_GENERIC_OR_ARRAY; - p.pos = tree.pos; - p.location = p.location.append(i); - setTypeAnnotationPos(tree.dimAnnotations.get(i), p); - } - - // handle "free" annotations - int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1; - JCExpression elemType = tree.elemtype; - while (elemType != null) { - if (elemType.getTag() == JCTree.ANNOTATED_TYPE) { - JCAnnotatedType at = (JCAnnotatedType)elemType; - TypeAnnotationPosition p = new TypeAnnotationPosition(); - p.type = TargetType.NEW_GENERIC_OR_ARRAY; - p.pos = tree.pos; - p.location = p.location.append(i); - setTypeAnnotationPos(at.annotations, p); - elemType = at.underlyingType; - } else if (elemType.getTag() == JCTree.TYPEARRAY) { - ++i; - elemType = ((JCArrayTypeTree)elemType).elemtype; - } else - break; - } - - // find annotations locations of initializer elements - scan(tree.elems); - } - - @Override - public void visitAnnotatedType(JCAnnotatedType tree) { - findPosition(tree, peek2(), tree.annotations); - super.visitAnnotatedType(tree); - } - - @Override - public void visitMethodDef(JCMethodDecl tree) { - TypeAnnotationPosition p = new TypeAnnotationPosition(); - p.type = TargetType.METHOD_RECEIVER; - setTypeAnnotationPos(tree.receiverAnnotations, p); - super.visitMethodDef(tree); - } - @Override - public void visitTypeParameter(JCTypeParameter tree) { - findPosition(tree, peek2(), tree.annotations); - super.visitTypeParameter(tree); - } - - void findPosition(JCTree tree, JCTree frame, List annotations) { - if (!annotations.isEmpty()) { - TypeAnnotationPosition p = - resolveFrame(tree, frame, frames.toList(), - new TypeAnnotationPosition()); - if (!p.location.isEmpty()) - p.type = p.type.getGenericComplement(); - setTypeAnnotationPos(annotations, p); - } - } - - private int methodParamIndex(List path, JCTree param) { - List curr = path; - if (curr.head != param) - curr = path.tail; - JCMethodDecl method = (JCMethodDecl)curr.tail.head; - return method.params.indexOf(param); - } - } - - private static class TypeAnnotationLift extends TreeScanner { - List recordedTypeAnnotations = List.nil(); - - boolean isInner = false; - @Override - public void visitClassDef(JCClassDecl tree) { - if (isInner) { - // tree is an inner class tree. stop now. - // TransTypes.visitClassDef makes an invocation for each class - // separately. - return; - } - isInner = true; - List prevTAs = recordedTypeAnnotations; - recordedTypeAnnotations = List.nil(); - try { - super.visitClassDef(tree); - } finally { - tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations); - recordedTypeAnnotations = prevTAs; - } - } - - @Override - public void visitMethodDef(JCMethodDecl tree) { - List prevTAs = recordedTypeAnnotations; - recordedTypeAnnotations = List.nil(); - try { - super.visitMethodDef(tree); - } finally { - tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations); - recordedTypeAnnotations = prevTAs; - } - } - - @Override - public void visitVarDef(JCVariableDecl tree) { - List prevTAs = recordedTypeAnnotations; - recordedTypeAnnotations = List.nil(); - ElementKind kind = tree.sym.getKind(); - if (kind == ElementKind.LOCAL_VARIABLE && tree.mods.annotations.nonEmpty()) { - // need to lift the annotations - TypeAnnotationPosition position = new TypeAnnotationPosition(); - position.pos = tree.pos; - position.type = TargetType.LOCAL_VARIABLE; - for (Attribute.Compound attribute : tree.sym.attributes_field) { - Attribute.TypeCompound tc = - new Attribute.TypeCompound(attribute.type, attribute.values, position); - recordedTypeAnnotations = recordedTypeAnnotations.append(tc); - } - } - try { - super.visitVarDef(tree); - } finally { - if (kind.isField() || kind == ElementKind.LOCAL_VARIABLE) - tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations); - recordedTypeAnnotations = kind.isField() ? prevTAs : prevTAs.appendList(recordedTypeAnnotations); - } - } - - @Override - public void visitApply(JCMethodInvocation tree) { - scan(tree.meth); - scan(tree.typeargs); - scan(tree.args); - } - - public void visitAnnotation(JCAnnotation tree) { - if (tree instanceof JCTypeAnnotation) - recordedTypeAnnotations = recordedTypeAnnotations.append(((JCTypeAnnotation)tree).attribute_field); - super.visitAnnotation(tree); - } - } - -} diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index be3f598158d..d97fb264301 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -2989,10 +2989,6 @@ public class Attr extends JCTree.Visitor { result = tree.type = syms.errType; } - public void visitAnnotatedType(JCAnnotatedType tree) { - result = tree.type = attribType(tree.getUnderlyingType(), env); - } - public void visitErroneous(JCErroneous tree) { if (tree.errs != null) for (JCTree err : tree.errs) @@ -3184,9 +3180,6 @@ public class Attr extends JCTree.Visitor { (c.flags() & ABSTRACT) == 0) { checkSerialVersionUID(tree, c); } - - // Check type annotations applicability rules - validateTypeAnnotations(tree); } // where /** check if a class is a subtype of Serializable, if that is available. */ @@ -3234,35 +3227,6 @@ public class Attr extends JCTree.Visitor { return types.capture(type); } - private void validateTypeAnnotations(JCTree tree) { - tree.accept(typeAnnotationsValidator); - } - //where - private final JCTree.Visitor typeAnnotationsValidator = - new TreeScanner() { - public void visitAnnotation(JCAnnotation tree) { - if (tree instanceof JCTypeAnnotation) { - chk.validateTypeAnnotation((JCTypeAnnotation)tree, false); - } - super.visitAnnotation(tree); - } - public void visitTypeParameter(JCTypeParameter tree) { - chk.validateTypeAnnotations(tree.annotations, true); - // don't call super. skip type annotations - scan(tree.bounds); - } - public void visitMethodDef(JCMethodDecl tree) { - // need to check static methods - if ((tree.sym.flags() & Flags.STATIC) != 0) { - for (JCTypeAnnotation a : tree.receiverAnnotations) { - if (chk.isTypeAnnotation(a, false)) - log.error(a.pos(), "annotation.type.not.applicable"); - } - } - super.visitMethodDef(tree); - } - }; - // /** diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index d8536f71173..622a633da4a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -1086,11 +1086,6 @@ public class Check { } } - @Override - public void visitAnnotatedType(JCAnnotatedType tree) { - tree.underlyingType.accept(this); - } - /** Default visitor method: do nothing. */ @Override @@ -2239,14 +2234,6 @@ public class Check { validateAnnotation(a, s); } - /** Check the type annotations - */ - public void validateTypeAnnotations(List annotations, boolean isTypeParameter) { - if (skipAnnotations) return; - for (JCTypeAnnotation a : annotations) - validateTypeAnnotation(a, isTypeParameter); - } - /** Check an annotation of a symbol. */ public void validateAnnotation(JCAnnotation a, Symbol s) { @@ -2261,15 +2248,6 @@ public class Check { } } - public void validateTypeAnnotation(JCTypeAnnotation a, boolean isTypeParameter) { - if (a.type == null) - throw new AssertionError("annotation tree hasn't been attributed yet: " + a); - validateAnnotationTree(a); - - if (!isTypeAnnotation(a, isTypeParameter)) - log.error(a.pos(), "annotation.type.not.applicable"); - } - /** Is s a method symbol that overrides a method in a superclass? */ boolean isOverrider(Symbol s) { if (s.kind != MTH || s.isStatic()) @@ -2288,25 +2266,6 @@ public class Check { return false; } - /** Is the annotation applicable to type annotations */ - boolean isTypeAnnotation(JCTypeAnnotation a, boolean isTypeParameter) { - Attribute.Compound atTarget = - a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym); - if (atTarget == null) return true; - Attribute atValue = atTarget.member(names.value); - if (!(atValue instanceof Attribute.Array)) return true; // error recovery - Attribute.Array arr = (Attribute.Array) atValue; - for (Attribute app : arr.values) { - if (!(app instanceof Attribute.Enum)) return true; // recovery - Attribute.Enum e = (Attribute.Enum) app; - if (!isTypeParameter && e.value.name == names.TYPE_USE) - return true; - else if (isTypeParameter && e.value.name == names.TYPE_PARAMETER) - return true; - } - return false; - } - /** Is the annotation applicable to the symbol? */ boolean annotationApplicable(JCAnnotation a, Symbol s) { Attribute.Compound atTarget = diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java index 57a2d52d0e8..65471db51e4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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,6 @@ import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.code.Symbol.*; -import com.sun.tools.javac.comp.Resolve; import com.sun.tools.javac.tree.JCTree.*; import static com.sun.tools.javac.code.Flags.*; @@ -1350,11 +1349,6 @@ public class Flow extends TreeScanner { } } - public void visitAnnotatedType(JCAnnotatedType tree) { - // annotations don't get scanned - tree.underlyingType.accept(this); - } - public void visitIdent(JCIdent tree) { if (tree.sym.kind == VAR) { checkInit(tree.pos(), (VarSymbol)tree.sym); @@ -1373,7 +1367,6 @@ public class Flow extends TreeScanner { if (!tree.type.isErroneous() && lint.isEnabled(Lint.LintCategory.CAST) && types.isSameType(tree.expr.type, tree.clazz.type) - && !(ignoreAnnotatedCasts && containsTypeAnnotation(tree.clazz)) && !is292targetTypeCast(tree)) { log.warning(Lint.LintCategory.CAST, tree.pos(), "redundant.cast", tree.expr.type); @@ -1396,23 +1389,6 @@ public class Flow extends TreeScanner { // Do nothing for TopLevel since each class is visited individually } -/************************************************************************** - * utility methods for ignoring type-annotated casts lint checking - *************************************************************************/ - private static final boolean ignoreAnnotatedCasts = true; - private static class AnnotationFinder extends TreeScanner { - public boolean foundTypeAnno = false; - public void visitAnnotation(JCAnnotation tree) { - foundTypeAnno = foundTypeAnno || (tree instanceof JCTypeAnnotation); - } - } - - private boolean containsTypeAnnotation(JCTree e) { - AnnotationFinder finder = new AnnotationFinder(); - finder.scan(e); - return finder.foundTypeAnno; - } - /************************************************************************** * main method *************************************************************************/ diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java index f7fdf8ef611..366af533eb5 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -2585,11 +2585,6 @@ public class Lower extends TreeTranslator { result = tree; } - public void visitAnnotatedType(JCAnnotatedType tree) { - tree.underlyingType = translate(tree.underlyingType); - result = tree.underlyingType; - } - public void visitTypeCast(JCTypeCast tree) { tree.clazz = translate(tree.clazz); if (tree.type.isPrimitive() != tree.expr.type.isPrimitive()) diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java index 2df1437748c..12ac02d4a2b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -928,10 +928,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer { if (hasDeprecatedAnnotation(tree.mods.annotations)) c.flags_field |= DEPRECATED; annotateLater(tree.mods.annotations, baseEnv, c); - // class type parameters use baseEnv but everything uses env - for (JCTypeParameter tp : tree.typarams) - tp.accept(new TypeAnnotate(baseEnv)); - tree.accept(new TypeAnnotate(env)); chk.checkNonCyclicDecl(tree); @@ -1014,86 +1010,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } } - // A sub-phase that "compiles" annotations in annotated types. - private class TypeAnnotate extends TreeScanner { - private Env env; - public TypeAnnotate(Env env) { this.env = env; } - - private void enterTypeAnnotations(List annotations) { - Set annotated = new HashSet(); - if (!skipAnnotations) - for (List al = annotations; al.nonEmpty(); al = al.tail) { - JCTypeAnnotation a = al.head; - Attribute.Compound c = annotate.enterAnnotation(a, - syms.annotationType, - env); - if (c == null) continue; - Attribute.TypeCompound tc = new Attribute.TypeCompound(c.type, c.values, a.annotation_position); - a.attribute_field = tc; - // Note: @Deprecated has no effect on local variables and parameters - if (!annotated.add(a.type.tsym)) - log.error(a.pos, "duplicate.annotation"); - } - } - - // each class (including enclosed inner classes) should be visited - // separately through MemberEnter.complete(Symbol) - // this flag is used to prevent from visiting inner classes. - private boolean isEnclosingClass = false; - @Override - public void visitClassDef(final JCClassDecl tree) { - if (isEnclosingClass) - return; - isEnclosingClass = true; - scan(tree.mods); - // type parameter need to be visited with a separate env - // scan(tree.typarams); - scan(tree.extending); - scan(tree.implementing); - scan(tree.defs); - } - - private void annotate(final JCTree tree, final List annotations) { - annotate.later(new Annotate.Annotator() { - public String toString() { - return "annotate " + annotations + " onto " + tree; - } - public void enterAnnotation() { - JavaFileObject prev = log.useSource(env.toplevel.sourcefile); - try { - enterTypeAnnotations(annotations); - } finally { - log.useSource(prev); - } - } - }); - } - - @Override - public void visitAnnotatedType(final JCAnnotatedType tree) { - annotate(tree, tree.annotations); - super.visitAnnotatedType(tree); - } - @Override - public void visitTypeParameter(final JCTypeParameter tree) { - annotate(tree, tree.annotations); - super.visitTypeParameter(tree); - } - @Override - public void visitNewArray(final JCNewArray tree) { - annotate(tree, tree.annotations); - for (List dimAnnos : tree.dimAnnotations) - annotate(tree, dimAnnos); - super.visitNewArray(tree); - } - @Override - public void visitMethodDef(JCMethodDecl tree) { - annotate(tree, tree.receiverAnnotations); - super.visitMethodDef(tree); - } - } - - private Env baseEnv(JCClassDecl tree, Env env) { Scope baseScope = new Scope.ClassScope(tree.sym, scopeCounter); //import already entered local classes into base scope diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java index e2ebc0170ec..6271510843c 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -69,7 +69,6 @@ public class TransTypes extends TreeTranslator { private boolean allowEnums; private Types types; private final Resolve resolve; - private final TypeAnnotations typeAnnotations; /** * Flag to indicate whether or not to generate bridge methods. @@ -91,7 +90,6 @@ public class TransTypes extends TreeTranslator { types = Types.instance(context); make = TreeMaker.instance(context); resolve = Resolve.instance(context); - typeAnnotations = TypeAnnotations.instance(context); } /** A hashtable mapping bridge methods to the methods they override after @@ -445,14 +443,12 @@ public class TransTypes extends TreeTranslator { } public void visitClassDef(JCClassDecl tree) { - typeAnnotations.taFillAndLift(tree, true); translateClass(tree.sym); result = tree; } JCMethodDecl currentMethod = null; public void visitMethodDef(JCMethodDecl tree) { - tree.sym.typeAnnotations = tree.sym.typeAnnotations; JCMethodDecl previousMethod = currentMethod; try { currentMethod = tree; diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 0024f2fb5bf..4467f3607a6 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -207,10 +207,6 @@ public class ClassReader implements Completer { /** The minor version number of the class file being read. */ int minorVersion; - /** Switch: debug output for JSR 308-related operations. - */ - boolean debugJSR308; - /** A table to hold the constant pool indices for method parameter * names, as given in LocalVariableTable attributes. */ @@ -297,7 +293,6 @@ public class ClassReader implements Completer { : null; typevars = new Scope(syms.noSymbol); - debugJSR308 = options.isSet("TA:reader"); lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE); @@ -1128,20 +1123,6 @@ public class ClassReader implements Completer { } }, - // v51 attributes - new AttributeReader(names.RuntimeVisibleTypeAnnotations, V51, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { - attachTypeAnnotations(sym); - } - }, - - new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V51, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { - attachTypeAnnotations(sym); - } - }, - - // The following attributes for a Code attribute are not currently handled // StackMapTable // SourceDebugExtension @@ -1351,17 +1332,6 @@ public class ClassReader implements Completer { } } - void attachTypeAnnotations(final Symbol sym) { - int numAttributes = nextChar(); - if (numAttributes != 0) { - ListBuffer proxies = - ListBuffer.lb(); - for (int i = 0; i < numAttributes; i++) - proxies.append(readTypeAnnotation()); - annotate.later(new TypeAnnotationCompleter(sym, proxies.toList())); - } - } - /** Attach the default value for an annotation element. */ void attachAnnotationDefault(final Symbol sym) { @@ -1398,121 +1368,6 @@ public class ClassReader implements Completer { return new CompoundAnnotationProxy(t, pairs.toList()); } - TypeAnnotationProxy readTypeAnnotation() { - CompoundAnnotationProxy proxy = readCompoundAnnotation(); - TypeAnnotationPosition position = readPosition(); - - if (debugJSR308) - System.out.println("TA: reading: " + proxy + " @ " + position - + " in " + log.currentSourceFile()); - - return new TypeAnnotationProxy(proxy, position); - } - - TypeAnnotationPosition readPosition() { - byte tag = nextByte(); - - if (!TargetType.isValidTargetTypeValue(tag)) - throw this.badClassFile("bad.type.annotation.value", tag); - - TypeAnnotationPosition position = new TypeAnnotationPosition(); - TargetType type = TargetType.fromTargetTypeValue(tag); - - position.type = type; - - switch (type) { - // type case - case TYPECAST: - case TYPECAST_GENERIC_OR_ARRAY: - // object creation - case INSTANCEOF: - case INSTANCEOF_GENERIC_OR_ARRAY: - // new expression - case NEW: - case NEW_GENERIC_OR_ARRAY: - position.offset = nextChar(); - break; - // local variable - case LOCAL_VARIABLE: - case LOCAL_VARIABLE_GENERIC_OR_ARRAY: - int table_length = nextChar(); - position.lvarOffset = new int[table_length]; - position.lvarLength = new int[table_length]; - position.lvarIndex = new int[table_length]; - - for (int i = 0; i < table_length; ++i) { - position.lvarOffset[i] = nextChar(); - position.lvarLength[i] = nextChar(); - position.lvarIndex[i] = nextChar(); - } - break; - // method receiver - case METHOD_RECEIVER: - // Do nothing - break; - // type parameters - case CLASS_TYPE_PARAMETER: - case METHOD_TYPE_PARAMETER: - position.parameter_index = nextByte(); - break; - // type parameter bounds - case CLASS_TYPE_PARAMETER_BOUND: - case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - case METHOD_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - position.parameter_index = nextByte(); - position.bound_index = nextByte(); - break; - // wildcard - case WILDCARD_BOUND: - case WILDCARD_BOUND_GENERIC_OR_ARRAY: - position.wildcard_position = readPosition(); - break; - // Class extends and implements clauses - case CLASS_EXTENDS: - case CLASS_EXTENDS_GENERIC_OR_ARRAY: - position.type_index = nextChar(); - break; - // throws - case THROWS: - position.type_index = nextChar(); - break; - case CLASS_LITERAL: - case CLASS_LITERAL_GENERIC_OR_ARRAY: - position.offset = nextChar(); - break; - // method parameter: not specified - case METHOD_PARAMETER_GENERIC_OR_ARRAY: - position.parameter_index = nextByte(); - break; - // method type argument: wasn't specified - case NEW_TYPE_ARGUMENT: - case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - case METHOD_TYPE_ARGUMENT: - case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - position.offset = nextChar(); - position.type_index = nextByte(); - break; - // We don't need to worry abut these - case METHOD_RETURN_GENERIC_OR_ARRAY: - case FIELD_GENERIC_OR_ARRAY: - break; - case UNKNOWN: - break; - default: - throw new AssertionError("unknown type: " + position); - } - - if (type.hasLocation()) { - int len = nextChar(); - ListBuffer loc = ListBuffer.lb(); - for (int i = 0; i < len; i++) - loc = loc.append((int)nextByte()); - position.location = loc.toList(); - } - - return position; - } Attribute readAttributeValue() { char c = (char) buf[bp++]; switch (c) { @@ -1825,45 +1680,6 @@ public class ClassReader implements Completer { } } - class TypeAnnotationCompleter extends AnnotationCompleter { - - List proxies; - - TypeAnnotationCompleter(Symbol sym, - List proxies) { - super(sym, List.nil()); - this.proxies = proxies; - } - - List deproxyTypeCompoundList(List proxies) { - ListBuffer buf = ListBuffer.lb(); - for (TypeAnnotationProxy proxy: proxies) { - Attribute.Compound compound = deproxyCompound(proxy.compound); - Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position); - buf.add(typeCompound); - } - return buf.toList(); - } - - @Override - public void enterAnnotation() { - JavaFileObject previousClassFile = currentClassFile; - try { - currentClassFile = classFile; - List newList = deproxyTypeCompoundList(proxies); - if (debugJSR308) - System.out.println("TA: reading: adding " + newList - + " to symbol " + sym + " in " + log.currentSourceFile()); - sym.typeAnnotations = ((sym.typeAnnotations == null) - ? newList - : newList.prependList(sym.typeAnnotations)); - - } finally { - currentClassFile = previousClassFile; - } - } - } - /************************************************************************ * Reading Symbols diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 357e9f037c7..7fa494b97e5 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,10 +65,6 @@ public class ClassWriter extends ClassFile { private final Options options; - /** Switch: debugging output for JSR 308-related operations. - */ - private boolean debugJSR308; - /** Switch: verbose output. */ private boolean verbose; @@ -180,7 +176,6 @@ public class ClassWriter extends ClassFile { types = Types.instance(context); fileManager = context.get(JavaFileManager.class); - debugJSR308 = options.isSet("TA:writer"); verbose = options.isSet(VERBOSE); scramble = options.isSet("-scramble"); scrambleAll = options.isSet("-scrambleAll"); @@ -677,7 +672,6 @@ public class ClassWriter extends ClassFile { acount++; } acount += writeJavaAnnotations(sym.getAnnotationMirrors()); - acount += writeTypeAnnotations(sym.typeAnnotations); return acount; } @@ -772,46 +766,6 @@ public class ClassWriter extends ClassFile { return attrCount; } - int writeTypeAnnotations(List typeAnnos) { - if (typeAnnos.isEmpty()) return 0; - - ListBuffer visibles = ListBuffer.lb(); - ListBuffer invisibles = ListBuffer.lb(); - - for (Attribute.TypeCompound tc : typeAnnos) { - if (tc.position.type == TargetType.UNKNOWN - || !tc.position.emitToClassfile()) - continue; - switch (types.getRetention(tc)) { - case SOURCE: break; - case CLASS: invisibles.append(tc); break; - case RUNTIME: visibles.append(tc); break; - default: ;// /* fail soft */ throw new AssertionError(vis); - } - } - - int attrCount = 0; - if (visibles.length() != 0) { - int attrIndex = writeAttr(names.RuntimeVisibleTypeAnnotations); - databuf.appendChar(visibles.length()); - for (Attribute.TypeCompound p : visibles) - writeTypeAnnotation(p); - endAttr(attrIndex); - attrCount++; - } - - if (invisibles.length() != 0) { - int attrIndex = writeAttr(names.RuntimeInvisibleTypeAnnotations); - databuf.appendChar(invisibles.length()); - for (Attribute.TypeCompound p : invisibles) - writeTypeAnnotation(p); - endAttr(attrIndex); - attrCount++; - } - - return attrCount; - } - /** A visitor to write an attribute including its leading * single-character marker. */ @@ -888,104 +842,6 @@ public class ClassWriter extends ClassFile { p.snd.accept(awriter); } } - - void writeTypeAnnotation(Attribute.TypeCompound c) { - if (debugJSR308) - System.out.println("TA: writing " + c + " at " + c.position - + " in " + log.currentSourceFile()); - writeCompoundAttribute(c); - writePosition(c.position); - } - - void writePosition(TypeAnnotationPosition p) { - databuf.appendByte(p.type.targetTypeValue()); - switch (p.type) { - // type case - case TYPECAST: - case TYPECAST_GENERIC_OR_ARRAY: - // object creation - case INSTANCEOF: - case INSTANCEOF_GENERIC_OR_ARRAY: - // new expression - case NEW: - case NEW_GENERIC_OR_ARRAY: - databuf.appendChar(p.offset); - break; - // local variable - case LOCAL_VARIABLE: - case LOCAL_VARIABLE_GENERIC_OR_ARRAY: - databuf.appendChar(p.lvarOffset.length); // for table length - for (int i = 0; i < p.lvarOffset.length; ++i) { - databuf.appendChar(p.lvarOffset[i]); - databuf.appendChar(p.lvarLength[i]); - databuf.appendChar(p.lvarIndex[i]); - } - break; - // method receiver - case METHOD_RECEIVER: - // Do nothing - break; - // type parameters - case CLASS_TYPE_PARAMETER: - case METHOD_TYPE_PARAMETER: - databuf.appendByte(p.parameter_index); - break; - // type parameters bounds - case CLASS_TYPE_PARAMETER_BOUND: - case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - case METHOD_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - databuf.appendByte(p.parameter_index); - databuf.appendByte(p.bound_index); - break; - // wildcards - case WILDCARD_BOUND: - case WILDCARD_BOUND_GENERIC_OR_ARRAY: - writePosition(p.wildcard_position); - break; - // Class extends and implements clauses - case CLASS_EXTENDS: - case CLASS_EXTENDS_GENERIC_OR_ARRAY: - databuf.appendChar(p.type_index); - break; - // throws - case THROWS: - databuf.appendChar(p.type_index); - break; - case CLASS_LITERAL: - case CLASS_LITERAL_GENERIC_OR_ARRAY: - databuf.appendChar(p.offset); - break; - // method parameter: not specified - case METHOD_PARAMETER_GENERIC_OR_ARRAY: - databuf.appendByte(p.parameter_index); - break; - // method type argument: wasn't specified - case NEW_TYPE_ARGUMENT: - case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - case METHOD_TYPE_ARGUMENT: - case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - databuf.appendChar(p.offset); - databuf.appendByte(p.type_index); - break; - // We don't need to worry abut these - case METHOD_RETURN_GENERIC_OR_ARRAY: - case FIELD_GENERIC_OR_ARRAY: - break; - case UNKNOWN: - break; - default: - throw new AssertionError("unknown position: " + p); - } - - // Append location data for generics/arrays. - if (p.type.hasLocation()) { - databuf.appendChar(p.location.size()); - for (int i : p.location) - databuf.appendByte((byte)i); - } - } - /********************************************************************** * Writing Objects **********************************************************************/ @@ -1698,7 +1554,6 @@ public class ClassWriter extends ClassFile { acount += writeFlagAttrs(c.flags()); acount += writeJavaAnnotations(c.getAnnotationMirrors()); - acount += writeTypeAnnotations(c.typeAnnotations); acount += writeEnclosingMethodAttribute(c); poolbuf.appendInt(JAVA_MAGIC); diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java index 54d2600f2f7..58e7c8a72ce 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -1912,29 +1912,12 @@ public class Code { if (length < Character.MAX_VALUE) { v.length = length; putVar(v); - fillLocalVarPosition(v); } } } state.defined.excl(adr); } - private void fillLocalVarPosition(LocalVar lv) { - if (lv == null || lv.sym == null - || lv.sym.typeAnnotations == null) - return; - for (Attribute.TypeCompound ta : lv.sym.typeAnnotations) { - TypeAnnotationPosition p = ta.position; - while (p != null) { - p.lvarOffset = new int[] { (int)lv.start_pc }; - p.lvarLength = new int[] { (int)lv.length }; - p.lvarIndex = new int[] { (int)lv.reg }; - p.isValidOffset = true; - p = p.wildcard_position; - } - } - } - /** Put a live variable range into the buffer to be output to the * class file. */ diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java index 452a439a6c5..e87bd6f7bb1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -1682,7 +1682,6 @@ public class Gen extends JCTree.Visitor { *************************************************************************/ public void visitApply(JCMethodInvocation tree) { - setTypeAnnotationPositions(tree.pos); // Generate code for method. Item m = genExpr(tree.meth, methodType); // Generate code for all arguments, where the expected types are @@ -1718,48 +1717,10 @@ public class Gen extends JCTree.Visitor { result = items.makeStackItem(pt); } - private void setTypeAnnotationPositions(int treePos) { - MethodSymbol meth = code.meth; - - for (Attribute.TypeCompound ta : meth.typeAnnotations) { - if (ta.position.pos == treePos) { - ta.position.offset = code.cp; - ta.position.lvarOffset = new int[] { code.cp }; - ta.position.isValidOffset = true; - } - } - - if (code.meth.getKind() != ElementKind.CONSTRUCTOR - && code.meth.getKind() != ElementKind.STATIC_INIT) - return; - - for (Attribute.TypeCompound ta : meth.owner.typeAnnotations) { - if (ta.position.pos == treePos) { - ta.position.offset = code.cp; - ta.position.lvarOffset = new int[] { code.cp }; - ta.position.isValidOffset = true; - } - } - - ClassSymbol clazz = meth.enclClass(); - for (Symbol s : new com.sun.tools.javac.model.FilteredMemberList(clazz.members())) { - if (!s.getKind().isField()) - continue; - for (Attribute.TypeCompound ta : s.typeAnnotations) { - if (ta.position.pos == treePos) { - ta.position.offset = code.cp; - ta.position.lvarOffset = new int[] { code.cp }; - ta.position.isValidOffset = true; - } - } - } - } - public void visitNewClass(JCNewClass tree) { // Enclosing instances or anonymous classes should have been eliminated // by now. assert tree.encl == null && tree.def == null; - setTypeAnnotationPositions(tree.pos); code.emitop2(new_, makeRef(tree.pos(), tree.type)); code.emitop0(dup); @@ -1774,7 +1735,6 @@ public class Gen extends JCTree.Visitor { } public void visitNewArray(JCNewArray tree) { - setTypeAnnotationPositions(tree.pos); if (tree.elems != null) { Type elemtype = types.elemtype(tree.type); @@ -2104,7 +2064,6 @@ public class Gen extends JCTree.Visitor { } public void visitTypeCast(JCTypeCast tree) { - setTypeAnnotationPositions(tree.pos); result = genExpr(tree.expr, tree.clazz.type).load(); // Additional code is only needed if we cast to a reference type // which is not statically a supertype of the expression's type. @@ -2121,8 +2080,6 @@ public class Gen extends JCTree.Visitor { } public void visitTypeTest(JCInstanceOf tree) { - setTypeAnnotationPositions(tree.pos); - genExpr(tree.expr, tree.expr.type).load(); code.emitop2(instanceof_, makeRef(tree.pos(), tree.clazz.type)); result = items.makeStackItem(syms.booleanType); @@ -2164,15 +2121,9 @@ public class Gen extends JCTree.Visitor { if (tree.name == names._class) { assert target.hasClassLiterals(); - setTypeAnnotationPositions(tree.pos); code.emitop2(ldc2, makeRef(tree.pos(), tree.selected.type)); result = items.makeStackItem(pt); return; - } else if (tree.name == names.TYPE) { - // Set the annotation positions for primitive class literals - // (e.g. int.class) which have been converted to TYPE field - // access on the corresponding boxed type (e.g. Integer.TYPE). - setTypeAnnotationPositions(tree.pos); } Symbol ssym = TreeInfo.symbol(tree.selected); diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 8e5884ded9b..7592e231265 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, 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 @@ -49,7 +49,6 @@ import javax.tools.StandardJavaFileManager; import javax.tools.JavaFileObject; import javax.tools.DiagnosticListener; -//308 import com.sun.source.util.AbstractTypeProcessor; import com.sun.source.util.TaskEvent; import com.sun.source.util.TaskListener; import com.sun.tools.javac.api.JavacTaskImpl; @@ -712,7 +711,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea } if (matchedNames.size() > 0 || ps.contributed) { -//308 foundTypeProcessors = foundTypeProcessors || (ps.processor instanceof AbstractTypeProcessor); boolean processingResult = callProcessor(ps.processor, typeElements, renv); ps.contributed = true; ps.removeSupportedOptions(unmatchedProcessorOptions); diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index a5b5991afc7..944fd7bd515 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2011, 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 @@ -971,8 +971,6 @@ compiler.misc.bad.const.pool.tag.at=\ bad constant pool tag: {0} at {1} compiler.misc.bad.signature=\ bad signature: {0} -compiler.misc.bad.type.annotation.value=\ - bad type annotation target type value: {0} compiler.misc.class.file.wrong.class=\ class file contains wrong class: {0} compiler.misc.class.file.not.found=\ diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java index 3e7296a71dd..13d0d076a47 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -640,7 +640,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public JCExpression restype; public List typarams; public List params; - public List receiverAnnotations; public List thrown; public JCBlock body; public JCExpression defaultValue; // for annotation types @@ -650,7 +649,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { JCExpression restype, List typarams, List params, - List receiver, List thrown, JCBlock body, JCExpression defaultValue, @@ -661,7 +659,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { this.restype = restype; this.typarams = typarams; this.params = params; - this.receiverAnnotations = (receiver != null ? receiver : List.nil()); this.thrown = thrown; this.body = body; this.defaultValue = defaultValue; @@ -680,7 +677,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public List getParameters() { return params; } - public List getReceiverAnnotations() { return receiverAnnotations; } public List getThrows() { return thrown; } @@ -1402,8 +1398,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public static class JCNewArray extends JCExpression implements NewArrayTree { public JCExpression elemtype; public List dims; - public List annotations; - public List> dimAnnotations; public List elems; protected JCNewArray(JCExpression elemtype, List dims, @@ -1411,8 +1405,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { { this.elemtype = elemtype; this.dims = dims; - this.annotations = List.nil(); - this.dimAnnotations = List.nil(); this.elems = elems; } @Override @@ -1923,11 +1915,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public static class JCTypeParameter extends JCTree implements TypeParameterTree { public Name name; public List bounds; - public List annotations; - protected JCTypeParameter(Name name, List bounds, List annotations) { + protected JCTypeParameter(Name name, List bounds) { this.name = name; this.bounds = bounds; - this.annotations = annotations; } @Override public void accept(Visitor v) { v.visitTypeParameter(this); } @@ -1937,9 +1927,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public List getBounds() { return bounds; } - public List getAnnotations() { - return annotations; - } @Override public R accept(TreeVisitor v, D d) { return v.visitTypeParameter(this, d); @@ -2030,16 +2017,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { } } - public static class JCTypeAnnotation extends JCAnnotation { - public TypeAnnotationPosition annotation_position; - public Attribute.TypeCompound attribute_field; - - protected JCTypeAnnotation(JCTree annotationType, List args) { - super(annotationType, args); - this.annotation_position = new TypeAnnotationPosition(); - } - } - public static class JCModifiers extends JCTree implements com.sun.source.tree.ModifiersTree { public long flags; public List annotations; @@ -2067,40 +2044,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { } } - public static class JCAnnotatedType extends JCExpression -//308 implements com.sun.source.tree.AnnotatedTypeTree - { - public List annotations; - public JCExpression underlyingType; - protected JCAnnotatedType(List annotations, JCExpression underlyingType) { - throw new UnsupportedOperationException(); -//308 this.annotations = annotations; -//308 this.underlyingType = underlyingType; - } - @Override - public void accept(Visitor v) { v.visitAnnotatedType(this); } - - public Kind getKind() { - throw new UnsupportedOperationException(); -//308 return Kind.ANNOTATED_TYPE; - } - public List getAnnotations() { - return annotations; - } - public JCExpression getUnderlyingType() { - return underlyingType; - } - @Override - public R accept(TreeVisitor v, D d) { - throw new UnsupportedOperationException(); -//308 return v.visitAnnotatedType(this, d); - } - @Override - public int getTag() { - return ANNOTATED_TYPE; - } - } - public static class JCErroneous extends JCExpression implements com.sun.source.tree.ErroneousTree { public List errs; @@ -2168,7 +2111,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { JCExpression restype, List typarams, List params, - List receiver, List thrown, JCBlock body, JCExpression defaultValue); @@ -2290,7 +2232,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public void visitTypeBoundKind(TypeBoundKind that) { visitTree(that); } public void visitAnnotation(JCAnnotation that) { visitTree(that); } public void visitModifiers(JCModifiers that) { visitTree(that); } - public void visitAnnotatedType(JCAnnotatedType that) { visitTree(that); } public void visitErroneous(JCErroneous that) { visitTree(that); } public void visitLetExpr(LetExpr that) { visitTree(that); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java index be5571dbddb..4c45a7225b3 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -224,15 +224,6 @@ public class Pretty extends JCTree.Visitor { } } - public void printTypeAnnotations(List trees) throws IOException { - if (trees.nonEmpty()) - print(" "); - for (List l = trees; l.nonEmpty(); l = l.tail) { - printExpr(l.head); - print(" "); - } - } - /** Print documentation comment, if it exists * @param tree The tree for which a documentation comment should be printed. */ @@ -890,33 +881,21 @@ public class Pretty extends JCTree.Visitor { try { if (tree.elemtype != null) { print("new "); - printTypeAnnotations(tree.annotations); JCTree elem = tree.elemtype; - printBaseElementType(elem); - boolean isElemAnnoType = elem instanceof JCAnnotatedType; - int i = 0; - List> da = tree.dimAnnotations; + if (elem.getTag() == JCTree.TYPEARRAY) + printBaseElementType((JCArrayTypeTree) elem); + else + printExpr(elem); for (List l = tree.dims; l.nonEmpty(); l = l.tail) { - if (da.size() > i) { - printTypeAnnotations(da.get(i)); - } print("["); - i++; printExpr(l.head); print("]"); } - if (tree.elems != null) { - if (isElemAnnoType) { - printTypeAnnotations(((JCAnnotatedType)tree.elemtype).annotations); - } - print("[]"); - } - if (isElemAnnoType) - elem = ((JCAnnotatedType)elem).underlyingType; if (elem instanceof JCArrayTypeTree) printBrackets((JCArrayTypeTree) elem); } if (tree.elems != null) { + if (tree.elemtype != null) print("[]"); print("{"); printExprs(tree.elems); print("}"); @@ -1173,11 +1152,6 @@ public class Pretty extends JCTree.Visitor { JCTree elem; while (true) { elem = tree.elemtype; - if (elem.getTag() == JCTree.ANNOTATED_TYPE) { - JCAnnotatedType atype = (JCAnnotatedType) elem; - printTypeAnnotations(atype.annotations); - elem = atype.underlyingType; - } print("[]"); if (elem.getTag() != JCTree.TYPEARRAY) break; tree = (JCArrayTypeTree) elem; @@ -1272,15 +1246,6 @@ public class Pretty extends JCTree.Visitor { } } - public void visitAnnotatedType(JCAnnotatedType tree) { - try { - printTypeAnnotations(tree.annotations); - printExpr(tree.underlyingType); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - public void visitTree(JCTree tree) { try { print("(UNKNOWN: " + tree + ")"); diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java index 13032f26155..a5e70fbf81c 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2011, 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 @@ -71,13 +71,6 @@ public class TreeCopier

implements TreeVisitor { return lb.toList(); } -//308 public JCTree visitAnnotatedType(AnnotatedTypeTree node, P p) { -//308 JCAnnotatedType t = (JCAnnotatedType) node; -//308 List annotations = copy(t.annotations, p); -//308 JCExpression underlyingType = copy(t.underlyingType, p); -//308 return M.at(t.pos).AnnotatedType(annotations, underlyingType); -//308 } - public JCTree visitAnnotation(AnnotationTree node, P p) { JCAnnotation t = (JCAnnotation) node; JCTree annotationType = copy(t.annotationType, p); @@ -240,11 +233,10 @@ public class TreeCopier

implements TreeVisitor { JCExpression restype = copy(t.restype, p); List typarams = copy(t.typarams, p); List params = copy(t.params, p); - List receiver = copy(t.receiverAnnotations, p); List thrown = copy(t.thrown, p); JCBlock body = copy(t.body, p); JCExpression defaultValue = copy(t.defaultValue, p); - return M.at(t.pos).MethodDef(mods, t.name, restype, typarams, params, receiver, thrown, body, defaultValue); + return M.at(t.pos).MethodDef(mods, t.name, restype, typarams, params, thrown, body, defaultValue); } public JCTree visitMethodInvocation(MethodInvocationTree node, P p) { @@ -372,9 +364,8 @@ public class TreeCopier

implements TreeVisitor { public JCTree visitTypeParameter(TypeParameterTree node, P p) { JCTypeParameter t = (JCTypeParameter) node; - List annos = copy(t.annotations, p); List bounds = copy(t.bounds, p); - return M.at(t.pos).TypeParameter(t.name, bounds, annos); + return M.at(t.pos).TypeParameter(t.name, bounds); } public JCTree visitInstanceOf(InstanceOfTree node, P p) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java index b33e200b4d7..f6e364e2936 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -311,12 +311,6 @@ public class TreeInfo { case(JCTree.POSTINC): case(JCTree.POSTDEC): return getStartPos(((JCUnary) tree).arg); - case(JCTree.ANNOTATED_TYPE): { - JCAnnotatedType node = (JCAnnotatedType) tree; - if (node.annotations.nonEmpty()) - return getStartPos(node.annotations.head); - return getStartPos(node.underlyingType); - } case(JCTree.NEWCLASS): { JCNewClass node = (JCNewClass)tree; if (node.encl != null) @@ -420,8 +414,6 @@ public class TreeInfo { return getEndPos(((JCUnary) tree).arg, endPositions); case(JCTree.WHILELOOP): return getEndPos(((JCWhileLoop) tree).body, endPositions); - case(JCTree.ANNOTATED_TYPE): - return getEndPos(((JCAnnotatedType) tree).underlyingType, endPositions); case(JCTree.ERRONEOUS): { JCErroneous node = (JCErroneous)tree; if (node.errs != null && node.errs.nonEmpty()) @@ -909,8 +901,6 @@ public class TreeInfo { */ public static JCExpression typeIn(JCExpression tree) { switch (tree.getTag()) { - case JCTree.ANNOTATED_TYPE: - return ((JCAnnotatedType)tree).underlyingType; case JCTree.IDENT: /* simple names */ case JCTree.TYPEIDENT: /* primitive name */ case JCTree.SELECT: /* qualified name */ @@ -930,8 +920,6 @@ public class TreeInfo { return innermostType(((JCArrayTypeTree)type).elemtype); case JCTree.WILDCARD: return innermostType(((JCWildcard)type).inner); - case JCTree.ANNOTATED_TYPE: - return innermostType(((JCAnnotatedType)type).underlyingType); default: return type; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java index 5d4cb59179a..879070f3595 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -169,27 +169,11 @@ public class TreeMaker implements JCTree.Factory { List thrown, JCBlock body, JCExpression defaultValue) { - return MethodDef( - mods, name, restype, typarams, params, - null, thrown, body, defaultValue); - } - - public JCMethodDecl MethodDef(JCModifiers mods, - Name name, - JCExpression restype, - List typarams, - List params, - List receiver, - List thrown, - JCBlock body, - JCExpression defaultValue) - { JCMethodDecl tree = new JCMethodDecl(mods, name, restype, typarams, params, - receiver, thrown, body, defaultValue, @@ -458,11 +442,7 @@ public class TreeMaker implements JCTree.Factory { } public JCTypeParameter TypeParameter(Name name, List bounds) { - return TypeParameter(name, bounds, List.nil()); - } - - public JCTypeParameter TypeParameter(Name name, List bounds, List annos) { - JCTypeParameter tree = new JCTypeParameter(name, bounds, annos); + JCTypeParameter tree = new JCTypeParameter(name, bounds); tree.pos = pos; return tree; } @@ -485,12 +465,6 @@ public class TreeMaker implements JCTree.Factory { return tree; } - public JCTypeAnnotation TypeAnnotation(JCTree annotationType, List args) { - JCTypeAnnotation tree = new JCTypeAnnotation(annotationType, args); - tree.pos = pos; - return tree; - } - public JCModifiers Modifiers(long flags, List annotations) { JCModifiers tree = new JCModifiers(flags, annotations); boolean noFlags = (flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0; @@ -502,12 +476,6 @@ public class TreeMaker implements JCTree.Factory { return Modifiers(flags, List.nil()); } - public JCAnnotatedType AnnotatedType(List annotations, JCExpression underlyingType) { - JCAnnotatedType tree = new JCAnnotatedType(annotations, underlyingType); - tree.pos = pos; - return tree; - } - public JCErroneous Erroneous() { return Erroneous(List.nil()); } @@ -821,7 +789,6 @@ public class TreeMaker implements JCTree.Factory { Type(mtype.getReturnType()), TypeParams(mtype.getTypeArguments()), Params(mtype.getParameterTypes(), m), - null, Types(mtype.getThrownTypes()), body, null, diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java index be0eb48a0d3..7cc9045fae9 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -85,7 +85,6 @@ public class TreeScanner extends Visitor { scan(tree.restype); scan(tree.typarams); scan(tree.params); - scan(tree.receiverAnnotations); scan(tree.thrown); scan(tree.defaultValue); scan(tree.body); @@ -208,11 +207,8 @@ public class TreeScanner extends Visitor { } public void visitNewArray(JCNewArray tree) { - scan(tree.annotations); scan(tree.elemtype); scan(tree.dims); - for (List annos : tree.dimAnnotations) - scan(annos); scan(tree.elems); } @@ -281,7 +277,6 @@ public class TreeScanner extends Visitor { } public void visitTypeParameter(JCTypeParameter tree) { - scan(tree.annotations); scan(tree.bounds); } @@ -305,11 +300,6 @@ public class TreeScanner extends Visitor { scan(tree.args); } - public void visitAnnotatedType(JCAnnotatedType tree) { - scan(tree.annotations); - scan(tree.underlyingType); - } - public void visitErroneous(JCErroneous tree) { } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java index 3b980884b27..d909b34bcba 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -283,11 +283,6 @@ public class TreeTranslator extends JCTree.Visitor { } public void visitNewArray(JCNewArray tree) { - tree.annotations = translate(tree.annotations); - List> dimAnnos = List.nil(); - for (List origDimAnnos : tree.dimAnnotations) - dimAnnos = dimAnnos.append(translate(origDimAnnos)); - tree.dimAnnotations = dimAnnos; tree.elemtype = translate(tree.elemtype); tree.dims = translate(tree.dims); tree.elems = translate(tree.elems); @@ -374,7 +369,6 @@ public class TreeTranslator extends JCTree.Visitor { } public void visitTypeParameter(JCTypeParameter tree) { - tree.annotations = translate(tree.annotations); tree.bounds = translate(tree.bounds); result = tree; } @@ -412,12 +406,6 @@ public class TreeTranslator extends JCTree.Visitor { result = tree; } - public void visitAnnotatedType(JCAnnotatedType tree) { - tree.annotations = translate(tree.annotations); - tree.underlyingType = translate(tree.underlyingType); - result = tree; - } - public void visitTree(JCTree tree) { throw new AssertionError(tree); } diff --git a/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java b/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java index 6e8b5cb7811..37ec6b291e4 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2011, 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 @@ -26,7 +26,6 @@ package com.sun.tools.javap; import com.sun.tools.classfile.Annotation; -import com.sun.tools.classfile.ExtendedAnnotation; import com.sun.tools.classfile.Annotation.Annotation_element_value; import com.sun.tools.classfile.Annotation.Array_element_value; import com.sun.tools.classfile.Annotation.Class_element_value; @@ -77,129 +76,6 @@ public class AnnotationWriter extends BasicWriter { print(")"); } - public void write(ExtendedAnnotation annot) { - write(annot, true, false); - } - - public void write(ExtendedAnnotation annot, boolean showOffsets, boolean resolveIndices) { - write(annot.annotation, resolveIndices); - print(": "); - write(annot.position, showOffsets); - } - - public void write(ExtendedAnnotation.Position pos, boolean showOffsets) { - print(pos.type); - - switch (pos.type) { - // type case - case TYPECAST: - case TYPECAST_GENERIC_OR_ARRAY: - // object creation - case INSTANCEOF: - case INSTANCEOF_GENERIC_OR_ARRAY: - // new expression - case NEW: - case NEW_GENERIC_OR_ARRAY: - case NEW_TYPE_ARGUMENT: - case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - if (showOffsets) { - print(", offset="); - print(pos.offset); - } - break; - // local variable - case LOCAL_VARIABLE: - case LOCAL_VARIABLE_GENERIC_OR_ARRAY: - print(", {"); - for (int i = 0; i < pos.lvarOffset.length; ++i) { - if (i != 0) print("; "); - if (showOffsets) { - print(", start_pc="); - print(pos.lvarOffset[i]); - } - print(", length="); - print(pos.lvarLength[i]); - print(", index="); - print(pos.lvarIndex[i]); - } - print("}"); - break; - // method receiver - case METHOD_RECEIVER: - // Do nothing - break; - // type parameters - case CLASS_TYPE_PARAMETER: - case METHOD_TYPE_PARAMETER: - print(", param_index="); - print(pos.parameter_index); - break; - // type parameters bound - case CLASS_TYPE_PARAMETER_BOUND: - case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - case METHOD_TYPE_PARAMETER_BOUND: - case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY: - print(", param_index="); - print(pos.parameter_index); - print(", bound_index="); - print(pos.bound_index); - break; - // wildcard - case WILDCARD_BOUND: - case WILDCARD_BOUND_GENERIC_OR_ARRAY: - print(", wild_card="); - print(pos.wildcard_position); - break; - // Class extends and implements clauses - case CLASS_EXTENDS: - case CLASS_EXTENDS_GENERIC_OR_ARRAY: - print(", type_index="); - print(pos.type_index); - break; - // throws - case THROWS: - print(", type_index="); - print(pos.type_index); - break; - case CLASS_LITERAL: - case CLASS_LITERAL_GENERIC_OR_ARRAY: - if (showOffsets) { - print(", offset="); - print(pos.offset); - } - break; - // method parameter: not specified - case METHOD_PARAMETER_GENERIC_OR_ARRAY: - print(", param_index="); - print(pos.parameter_index); - break; - // method type argument: wasn't specified - case METHOD_TYPE_ARGUMENT: - case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY: - if (showOffsets) { - print(", offset="); - print(pos.offset); - } - print(", type_index="); - print(pos.type_index); - break; - // We don't need to worry abut these - case METHOD_RETURN_GENERIC_OR_ARRAY: - case FIELD_GENERIC_OR_ARRAY: - break; - case UNKNOWN: - break; - default: - throw new AssertionError("unknown type: " + pos.type); - } - - // Append location data for generics/arrays. - if (pos.type.hasLocation()) { - print(", location="); - print(pos.location); - } - } - public void write(Annotation.element_value_pair pair) { write(pair, false); } diff --git a/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java b/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java index 56f2f562e00..6d7efe1008b 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2011, 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 @@ -47,10 +47,8 @@ import com.sun.tools.classfile.LocalVariableTable_attribute; import com.sun.tools.classfile.LocalVariableTypeTable_attribute; import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; -import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute; -import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; import com.sun.tools.classfile.Signature_attribute; import com.sun.tools.classfile.SourceDebugExtension_attribute; import com.sun.tools.classfile.SourceFile_attribute; @@ -392,30 +390,6 @@ public class AttributeWriter extends BasicWriter return null; } - public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, Void ignore) { - println("RuntimeVisibleTypeAnnotations:"); - indent(+1); - for (int i = 0; i < attr.annotations.length; i++) { - print(i + ": "); - annotationWriter.write(attr.annotations[i]); - println(); - } - indent(-1); - return null; - } - - public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, Void ignore) { - println("RuntimeInvisibleTypeAnnotations:"); - indent(+1); - for (int i = 0; i < attr.annotations.length; i++) { - print(i + ": "); - annotationWriter.write(attr.annotations[i]); - println(); - } - indent(-1); - return null; - } - public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) { println("RuntimeVisibleParameterAnnotations:"); indent(+1); diff --git a/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java b/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java index 06d2b3c39d0..56bf415843e 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2011, 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 @@ -64,7 +64,6 @@ class CodeWriter extends BasicWriter { stackMapWriter = StackMapWriter.instance(context); localVariableTableWriter = LocalVariableTableWriter.instance(context); localVariableTypeTableWriter = LocalVariableTypeTableWriter.instance(context); - typeAnnotationWriter = TypeAnnotationWriter.instance(context); options = Options.instance(context); } @@ -266,11 +265,6 @@ class CodeWriter extends BasicWriter { detailWriters.add(tryBlockWriter); } - if (options.details.contains(InstructionDetailWriter.Kind.TYPE_ANNOS)) { - typeAnnotationWriter.reset(attr); - detailWriters.add(typeAnnotationWriter); - } - return detailWriters; } @@ -279,7 +273,6 @@ class CodeWriter extends BasicWriter { private ConstantWriter constantWriter; private LocalVariableTableWriter localVariableTableWriter; private LocalVariableTypeTableWriter localVariableTypeTableWriter; - private TypeAnnotationWriter typeAnnotationWriter; private SourceWriter sourceWriter; private StackMapWriter stackMapWriter; private TryBlockWriter tryBlockWriter; diff --git a/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java b/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java index c863793319c..7459d6c0d11 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, 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 @@ -42,13 +42,13 @@ public abstract class InstructionDetailWriter extends BasicWriter { LOCAL_VAR_TYPES("localVariableTypes"), SOURCE("source"), STACKMAPS("stackMaps"), - TRY_BLOCKS("tryBlocks"), - TYPE_ANNOS("typeAnnotations"); + TRY_BLOCKS("tryBlocks"); Kind(String option) { this.option = option; } final String option; } + InstructionDetailWriter(Context context) { super(context); } diff --git a/langtools/src/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java b/langtools/src/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java deleted file mode 100644 index 3a1a86f9633..00000000000 --- a/langtools/src/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2009, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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. - */ -package com.sun.tools.javap; - -import com.sun.tools.classfile.Attribute; -import com.sun.tools.classfile.Code_attribute; -import com.sun.tools.classfile.ExtendedAnnotation; -import com.sun.tools.classfile.ExtendedAnnotation.Position; -import com.sun.tools.classfile.Instruction; -import com.sun.tools.classfile.Method; -import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; -import com.sun.tools.classfile.RuntimeTypeAnnotations_attribute; -import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Annotate instructions with details about type annotations. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class TypeAnnotationWriter extends InstructionDetailWriter { - public enum NoteKind { VISIBLE, INVISIBLE }; - public static class Note { - Note(NoteKind kind, ExtendedAnnotation anno) { - this.kind = kind; - this.anno = anno; - } - public final NoteKind kind; - public final ExtendedAnnotation anno; - } - - static TypeAnnotationWriter instance(Context context) { - TypeAnnotationWriter instance = context.get(TypeAnnotationWriter.class); - if (instance == null) - instance = new TypeAnnotationWriter(context); - return instance; - } - - protected TypeAnnotationWriter(Context context) { - super(context); - context.put(TypeAnnotationWriter.class, this); - annotationWriter = AnnotationWriter.instance(context); - classWriter = ClassWriter.instance(context); - } - - public void reset(Code_attribute attr) { - Method m = classWriter.getMethod(); - pcMap = new HashMap>(); - check(NoteKind.VISIBLE, (RuntimeVisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeVisibleTypeAnnotations)); - check(NoteKind.INVISIBLE, (RuntimeInvisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeInvisibleTypeAnnotations)); - } - - private void check(NoteKind kind, RuntimeTypeAnnotations_attribute attr) { - if (attr == null) - return; - - for (ExtendedAnnotation anno: attr.annotations) { - Position p = anno.position; - Note note = null; - if (p.offset != -1) - addNote(p.offset, note = new Note(kind, anno)); - if (p.lvarOffset != null) { - for (int i = 0; i < p.lvarOffset.length; i++) { - if (note == null) - note = new Note(kind, anno); - addNote(p.lvarOffset[i], note); - } - } - } - } - - private void addNote(int pc, Note note) { - List list = pcMap.get(pc); - if (list == null) - pcMap.put(pc, list = new ArrayList()); - list.add(note); - } - - @Override - void writeDetails(Instruction instr) { - String indent = space(2); // get from Options? - int pc = instr.getPC(); - List notes = pcMap.get(pc); - if (notes != null) { - for (Note n: notes) { - print(indent); - print("@"); - annotationWriter.write(n.anno, false, true); - print(", "); - println(n.kind.toString().toLowerCase()); - } - } - } - - private AnnotationWriter annotationWriter; - private ClassWriter classWriter; - private Map> pcMap; -} diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt index 7979febe830..5f83a184979 100644 --- a/langtools/test/tools/javac/diags/examples.not-yet.txt +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt @@ -52,7 +52,6 @@ compiler.misc.bad.const.pool.tag.at # bad class file compiler.misc.bad.enclosing.method # bad class file compiler.misc.bad.runtime.invisible.param.annotations # bad class file compiler.misc.bad.signature # bad class file -compiler.misc.bad.type.annotation.value compiler.misc.base.membership # UNUSED compiler.misc.ccf.found.later.version compiler.misc.ccf.unrecognized.attribute From e2ed68fb2f97a7f66ed09677e7f80043a07dff90 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Mon, 10 Jan 2011 15:08:31 -0800 Subject: [PATCH 021/152] 6396503: javac should not require assertions enabled Reviewed-by: mcimadamore --- .../classes/com/sun/tools/javac/Main.java | 8 +- .../com/sun/tools/javac/code/Attribute.java | 3 +- .../com/sun/tools/javac/code/Scope.java | 22 +-- .../com/sun/tools/javac/code/Symbol.java | 15 +- .../com/sun/tools/javac/code/Type.java | 18 +-- .../com/sun/tools/javac/code/Types.java | 25 ++-- .../com/sun/tools/javac/comp/Attr.java | 21 ++- .../com/sun/tools/javac/comp/Check.java | 2 +- .../com/sun/tools/javac/comp/Flow.java | 4 +- .../com/sun/tools/javac/comp/Lower.java | 43 +++--- .../com/sun/tools/javac/comp/MemberEnter.java | 9 +- .../com/sun/tools/javac/comp/Resolve.java | 4 +- .../com/sun/tools/javac/comp/TransTypes.java | 4 +- .../tools/javac/file/ZipFileIndexArchive.java | 5 +- .../com/sun/tools/javac/jvm/CRTable.java | 6 +- .../com/sun/tools/javac/jvm/ClassReader.java | 22 +-- .../com/sun/tools/javac/jvm/ClassWriter.java | 35 +++-- .../classes/com/sun/tools/javac/jvm/Code.java | 52 +++---- .../classes/com/sun/tools/javac/jvm/Gen.java | 26 ++-- .../com/sun/tools/javac/jvm/Items.java | 18 +-- .../sun/tools/javac/main/JavaCompiler.java | 12 +- .../sun/tools/javac/parser/JavacParser.java | 6 +- .../com/sun/tools/javac/parser/Scanner.java | 4 +- .../JavacProcessingEnvironment.java | 15 +- .../com/sun/tools/javac/tree/JCTree.java | 2 +- .../com/sun/tools/javac/tree/TreeInfo.java | 2 +- .../com/sun/tools/javac/tree/TreeMaker.java | 19 +-- .../com/sun/tools/javac/tree/TreeScanner.java | 2 +- .../util/AbstractDiagnosticFormatter.java | 4 +- .../com/sun/tools/javac/util/Assert.java | 138 ++++++++++++++++++ .../com/sun/tools/javac/util/Bits.java | 8 +- .../com/sun/tools/javac/util/Context.java | 4 +- .../com/sun/tools/javac/util/List.java | 4 +- .../tools/javac/util/UnsharedNameTable.java | 6 +- .../classes/javax/tools/ToolProvider.java | 21 +-- 35 files changed, 346 insertions(+), 243 deletions(-) create mode 100644 langtools/src/share/classes/com/sun/tools/javac/util/Assert.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/Main.java b/langtools/src/share/classes/com/sun/tools/javac/Main.java index 25ccd98490e..e569c1befbe 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/Main.java +++ b/langtools/src/share/classes/com/sun/tools/javac/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -43,12 +43,6 @@ import java.lang.reflect.*; */ public class Main { - static { - ClassLoader loader = Main.class.getClassLoader(); - if (loader != null) - loader.setPackageAssertionStatus("com.sun.tools.javac", true); - } - /** Unsupported command line interface. * @param args The command line parameters. */ diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java b/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java index 8f3c7ed1963..37bb6eebe72 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java @@ -240,8 +240,7 @@ public abstract class Attribute implements AnnotationValue { public VarSymbol value; public Enum(Type type, VarSymbol value) { super(type); - assert value != null; - this.value = value; + this.value = Assert.checkNonNull(value); } public void accept(Visitor v) { v.visitEnum(this); } public String toString() { diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Scope.java b/langtools/src/share/classes/com/sun/tools/javac/code/Scope.java index 4f58c78011a..20d88df157c 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Scope.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Scope.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -133,7 +133,7 @@ public class Scope { */ private Scope(Scope next, Symbol owner, Entry[] table, ScopeCounter scopeCounter) { this.next = next; - assert emptyScope == null || owner != null; + Assert.check(emptyScope == null || owner != null); this.owner = owner; this.table = table; this.hashMask = table.length - 1; @@ -191,16 +191,16 @@ public class Scope { * with next. */ public Scope leave() { - assert shared == 0; + Assert.check(shared == 0); if (table != next.table) return next; while (elems != null) { int hash = getIndex(elems.sym.name); Entry e = table[hash]; - assert e == elems : elems.sym; + Assert.check(e == elems, elems.sym); table[hash] = elems.shadowed; elems = elems.sibling; } - assert next.shared > 0; + Assert.check(next.shared > 0); next.shared--; next.nelems = nelems; // System.out.println("====> leaving scope " + this.hashCode() + " owned by " + this.owner + " to " + next.hashCode()); @@ -211,12 +211,12 @@ public class Scope { /** Double size of hash table. */ private void dble() { - assert shared == 0; + Assert.check(shared == 0); Entry[] oldtable = table; Entry[] newtable = new Entry[oldtable.length * 2]; for (Scope s = this; s != null; s = s.next) { if (s.table == oldtable) { - assert s == this || s.shared != 0; + Assert.check(s == this || s.shared != 0); s.table = newtable; s.hashMask = newtable.length - 1; } @@ -237,7 +237,7 @@ public class Scope { /** Enter symbol sym in this scope. */ public void enter(Symbol sym) { - assert shared == 0; + Assert.check(shared == 0); enter(sym, this); } @@ -251,7 +251,7 @@ public class Scope { * arguments are only used in import scopes. */ public void enter(Symbol sym, Scope s, Scope origin) { - assert shared == 0; + Assert.check(shared == 0); if (nelems * 3 >= hashMask * 2) dble(); int hash = getIndex(sym.name); @@ -274,7 +274,7 @@ public class Scope { * attribute tells us that the class isn't a package member. */ public void remove(Symbol sym) { - assert shared == 0; + Assert.check(shared == 0); Entry e = lookup(sym.name); if (e.scope == null) return; @@ -314,7 +314,7 @@ public class Scope { /** Enter symbol sym in this scope if not already there. */ public void enterIfAbsent(Symbol sym) { - assert shared == 0; + Assert.check(shared == 0); Entry e = lookup(sym.name); while (e.scope == this && e.sym.kind != sym.kind) e = e.next(); if (e.scope != this) enter(sym); diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java index 20c33d7365d..8ef070de9d5 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java @@ -81,8 +81,7 @@ public abstract class Symbol implements Element { * method to make sure that the class symbol is loaded. */ public List getAnnotationMirrors() { - assert attributes_field != null; - return attributes_field; + return Assert.checkNonNull(attributes_field); } /** Fetch a particular annotation from a symbol. */ @@ -596,7 +595,7 @@ public abstract class Symbol implements Element { } public R accept(ElementVisitor v, P p) { - assert type.tag == TYPEVAR; // else override will be invoked + Assert.check(type.tag == TYPEVAR); // else override will be invoked return v.visitTypeParameter(this, p); } @@ -670,8 +669,7 @@ public abstract class Symbol implements Element { if (attributes_field.isEmpty()) attributes_field = package_info.attributes_field; } - assert attributes_field != null; - return attributes_field; + return Assert.checkNonNull(attributes_field); } /** A package "exists" if a type or package that exists has @@ -768,8 +766,7 @@ public abstract class Symbol implements Element { public List getAnnotationMirrors() { if (completer != null) complete(); - assert attributes_field != null; - return attributes_field; + return Assert.checkNonNull(attributes_field); } public Type erasure(Types types) { @@ -1020,7 +1017,7 @@ public abstract class Symbol implements Element { } public void setData(Object data) { - assert !(data instanceof Env) : this; + Assert.check(!(data instanceof Env), this); this.data = data; } @@ -1052,7 +1049,7 @@ public abstract class Symbol implements Element { */ public MethodSymbol(long flags, Name name, Type type, Symbol owner) { super(MTH, flags, name, type, owner); - assert owner.type.tag != TYPEVAR : owner + "." + name; + if (owner.type.tag == TYPEVAR) Assert.error(owner + "." + name); } /** Clone this symbol with new owner. diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java index d75157cd781..bda5d843148 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -138,7 +138,7 @@ public class Type implements PrimitiveType { */ public Type constType(Object constValue) { final Object value = constValue; - assert tag <= BOOLEAN; + Assert.check(tag <= BOOLEAN); return new Type(tag, tsym) { @Override public Object constValue() { @@ -202,13 +202,13 @@ public class Type implements PrimitiveType { * The constant value of this type, converted to String */ public String stringValue() { - assert constValue() != null; + Object cv = Assert.checkNonNull(constValue()); if (tag == BOOLEAN) - return ((Integer) constValue()).intValue() == 0 ? "false" : "true"; + return ((Integer) cv).intValue() == 0 ? "false" : "true"; else if (tag == CHAR) - return String.valueOf((char) ((Integer) constValue()).intValue()); + return String.valueOf((char) ((Integer) cv).intValue()); else - return constValue().toString(); + return cv.toString(); } /** @@ -428,9 +428,8 @@ public class Type implements PrimitiveType { public WildcardType(Type type, BoundKind kind, TypeSymbol tsym) { super(WILDCARD, tsym); - assert(type != null); + this.type = Assert.checkNonNull(type); this.kind = kind; - this.type = type; } public WildcardType(WildcardType t, TypeVar bound) { this(t.type, t.kind, t.tsym, bound); @@ -1021,9 +1020,8 @@ public class Type implements PrimitiveType { Type lower, WildcardType wildcard) { super(name, owner, lower); - assert lower != null; + this.lower = Assert.checkNonNull(lower); this.bound = upper; - this.lower = lower; this.wildcard = wildcard; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index 010e2a980da..8c36c551dab 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -1061,8 +1061,9 @@ public class Types { highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym); } if (highSub != null) { - assert a.tsym == highSub.tsym && a.tsym == lowSub.tsym - : a.tsym + " != " + highSub.tsym + " != " + lowSub.tsym; + if (!(a.tsym == highSub.tsym && a.tsym == lowSub.tsym)) { + Assert.error(a.tsym + " != " + highSub.tsym + " != " + lowSub.tsym); + } if (!disjointTypes(aHigh.allparams(), highSub.allparams()) && !disjointTypes(aHigh.allparams(), lowSub.allparams()) && !disjointTypes(aLow.allparams(), highSub.allparams()) @@ -1703,9 +1704,9 @@ public class Types { bt.supertype_field = bounds.head; bt.interfaces_field = bounds.tail; } - assert bt.supertype_field.tsym.completer != null - || !bt.supertype_field.isInterface() - : bt.supertype_field; + Assert.check(bt.supertype_field.tsym.completer != null + || !bt.supertype_field.isInterface(), + bt.supertype_field); return bt; } @@ -1834,7 +1835,7 @@ public class Types { // t.interfaces_field is null after // completion, we can assume that t is not the // type of a class/interface declaration. - assert t != t.tsym.type : t.toString(); + Assert.check(t != t.tsym.type, t); List actuals = t.allparams(); List formals = t.tsym.type.allparams(); if (t.hasErasedSupertypes()) { @@ -2646,7 +2647,7 @@ public class Types { act2 = act2.tail; typarams = typarams.tail; } - assert(act1.isEmpty() && act2.isEmpty() && typarams.isEmpty()); + Assert.check(act1.isEmpty() && act2.isEmpty() && typarams.isEmpty()); return new ClassType(class1.getEnclosingType(), merged.toList(), class1.tsym); } @@ -2758,7 +2759,7 @@ public class Types { // calculate lub(A, B) while (ts.head.tag != CLASS && ts.head.tag != TYPEVAR) ts = ts.tail; - assert !ts.isEmpty(); + Assert.check(!ts.isEmpty()); List cl = closure(ts.head); for (Type t : ts.tail) { if (t.tag == CLASS || t.tag == TYPEVAR) @@ -3138,7 +3139,7 @@ public class Types { boolean reverse = false; Type target = to; if ((to.tsym.flags() & INTERFACE) == 0) { - assert (from.tsym.flags() & INTERFACE) != 0; + Assert.check((from.tsym.flags() & INTERFACE) != 0); reverse = true; to = from; from = target; @@ -3173,12 +3174,12 @@ public class Types { boolean reverse = false; Type target = to; if ((to.tsym.flags() & INTERFACE) == 0) { - assert (from.tsym.flags() & INTERFACE) != 0; + Assert.check((from.tsym.flags() & INTERFACE) != 0); reverse = true; to = from; from = target; } - assert (from.tsym.flags() & FINAL) != 0; + Assert.check((from.tsym.flags() & FINAL) != 0); Type t1 = asSuper(from, to.tsym); if (t1 == null) return false; Type t2 = to; diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index d97fb264301..c879974fe15 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -563,7 +563,7 @@ public class Attr extends JCTree.Visitor { if (bound != null && bound.tsym instanceof ClassSymbol) { ClassSymbol c = (ClassSymbol)bound.tsym; if ((c.flags_field & COMPOUND) != 0) { - assert (c.flags_field & UNATTRIBUTED) != 0 : c; + Assert.check((c.flags_field & UNATTRIBUTED) != 0, c); attribClass(typaram.pos(), c); } } @@ -1434,7 +1434,7 @@ public class Attr extends JCTree.Visitor { localEnv.info.varArgs = false; Type mtype = attribExpr(tree.meth, localEnv, mpt); if (localEnv.info.varArgs) - assert mtype.isErroneous() || tree.varargsElement != null; + Assert.check(mtype.isErroneous() || tree.varargsElement != null); // Compute the result type. Type restype = mtype.getReturnType(); @@ -1667,7 +1667,7 @@ public class Attr extends JCTree.Visitor { typeargtypes, localEnv.info.varArgs); if (localEnv.info.varArgs) - assert tree.constructorType.isErroneous() || tree.varargsElement != null; + Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null); } if (cdef != null) { @@ -1727,7 +1727,7 @@ public class Attr extends JCTree.Visitor { Symbol sym = rs.resolveConstructor( tree.pos(), localEnv, clazztype, argtypes, typeargtypes, true, tree.varargsElement != null); - assert sym.kind < AMBIGUOUS || tree.constructor.type.isErroneous(); + Assert.check(sym.kind < AMBIGUOUS || tree.constructor.type.isErroneous()); tree.constructor = sym; if (tree.constructor.kind > ERRONEOUS) { tree.constructorType = syms.errType; @@ -2961,7 +2961,7 @@ public class Attr extends JCTree.Visitor { extending, implementing, List.nil()); ClassSymbol c = (ClassSymbol)a.getUpperBound().tsym; - assert (c.flags() & COMPOUND) != 0; + Assert.check((c.flags() & COMPOUND) != 0); cd.sym = c; c.sourcefile = env.toplevel.sourcefile; @@ -3093,7 +3093,7 @@ public class Attr extends JCTree.Visitor { /** Finish the attribution of a class. */ private void attribClassBody(Env env, ClassSymbol c) { JCClassDecl tree = (JCClassDecl)env.tree; - assert c == tree.sym; + Assert.check(c == tree.sym); // Validate annotations chk.validateAnnotations(tree.mods.annotations, c); @@ -3134,12 +3134,9 @@ public class Attr extends JCTree.Visitor { tree.type = c.type; - boolean assertsEnabled = false; - assert assertsEnabled = true; - if (assertsEnabled) { - for (List l = tree.typarams; - l.nonEmpty(); l = l.tail) - assert env.info.scope.lookup(l.head.name).scope != null; + for (List l = tree.typarams; + l.nonEmpty(); l = l.tail) { + Assert.checkNonNull(env.info.scope.lookup(l.head.name).scope); } // Check that a generic class doesn't extend Throwable diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index 622a633da4a..30198a36925 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -2397,7 +2397,7 @@ public class Check { */ void checkNonCyclicElements(JCClassDecl tree) { if ((tree.sym.flags_field & ANNOTATION) == 0) return; - assert (tree.sym.flags_field & LOCKED) == 0; + Assert.check((tree.sym.flags_field & LOCKED) == 0); try { tree.sym.flags_field |= LOCKED; for (JCTree def : tree.defs) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java index 65471db51e4..e047f29eece 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java @@ -708,7 +708,7 @@ public class Flow extends TreeScanner { lint = lint.augment(tree.sym.attributes_field); - assert pendingExits.isEmpty(); + Assert.check(pendingExits.isEmpty()); try { boolean isInitialConstructor = @@ -746,7 +746,7 @@ public class Flow extends TreeScanner { PendingExit exit = exits.head; exits = exits.tail; if (exit.thrown == null) { - assert exit.tree.getTag() == JCTree.RETURN; + Assert.check(exit.tree.getTag() == JCTree.RETURN); if (isInitialConstructor) { inits = exit.inits; for (int i = firstadr; i < nextadr; i++) diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java index 366af533eb5..7a19fb95729 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java @@ -1057,7 +1057,7 @@ public class Lower extends TreeTranslator { } // Otherwise replace the variable by its proxy. sym = proxies.lookup(proxyName(sym.name)).sym; - assert sym != null && (sym.flags_field & FINAL) != 0; + Assert.check(sym != null && (sym.flags_field & FINAL) != 0); tree = make.at(tree.pos).Ident(sym); } JCExpression base = (tree.getTag() == JCTree.SELECT) ? ((JCFieldAccess) tree).selected : null; @@ -1208,7 +1208,7 @@ public class Lower extends TreeTranslator { */ void makeAccessible(Symbol sym) { JCClassDecl cdef = classDef(sym.owner.enclClass()); - assert cdef != null : "class def not found: " + sym + " in " + sym.owner; + if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner); if (sym.name == names.init) { cdef.defs = cdef.defs.prepend( accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym))); @@ -1458,7 +1458,7 @@ public class Lower extends TreeTranslator { expr = make.Ident(var.sym).setType(resource.type); stats.add(var); } else { - assert resource instanceof JCExpression; + Assert.check(resource instanceof JCExpression); VarSymbol syntheticTwrVar = new VarSymbol(SYNTHETIC | FINAL, makeSyntheticName(names.fromString("twrVar" + @@ -1552,7 +1552,7 @@ public class Lower extends TreeTranslator { List ots = outerThisStack; if (ots.isEmpty()) { log.error(pos, "no.encl.instance.of.type.in.scope", c); - assert false; + Assert.error(); return makeNull(); } VarSymbol ot = ots.head; @@ -1565,14 +1565,14 @@ public class Lower extends TreeTranslator { log.error(pos, "no.encl.instance.of.type.in.scope", c); - assert false; // should have been caught in Attr + Assert.error(); // should have been caught in Attr return tree; } ot = ots.head; } while (ot.owner != otc); if (otc.owner.kind != PCK && !otc.hasOuterInstance()) { chk.earlyRefError(pos, c); - assert false; // should have been caught in Attr + Assert.error(); // should have been caught in Attr return makeNull(); } tree = access(make.at(pos).Select(tree, ot)); @@ -1610,7 +1610,7 @@ public class Lower extends TreeTranslator { List ots = outerThisStack; if (ots.isEmpty()) { log.error(pos, "no.encl.instance.of.type.in.scope", c); - assert false; + Assert.error(); return makeNull(); } VarSymbol ot = ots.head; @@ -1623,7 +1623,7 @@ public class Lower extends TreeTranslator { log.error(pos, "no.encl.instance.of.type.in.scope", c); - assert false; + Assert.error(); return tree; } ot = ots.head; @@ -1640,9 +1640,9 @@ public class Lower extends TreeTranslator { JCStatement initField(int pos, Name name) { Scope.Entry e = proxies.lookup(name); Symbol rhs = e.sym; - assert rhs.owner.kind == MTH; + Assert.check(rhs.owner.kind == MTH); Symbol lhs = e.next().sym; - assert rhs.owner.owner == lhs.owner; + Assert.check(rhs.owner.owner == lhs.owner); make.at(pos); return make.Exec( @@ -1655,9 +1655,9 @@ public class Lower extends TreeTranslator { */ JCStatement initOuterThis(int pos) { VarSymbol rhs = outerThisStack.head; - assert rhs.owner.kind == MTH; + Assert.check(rhs.owner.kind == MTH); VarSymbol lhs = outerThisStack.tail.head; - assert rhs.owner.owner == lhs.owner; + Assert.check(rhs.owner.owner == lhs.owner); make.at(pos); return make.Exec( @@ -1856,7 +1856,7 @@ public class Lower extends TreeTranslator { // where /** Create an attributed tree of the form left.name(). */ private JCMethodInvocation makeCall(JCExpression left, Name name, List args) { - assert left.type != null; + Assert.checkNonNull(left.type); Symbol funcsym = lookupMethod(make_pos, name, left.type, TreeInfo.types(args)); return make.App(make.Select(left, funcsym), args); @@ -2399,7 +2399,7 @@ public class Lower extends TreeTranslator { names.valueOf, tree.sym.type, List.of(syms.stringType)); - assert (valueOfSym.flags() & STATIC) != 0; + Assert.check((valueOfSym.flags() & STATIC) != 0); VarSymbol nameArgSym = valueOfSym.params.head; JCIdent nameVal = make.Ident(nameArgSym); JCStatement enum_ValueOf = @@ -3416,7 +3416,7 @@ public class Lower extends TreeTranslator { if (expression != null) { // expression for a "default" case is null String labelExpr = (String) expression.type.constValue(); Integer mapping = caseLabelToPosition.put(labelExpr, casePosition); - assert mapping == null; + Assert.checkNull(mapping); int hashCode = labelExpr.hashCode(); Set stringSet = hashToString.get(hashCode); @@ -3426,7 +3426,7 @@ public class Lower extends TreeTranslator { hashToString.put(hashCode, stringSet); } else { boolean added = stringSet.add(labelExpr); - assert added; + Assert.check(added); } } casePosition++; @@ -3478,7 +3478,7 @@ public class Lower extends TreeTranslator { for(Map.Entry> entry : hashToString.entrySet()) { int hashCode = entry.getKey(); Set stringsWithHashCode = entry.getValue(); - assert stringsWithHashCode.size() >= 1; + Assert.check(stringsWithHashCode.size() >= 1); JCStatement elsepart = null; for(String caseLabel : stringsWithHashCode ) { @@ -3692,8 +3692,7 @@ public class Lower extends TreeTranslator { cdef.type, List.nil()); - assert(ordinalSym != null); - assert(ordinalSym instanceof MethodSymbol); + Assert.check(ordinalSym instanceof MethodSymbol); JCStatement ret = make.Return(make.Ident(ordinalSymbol)); cdef.defs = cdef.defs.append(make.MethodDef((MethodSymbol)ordinalSym, @@ -3709,8 +3708,7 @@ public class Lower extends TreeTranslator { cdef.type, List.nil()); - assert(nameSym != null); - assert(nameSym instanceof MethodSymbol); + Assert.check(nameSym instanceof MethodSymbol); JCStatement ret = make.Return(make.Ident(nameSymbol)); @@ -3761,8 +3759,7 @@ public class Lower extends TreeTranslator { cdef.type, List.of(cdef.sym.type)); - assert(compareToSym != null); - assert(compareToSym instanceof MethodSymbol); + Assert.check(compareToSym instanceof MethodSymbol); JCMethodDecl compareToDecl = (JCMethodDecl) TreeInfo.declarationFor(compareToSym, cdef); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java index 12ac02d4a2b..c41ddbf2116 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java @@ -581,8 +581,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { JCVariableDecl lastParam = null; for (List l = tree.params; l.nonEmpty(); l = l.tail) { JCVariableDecl param = lastParam = l.head; - assert param.sym != null; - params.append(param.sym); + params.append(Assert.checkNonNull(param.sym)); } m.params = params.toList(); @@ -699,7 +698,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { *********************************************************************/ Type attribImportType(JCTree tree, Env env) { - assert completionEnabled; + Assert.check(completionEnabled); try { // To prevent deep recursion, suppress completion of some // types. @@ -725,7 +724,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { return "annotate " + annotations + " onto " + s + " in " + s.owner; } public void enterAnnotation() { - assert s.kind == PCK || s.attributes_field == null; + Assert.check(s.kind == PCK || s.attributes_field == null); JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); try { if (s.attributes_field != null && @@ -836,7 +835,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { // Suppress some (recursive) MemberEnter invocations if (!completionEnabled) { // Re-install same completer for next time around and return. - assert (sym.flags() & Flags.COMPOUND) == 0; + Assert.check((sym.flags() & Flags.COMPOUND) == 0); sym.completer = this; return; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java index fdba568bc10..b833af28fba 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -679,7 +679,7 @@ public class Resolve { boolean operator) { if (sym.kind == ERR) return bestSoFar; if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar; - assert sym.kind < AMBIGUOUS; + Assert.check(sym.kind < AMBIGUOUS); try { rawInstantiate(env, site, sym, argtypes, typeargtypes, allowBoxing, useVarargs, Warner.noWarnings); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java index 6271510843c..b69b4981853 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -180,7 +180,7 @@ public class TransTypes extends TreeTranslator { parameters = parameters.tail; } Type parameter = parameters.head; - assert varargsElement != null || args.length() == 1; + Assert.check(varargsElement != null || args.length() == 1); if (varargsElement != null) { while (args.nonEmpty()) { args.head = translate(args.head, varargsElement); @@ -594,7 +594,7 @@ public class TransTypes extends TreeTranslator { if (tree.varargsElement != null) tree.varargsElement = types.erasure(tree.varargsElement); else - assert tree.args.length() == argtypes.length(); + Assert.check(tree.args.length() == argtypes.length()); tree.args = translateArgs(tree.args, argtypes, tree.varargsElement); // Insert casts of method invocation results as needed. diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java b/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java index 66f08fea2d4..4a46601908e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, 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 @@ -42,6 +42,7 @@ import java.nio.charset.CharsetDecoder; import com.sun.tools.javac.file.JavacFileManager.Archive; import com.sun.tools.javac.file.RelativePath.RelativeDirectory; import com.sun.tools.javac.file.RelativePath.RelativeFile; +import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.List; /** @@ -146,7 +147,7 @@ public class ZipFileIndexArchive implements Archive { @Override public InputStream openInputStream() throws IOException { if (inputStream == null) { - assert entry != null; // see constructor + Assert.checkNonNull(entry); // see constructor inputStream = new ByteArrayInputStream(zfIndex.read(entry)); } return inputStream; diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java index fa190db64c9..a2c1edc9735 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -101,7 +101,7 @@ implements CRTFlags { continue; SourceRange pos = positions.get(entry.tree); - assert pos != null : "CRT: tree source positions are undefined"; + Assert.checkNonNull(pos, "CRT: tree source positions are undefined"); if ((pos.startPos == Position.NOPOS) || (pos.endPos == Position.NOPOS)) continue; @@ -517,7 +517,7 @@ implements CRTFlags { } public void visitTree(JCTree tree) { - assert false; + Assert.error(); } /** The start position of given tree. diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 4467f3607a6..202c22c4968 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -242,9 +242,9 @@ public class ClassReader implements Completer { if (classes != null) return; if (definitive) { - assert packages == null || packages == syms.packages; + Assert.check(packages == null || packages == syms.packages); packages = syms.packages; - assert classes == null || classes == syms.classes; + Assert.check(classes == null || classes == syms.classes); classes = syms.classes; } else { packages = new HashMap(); @@ -530,7 +530,7 @@ public class ClassReader implements Completer { int index = poolIdx[i]; int len = getChar(index + 1); int start = index + 3; - assert buf[start] == '[' || buf[start + len - 1] != ';'; + Assert.check(buf[start] == '[' || buf[start + len - 1] != ';'); // by the above assertion, the following test can be // simplified to (buf[start] == '[') return (buf[start] == '[' || buf[start + len - 1] == ';') @@ -1041,7 +1041,7 @@ public class ClassReader implements Completer { readingClassAttr = true; try { ClassType ct1 = (ClassType)c.type; - assert c == currentOwner; + Assert.check(c == currentOwner); ct1.typarams_field = readTypeParams(nextChar()); ct1.supertype_field = sigToType(); ListBuffer is = new ListBuffer(); @@ -1908,9 +1908,9 @@ public class ClassReader implements Completer { if (ct.interfaces_field == null) ct.interfaces_field = is.reverse(); - if (fieldCount != nextChar()) assert false; + Assert.check(fieldCount == nextChar()); for (int i = 0; i < fieldCount; i++) enterMember(c, readField()); - if (methodCount != nextChar()) assert false; + Assert.check(methodCount == nextChar()); for (int i = 0; i < methodCount; i++) enterMember(c, readMethod()); typevars = typevars.leave(); @@ -2019,7 +2019,7 @@ public class ClassReader implements Completer { public ClassSymbol defineClass(Name name, Symbol owner) { ClassSymbol c = new ClassSymbol(0, name, owner); if (owner.kind == PCK) - assert classes.get(c.flatname) == null : c; + Assert.checkNull(classes.get(c.flatname), c); c.completer = this; return c; } @@ -2159,9 +2159,9 @@ public class ClassReader implements Completer { if (classfile != null) { JavaFileObject previousClassFile = currentClassFile; try { - assert !filling : - "Filling " + classfile.toUri() + - " during " + previousClassFile; + if (filling) { + Assert.error("Filling " + classfile.toUri() + " during " + previousClassFile); + } currentClassFile = classfile; if (verbose) { printVerbose("loading", currentClassFile.toString()); @@ -2307,7 +2307,7 @@ public class ClassReader implements Completer { public PackageSymbol enterPackage(Name fullname) { PackageSymbol p = packages.get(fullname); if (p == null) { - assert !fullname.isEmpty() : "rootPackage missing!"; + Assert.check(!fullname.isEmpty(), "rootPackage missing!"); p = new PackageSymbol( Convert.shortName(fullname), enterPackage(Convert.packagePart(fullname))); diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 7fa494b97e5..eb93646ec65 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -219,11 +219,14 @@ public class ClassWriter extends ClassFile { /** Return flags as a string, separated by " ". */ public static String flagNames(long flags) { - StringBuffer sbuf = new StringBuffer(); + StringBuilder sbuf = new StringBuilder(); int i = 0; long f = flags & StandardFlags; while (f != 0) { - if ((f & 1) != 0) sbuf.append(" " + flagName[i]); + if ((f & 1) != 0) { + sbuf.append(" "); + sbuf.append(flagName[i]); + } f = f >> 1; i++; } @@ -376,7 +379,7 @@ public class ClassWriter extends ClassFile { ? types.erasure(outer) : outer); sigbuf.appendByte('.'); - assert c.flatname.startsWith(c.owner.enclClass().flatname); + Assert.check(c.flatname.startsWith(c.owner.enclClass().flatname)); sigbuf.appendName(rawOuter ? c.flatname.subName(c.owner.enclClass().flatname.getByteLength()+1,c.flatname.getByteLength()) : c.name); @@ -416,7 +419,7 @@ public class ClassWriter extends ClassFile { /** Return signature of given type */ Name typeSig(Type type) { - assert sigbuf.length == 0; + Assert.check(sigbuf.length == 0); //- System.out.println(" ? " + type); assembleSig(type); Name n = sigbuf.toName(names); @@ -466,7 +469,7 @@ public class ClassWriter extends ClassFile { int i = 1; while (i < pool.pp) { Object value = pool.pool[i]; - assert value != null; + Assert.checkNonNull(value); if (value instanceof Pool.Method) value = ((Pool.Method)value).m; else if (value instanceof Pool.Variable) @@ -529,7 +532,7 @@ public class ClassWriter extends ClassFile { poolbuf.appendByte(CONSTANT_Class); poolbuf.appendChar(pool.put(xClassName(type))); } else { - assert false : "writePool " + value; + Assert.error("writePool " + value); } i++; } @@ -798,7 +801,7 @@ public class ClassWriter extends ClassFile { databuf.appendByte('Z'); break; case CLASS: - assert value instanceof String; + Assert.check(value instanceof String); databuf.appendByte('s'); value = names.fromString(value.toString()); // CONSTANT_Utf8 break; @@ -1015,11 +1018,11 @@ public class ClassWriter extends ClassFile { Code.LocalVar var = code.varBuffer[i]; // write variable info - assert var.start_pc >= 0; - assert var.start_pc <= code.cp; + Assert.check(var.start_pc >= 0 + && var.start_pc <= code.cp); databuf.appendChar(var.start_pc); - assert var.length >= 0; - assert (var.start_pc + var.length) <= code.cp; + Assert.check(var.length >= 0 + && (var.start_pc + var.length) <= code.cp); databuf.appendChar(var.length); VarSymbol sym = var.sym; databuf.appendChar(pool.put(sym.name)); @@ -1051,7 +1054,7 @@ public class ClassWriter extends ClassFile { databuf.appendChar(pool.put(typeSig(sym.type))); databuf.appendChar(var.reg); } - assert count == nGenericVars; + Assert.check(count == nGenericVars); endAttr(alenIdx); acount++; } @@ -1122,7 +1125,7 @@ public class ClassWriter extends ClassFile { } break; case JSR202: { - assert code.stackMapBuffer == null; + Assert.checkNull(code.stackMapBuffer); for (int i=0; i l = interfaces; !sigReq && l.nonEmpty(); l = l.tail) sigReq = l.head.allparams().length() != 0; if (sigReq) { - assert source.allowGenerics(); + Assert.check(source.allowGenerics()); int alenIdx = writeAttr(names.Signature); if (typarams.length() != 0) assembleParamsSig(typarams); assembleSig(supertype); diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java index 58e7c8a72ce..84ae10c36e9 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java @@ -372,7 +372,7 @@ public class Code { } void postop() { - assert alive || state.stacksize == 0; + Assert.check(alive || state.stacksize == 0); } /** Emit a multinewarray instruction. @@ -583,7 +583,7 @@ public class Code { case areturn: case ireturn: case freturn: - assert state.nlocks == 0; + Assert.check(state.nlocks == 0); state.pop(1); markDead(); break; @@ -604,7 +604,7 @@ public class Code { break; case lreturn: case dreturn: - assert state.nlocks == 0; + Assert.check(state.nlocks == 0); state.pop(2); markDead(); break; @@ -612,7 +612,7 @@ public class Code { state.push(state.stack[state.stacksize-1]); break; case return_: - assert state.nlocks == 0; + Assert.check(state.nlocks == 0); markDead(); break; case arraylength: @@ -1147,7 +1147,7 @@ public class Code { int pc = curPc(); alive = true; this.state = state.dup(); - assert state.stacksize <= max_stack; + Assert.check(state.stacksize <= max_stack); if (debugCode) System.err.println("entry point " + state); pendingStackMap = needStackMap; return pc; @@ -1160,7 +1160,7 @@ public class Code { int pc = curPc(); alive = true; this.state = state.dup(); - assert state.stacksize <= max_stack; + Assert.check(state.stacksize <= max_stack); this.state.push(pushed); if (debugCode) System.err.println("entry point " + state); pendingStackMap = needStackMap; @@ -1289,7 +1289,7 @@ public class Code { } frame.locals = new Type[localCount]; for (int i=0, j=0; i 1) i++; } @@ -1435,8 +1435,8 @@ public class Code { boolean changed = false; State newState = state; for (; chain != null; chain = chain.next) { - assert state != chain.state; - assert target > chain.pc || state.stacksize == 0; + Assert.check(state != chain.state + && (target > chain.pc || state.stacksize == 0)); if (target >= cp) { target = cp; } else if (get1(target) == goto_) { @@ -1464,9 +1464,9 @@ public class Code { fatcode = true; else put2(chain.pc + 1, target - chain.pc); - assert !alive || + Assert.check(!alive || chain.state.stacksize == newState.stacksize && - chain.state.nlocks == newState.nlocks; + chain.state.nlocks == newState.nlocks); } fixedPc = true; if (cp == target) { @@ -1481,7 +1481,7 @@ public class Code { } } } - assert !changed || state != newState; + Assert.check(!changed || state != newState); if (state != newState) { setDefined(newState.defined); state = newState; @@ -1492,11 +1492,11 @@ public class Code { /** Resolve chain to point to current code pointer. */ public void resolve(Chain chain) { - assert + Assert.check( !alive || chain==null || state.stacksize == chain.state.stacksize && - state.nlocks == chain.state.nlocks; + state.nlocks == chain.state.nlocks); pendingJumps = mergeChains(chain, pendingJumps); } @@ -1514,9 +1514,9 @@ public class Code { // recursive merge sort if (chain2 == null) return chain1; if (chain1 == null) return chain2; - assert + Assert.check( chain1.state.stacksize == chain2.state.stacksize && - chain1.state.nlocks == chain2.state.nlocks; + chain1.state.nlocks == chain2.state.nlocks); if (chain1.pc < chain2.pc) return new Chain( chain2.pc, @@ -1631,7 +1631,7 @@ public class Code { void unlock(int register) { nlocks--; - assert locks[nlocks] == register; + Assert.check(locks[nlocks] == register); locks[nlocks] = -1; } @@ -1673,7 +1673,7 @@ public class Code { stacksize--; Type result = stack[stacksize]; stack[stacksize] = null; - assert result != null && width(result) == 1; + Assert.check(result != null && width(result) == 1); return result; } @@ -1686,8 +1686,8 @@ public class Code { stacksize -= 2; Type result = stack[stacksize]; stack[stacksize] = null; - assert stack[stacksize+1] == null; - assert result != null && width(result) == 2; + Assert.check(stack[stacksize+1] == null + && result != null && width(result) == 2); return result; } @@ -1712,8 +1712,8 @@ public class Code { case ARRAY: int width = width(t); Type old = stack[stacksize-width]; - assert types.isSubtype(types.erasure(old), - types.erasure(t)); + Assert.check(types.isSubtype(types.erasure(old), + types.erasure(t))); stack[stacksize-width] = t; break; default: @@ -1739,8 +1739,8 @@ public class Code { State join(State other) { defined = defined.andSet(other.defined); - assert stacksize == other.stacksize; - assert nlocks == other.nlocks; + Assert.check(stacksize == other.stacksize + && nlocks == other.nlocks); for (int i=0; i cases = tree.cases; @@ -1148,7 +1148,7 @@ public class Gen extends JCTree.Visitor { if (hi < val) hi = val; nlabels++; } else { - assert defaultIndex == -1; + Assert.check(defaultIndex == -1); defaultIndex = i; } l = l.tail; @@ -1290,7 +1290,7 @@ public class Gen extends JCTree.Visitor { syncEnv.info.finalize = new GenFinalizer() { void gen() { genLast(); - assert syncEnv.info.gaps.length() % 2 == 0; + Assert.check(syncEnv.info.gaps.length() % 2 == 0); syncEnv.info.gaps.append(code.curPc()); } void genLast() { @@ -1329,10 +1329,10 @@ public class Gen extends JCTree.Visitor { tryEnv.info.cont, jsrState); } - assert tryEnv.info.gaps.length() % 2 == 0; + Assert.check(tryEnv.info.gaps.length() % 2 == 0); tryEnv.info.gaps.append(code.curPc()); } else { - assert tryEnv.info.gaps.length() % 2 == 0; + Assert.check(tryEnv.info.gaps.length() % 2 == 0); tryEnv.info.gaps.append(code.curPc()); genLast(); } @@ -1640,14 +1640,14 @@ public class Gen extends JCTree.Visitor { public void visitBreak(JCBreak tree) { Env targetEnv = unwind(tree.target, env); - assert code.state.stacksize == 0; + Assert.check(code.state.stacksize == 0); targetEnv.info.addExit(code.branch(goto_)); endFinalizerGaps(env, targetEnv); } public void visitContinue(JCContinue tree) { Env targetEnv = unwind(tree.target, env); - assert code.state.stacksize == 0; + Assert.check(code.state.stacksize == 0); targetEnv.info.addCont(code.branch(goto_)); endFinalizerGaps(env, targetEnv); } @@ -1720,7 +1720,7 @@ public class Gen extends JCTree.Visitor { public void visitNewClass(JCNewClass tree) { // Enclosing instances or anonymous classes should have been eliminated // by now. - assert tree.encl == null && tree.def == null; + Assert.check(tree.encl == null && tree.def == null); code.emitop2(new_, makeRef(tree.pos(), tree.type)); code.emitop0(dup); @@ -1902,7 +1902,7 @@ public class Gen extends JCTree.Visitor { genNullCheck(tree.pos()); break; default: - assert false; + Assert.error(); } } } @@ -1977,7 +1977,7 @@ public class Gen extends JCTree.Visitor { items.makeMemberItem(getStringBufferAppend(tree, t), false).invoke(); } Symbol getStringBufferAppend(JCTree tree, Type t) { - assert t.constValue() == null; + Assert.checkNull(t.constValue()); Symbol method = stringBufferAppend.get(t); if (method == null) { method = rs.resolveInternalMethod(tree.pos(), @@ -2120,7 +2120,7 @@ public class Gen extends JCTree.Visitor { Symbol sym = tree.sym; if (tree.name == names._class) { - assert target.hasClassLiterals(); + Assert.check(target.hasClassLiterals()); code.emitop2(ldc2, makeRef(tree.pos(), tree.selected.type)); result = items.makeStackItem(pt); return; diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java index 6bbf39f0580..36f649ee62b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -26,11 +26,11 @@ package com.sun.tools.javac.jvm; import com.sun.tools.javac.code.*; - import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.jvm.Code.*; import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.util.Assert; import static com.sun.tools.javac.jvm.ByteCodes.*; @@ -387,7 +387,7 @@ public class Items { LocalItem(Type type, int reg) { super(Code.typecode(type)); - assert reg >= 0; + Assert.check(reg >= 0); this.type = type; this.reg = reg; } @@ -469,16 +469,16 @@ public class Items { class DynamicItem extends StaticItem { DynamicItem(Symbol member) { super(member); - assert member.owner == syms.invokeDynamicType.tsym; + Assert.check(member.owner == syms.invokeDynamicType.tsym); } Item load() { - assert false; + Assert.error(); return null; } void store() { - assert false; + Assert.error(); } Item invoke() { @@ -620,7 +620,7 @@ public class Items { ldc(); break; default: - assert false; + Assert.error(); } return stackItem[typecode]; } @@ -716,7 +716,7 @@ public class Items { } void stash(int toscode) { - assert false; + Assert.error(); } int width() { @@ -784,7 +784,7 @@ public class Items { } void stash(int toscode) { - assert false; + Assert.error(); } CondItem mkCond() { diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 4e190e8a5f8..d4579d6dfc5 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -848,7 +848,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { break; default: - assert false: "unknown compile policy"; + Assert.error("unknown compile policy"); } } catch (Abort ex) { if (devVerbose) @@ -1066,7 +1066,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { classSymbols = classSymbols.prepend((ClassSymbol)sym); continue; } - assert sym.kind == Kinds.PCK; + Assert.check(sym.kind == Kinds.PCK); log.warning("proc.package.does.not.exist", nameStr); pckSymbols = pckSymbols.prepend((PackageSymbol)sym); } catch (CompletionFailure e) { @@ -1086,8 +1086,8 @@ public class JavaCompiler implements ClassReader.SourceCompleter { if (c != this) annotationProcessingOccurred = c.annotationProcessingOccurred = true; // doProcessing will have handled deferred diagnostics - assert c.log.deferDiagnostics == false; - assert c.log.deferredDiagnostics.size() == 0; + Assert.check(c.log.deferDiagnostics == false + && c.log.deferredDiagnostics.size() == 0); return c; } finally { procEnvImpl.close(); @@ -1324,7 +1324,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { return; List pdef = lower.translateTopLevelClass(env, env.tree, localMake); if (pdef.head != null) { - assert pdef.tail.isEmpty(); + Assert.check(pdef.tail.isEmpty()); results.add(new Pair, JCClassDecl>(env, (JCClassDecl)pdef.head)); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index feb20a1de72..177168731e4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -547,7 +547,7 @@ public class JavacParser implements Parser { null); break; default: - assert false; + Assert.error(); } if (t == errorTree) t = F.at(pos).Erroneous(); @@ -724,7 +724,7 @@ public class JavacParser implements Parser { topOpPos = posStack[top]; } } - assert top == 0; + Assert.check(top == 0); t = odStack[0]; if (t.getTag() == JCTree.PLUS) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java index cdf54b219f4..935e29bf083 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -445,7 +445,7 @@ public class Scanner implements Lexer { */ private void scanHexFractionAndSuffix(boolean seendigit) { this.radix = 16; - assert ch == '.'; + Assert.check(ch == '.'); putChar(ch); scanChar(); skipIllegalUnderscores(); diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 7592e231265..a5617e3f737 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -65,6 +65,7 @@ import com.sun.tools.javac.parser.*; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.Abort; +import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Convert; import com.sun.tools.javac.util.FatalError; @@ -1046,17 +1047,17 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea Context next = new Context(); Options options = Options.instance(context); - assert options != null; + Assert.checkNonNull(options); next.put(Options.optionsKey, options); PrintWriter out = context.get(Log.outKey); - assert out != null; + Assert.checkNonNull(out); next.put(Log.outKey, out); final boolean shareNames = true; if (shareNames) { Names names = Names.instance(context); - assert names != null; + Assert.checkNonNull(names); next.put(Names.namesKey, names); } @@ -1069,18 +1070,18 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea next.put(TaskListener.class, tl); JavaFileManager jfm = context.get(JavaFileManager.class); - assert jfm != null; + Assert.checkNonNull(jfm); next.put(JavaFileManager.class, jfm); if (jfm instanceof JavacFileManager) { ((JavacFileManager)jfm).setContext(next); } Names names = Names.instance(context); - assert names != null; + Assert.checkNonNull(names); next.put(Names.namesKey, names); Keywords keywords = Keywords.instance(context); - assert(keywords != null); + Assert.checkNonNull(keywords); next.put(Keywords.keywordsKey, keywords); JavaCompiler oldCompiler = JavaCompiler.instance(context); @@ -1239,7 +1240,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea for (JCTree node : unit.defs) { if (node.getTag() == JCTree.CLASSDEF) { ClassSymbol sym = ((JCClassDecl) node).sym; - assert sym != null; + Assert.checkNonNull(sym); classes = classes.prepend(sym); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java index 13d0d076a47..b061c1b8ccb 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -2235,7 +2235,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public void visitErroneous(JCErroneous that) { visitTree(that); } public void visitLetExpr(LetExpr that) { visitTree(that); } - public void visitTree(JCTree that) { assert false; } + public void visitTree(JCTree that) { Assert.error(); } } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java index f6e364e2936..ee5f70b59e1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -445,7 +445,7 @@ public class TreeInfo { public static int finalizerPos(JCTree tree) { if (tree.getTag() == JCTree.TRY) { JCTry t = (JCTry) tree; - assert t.finalizer != null; + Assert.checkNonNull(t.finalizer); return firstStatPos(t.finalizer); } else if (tree.getTag() == JCTree.SYNCHRONIZED) { return endPos(((JCSynchronized) tree).body); diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java index 879070f3595..240ec02cf40 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -122,15 +122,15 @@ public class TreeMaker implements JCTree.Factory { public JCCompilationUnit TopLevel(List packageAnnotations, JCExpression pid, List defs) { - assert packageAnnotations != null; + Assert.checkNonNull(packageAnnotations); for (JCTree node : defs) - assert node instanceof JCClassDecl + Assert.check(node instanceof JCClassDecl || node instanceof JCImport || node instanceof JCSkip || node instanceof JCErroneous || (node instanceof JCExpressionStatement - && ((JCExpressionStatement)node).expr instanceof JCErroneous) - : node.getClass().getSimpleName(); + && ((JCExpressionStatement)node).expr instanceof JCErroneous), + node.getClass().getSimpleName()); JCCompilationUnit tree = new JCCompilationUnit(packageAnnotations, pid, defs, null, null, null, null); tree.pos = pos; @@ -647,19 +647,14 @@ public class TreeMaker implements JCTree.Factory { } return tp.setType(t); } -//where - private JCExpression Selectors(JCExpression base, Symbol sym, Symbol limit) { - if (sym == limit) return base; - else return Select(Selectors(base, sym.owner, limit), sym); - } /** Create a list of trees representing given list of types. */ public List Types(List ts) { - ListBuffer types = new ListBuffer(); + ListBuffer lb = new ListBuffer(); for (List l = ts; l.nonEmpty(); l = l.tail) - types.append(Type(l.head)); - return types.toList(); + lb.append(Type(l.head)); + return lb.toList(); } /** Create a variable definition from a variable symbol and an initializer diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java index 7cc9045fae9..7d4086fdf6d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java @@ -309,6 +309,6 @@ public class TreeScanner extends Visitor { } public void visitTree(JCTree tree) { - assert false; + Assert.error(); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java index 01730c32341..4ff2376a747 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2011, 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 @@ -117,7 +117,7 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter protected abstract String formatDiagnostic(JCDiagnostic d, Locale locale); public String formatPosition(JCDiagnostic d, PositionKind pk,Locale l) { - assert (d.getPosition() != Position.NOPOS); + Assert.check(d.getPosition() != Position.NOPOS); return String.valueOf(getPosition(d, pk)); } //where diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/Assert.java b/langtools/src/share/classes/com/sun/tools/javac/util/Assert.java new file mode 100644 index 00000000000..7fcc4161295 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Assert.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2011, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package com.sun.tools.javac.util; + + +/** + * Simple facility for unconditional assertions. + * The methods in this class are described in terms of equivalent assert + * statements, assuming that assertions have been enabled. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class Assert { + /** Equivalent to + * assert cond; + */ + public static void check(boolean cond) { + if (!cond) + error(); + } + + /** Equivalent to + * assert (o == null); + */ + public static void checkNull(Object o) { + if (o != null) + error(); + } + + /** Equivalent to + * assert (t != null); return t; + */ + public static T checkNonNull(T t) { + if (t == null) + error(); + return t; + } + + /** Equivalent to + * assert cond : value; + */ + public static void check(boolean cond, int value) { + if (!cond) + error(String.valueOf(value)); + } + + /** Equivalent to + * assert cond : value; + */ + public static void check(boolean cond, long value) { + if (!cond) + error(String.valueOf(value)); + } + + /** Equivalent to + * assert cond : value; + */ + public static void check(boolean cond, Object value) { + if (!cond) + error(String.valueOf(value)); + } + + /** Equivalent to + * assert cond : value; + */ + public static void check(boolean cond, String msg) { + if (!cond) + error(msg); + } + + /** Equivalent to + * assert (o == null) : value; + */ + public static void checkNull(Object o, Object value) { + if (o != null) + error(String.valueOf(value)); + } + + /** Equivalent to + * assert (o == null) : value; + */ + public static void checkNull(Object o, String msg) { + if (o != null) + error(msg); + } + + /** Equivalent to + * assert (o != null) : value; + */ + public static T checkNonNull(T t, String msg) { + if (t == null) + error(msg); + return t; + } + + /** Equivalent to + * assert false; + */ + public static void error() { + throw new AssertionError(); + } + + /** Equivalent to + * assert false : msg; + */ + public static void error(String msg) { + throw new AssertionError(msg); + } + + /** Prevent instantiation. */ + private Assert() { } +} diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java b/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java index a92f286fac6..2fe9ea0bb27 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -85,7 +85,7 @@ public class Bits { /** Include x in this set. */ public void incl(int x) { - assert x >= 0; + Assert.check(x >= 0); sizeTo((x >>> wordshift) + 1); bits[x >>> wordshift] = bits[x >>> wordshift] | (1 << (x & wordmask)); @@ -113,7 +113,7 @@ public class Bits { /** Exclude x from this set. */ public void excl(int x) { - assert x >= 0; + Assert.check(x >= 0); sizeTo((x >>> wordshift) + 1); bits[x >>> wordshift] = bits[x >>> wordshift] & ~(1 << (x & wordmask)); @@ -169,7 +169,7 @@ public class Bits { * Delight" by Henry S. Warren Jr. (figure 5-13) */ private static int trailingZeroBits(int x) { - assert wordlen == 32; + Assert.check(wordlen == 32); if (x == 0) return 32; int n = 1; if ((x & 0xffff) == 0) { n += 16; x >>>= 16; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/Context.java b/langtools/src/share/classes/com/sun/tools/javac/util/Context.java index 4fe3c45b4f8..b1fd87183ab 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/Context.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Context.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -145,7 +145,7 @@ public class Context { o = fac.make(); if (o instanceof Factory) throw new AssertionError("T extends Context.Factory"); - assert ht.get(key) == o; + Assert.check(ht.get(key) == o); } /* The following cast can't fail unless there was diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/List.java b/langtools/src/share/classes/com/sun/tools/javac/util/List.java index 80f2e3d3c2d..baad763816d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/List.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/List.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -184,7 +184,7 @@ public class List extends AbstractCollection implements java.util.List // return this.prependList(xs.tail).prepend(xs.head); List result = this; List rev = xs.reverse(); - assert rev != xs; + Assert.check(rev != xs); // since xs.reverse() returned a new list, we can reuse the // individual List objects, instead of allocating new ones. while (rev.nonEmpty()) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/UnsharedNameTable.java b/langtools/src/share/classes/com/sun/tools/javac/util/UnsharedNameTable.java index ca765e3eec2..fe88c122805 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/UnsharedNameTable.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/UnsharedNameTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -107,7 +107,7 @@ public class UnsharedNameTable extends Name.Table { hashes[h] = firstTableEntry = element.next; } else { - assert previousNonNullTableEntry != null : "previousNonNullTableEntry cannot be null here."; + Assert.checkNonNull(previousNonNullTableEntry, "previousNonNullTableEntry cannot be null here."); previousNonNullTableEntry.next = element.next; } } @@ -133,7 +133,7 @@ public class UnsharedNameTable extends Name.Table { hashes[h] = newEntry; } else { - assert previousNonNullTableEntry.next == null : "previousNonNullTableEntry.next must be null."; + Assert.checkNull(previousNonNullTableEntry.next, "previousNonNullTableEntry.next must be null."); previousNonNullTableEntry.next = newEntry; } diff --git a/langtools/src/share/classes/javax/tools/ToolProvider.java b/langtools/src/share/classes/javax/tools/ToolProvider.java index a87059953f7..7fc4a9cd280 100644 --- a/langtools/src/share/classes/javax/tools/ToolProvider.java +++ b/langtools/src/share/classes/javax/tools/ToolProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, 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 @@ -172,7 +172,7 @@ public class ToolProvider { { // try loading class directly, in case tool is on the bootclasspath try { - return enableAsserts(Class.forName(toolClassName, false, null)); + return Class.forName(toolClassName, false, null); } catch (ClassNotFoundException e) { trace(FINE, e); @@ -194,27 +194,10 @@ public class ToolProvider { trace(FINE, urls[0].toString()); cl = URLClassLoader.newInstance(urls); - cl.setPackageAssertionStatus("com.sun.tools.javac", true); refToolClassLoader = new WeakReference(cl); } return Class.forName(toolClassName, false, cl); } - } - - private static Class enableAsserts(Class cls) { - try { - ClassLoader loader = cls.getClassLoader(); - if (loader != null) - loader.setPackageAssertionStatus("com.sun.tools.javac", true); - else - trace(FINE, "loader == null"); - } catch (SecurityException ex) { - trace(FINE, ex); - } - return cls; - } - - } From fc42d65040f962e521a2381723ab638469f6756e Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Mon, 10 Jan 2011 17:00:05 -0800 Subject: [PATCH 022/152] 7011382: Fix use of VS100COMNTOOLS when installed in non-default or non-space path Reviewed-by: prr --- jdk/make/common/shared/Defs-windows.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/make/common/shared/Defs-windows.gmk b/jdk/make/common/shared/Defs-windows.gmk index 95a47c206f9..bf67dd016e9 100644 --- a/jdk/make/common/shared/Defs-windows.gmk +++ b/jdk/make/common/shared/Defs-windows.gmk @@ -288,8 +288,8 @@ ifndef VS2010_EXISTS xVS100COMNTOOLS :="$(_program_files32)/Microsoft Visual Studio 10.0/Common7/Tools/" fVS100COMNTOOLS :=$(call FullPath,$(xVS100COMNTOOLS)) else + xVS100COMNTOOLS :="$(subst \,/,$(VS100COMNTOOLS))" ifneq ($(word 2,$(VS100COMNTOOLS)),) - xVS100COMNTOOLS :="$(subst \,/,$(VS100COMNTOOLS))" fVS100COMNTOOLS :=$(call FullPath,$(xVS100COMNTOOLS)) else fVS100COMNTOOLS :=$(xVS100COMNTOOLS) From 571f84fa868413686c5ed1191802d94a55b7c234 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Mon, 10 Jan 2011 17:06:10 -0800 Subject: [PATCH 023/152] 7005608: diamond conversion of JCA and crypto providers Reviewed-by: wetmore --- jdk/src/share/classes/java/security/Security.java | 2 +- .../classes/sun/security/jca/ProviderList.java | 8 ++++---- .../share/classes/sun/security/jca/Providers.java | 2 +- .../classes/sun/security/provider/PolicyFile.java | 15 ++++++--------- .../share/classes/sun/security/provider/Sun.java | 2 +- .../security/provider/VerificationProvider.java | 2 +- .../sun/security/provider/X509Factory.java | 12 ++++++------ .../share/classes/sun/security/rsa/RSACore.java | 6 +++--- .../classes/sun/security/rsa/SunRsaSign.java | 2 +- 9 files changed, 24 insertions(+), 27 deletions(-) diff --git a/jdk/src/share/classes/java/security/Security.java b/jdk/src/share/classes/java/security/Security.java index 72d0b0b8778..55816d9aefd 100644 --- a/jdk/src/share/classes/java/security/Security.java +++ b/jdk/src/share/classes/java/security/Security.java @@ -659,7 +659,7 @@ public final class Security { } // Map containing cached Spi Class objects of the specified type - private static final Map spiMap = new ConcurrentHashMap<>(); + private static final Map spiMap = new ConcurrentHashMap<>(); /** * Return the Class object for the given engine type diff --git a/jdk/src/share/classes/sun/security/jca/ProviderList.java b/jdk/src/share/classes/sun/security/jca/ProviderList.java index aae0fd2dcde..26bc9162761 100644 --- a/jdk/src/share/classes/sun/security/jca/ProviderList.java +++ b/jdk/src/share/classes/sun/security/jca/ProviderList.java @@ -96,7 +96,7 @@ public final class ProviderList { if (providerList.getProvider(p.getName()) != null) { return providerList; } - List list = new ArrayList + List list = new ArrayList<> (Arrays.asList(providerList.configs)); int n = list.size(); if ((position < 0) || (position > n)) { @@ -160,7 +160,7 @@ public final class ProviderList { * Return a new ProviderList parsed from the java.security Properties. */ private ProviderList() { - List configList = new ArrayList(); + List configList = new ArrayList<>(); for (int i = 1; true; i++) { String entry = Security.getProperty("security.provider." + i); if (entry == null) { @@ -200,7 +200,7 @@ public final class ProviderList { * possible recursion and deadlock during verification. */ ProviderList getJarList(String[] jarClassNames) { - List newConfigs = new ArrayList(); + List newConfigs = new ArrayList<>(); for (String className : jarClassNames) { ProviderConfig newConfig = new ProviderConfig(className); for (ProviderConfig config : configs) { @@ -356,7 +356,7 @@ public final class ProviderList { */ @Deprecated public List getServices(String type, List algorithms) { - List ids = new ArrayList(); + List ids = new ArrayList<>(); for (String alg : algorithms) { ids.add(new ServiceId(type, alg)); } diff --git a/jdk/src/share/classes/sun/security/jca/Providers.java b/jdk/src/share/classes/sun/security/jca/Providers.java index 329689f1aab..c3903b7145e 100644 --- a/jdk/src/share/classes/sun/security/jca/Providers.java +++ b/jdk/src/share/classes/sun/security/jca/Providers.java @@ -40,7 +40,7 @@ import java.security.Security; public class Providers { private static final ThreadLocal threadLists = - new InheritableThreadLocal(); + new InheritableThreadLocal<>(); // number of threads currently using thread-local provider lists // tracked to allow an optimization if == 0 diff --git a/jdk/src/share/classes/sun/security/provider/PolicyFile.java b/jdk/src/share/classes/sun/security/provider/PolicyFile.java index 739c375796f..7112a7f60c5 100644 --- a/jdk/src/share/classes/sun/security/provider/PolicyFile.java +++ b/jdk/src/share/classes/sun/security/provider/PolicyFile.java @@ -299,8 +299,7 @@ public class PolicyFile extends java.security.Policy { private static final int DEFAULT_CACHE_SIZE = 1; // contains the policy grant entries, PD cache, and alias mapping - private AtomicReference policyInfo = - new AtomicReference(); + private AtomicReference policyInfo = new AtomicReference<>(); private boolean constructed = false; private boolean expandProperties = true; @@ -1334,8 +1333,7 @@ public class PolicyFile extends java.security.Policy { List entryPs = entry.getPrincipals(); if (debug != null) { - ArrayList accPs = - new ArrayList(); + ArrayList accPs = new ArrayList<>(); if (principals != null) { for (int i = 0; i < principals.length; i++) { accPs.add(new PolicyParser.PrincipalEntry @@ -1416,8 +1414,7 @@ public class PolicyFile extends java.security.Policy { // check if the PrincipalComparator // implies the current thread's principals - Set pSet = - new HashSet(principals.length); + Set pSet = new HashSet<>(principals.length); for (int j = 0; j < principals.length; j++) { pSet.add(principals[j]); } @@ -1700,7 +1697,7 @@ public class PolicyFile extends java.security.Policy { // build an info array for every principal // in the current domain which has a principal class // that is equal to policy entry principal class name - List plist = new ArrayList(); + List plist = new ArrayList<>(); for (int i = 0; i < pdp.length; i++) { if(pe.principalClass.equals(pdp[i].getClass().getName())) plist.add(pdp[i]); @@ -1770,7 +1767,7 @@ public class PolicyFile extends java.security.Policy { // Done return certs; - ArrayList userCertList = new ArrayList(); + ArrayList userCertList = new ArrayList<>(); i = 0; while (i < certs.length) { userCertList.add(certs[i]); @@ -2234,7 +2231,7 @@ public class PolicyFile extends java.security.Policy { if (this.certs == null) { // extract the signer certs ArrayList signerCerts = - new ArrayList(); + new ArrayList<>(); i = 0; while (i < certs.length) { signerCerts.add(certs[i]); diff --git a/jdk/src/share/classes/sun/security/provider/Sun.java b/jdk/src/share/classes/sun/security/provider/Sun.java index e2fed0363a2..078bef6cdf1 100644 --- a/jdk/src/share/classes/sun/security/provider/Sun.java +++ b/jdk/src/share/classes/sun/security/provider/Sun.java @@ -55,7 +55,7 @@ public final class Sun extends Provider { SunEntries.putEntries(this); } else { // use LinkedHashMap to preserve the order of the PRNGs - Map map = new LinkedHashMap(); + Map map = new LinkedHashMap<>(); SunEntries.putEntries(map); AccessController.doPrivileged(new PutAllAction(this, map)); } diff --git a/jdk/src/share/classes/sun/security/provider/VerificationProvider.java b/jdk/src/share/classes/sun/security/provider/VerificationProvider.java index 18af2e88f6f..86801228abe 100644 --- a/jdk/src/share/classes/sun/security/provider/VerificationProvider.java +++ b/jdk/src/share/classes/sun/security/provider/VerificationProvider.java @@ -76,7 +76,7 @@ public final class VerificationProvider extends Provider { SunRsaSignEntries.putEntries(this); } else { // use LinkedHashMap to preserve the order of the PRNGs - Map map = new LinkedHashMap(); + Map map = new LinkedHashMap<>(); SunEntries.putEntries(map); SunRsaSignEntries.putEntries(map); AccessController.doPrivileged(new PutAllAction(this, map)); diff --git a/jdk/src/share/classes/sun/security/provider/X509Factory.java b/jdk/src/share/classes/sun/security/provider/X509Factory.java index e785b655a2e..8ec0cbe5941 100644 --- a/jdk/src/share/classes/sun/security/provider/X509Factory.java +++ b/jdk/src/share/classes/sun/security/provider/X509Factory.java @@ -409,10 +409,10 @@ public class X509Factory extends CertificateFactorySpi { parseX509orPKCS7Cert(InputStream is) throws CertificateException, IOException { - Collection coll = new ArrayList(); + Collection coll = new ArrayList<>(); byte[] data = readOneBlock(is); if (data == null) { - return new ArrayList(0); + return new ArrayList<>(0); } try { PKCS7 pkcs7 = new PKCS7(data); @@ -422,7 +422,7 @@ public class X509Factory extends CertificateFactorySpi { return Arrays.asList(certs); } else { // no crls provided - return new ArrayList(0); + return new ArrayList<>(0); } } catch (ParsingException e) { while (data != null) { @@ -442,10 +442,10 @@ public class X509Factory extends CertificateFactorySpi { parseX509orPKCS7CRL(InputStream is) throws CRLException, IOException { - Collection coll = new ArrayList(); + Collection coll = new ArrayList<>(); byte[] data = readOneBlock(is); if (data == null) { - return new ArrayList(0); + return new ArrayList<>(0); } try { PKCS7 pkcs7 = new PKCS7(data); @@ -455,7 +455,7 @@ public class X509Factory extends CertificateFactorySpi { return Arrays.asList(crls); } else { // no crls provided - return new ArrayList(0); + return new ArrayList<>(0); } } catch (ParsingException e) { while (data != null) { diff --git a/jdk/src/share/classes/sun/security/rsa/RSACore.java b/jdk/src/share/classes/sun/security/rsa/RSACore.java index 4b3ec9afa28..42ebc3c1a48 100644 --- a/jdk/src/share/classes/sun/security/rsa/RSACore.java +++ b/jdk/src/share/classes/sun/security/rsa/RSACore.java @@ -215,11 +215,11 @@ public final class RSACore { // value suggested by Paul Kocher (quoted by NSS) private final static int BLINDING_MAX_REUSE = 50; - // cache for blinding parameters. Map + // cache for blinding parameters. Map // use a weak hashmap so that cached values are automatically cleared // when the modulus is GC'ed - private final static Map blindingCache = - new WeakHashMap(); + private final static Map blindingCache = + new WeakHashMap<>(); /** * Set of blinding parameters for a given RSA key. diff --git a/jdk/src/share/classes/sun/security/rsa/SunRsaSign.java b/jdk/src/share/classes/sun/security/rsa/SunRsaSign.java index 20e56311eb8..b48882c2824 100644 --- a/jdk/src/share/classes/sun/security/rsa/SunRsaSign.java +++ b/jdk/src/share/classes/sun/security/rsa/SunRsaSign.java @@ -52,7 +52,7 @@ public final class SunRsaSign extends Provider { SunRsaSignEntries.putEntries(this); } else { // use LinkedHashMap to preserve the order of the PRNGs - Map map = new HashMap(); + Map map = new HashMap<>(); SunRsaSignEntries.putEntries(map); AccessController.doPrivileged(new PutAllAction(this, map)); } From d0cebf135064d587fcac34604c074e52e4c1240f Mon Sep 17 00:00:00 2001 From: Kelly O'Hair Date: Mon, 10 Jan 2011 18:07:58 -0800 Subject: [PATCH 024/152] 6989472: Provide simple jdk identification information in the install image Reviewed-by: alanb --- jdk/make/common/Release.gmk | 54 +++++++++++++++++++++--- jdk/make/common/shared/Defs-versions.gmk | 3 ++ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/jdk/make/common/Release.gmk b/jdk/make/common/Release.gmk index 271f74695b3..1dc3a208ccb 100644 --- a/jdk/make/common/Release.gmk +++ b/jdk/make/common/Release.gmk @@ -26,6 +26,9 @@ include $(JDK_TOPDIR)/make/docs/CORE_PKGS.gmk include $(JDK_TOPDIR)/make/docs/NON_CORE_PKGS.gmk +# What jdk version are we building +THIS_JDK_VERSION := $(JDK_MAJOR_VERSION).$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION) + # # Perform release engineering tasks. # @@ -72,9 +75,6 @@ endif JTG_DOCS = $(JDK_TOPDIR)/src/solaris/doc -#We use this for man page header -jdkversion := $(JDK_MAJOR_VERSION).$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION) - # The base names of all the license and document files for the jdk and jre # (These files get placed in the jdk and jre install images) ifdef OPENJDK @@ -185,7 +185,7 @@ for manbase in $(MANBASEDIRS:%=%/$(MAN1SUBDIR)) ; do \ $(MKDIR) -p $1/man/$${ja_dir}/man1; \ $(CAT) $${manbase}/ja/$${manpage} \ | $(NATIVE2ASCII) -encoding $(JA_SOURCE_ENCODING) \ - | $(SED) 's/@@VERSION@@/$(jdkversion)/g' \ + | $(SED) 's/@@VERSION@@/$(THIS_JDK_VERSION)/g' \ | $(NATIVE2ASCII) -reverse -encoding $${ja_encoding} \ > $1/man/$${ja_dir}/man1/$${manpage}; \ done; \ @@ -215,6 +215,7 @@ images images-clobber \ initial-image-jre initial-image-jdk \ initial-image-jre-sol64 initial-image-jdk-sol64 \ trim-image-jre trim-image-jdk \ +identify-image-jre identify-image-jdk \ process-image-jre process-image-jdk \ compare-image \ sec-files sec-files-win jgss-files :: @@ -224,11 +225,12 @@ sec-files sec-files-win jgss-files :: images:: sanity-images post-sanity-images \ $(INITIAL_IMAGE_JRE) $(INITIAL_IMAGE_JDK) \ trim-image-jre trim-image-jdk \ + identify-image-jre identify-image-jdk \ process-image-jre process-image-jdk sec-files sec-files-win jgss-files # Don't use these -image-jre:: initial-image-jre trim-image-jre process-image-jre -image-jdk:: initial-image-jdk trim-image-jdk process-image-jdk +image-jre:: initial-image-jre trim-image-jre identify-image-jre process-image-jre +image-jdk:: initial-image-jdk trim-image-jdk identify-image-jdk process-image-jdk # # Sources we ship in the SDK. @@ -1087,6 +1089,45 @@ endif done $(RM) $(JDK_BIN_LIST) +################################################################### +# What did we build +################################################################### + +# The jdk text info file that lives at the root of the install image. + +JDK_INFO_FILE = $(JDK_IMAGE_DIR)/release +JRE_INFO_FILE = $(JRE_IMAGE_DIR)/release + +# Common way to emit a line into the release or info file +define info-file-item # name value +$(PRINTF) "%s=\"%s\"\n" $1 $2 >> $@ +endef + +# Values to emit +MINIMUM_OS_NAME := $(REQUIRED_OS_NAME) +MINIMUM_OS_VERSION := $(REQUIRED_OS_VERSION) +MINIMUM_OS_ARCH := $(ARCH) + +$(JDK_INFO_FILE): FRC + $(prep-target) + $(call info-file-item, "JAVA_VERSION", "$(THIS_JDK_VERSION)") + $(call info-file-item, "OS_NAME", "$(MINIMUM_OS_NAME)") + $(call info-file-item, "OS_VERSION", "$(MINIMUM_OS_VERSION)") + $(call info-file-item, "OS_ARCH", "$(MINIMUM_OS_ARCH)") + +# Create release file to identify this image +identify-image-jdk:: $(JDK_INFO_FILE) + +$(JRE_INFO_FILE): FRC + $(prep-target) + $(call info-file-item, "JAVA_VERSION", "$(THIS_JDK_VERSION)") + $(call info-file-item, "OS_NAME", "$(MINIMUM_OS_NAME)") + $(call info-file-item, "OS_VERSION", "$(MINIMUM_OS_VERSION)") + $(call info-file-item, "OS_ARCH", "$(MINIMUM_OS_ARCH)") + +# Create release file to identify this image +identify-image-jre:: $(JRE_INFO_FILE) + ################################################################### # What do we compare against ################################################################### @@ -1240,6 +1281,7 @@ images images-clobber:: initial-image-jre-setup \ trim-image-jre trim-image-jdk \ process-image-jre process-image-jdk \ + identify-image-jre identify-image-jdk \ install-previous-jre install-previous-jdk \ compare-image-jre compare-image-jdk \ compare-image compare-image-clobber \ diff --git a/jdk/make/common/shared/Defs-versions.gmk b/jdk/make/common/shared/Defs-versions.gmk index 6784be6f04a..a51cb2b75d5 100644 --- a/jdk/make/common/shared/Defs-versions.gmk +++ b/jdk/make/common/shared/Defs-versions.gmk @@ -127,6 +127,7 @@ endif # Solaris specific ifeq ($(PLATFORM), solaris) + REQUIRED_OS_NAME = SunOS REQUIRED_OS_VERSION = 5.10 REQUIRED_OS_VARIANT_NAME = Solaris REQUIRED_OS_VARIANT_VERSION = $(REQUIRED_OS_VERSION) @@ -148,6 +149,7 @@ endif # Linux specific ifeq ($(PLATFORM), linux) + REQUIRED_OS_NAME = Linux REQUIRED_OS_VERSION = 2.6 REQUIRED_OS_VARIANT_NAME = Fedora REQUIRED_OS_VARIANT_VERSION = 9 @@ -166,6 +168,7 @@ endif # Windows specific ifeq ($(PLATFORM), windows) + REQUIRED_OS_NAME = Windows ifeq ($(ARCH_DATA_MODEL),64) REQUIRED_OS_VERSION = 5.2 REQUIRED_OS_VARIANT_NAME = Windows2003 From 6a80d2126c70bf52a4b0602c61b9af33eb7ef7f9 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Mon, 10 Jan 2011 18:46:29 -0800 Subject: [PATCH 025/152] 4930919: race condition in MDO creation at back branch locations Reuse set_method_data_for_bcp() to setup mdp after MDO creation. Reviewed-by: kvn, never --- hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp | 17 +++++++---------- hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp | 7 +++---- .../cpu/sparc/vm/templateInterpreter_sparc.cpp | 13 +++---------- .../src/cpu/sparc/vm/templateTable_sparc.cpp | 4 ++-- hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp | 18 +++++++----------- hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp | 18 +++++++----------- .../cpu/x86/vm/templateInterpreter_x86_32.cpp | 13 +++---------- .../cpu/x86/vm/templateInterpreter_x86_64.cpp | 18 +++--------------- .../src/cpu/x86/vm/templateTable_x86_32.cpp | 13 +++---------- .../src/cpu/x86/vm/templateTable_x86_64.cpp | 18 +++--------------- .../vm/interpreter/interpreterRuntime.cpp | 8 ++------ .../vm/interpreter/interpreterRuntime.hpp | 4 ++-- 12 files changed, 45 insertions(+), 106 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index ea17d6f574e..c6b33222a6c 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -1295,16 +1295,13 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) { // Get the method data pointer from the methodOop and set the // specified register to its value. -void InterpreterMacroAssembler::set_method_data_pointer_offset(Register Roff) { +void InterpreterMacroAssembler::set_method_data_pointer() { assert(ProfileInterpreter, "must be profiling interpreter"); Label get_continue; ld_ptr(Lmethod, in_bytes(methodOopDesc::method_data_offset()), ImethodDataPtr); test_method_data_pointer(get_continue); add(ImethodDataPtr, in_bytes(methodDataOopDesc::data_offset()), ImethodDataPtr); - if (Roff != noreg) - // Roff contains a method data index ("mdi"). It defaults to zero. - add(ImethodDataPtr, Roff, ImethodDataPtr); bind(get_continue); } @@ -1315,10 +1312,11 @@ void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { Label zero_continue; // Test MDO to avoid the call if it is NULL. - ld_ptr(Lmethod, methodOopDesc::method_data_offset(), ImethodDataPtr); + ld_ptr(Lmethod, in_bytes(methodOopDesc::method_data_offset()), ImethodDataPtr); test_method_data_pointer(zero_continue); call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), Lmethod, Lbcp); - set_method_data_pointer_offset(O0); + add(ImethodDataPtr, in_bytes(methodDataOopDesc::data_offset()), ImethodDataPtr); + add(ImethodDataPtr, O0, ImethodDataPtr); bind(zero_continue); } @@ -1369,7 +1367,6 @@ void InterpreterMacroAssembler::verify_method_data_pointer() { } void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocation_count, - Register cur_bcp, Register Rtmp, Label &profile_continue) { assert(ProfileInterpreter, "must be profiling interpreter"); @@ -1400,8 +1397,8 @@ void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocat delayed()->nop(); // Build it now. - call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), cur_bcp); - set_method_data_pointer_offset(O0); + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); + set_method_data_pointer_for_bcp(); ba(false, profile_continue); delayed()->nop(); bind(done); diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp index 835dcac6836..be3840c67bf 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -269,12 +269,11 @@ class InterpreterMacroAssembler: public MacroAssembler { #ifndef CC_INTERP // Interpreter profiling operations - void set_method_data_pointer() { set_method_data_pointer_offset(noreg); } + void set_method_data_pointer(); void set_method_data_pointer_for_bcp(); - void set_method_data_pointer_offset(Register mdi_reg); void test_method_data_pointer(Label& zero_continue); void verify_method_data_pointer(); - void test_invocation_counter_for_mdp(Register invocation_count, Register cur_bcp, Register Rtmp, Label &profile_continue); + void test_invocation_counter_for_mdp(Register invocation_count, Register Rtmp, Label &profile_continue); void set_mdp_data_at(int constant, Register value); void increment_mdp_data_at(Address counter, Register bumped_count, diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp index 80e3a759d1d..8984a1df357 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -1364,15 +1364,8 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { // We have decided to profile this method in the interpreter __ bind(profile_method); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), Lbcp, true); - -#ifdef ASSERT - __ tst(O0); - __ breakpoint_trap(Assembler::notEqual); -#endif - - __ set_method_data_pointer(); - + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); + __ set_method_data_pointer_for_bcp(); __ ba(false, profile_method_continue); __ delayed()->nop(); } diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 89637223745..c4ec6758a0a 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -1689,7 +1689,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { const Register G4_invoke_ctr = G4; __ increment_backedge_counter(G4_invoke_ctr, G1_scratch); if (ProfileInterpreter) { - __ test_invocation_counter_for_mdp(G4_invoke_ctr, Lbcp, G3_scratch, Lforward); + __ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_scratch, Lforward); if (UseOnStackReplacement) { __ test_backedge_count_for_osr(O2_bumped_count, O0_cur_bcp, G3_scratch); } diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp index 6cc321b5576..33daeac2441 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -819,7 +819,7 @@ void InterpreterMacroAssembler::test_method_data_pointer(Register mdp, Label& ze // Set the method data pointer for the current bcp. void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { assert(ProfileInterpreter, "must be profiling interpreter"); - Label zero_continue; + Label set_mdp; push(rax); push(rbx); @@ -827,21 +827,17 @@ void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { // Test MDO to avoid the call if it is NULL. movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); testptr(rax, rax); - jcc(Assembler::zero, zero_continue); - + jcc(Assembler::zero, set_mdp); // rbx,: method // rsi: bcp call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, rsi); // rax,: mdi - + // mdo is guaranteed to be non-zero here, we checked for it before the call. movptr(rbx, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); - testptr(rbx, rbx); - jcc(Assembler::zero, zero_continue); addptr(rbx, in_bytes(methodDataOopDesc::data_offset())); - addptr(rbx, rax); - movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rbx); - - bind(zero_continue); + addptr(rax, rbx); + bind(set_mdp); + movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax); pop(rbx); pop(rax); } diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp index a156d24d66a..3c235ce2190 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -855,7 +855,7 @@ void InterpreterMacroAssembler::test_method_data_pointer(Register mdp, // Set the method data pointer for the current bcp. void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { assert(ProfileInterpreter, "must be profiling interpreter"); - Label zero_continue; + Label set_mdp; push(rax); push(rbx); @@ -863,21 +863,17 @@ void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { // Test MDO to avoid the call if it is NULL. movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); testptr(rax, rax); - jcc(Assembler::zero, zero_continue); - + jcc(Assembler::zero, set_mdp); // rbx: method // r13: bcp call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, r13); // rax: mdi - + // mdo is guaranteed to be non-zero here, we checked for it before the call. movptr(rbx, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); - testptr(rbx, rbx); - jcc(Assembler::zero, zero_continue); addptr(rbx, in_bytes(methodDataOopDesc::data_offset())); - addptr(rbx, rax); - movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rbx); - - bind(zero_continue); + addptr(rax, rbx); + bind(set_mdp); + movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax); pop(rbx); pop(rax); } diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp index ee518b31405..6471c21538f 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -1367,15 +1367,8 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { if (ProfileInterpreter) { // We have decided to profile this method in the interpreter __ bind(profile_method); - - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), rsi, true); - - __ movptr(rbx, Address(rbp, method_offset)); // restore methodOop - __ movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset()))); - __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax); - __ test_method_data_pointer(rax, profile_method_continue); - __ addptr(rax, in_bytes(methodDataOopDesc::data_offset())); - __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); + __ set_method_data_pointer_for_bcp(); __ jmp(profile_method_continue); } // Handle overflow of counter and compile method diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp index 2d7aa60cfca..4bbf0ff51dd 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -1383,20 +1383,8 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) { if (ProfileInterpreter) { // We have decided to profile this method in the interpreter __ bind(profile_method); - - __ call_VM(noreg, - CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), - r13, true); - - __ movptr(rbx, Address(rbp, method_offset)); // restore methodOop - __ movptr(rax, Address(rbx, - in_bytes(methodOopDesc::method_data_offset()))); - __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), - rax); - __ test_method_data_pointer(rax, profile_method_continue); - __ addptr(rax, in_bytes(methodDataOopDesc::data_offset())); - __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), - rax); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); + __ set_method_data_pointer_for_bcp(); __ jmp(profile_method_continue); } // Handle overflow of counter and compile method diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp index 898069bc948..745f5dc6d6c 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -1665,16 +1665,9 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { if (ProfileInterpreter) { // Out-of-line code to allocate method data oop. __ bind(profile_method); - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), rsi); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); __ load_unsigned_byte(rbx, Address(rsi, 0)); // restore target bytecode - __ movptr(rcx, Address(rbp, method_offset)); - __ movptr(rcx, Address(rcx, in_bytes(methodOopDesc::method_data_offset()))); - __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rcx); - __ test_method_data_pointer(rcx, dispatch); - // offset non-null mdp by MDO::data_offset() + IR::profile_method() - __ addptr(rcx, in_bytes(methodDataOopDesc::data_offset())); - __ addptr(rcx, rax); - __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rcx); + __ set_method_data_pointer_for_bcp(); __ jmp(dispatch); } diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp index a396e88da8b..1db9004e7d2 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -1695,21 +1695,9 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { if (ProfileInterpreter) { // Out-of-line code to allocate method data oop. __ bind(profile_method); - __ call_VM(noreg, - CAST_FROM_FN_PTR(address, - InterpreterRuntime::profile_method), r13); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); __ load_unsigned_byte(rbx, Address(r13, 0)); // restore target bytecode - __ movptr(rcx, Address(rbp, method_offset)); - __ movptr(rcx, Address(rcx, - in_bytes(methodOopDesc::method_data_offset()))); - __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), - rcx); - __ test_method_data_pointer(rcx, dispatch); - // offset non-null mdp by MDO::data_offset() + IR::profile_method() - __ addptr(rcx, in_bytes(methodDataOopDesc::data_offset())); - __ addptr(rcx, rax); - __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), - rcx); + __ set_method_data_pointer_for_bcp(); __ jmp(dispatch); } diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 494ba1fccbf..4c7b429d5e0 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -884,7 +884,7 @@ IRT_LEAF(jint, InterpreterRuntime::bcp_to_di(methodOopDesc* method, address cur_ return mdo->bci_to_di(bci); IRT_END -IRT_ENTRY(jint, InterpreterRuntime::profile_method(JavaThread* thread, address cur_bcp)) +IRT_ENTRY(void, InterpreterRuntime::profile_method(JavaThread* thread)) // use UnlockFlagSaver to clear and restore the _do_not_unlock_if_synchronized // flag, in case this method triggers classloading which will call into Java. UnlockFlagSaver fs(thread); @@ -893,16 +893,12 @@ IRT_ENTRY(jint, InterpreterRuntime::profile_method(JavaThread* thread, address c frame fr = thread->last_frame(); assert(fr.is_interpreted_frame(), "must come from interpreter"); methodHandle method(thread, fr.interpreter_frame_method()); - int bci = method->bci_from(cur_bcp); methodOopDesc::build_interpreter_method_data(method, THREAD); if (HAS_PENDING_EXCEPTION) { assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here"); CLEAR_PENDING_EXCEPTION; // and fall through... } - methodDataOop mdo = method->method_data(); - if (mdo == NULL) return 0; - return mdo->bci_to_di(bci); IRT_END diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp index 0a48ce16dc8..1115ac1a39c 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -164,7 +164,7 @@ class InterpreterRuntime: AllStatic { // Interpreter profiling support static jint bcp_to_di(methodOopDesc* method, address cur_bcp); - static jint profile_method(JavaThread* thread, address cur_bcp); + static void profile_method(JavaThread* thread); static void update_mdp_for_ret(JavaThread* thread, int bci); #ifdef ASSERT static void verify_mdp(methodOopDesc* method, address bcp, address mdp); From 6308eab4d575c053a77cf371105087c444544f3f Mon Sep 17 00:00:00 2001 From: Keith McGuigan Date: Tue, 11 Jan 2011 10:06:00 -0500 Subject: [PATCH 026/152] 6814943: getcpool001 catches more than one JvmtiThreadState problem Mark field volatile, use membars, and change access order to close race Reviewed-by: dcubed, dholmes --- hotspot/src/share/vm/prims/jvmtiEventController.cpp | 7 +++---- hotspot/src/share/vm/prims/jvmtiExport.cpp | 12 +++++++----- hotspot/src/share/vm/runtime/thread.cpp | 3 ++- hotspot/src/share/vm/runtime/thread.hpp | 2 +- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/hotspot/src/share/vm/prims/jvmtiEventController.cpp b/hotspot/src/share/vm/prims/jvmtiEventController.cpp index 0e32f85c141..ccb22b550b8 100644 --- a/hotspot/src/share/vm/prims/jvmtiEventController.cpp +++ b/hotspot/src/share/vm/prims/jvmtiEventController.cpp @@ -667,14 +667,13 @@ void JvmtiEventControllerPrivate::thread_ended(JavaThread *thread) { // Removes the JvmtiThreadState associated with the specified thread. // May be called after all environments have been disposed. + assert(JvmtiThreadState_lock->is_locked(), "sanity check"); EC_TRACE(("JVMTI [%s] # thread ended", JvmtiTrace::safe_get_thread_name(thread))); JvmtiThreadState *state = thread->jvmti_thread_state(); - if (state != NULL) { - MutexLocker mu(JvmtiThreadState_lock); - delete state; - } + assert(state != NULL, "else why are we here?"); + delete state; } void JvmtiEventControllerPrivate::set_event_callbacks(JvmtiEnvBase *env, diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index 6e87bbc8c90..4cf7d187b36 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -2253,12 +2253,14 @@ void JvmtiExport::post_vm_object_alloc(JavaThread *thread, oop object) { void JvmtiExport::cleanup_thread(JavaThread* thread) { assert(JavaThread::current() == thread, "thread is not current"); + MutexLocker mu(JvmtiThreadState_lock); - - // This has to happen after the thread state is removed, which is - // why it is not in post_thread_end_event like its complement - // Maybe both these functions should be rolled into the posts? - JvmtiEventController::thread_ended(thread); + if (thread->jvmti_thread_state() != NULL) { + // This has to happen after the thread state is removed, which is + // why it is not in post_thread_end_event like its complement + // Maybe both these functions should be rolled into the posts? + JvmtiEventController::thread_ended(thread); + } } void JvmtiExport::oops_do(OopClosure* f) { diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index fbb6ca93b5c..ee26bf4ac2e 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -31,6 +31,7 @@ #include "compiler/compileBroker.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/linkResolver.hpp" +#include "jvmtifiles/jvmtiEnv.hpp" #include "memory/oopFactory.hpp" #include "memory/universe.inline.hpp" #include "oops/instanceKlass.hpp" @@ -1699,7 +1700,7 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { tlab().make_parsable(true); // retire TLAB } - if (jvmti_thread_state() != NULL) { + if (JvmtiEnv::environments_might_exist()) { JvmtiExport::cleanup_thread(this); } diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index a0ca83c56c5..acdc227bdcc 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -809,7 +809,7 @@ class JavaThread: public Thread { // // _vm_exited is a special value to cover the case of a JavaThread // executing native code after the VM itself is terminated. - TerminatedTypes _terminated; + volatile TerminatedTypes _terminated; // suspend/resume support volatile bool _suspend_equivalent; // Suspend equivalent condition jint _in_deopt_handler; // count of deoptimization From 12f8b2493ef0a70fe6e87b14eadb5d1a39dc9b24 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 11 Jan 2011 08:05:28 -0800 Subject: [PATCH 027/152] 6993305: starting position of a method without modifiers and with type parameters is incorrect Reviewed-by: mcimadamore --- .../sun/tools/javac/parser/JavacParser.java | 6 + langtools/test/tools/javac/tree/T6993305.java | 124 ++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 langtools/test/tools/javac/tree/T6993305.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index 177168731e4..f42a6712979 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -2569,6 +2569,12 @@ public class JavacParser implements Parser { } else { pos = S.pos(); List typarams = typeParametersOpt(); + // if there are type parameters but no modifiers, save the start + // position of the method in the modifiers. + if (typarams.nonEmpty() && mods.pos == Position.NOPOS) { + mods.pos = pos; + storeEnd(mods, pos); + } Name name = S.name(); pos = S.pos(); JCExpression type; diff --git a/langtools/test/tools/javac/tree/T6993305.java b/langtools/test/tools/javac/tree/T6993305.java new file mode 100644 index 00000000000..24a2a6c1fb1 --- /dev/null +++ b/langtools/test/tools/javac/tree/T6993305.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2011, 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 6993305 + * @summary starting position of a method without modifiers and with type parameters is incorrect + */ + +import java.io.File; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.util.JavacTask; +import com.sun.source.util.SourcePositions; +import com.sun.source.util.TreeScanner; +import com.sun.source.util.Trees; +import com.sun.tools.javac.api.JavacTool; +import java.io.IOException; + +/* + * Test verifies the starting position of all methods by computing the start position + * of each method as the first non-white character on the first line containing + * (" " + methodName + "("), and then comparing this value against the reported + * value in the SourcePositions table. + */ +public class T6993305 { + void test1(T t) { } // this is the primary case to be tested + public void test2(T t) { } + @Deprecated void test3(T t) { } + + public static void main(String... args) throws Exception { + new T6993305().run(); + } + + void run() throws Exception { + File testSrc = new File(System.getProperty("test.src")); + + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null); + + File f = new File(testSrc, T6993305.class.getSimpleName() + ".java"); + Iterable fos = fm.getJavaFileObjects(f); + JavacTask task = tool.getTask(null, fm, null, null, null, fos); + Iterable cus = task.parse(); + + TestScanner s = new TestScanner(); + s.scan(cus, task); + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int errors; + + class TestScanner extends TreeScanner { + CompilationUnitTree cu; + SourcePositions sourcePositions; + String source; + + void show(String label, int pos) { + System.err.println(label + ": " + + source.substring(pos, Math.min(source.length(), pos + 10))); + } + + @Override public Void visitCompilationUnit(CompilationUnitTree tree, JavacTask task) { + cu = tree; + Trees trees = Trees.instance(task); + sourcePositions = trees.getSourcePositions(); + try { + source = String.valueOf(tree.getSourceFile().getCharContent(true)); + } catch (IOException e) { + throw new Error(e); + } + return super.visitCompilationUnit(tree, task); + } + + // this is the core of the test + @Override public Void visitMethod(MethodTree tree, JavacTask task) { + String name = String.valueOf(tree.getName()); + int pos = source.indexOf(" " + name + "("); + while (source.charAt(pos - 1) != '\n') pos--; + while (source.charAt(pos) == ' ') pos++; + int expectedStart = pos; + int reportedStart = (int) sourcePositions.getStartPosition(cu, tree); + System.err.println("Method " + name + + " expectedStart:" + expectedStart + + " reportedStart:" + reportedStart); + if (expectedStart != reportedStart) { + error("Unexpected value for " + name); + show("expected", expectedStart); + show("reported", reportedStart); + } + return super.visitMethod(tree, task); + } + } +} From 10467906c4146ce006bfac9e78fe0dba025c2768 Mon Sep 17 00:00:00 2001 From: Lance Andersen Date: Tue, 11 Jan 2011 12:36:43 -0500 Subject: [PATCH 028/152] 7000693: java.sql.Timestamp compareTo() issues using low values Reviewed-by: okutsu --- jdk/src/share/classes/java/sql/Timestamp.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/sql/Timestamp.java b/jdk/src/share/classes/java/sql/Timestamp.java index 411c04eb19e..f92a89a8778 100644 --- a/jdk/src/share/classes/java/sql/Timestamp.java +++ b/jdk/src/share/classes/java/sql/Timestamp.java @@ -473,7 +473,9 @@ public class Timestamp extends java.util.Date { * @since 1.4 */ public int compareTo(Timestamp ts) { - int i = super.compareTo(ts); + long thisTime = this.getTime(); + long anotherTime = ts.getTime(); + int i = (thisTime ts.nanos) { return 1; From 259f06de383a1723ea03e811d86e8e23e9abfe67 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Tue, 11 Jan 2011 13:42:34 -0800 Subject: [PATCH 029/152] 7011095: revert diamond changes from 6880112 that occur in method args Reviewed-by: darcy, alanb --- .../classes/com/sun/java/util/jar/pack/BandStructure.java | 2 +- jdk/src/share/classes/java/io/ObjectStreamClass.java | 4 ++-- jdk/src/share/classes/java/lang/StringCoding.java | 2 +- jdk/src/share/classes/java/util/logging/Logger.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java index 3a154a088b9..473d51108c0 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java @@ -1704,7 +1704,7 @@ class BandStructure { for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) { assert(attrIndexLimit[i] == 0); attrIndexLimit[i] = 32; // just for the sake of predefs. - attrDefs.set(i, new ArrayList<>(Collections.nCopies( + attrDefs.set(i, new ArrayList(Collections.nCopies( attrIndexLimit[i], (Attribute.Layout)null))); } diff --git a/jdk/src/share/classes/java/io/ObjectStreamClass.java b/jdk/src/share/classes/java/io/ObjectStreamClass.java index 2d3e2055860..74608db0c1c 100644 --- a/jdk/src/share/classes/java/io/ObjectStreamClass.java +++ b/jdk/src/share/classes/java/io/ObjectStreamClass.java @@ -329,7 +329,7 @@ public class ObjectStreamClass implements Serializable { entry = th; } if (future.set(entry)) { - Caches.localDescs.put(key, new SoftReference<>(entry)); + Caches.localDescs.put(key, new SoftReference(entry)); } else { // nested lookup call already set future entry = future.get(); @@ -2118,7 +2118,7 @@ public class ObjectStreamClass implements Serializable { entry = th; } future.set(entry); - Caches.reflectors.put(key, new SoftReference<>(entry)); + Caches.reflectors.put(key, new SoftReference(entry)); } if (entry instanceof FieldReflector) { diff --git a/jdk/src/share/classes/java/lang/StringCoding.java b/jdk/src/share/classes/java/lang/StringCoding.java index 42849479fcc..4043d5d2a89 100644 --- a/jdk/src/share/classes/java/lang/StringCoding.java +++ b/jdk/src/share/classes/java/lang/StringCoding.java @@ -67,7 +67,7 @@ class StringCoding { } private static void set(ThreadLocal> tl, T ob) { - tl.set(new SoftReference<>(ob)); + tl.set(new SoftReference(ob)); } // Trim the given byte array to the given length diff --git a/jdk/src/share/classes/java/util/logging/Logger.java b/jdk/src/share/classes/java/util/logging/Logger.java index 4d822de4792..b75caa56005 100644 --- a/jdk/src/share/classes/java/util/logging/Logger.java +++ b/jdk/src/share/classes/java/util/logging/Logger.java @@ -1426,7 +1426,7 @@ public class Logger { // we didn't have a previous parent ref = manager.new LoggerWeakRef(this); } - ref.setParentRef(new WeakReference<>(parent)); + ref.setParentRef(new WeakReference(parent)); parent.kids.add(ref); // As a result of the reparenting, the effective level From 6931aa0a24a4a45db6c4b36961b2626f8532053e Mon Sep 17 00:00:00 2001 From: Paul Hohensee Date: Tue, 11 Jan 2011 17:33:21 -0500 Subject: [PATCH 030/152] 7011463: Sparc MacroAssembler::incr_allocated_bytes() needs a RegisterOrConstant argument Replaced incr_allocated_bytes() formals var_size_in_bytes and con_size_in_bytes with a single RegisterOrConstant formal. Reviewed-by: twisti, jcoomes --- hotspot/src/cpu/sparc/vm/assembler_sparc.cpp | 15 +++++---------- hotspot/src/cpu/sparc/vm/assembler_sparc.hpp | 3 ++- .../src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp | 4 +++- hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp | 4 ++-- hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp | 3 ++- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index f1c39036251..0d81e2d1254 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -4104,7 +4104,7 @@ void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, Label& slow_case ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t1); sub(top, t1, t1); // size of tlab's allocated portion - incr_allocated_bytes(t1, 0, t2); + incr_allocated_bytes(t1, t2, t3); // refill the tlab with an eden allocation bind(do_refill); @@ -4138,19 +4138,14 @@ void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, Label& slow_case delayed()->nop(); } -void MacroAssembler::incr_allocated_bytes(Register var_size_in_bytes, - int con_size_in_bytes, - Register t1) { +void MacroAssembler::incr_allocated_bytes(RegisterOrConstant size_in_bytes, + Register t1, Register t2) { // Bump total bytes allocated by this thread assert(t1->is_global(), "must be global reg"); // so all 64 bits are saved on a context switch - assert_different_registers(var_size_in_bytes, t1); + assert_different_registers(size_in_bytes.register_or_noreg(), t1, t2); // v8 support has gone the way of the dodo ldx(G2_thread, in_bytes(JavaThread::allocated_bytes_offset()), t1); - if (var_size_in_bytes->is_valid()) { - add(t1, var_size_in_bytes, t1); - } else { - add(t1, con_size_in_bytes, t1); - } + add(t1, ensure_simm13_or_reg(size_in_bytes, t2), t1); stx(t1, G2_thread, in_bytes(JavaThread::allocated_bytes_offset())); } diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index 296305664cc..50aacafc9d8 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -2389,7 +2389,8 @@ public: Label& slow_case // continuation point if fast allocation fails ); void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case); - void incr_allocated_bytes(Register var_size_in_bytes, int con_size_in_bytes, Register t1); + void incr_allocated_bytes(RegisterOrConstant size_in_bytes, + Register t1, Register t2); // interface method calling void lookup_interface_method(Register recv_klass, diff --git a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp index 85eb668337c..c3556e2147e 100644 --- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp @@ -170,11 +170,13 @@ void C1_MacroAssembler::try_allocate( Register t2, // temp register Label& slow_case // continuation point if fast allocation fails ) { + RegisterOrConstant size_in_bytes = var_size_in_bytes->is_valid() + ? RegisterOrConstant(var_size_in_bytes) : RegisterOrConstant(con_size_in_bytes); if (UseTLAB) { tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case); } else { eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); - incr_allocated_bytes(var_size_in_bytes, con_size_in_bytes, t1); + incr_allocated_bytes(size_in_bytes, t1, t2); } } diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index 7ce9a73b610..d968c4e30e3 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -461,7 +461,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { // get the instance size __ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size); __ eden_allocate(O0_obj, G1_obj_size, 0, G3_t1, G4_t2, slow_path); - __ incr_allocated_bytes(G1_obj_size, 0, G3_t1); + __ incr_allocated_bytes(G1_obj_size, G3_t1, G4_t2); __ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2); __ verify_oop(O0_obj); @@ -577,7 +577,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ and3(G1_arr_size, ~MinObjAlignmentInBytesMask, G1_arr_size); __ eden_allocate(O0_obj, G1_arr_size, 0, G3_t1, O1_t2, slow_path); // preserves G1_arr_size - __ incr_allocated_bytes(G1_arr_size, 0, G3_t1); + __ incr_allocated_bytes(G1_arr_size, G3_t1, O1_t2); __ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2); __ ldub(klass_lh, G3_t1, klass_lh_header_size_offset); diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index 6bfaccd64e3..77548b7bcac 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -3447,7 +3447,8 @@ void TemplateTable::_new() { __ delayed()->nop(); // bump total bytes allocated by this thread - __ incr_allocated_bytes(Roffset, 0, G1_scratch); + // RoldTopValue and RtopAddr are dead, so can use G1 and G3 + __ incr_allocated_bytes(Roffset, G1_scratch, G3_scratch); } if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) { From 4912ef0e5d604f53db717c721ed3adeac12f91ac Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 11 Jan 2011 20:26:13 -0800 Subject: [PATCH 031/152] 7011386: race in objArrayKlass::array_klass_impl Move _lower_dimension field initialization before _higher_dimension and add storestore barrier. Reviewed-by: dholmes, iveresov, never --- hotspot/src/share/vm/oops/arrayKlass.hpp | 6 +++--- hotspot/src/share/vm/oops/objArrayKlass.cpp | 5 +++-- hotspot/src/share/vm/oops/typeArrayKlass.cpp | 3 ++- hotspot/src/share/vm/runtime/vmStructs.cpp | 6 +++--- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index 4b504ec476d..dff8363b2f0 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -36,8 +36,8 @@ class arrayKlass: public Klass { friend class VMStructs; private: int _dimension; // This is n'th-dimensional array. - klassOop _higher_dimension; // Refers the (n+1)'th-dimensional array (if present). - klassOop _lower_dimension; // Refers the (n-1)'th-dimensional array (if present). + volatile klassOop _higher_dimension; // Refers the (n+1)'th-dimensional array (if present). + volatile klassOop _lower_dimension; // Refers the (n-1)'th-dimensional array (if present). int _vtable_len; // size of vtable for this klass juint _alloc_size; // allocation profiling support oop _component_mirror; // component type, as a java/lang/Class diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp index 3233a4d225c..d31d710bc63 100644 --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -235,8 +235,9 @@ klassOop objArrayKlass::array_klass_impl(objArrayKlassHandle this_oop, bool or_n objArrayKlassKlass::cast(Universe::objArrayKlassKlassObj())-> allocate_objArray_klass(dimension + 1, this_oop, CHECK_NULL); ak = objArrayKlassHandle(THREAD, new_klass); - this_oop->set_higher_dimension(ak()); ak->set_lower_dimension(this_oop()); + OrderAccess::storestore(); + this_oop->set_higher_dimension(ak()); assert(ak->oop_is_objArray(), "incorrect initialization of objArrayKlass"); } } diff --git a/hotspot/src/share/vm/oops/typeArrayKlass.cpp b/hotspot/src/share/vm/oops/typeArrayKlass.cpp index 8d317dff9af..99d3f65cb80 100644 --- a/hotspot/src/share/vm/oops/typeArrayKlass.cpp +++ b/hotspot/src/share/vm/oops/typeArrayKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -179,6 +179,7 @@ klassOop typeArrayKlass::array_klass_impl(typeArrayKlassHandle h_this, bool or_n dimension + 1, h_this, CHECK_NULL); h_ak = objArrayKlassHandle(THREAD, oak); h_ak->set_lower_dimension(h_this()); + OrderAccess::storestore(); h_this->set_higher_dimension(h_ak()); assert(h_ak->oop_is_objArray(), "incorrect initialization of objArrayKlass"); } diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 2d440e58f3c..30973292d2a 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, 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 @@ -219,8 +219,8 @@ static inline uint64_t cast_uint64_t(size_t x) volatile_nonstatic_field(oopDesc, _metadata._compressed_klass, narrowOop) \ static_field(oopDesc, _bs, BarrierSet*) \ nonstatic_field(arrayKlass, _dimension, int) \ - nonstatic_field(arrayKlass, _higher_dimension, klassOop) \ - nonstatic_field(arrayKlass, _lower_dimension, klassOop) \ + volatile_nonstatic_field(arrayKlass, _higher_dimension, klassOop) \ + volatile_nonstatic_field(arrayKlass, _lower_dimension, klassOop) \ nonstatic_field(arrayKlass, _vtable_len, int) \ nonstatic_field(arrayKlass, _alloc_size, juint) \ nonstatic_field(arrayKlass, _component_mirror, oop) \ From 677a39996a45f738d0488bc0b69d54581d4cb373 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Wed, 12 Jan 2011 14:40:36 +0000 Subject: [PATCH 032/152] 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011 Reviewed-by: dholmes, chegar, mduigou --- .../share/classes/java/util/Collections.java | 6 +- .../share/classes/java/util/LinkedList.java | 8 +- .../util/concurrent/ArrayBlockingQueue.java | 436 ++++--- .../concurrent/ConcurrentLinkedDeque.java | 13 +- .../concurrent/ConcurrentLinkedQueue.java | 3 + .../concurrent/ConcurrentSkipListMap.java | 167 +-- .../util/concurrent/CopyOnWriteArrayList.java | 14 +- .../java/util/concurrent/ForkJoinPool.java | 227 ++-- .../java/util/concurrent/ForkJoinTask.java | 286 ++--- .../util/concurrent/ForkJoinWorkerThread.java | 274 ++-- .../util/concurrent/LinkedBlockingDeque.java | 2 + .../util/concurrent/LinkedBlockingQueue.java | 66 +- .../util/concurrent/LinkedTransferQueue.java | 121 +- .../classes/java/util/concurrent/Phaser.java | 1134 +++++++++-------- .../concurrent/PriorityBlockingQueue.java | 601 +++++++-- .../ScheduledThreadPoolExecutor.java | 6 +- .../util/concurrent/SynchronousQueue.java | 134 +- .../util/concurrent/ThreadPoolExecutor.java | 41 +- .../concurrent/atomic/AtomicIntegerArray.java | 116 +- .../concurrent/atomic/AtomicLongArray.java | 124 +- .../atomic/AtomicMarkableReference.java | 96 +- .../atomic/AtomicReferenceArray.java | 79 +- .../atomic/AtomicStampedReference.java | 111 +- .../java/util/concurrent/locks/Condition.java | 66 +- jdk/test/ProblemList.txt | 4 +- .../util/WeakHashMap/GCDuringIteration.java | 62 +- .../CancelledProducerConsumerLoops.java | 34 +- .../MultipleProducersSingleConsumerLoops.java | 30 +- .../BlockingQueue/ProducerConsumerLoops.java | 30 +- .../SingleProducerMultipleConsumerLoops.java | 30 +- .../IteratorWeakConsistency.java | 4 +- .../concurrent/Executors/AutoShutdown.java | 1 + .../java/util/concurrent/Phaser/Basic.java | 33 +- .../concurrent/Phaser/FickleRegister.java | 150 +++ .../util/concurrent/Phaser/PhaseOverflow.java | 158 +++ .../concurrent/Phaser/TieredArriveLoops.java | 117 ++ .../ThreadPoolExecutor/CoreThreadTimeOut.java | 62 +- 37 files changed, 3014 insertions(+), 1832 deletions(-) create mode 100644 jdk/test/java/util/concurrent/Phaser/FickleRegister.java create mode 100644 jdk/test/java/util/concurrent/Phaser/PhaseOverflow.java create mode 100644 jdk/test/java/util/concurrent/Phaser/TieredArriveLoops.java diff --git a/jdk/src/share/classes/java/util/Collections.java b/jdk/src/share/classes/java/util/Collections.java index 08f8adbe5b2..8be24796f7d 100644 --- a/jdk/src/share/classes/java/util/Collections.java +++ b/jdk/src/share/classes/java/util/Collections.java @@ -1452,10 +1452,10 @@ public class Collections { * when o is a Map.Entry, and calls o.setValue. */ public boolean containsAll(Collection coll) { - Iterator it = coll.iterator(); - while (it.hasNext()) - if (!contains(it.next())) // Invokes safe contains() above + for (Object e : coll) { + if (!contains(e)) // Invokes safe contains() above return false; + } return true; } public boolean equals(Object o) { diff --git a/jdk/src/share/classes/java/util/LinkedList.java b/jdk/src/share/classes/java/util/LinkedList.java index fbf8f5f92ce..e4d0ddc0787 100644 --- a/jdk/src/share/classes/java/util/LinkedList.java +++ b/jdk/src/share/classes/java/util/LinkedList.java @@ -26,9 +26,9 @@ package java.util; /** - * Linked list implementation of the {@link List} and {@link Deque} interfaces. - * Implements all optional operations, and permits all elements (including - * {@code null}). + * Doubly-linked list implementation of the {@code List} and {@code Deque} + * interfaces. Implements all optional list operations, and permits all + * elements (including {@code null}). * *

All of the operations perform as could be expected for a doubly-linked * list. Operations that index into the list will traverse the list from @@ -249,7 +249,7 @@ public class LinkedList * @return the last element in this list * @throws NoSuchElementException if this list is empty */ - public E getLast() { + public E getLast() { final Node l = last; if (l == null) throw new NoSuchElementException(); diff --git a/jdk/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java b/jdk/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java index 0690c8216e9..4f4b9d96af6 100644 --- a/jdk/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java +++ b/jdk/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java @@ -49,14 +49,14 @@ import java.util.*; *

This is a classic "bounded buffer", in which a * fixed-sized array holds elements inserted by producers and * extracted by consumers. Once created, the capacity cannot be - * increased. Attempts to put an element into a full queue - * will result in the operation blocking; attempts to take an + * changed. Attempts to {@code put} an element into a full queue + * will result in the operation blocking; attempts to {@code take} an * element from an empty queue will similarly block. * - *

This class supports an optional fairness policy for ordering + *

This class supports an optional fairness policy for ordering * waiting producer and consumer threads. By default, this ordering * is not guaranteed. However, a queue constructed with fairness set - * to true grants threads access in FIFO order. Fairness + * to {@code true} grants threads access in FIFO order. Fairness * generally decreases throughput but reduces variability and avoids * starvation. * @@ -83,14 +83,17 @@ public class ArrayBlockingQueue extends AbstractQueue */ private static final long serialVersionUID = -817911632652898426L; - /** The queued items */ - private final E[] items; - /** items index for next take, poll or remove */ - private int takeIndex; - /** items index for next put, offer, or add. */ - private int putIndex; - /** Number of items in the queue */ - private int count; + /** The queued items */ + final Object[] items; + + /** items index for next take, poll, peek or remove */ + int takeIndex; + + /** items index for next put, offer, or add */ + int putIndex; + + /** Number of elements in the queue */ + int count; /* * Concurrency control uses the classic two-condition algorithm @@ -98,7 +101,7 @@ public class ArrayBlockingQueue extends AbstractQueue */ /** Main lock guarding all access */ - private final ReentrantLock lock; + final ReentrantLock lock; /** Condition for waiting takes */ private final Condition notEmpty; /** Condition for waiting puts */ @@ -110,7 +113,36 @@ public class ArrayBlockingQueue extends AbstractQueue * Circularly increment i. */ final int inc(int i) { - return (++i == items.length)? 0 : i; + return (++i == items.length) ? 0 : i; + } + + /** + * Circularly decrement i. + */ + final int dec(int i) { + return ((i == 0) ? items.length : i) - 1; + } + + @SuppressWarnings("unchecked") + static E cast(Object item) { + return (E) item; + } + + /** + * Returns item at index i. + */ + final E itemAt(int i) { + return this.cast(items[i]); + } + + /** + * Throws NullPointerException if argument is null. + * + * @param v the element + */ + private static void checkNotNull(Object v) { + if (v == null) + throw new NullPointerException(); } /** @@ -129,8 +161,8 @@ public class ArrayBlockingQueue extends AbstractQueue * Call only when holding lock. */ private E extract() { - final E[] items = this.items; - E x = items[takeIndex]; + final Object[] items = this.items; + E x = this.cast(items[takeIndex]); items[takeIndex] = null; takeIndex = inc(takeIndex); --count; @@ -139,11 +171,12 @@ public class ArrayBlockingQueue extends AbstractQueue } /** - * Utility for remove and iterator.remove: Delete item at position i. + * Deletes item at position i. + * Utility for remove and iterator.remove. * Call only when holding lock. */ void removeAt(int i) { - final E[] items = this.items; + final Object[] items = this.items; // if removing front item, just advance if (i == takeIndex) { items[takeIndex] = null; @@ -167,69 +200,82 @@ public class ArrayBlockingQueue extends AbstractQueue } /** - * Creates an ArrayBlockingQueue with the given (fixed) + * Creates an {@code ArrayBlockingQueue} with the given (fixed) * capacity and default access policy. * * @param capacity the capacity of this queue - * @throws IllegalArgumentException if capacity is less than 1 + * @throws IllegalArgumentException if {@code capacity < 1} */ public ArrayBlockingQueue(int capacity) { this(capacity, false); } /** - * Creates an ArrayBlockingQueue with the given (fixed) + * Creates an {@code ArrayBlockingQueue} with the given (fixed) * capacity and the specified access policy. * * @param capacity the capacity of this queue - * @param fair if true then queue accesses for threads blocked + * @param fair if {@code true} then queue accesses for threads blocked * on insertion or removal, are processed in FIFO order; - * if false the access order is unspecified. - * @throws IllegalArgumentException if capacity is less than 1 + * if {@code false} the access order is unspecified. + * @throws IllegalArgumentException if {@code capacity < 1} */ public ArrayBlockingQueue(int capacity, boolean fair) { if (capacity <= 0) throw new IllegalArgumentException(); - this.items = (E[]) new Object[capacity]; + this.items = new Object[capacity]; lock = new ReentrantLock(fair); notEmpty = lock.newCondition(); notFull = lock.newCondition(); } /** - * Creates an ArrayBlockingQueue with the given (fixed) + * Creates an {@code ArrayBlockingQueue} with the given (fixed) * capacity, the specified access policy and initially containing the * elements of the given collection, * added in traversal order of the collection's iterator. * * @param capacity the capacity of this queue - * @param fair if true then queue accesses for threads blocked + * @param fair if {@code true} then queue accesses for threads blocked * on insertion or removal, are processed in FIFO order; - * if false the access order is unspecified. + * if {@code false} the access order is unspecified. * @param c the collection of elements to initially contain - * @throws IllegalArgumentException if capacity is less than - * c.size(), or less than 1. + * @throws IllegalArgumentException if {@code capacity} is less than + * {@code c.size()}, or less than 1. * @throws NullPointerException if the specified collection or any * of its elements are null */ public ArrayBlockingQueue(int capacity, boolean fair, Collection c) { this(capacity, fair); - if (capacity < c.size()) - throw new IllegalArgumentException(); - for (E e : c) - add(e); + final ReentrantLock lock = this.lock; + lock.lock(); // Lock only for visibility, not mutual exclusion + try { + int i = 0; + try { + for (E e : c) { + checkNotNull(e); + items[i++] = e; + } + } catch (ArrayIndexOutOfBoundsException ex) { + throw new IllegalArgumentException(); + } + count = i; + putIndex = (i == capacity) ? 0 : i; + } finally { + lock.unlock(); + } } /** * Inserts the specified element at the tail of this queue if it is * possible to do so immediately without exceeding the queue's capacity, - * returning true upon success and throwing an - * IllegalStateException if this queue is full. + * returning {@code true} upon success and throwing an + * {@code IllegalStateException} if this queue is full. * * @param e the element to add - * @return true (as specified by {@link Collection#add}) + * @return {@code true} (as specified by {@link Collection#add}) * @throws IllegalStateException if this queue is full * @throws NullPointerException if the specified element is null */ @@ -240,14 +286,14 @@ public class ArrayBlockingQueue extends AbstractQueue /** * Inserts the specified element at the tail of this queue if it is * possible to do so immediately without exceeding the queue's capacity, - * returning true upon success and false if this queue + * returning {@code true} upon success and {@code false} if this queue * is full. This method is generally preferable to method {@link #add}, * which can fail to insert an element only by throwing an exception. * * @throws NullPointerException if the specified element is null */ public boolean offer(E e) { - if (e == null) throw new NullPointerException(); + checkNotNull(e); final ReentrantLock lock = this.lock; lock.lock(); try { @@ -270,18 +316,12 @@ public class ArrayBlockingQueue extends AbstractQueue * @throws NullPointerException {@inheritDoc} */ public void put(E e) throws InterruptedException { - if (e == null) throw new NullPointerException(); - final E[] items = this.items; + checkNotNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - try { - while (count == items.length) - notFull.await(); - } catch (InterruptedException ie) { - notFull.signal(); // propagate to non-interrupted thread - throw ie; - } + while (count == items.length) + notFull.await(); insert(e); } finally { lock.unlock(); @@ -299,25 +339,18 @@ public class ArrayBlockingQueue extends AbstractQueue public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException { - if (e == null) throw new NullPointerException(); + checkNotNull(e); long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - for (;;) { - if (count != items.length) { - insert(e); - return true; - } + while (count == items.length) { if (nanos <= 0) return false; - try { - nanos = notFull.awaitNanos(nanos); - } catch (InterruptedException ie) { - notFull.signal(); // propagate to non-interrupted thread - throw ie; - } + nanos = notFull.awaitNanos(nanos); } + insert(e); + return true; } finally { lock.unlock(); } @@ -327,10 +360,7 @@ public class ArrayBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - if (count == 0) - return null; - E x = extract(); - return x; + return (count == 0) ? null : extract(); } finally { lock.unlock(); } @@ -340,15 +370,9 @@ public class ArrayBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - try { - while (count == 0) - notEmpty.await(); - } catch (InterruptedException ie) { - notEmpty.signal(); // propagate to non-interrupted thread - throw ie; - } - E x = extract(); - return x; + while (count == 0) + notEmpty.await(); + return extract(); } finally { lock.unlock(); } @@ -359,21 +383,12 @@ public class ArrayBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - for (;;) { - if (count != 0) { - E x = extract(); - return x; - } + while (count == 0) { if (nanos <= 0) return null; - try { - nanos = notEmpty.awaitNanos(nanos); - } catch (InterruptedException ie) { - notEmpty.signal(); // propagate to non-interrupted thread - throw ie; - } - + nanos = notEmpty.awaitNanos(nanos); } + return extract(); } finally { lock.unlock(); } @@ -383,7 +398,7 @@ public class ArrayBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - return (count == 0) ? null : items[takeIndex]; + return (count == 0) ? null : itemAt(takeIndex); } finally { lock.unlock(); } @@ -412,10 +427,10 @@ public class ArrayBlockingQueue extends AbstractQueue * Returns the number of additional elements that this queue can ideally * (in the absence of memory or resource constraints) accept without * blocking. This is always equal to the initial capacity of this queue - * less the current size of this queue. + * less the current {@code size} of this queue. * *

Note that you cannot always tell if an attempt to insert - * an element will succeed by inspecting remainingCapacity + * an element will succeed by inspecting {@code remainingCapacity} * because it may be the case that another thread is about to * insert or remove an element. */ @@ -431,59 +446,56 @@ public class ArrayBlockingQueue extends AbstractQueue /** * Removes a single instance of the specified element from this queue, - * if it is present. More formally, removes an element e such - * that o.equals(e), if this queue contains one or more such + * if it is present. More formally, removes an element {@code e} such + * that {@code o.equals(e)}, if this queue contains one or more such * elements. - * Returns true if this queue contained the specified element + * Returns {@code true} if this queue contained the specified element * (or equivalently, if this queue changed as a result of the call). * + *

Removal of interior elements in circular array based queues + * is an intrinsically slow and disruptive operation, so should + * be undertaken only in exceptional circumstances, ideally + * only when the queue is known not to be accessible by other + * threads. + * * @param o element to be removed from this queue, if present - * @return true if this queue changed as a result of the call + * @return {@code true} if this queue changed as a result of the call */ public boolean remove(Object o) { if (o == null) return false; - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { - int i = takeIndex; - int k = 0; - for (;;) { - if (k++ >= count) - return false; + for (int i = takeIndex, k = count; k > 0; i = inc(i), k--) { if (o.equals(items[i])) { removeAt(i); return true; } - i = inc(i); } - + return false; } finally { lock.unlock(); } } /** - * Returns true if this queue contains the specified element. - * More formally, returns true if and only if this queue contains - * at least one element e such that o.equals(e). + * Returns {@code true} if this queue contains the specified element. + * More formally, returns {@code true} if and only if this queue contains + * at least one element {@code e} such that {@code o.equals(e)}. * * @param o object to be checked for containment in this queue - * @return true if this queue contains the specified element + * @return {@code true} if this queue contains the specified element */ public boolean contains(Object o) { if (o == null) return false; - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { - int i = takeIndex; - int k = 0; - while (k++ < count) { + for (int i = takeIndex, k = count; k > 0; i = inc(i), k--) if (o.equals(items[i])) return true; - i = inc(i); - } return false; } finally { lock.unlock(); @@ -504,17 +516,14 @@ public class ArrayBlockingQueue extends AbstractQueue * @return an array containing all of the elements in this queue */ public Object[] toArray() { - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { + final int count = this.count; Object[] a = new Object[count]; - int k = 0; - int i = takeIndex; - while (k < count) { - a[k++] = items[i]; - i = inc(i); - } + for (int i = takeIndex, k = 0; k < count; i = inc(i), k++) + a[k] = items[i]; return a; } finally { lock.unlock(); @@ -531,22 +540,22 @@ public class ArrayBlockingQueue extends AbstractQueue *

If this queue fits in the specified array with room to spare * (i.e., the array has more elements than this queue), the element in * the array immediately following the end of the queue is set to - * null. + * {@code null}. * *

Like the {@link #toArray()} method, this method acts as bridge between * array-based and collection-based APIs. Further, this method allows * precise control over the runtime type of the output array, and may, * under certain circumstances, be used to save allocation costs. * - *

Suppose x is a queue known to contain only strings. + *

Suppose {@code x} is a queue known to contain only strings. * The following code can be used to dump the queue into a newly - * allocated array of String: + * allocated array of {@code String}: * *

      *     String[] y = x.toArray(new String[0]);
* - * Note that toArray(new Object[0]) is identical in function to - * toArray(). + * Note that {@code toArray(new Object[0])} is identical in function to + * {@code toArray()}. * * @param a the array into which the elements of the queue are to * be stored, if it is big enough; otherwise, a new array of the @@ -557,24 +566,20 @@ public class ArrayBlockingQueue extends AbstractQueue * this queue * @throws NullPointerException if the specified array is null */ + @SuppressWarnings("unchecked") public T[] toArray(T[] a) { - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { - if (a.length < count) + final int count = this.count; + final int len = a.length; + if (len < count) a = (T[])java.lang.reflect.Array.newInstance( - a.getClass().getComponentType(), - count - ); - - int k = 0; - int i = takeIndex; - while (k < count) { - a[k++] = (T)items[i]; - i = inc(i); - } - if (a.length > count) + a.getClass().getComponentType(), count); + for (int i = takeIndex, k = 0; k < count; i = inc(i), k++) + a[k] = (T) items[i]; + if (len > count) a[count] = null; return a; } finally { @@ -586,7 +591,19 @@ public class ArrayBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - return super.toString(); + int k = count; + if (k == 0) + return "[]"; + + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (int i = takeIndex; ; i = inc(i)) { + Object e = items[i]; + sb.append(e == this ? "(this Collection)" : e); + if (--k == 0) + return sb.append(']').toString(); + sb.append(',').append(' '); + } } finally { lock.unlock(); } @@ -597,16 +614,12 @@ public class ArrayBlockingQueue extends AbstractQueue * The queue will be empty after this call returns. */ public void clear() { - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { - int i = takeIndex; - int k = count; - while (k-- > 0) { + for (int i = takeIndex, k = count; k > 0; i = inc(i), k--) items[i] = null; - i = inc(i); - } count = 0; putIndex = 0; takeIndex = 0; @@ -623,11 +636,10 @@ public class ArrayBlockingQueue extends AbstractQueue * @throws IllegalArgumentException {@inheritDoc} */ public int drainTo(Collection c) { - if (c == null) - throw new NullPointerException(); + checkNotNull(c); if (c == this) throw new IllegalArgumentException(); - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { @@ -635,7 +647,7 @@ public class ArrayBlockingQueue extends AbstractQueue int n = 0; int max = count; while (n < max) { - c.add(items[i]); + c.add(this.cast(items[i])); items[i] = null; i = inc(i); ++n; @@ -659,22 +671,20 @@ public class ArrayBlockingQueue extends AbstractQueue * @throws IllegalArgumentException {@inheritDoc} */ public int drainTo(Collection c, int maxElements) { - if (c == null) - throw new NullPointerException(); + checkNotNull(c); if (c == this) throw new IllegalArgumentException(); if (maxElements <= 0) return 0; - final E[] items = this.items; + final Object[] items = this.items; final ReentrantLock lock = this.lock; lock.lock(); try { int i = takeIndex; int n = 0; - int sz = count; - int max = (maxElements < count)? maxElements : count; + int max = (maxElements < count) ? maxElements : count; while (n < max) { - c.add(items[i]); + c.add(this.cast(items[i])); items[i] = null; i = inc(i); ++n; @@ -690,11 +700,13 @@ public class ArrayBlockingQueue extends AbstractQueue } } - /** * Returns an iterator over the elements in this queue in proper sequence. - * The returned Iterator is a "weakly consistent" iterator that - * will never throw {@link ConcurrentModificationException}, + * The elements will be returned in order from first (head) to last (tail). + * + *

The returned {@code Iterator} is a "weakly consistent" iterator that + * will never throw {@link java.util.ConcurrentModificationException + * ConcurrentModificationException}, * and guarantees to traverse elements as they existed upon * construction of the iterator, and may (but is not guaranteed to) * reflect any modifications subsequent to construction. @@ -702,83 +714,65 @@ public class ArrayBlockingQueue extends AbstractQueue * @return an iterator over the elements in this queue in proper sequence */ public Iterator iterator() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return new Itr(); - } finally { - lock.unlock(); - } + return new Itr(); } /** - * Iterator for ArrayBlockingQueue + * Iterator for ArrayBlockingQueue. To maintain weak consistency + * with respect to puts and takes, we (1) read ahead one slot, so + * as to not report hasNext true but then not have an element to + * return -- however we later recheck this slot to use the most + * current value; (2) ensure that each array slot is traversed at + * most once (by tracking "remaining" elements); (3) skip over + * null slots, which can occur if takes race ahead of iterators. + * However, for circular array-based queues, we cannot rely on any + * well established definition of what it means to be weakly + * consistent with respect to interior removes since these may + * require slot overwrites in the process of sliding elements to + * cover gaps. So we settle for resiliency, operating on + * established apparent nexts, which may miss some elements that + * have moved between calls to next. */ private class Itr implements Iterator { - /** - * Index of element to be returned by next, - * or a negative number if no such. - */ - private int nextIndex; - - /** - * nextItem holds on to item fields because once we claim - * that an element exists in hasNext(), we must return it in - * the following next() call even if it was in the process of - * being removed when hasNext() was called. - */ - private E nextItem; - - /** - * Index of element returned by most recent call to next. - * Reset to -1 if this element is deleted by a call to remove. - */ - private int lastRet; + private int remaining; // Number of elements yet to be returned + private int nextIndex; // Index of element to be returned by next + private E nextItem; // Element to be returned by next call to next + private E lastItem; // Element returned by last call to next + private int lastRet; // Index of last element returned, or -1 if none Itr() { - lastRet = -1; - if (count == 0) - nextIndex = -1; - else { - nextIndex = takeIndex; - nextItem = items[takeIndex]; + final ReentrantLock lock = ArrayBlockingQueue.this.lock; + lock.lock(); + try { + lastRet = -1; + if ((remaining = count) > 0) + nextItem = itemAt(nextIndex = takeIndex); + } finally { + lock.unlock(); } } public boolean hasNext() { - /* - * No sync. We can return true by mistake here - * only if this iterator passed across threads, - * which we don't support anyway. - */ - return nextIndex >= 0; - } - - /** - * Checks whether nextIndex is valid; if so setting nextItem. - * Stops iterator when either hits putIndex or sees null item. - */ - private void checkNext() { - if (nextIndex == putIndex) { - nextIndex = -1; - nextItem = null; - } else { - nextItem = items[nextIndex]; - if (nextItem == null) - nextIndex = -1; - } + return remaining > 0; } public E next() { final ReentrantLock lock = ArrayBlockingQueue.this.lock; lock.lock(); try { - if (nextIndex < 0) + if (remaining <= 0) throw new NoSuchElementException(); lastRet = nextIndex; - E x = nextItem; - nextIndex = inc(nextIndex); - checkNext(); + E x = itemAt(nextIndex); // check for fresher value + if (x == null) { + x = nextItem; // we are forced to report old value + lastItem = null; // but ensure remove fails + } + else + lastItem = x; + while (--remaining > 0 && // skip over nulls + (nextItem = itemAt(nextIndex = inc(nextIndex))) == null) + ; return x; } finally { lock.unlock(); @@ -793,15 +787,19 @@ public class ArrayBlockingQueue extends AbstractQueue if (i == -1) throw new IllegalStateException(); lastRet = -1; - - int ti = takeIndex; - removeAt(i); - // back up cursor (reset to front if was first element) - nextIndex = (i == ti) ? takeIndex : i; - checkNext(); + E x = lastItem; + lastItem = null; + // only remove if item still at index + if (x != null && x == items[i]) { + boolean removingHead = (i == takeIndex); + removeAt(i); + if (!removingHead) + nextIndex = dec(nextIndex); + } } finally { lock.unlock(); } } } + } diff --git a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java index 72133fedad7..2158084f9f9 100644 --- a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java +++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java @@ -869,6 +869,8 @@ public class ConcurrentLinkedDeque /** * Inserts the specified element at the front of this deque. + * As the deque is unbounded, this method will never throw + * {@link IllegalStateException}. * * @throws NullPointerException if the specified element is null */ @@ -878,6 +880,8 @@ public class ConcurrentLinkedDeque /** * Inserts the specified element at the end of this deque. + * As the deque is unbounded, this method will never throw + * {@link IllegalStateException}. * *

This method is equivalent to {@link #add}. * @@ -889,8 +893,9 @@ public class ConcurrentLinkedDeque /** * Inserts the specified element at the front of this deque. + * As the deque is unbounded, this method will never return {@code false}. * - * @return {@code true} always + * @return {@code true} (as specified by {@link Deque#offerFirst}) * @throws NullPointerException if the specified element is null */ public boolean offerFirst(E e) { @@ -900,10 +905,11 @@ public class ConcurrentLinkedDeque /** * Inserts the specified element at the end of this deque. + * As the deque is unbounded, this method will never return {@code false}. * *

This method is equivalent to {@link #add}. * - * @return {@code true} always + * @return {@code true} (as specified by {@link Deque#offerLast}) * @throws NullPointerException if the specified element is null */ public boolean offerLast(E e) { @@ -983,6 +989,7 @@ public class ConcurrentLinkedDeque /** * Inserts the specified element at the tail of this deque. + * As the deque is unbounded, this method will never return {@code false}. * * @return {@code true} (as specified by {@link Queue#offer}) * @throws NullPointerException if the specified element is null @@ -993,6 +1000,8 @@ public class ConcurrentLinkedDeque /** * Inserts the specified element at the tail of this deque. + * As the deque is unbounded, this method will never throw + * {@link IllegalStateException} or return {@code false}. * * @return {@code true} (as specified by {@link Collection#add}) * @throws NullPointerException if the specified element is null diff --git a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java index 6ff1b8a5119..b7beda274da 100644 --- a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java @@ -269,6 +269,8 @@ public class ConcurrentLinkedQueue extends AbstractQueue /** * Inserts the specified element at the tail of this queue. + * As the queue is unbounded, this method will never throw + * {@link IllegalStateException} or return {@code false}. * * @return {@code true} (as specified by {@link Collection#add}) * @throws NullPointerException if the specified element is null @@ -298,6 +300,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue /** * Inserts the specified element at the tail of this queue. + * As the queue is unbounded, this method will never return {@code false}. * * @return {@code true} (as specified by {@link Queue#offer}) * @throws NullPointerException if the specified element is null diff --git a/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java b/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java index 4e0457f2877..64d28cf6040 100644 --- a/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java +++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java @@ -374,17 +374,11 @@ public class ConcurrentSkipListMap extends AbstractMap null, null, 1); } - /** Updater for casHead */ - private static final - AtomicReferenceFieldUpdater - headUpdater = AtomicReferenceFieldUpdater.newUpdater - (ConcurrentSkipListMap.class, HeadIndex.class, "head"); - /** * compareAndSet head node */ private boolean casHead(HeadIndex cmp, HeadIndex val) { - return headUpdater.compareAndSet(this, cmp, val); + return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val); } /* ---------------- Nodes -------------- */ @@ -423,28 +417,18 @@ public class ConcurrentSkipListMap extends AbstractMap this.next = next; } - /** Updater for casNext */ - static final AtomicReferenceFieldUpdater - nextUpdater = AtomicReferenceFieldUpdater.newUpdater - (Node.class, Node.class, "next"); - - /** Updater for casValue */ - static final AtomicReferenceFieldUpdater - valueUpdater = AtomicReferenceFieldUpdater.newUpdater - (Node.class, Object.class, "value"); - /** * compareAndSet value field */ boolean casValue(Object cmp, Object val) { - return valueUpdater.compareAndSet(this, cmp, val); + return UNSAFE.compareAndSwapObject(this, valueOffset, cmp, val); } /** * compareAndSet next field */ boolean casNext(Node cmp, Node val) { - return nextUpdater.compareAndSet(this, cmp, val); + return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); } /** @@ -522,6 +506,14 @@ public class ConcurrentSkipListMap extends AbstractMap return null; return new AbstractMap.SimpleImmutableEntry(key, v); } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long valueOffset = + objectFieldOffset(UNSAFE, "value", Node.class); + private static final long nextOffset = + objectFieldOffset(UNSAFE, "next", Node.class); + } /* ---------------- Indexing -------------- */ @@ -547,16 +539,11 @@ public class ConcurrentSkipListMap extends AbstractMap this.right = right; } - /** Updater for casRight */ - static final AtomicReferenceFieldUpdater - rightUpdater = AtomicReferenceFieldUpdater.newUpdater - (Index.class, Index.class, "right"); - /** * compareAndSet right field */ final boolean casRight(Index cmp, Index val) { - return rightUpdater.compareAndSet(this, cmp, val); + return UNSAFE.compareAndSwapObject(this, rightOffset, cmp, val); } /** @@ -591,6 +578,12 @@ public class ConcurrentSkipListMap extends AbstractMap final boolean unlink(Index succ) { return !indexesDeletedNode() && casRight(succ, succ.right); } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long rightOffset = + objectFieldOffset(UNSAFE, "right", Index.class); + } /* ---------------- Head nodes -------------- */ @@ -640,7 +633,8 @@ public class ConcurrentSkipListMap extends AbstractMap * cast key as Comparable, which may cause ClassCastException, * which is propagated back to caller. */ - private Comparable comparable(Object key) throws ClassCastException { + private Comparable comparable(Object key) + throws ClassCastException { if (key == null) throw new NullPointerException(); if (comparator != null) @@ -799,68 +793,12 @@ public class ConcurrentSkipListMap extends AbstractMap } /** - * Specialized variant of findNode to perform Map.get. Does a weak - * traversal, not bothering to fix any deleted index nodes, - * returning early if it happens to see key in index, and passing - * over any deleted base nodes, falling back to getUsingFindNode - * only if it would otherwise return value from an ongoing - * deletion. Also uses "bound" to eliminate need for some - * comparisons (see Pugh Cookbook). Also folds uses of null checks - * and node-skipping because markers have null keys. + * Gets value for key using findNode. * @param okey the key * @return the value, or null if absent */ private V doGet(Object okey) { Comparable key = comparable(okey); - Node bound = null; - Index q = head; - Index r = q.right; - Node n; - K k; - int c; - for (;;) { - Index d; - // Traverse rights - if (r != null && (n = r.node) != bound && (k = n.key) != null) { - if ((c = key.compareTo(k)) > 0) { - q = r; - r = r.right; - continue; - } else if (c == 0) { - Object v = n.value; - return (v != null)? (V)v : getUsingFindNode(key); - } else - bound = n; - } - - // Traverse down - if ((d = q.down) != null) { - q = d; - r = d.right; - } else - break; - } - - // Traverse nexts - for (n = q.node.next; n != null; n = n.next) { - if ((k = n.key) != null) { - if ((c = key.compareTo(k)) == 0) { - Object v = n.value; - return (v != null)? (V)v : getUsingFindNode(key); - } else if (c < 0) - break; - } - } - return null; - } - - /** - * Performs map.get via findNode. Used as a backup if doGet - * encounters an in-progress deletion. - * @param key the key - * @return the value, or null if absent - */ - private V getUsingFindNode(Comparable key) { /* * Loop needed here and elsewhere in case value field goes * null just as it is about to be returned, in which case we @@ -943,7 +881,7 @@ public class ConcurrentSkipListMap extends AbstractMap x ^= x << 13; x ^= x >>> 17; randomSeed = x ^= x << 5; - if ((x & 0x8001) != 0) // test highest and lowest bits + if ((x & 0x80000001) != 0) // test highest and lowest bits return 0; int level = 1; while (((x >>>= 1) & 1) != 0) ++level; @@ -1256,7 +1194,7 @@ public class ConcurrentSkipListMap extends AbstractMap Node n = b.next; for (;;) { if (n == null) - return (b.isBaseHeader())? null : b; + return b.isBaseHeader() ? null : b; Node f = n.next; // inconsistent read if (n != b.next) break; @@ -1374,7 +1312,7 @@ public class ConcurrentSkipListMap extends AbstractMap Node n = b.next; for (;;) { if (n == null) - return ((rel & LT) == 0 || b.isBaseHeader())? null : b; + return ((rel & LT) == 0 || b.isBaseHeader()) ? null : b; Node f = n.next; if (n != b.next) // inconsistent read break; @@ -1390,7 +1328,7 @@ public class ConcurrentSkipListMap extends AbstractMap (c < 0 && (rel & LT) == 0)) return n; if ( c <= 0 && (rel & LT) != 0) - return (b.isBaseHeader())? null : b; + return b.isBaseHeader() ? null : b; b = n; n = f; } @@ -1744,7 +1682,7 @@ public class ConcurrentSkipListMap extends AbstractMap if (n.getValidValue() != null) ++count; } - return (count >= Integer.MAX_VALUE)? Integer.MAX_VALUE : (int)count; + return (count >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) count; } /** @@ -2099,7 +2037,7 @@ public class ConcurrentSkipListMap extends AbstractMap */ public K lowerKey(K key) { Node n = findNear(key, LT); - return (n == null)? null : n.key; + return (n == null) ? null : n.key; } /** @@ -2123,7 +2061,7 @@ public class ConcurrentSkipListMap extends AbstractMap */ public K floorKey(K key) { Node n = findNear(key, LT|EQ); - return (n == null)? null : n.key; + return (n == null) ? null : n.key; } /** @@ -2145,7 +2083,7 @@ public class ConcurrentSkipListMap extends AbstractMap */ public K ceilingKey(K key) { Node n = findNear(key, GT|EQ); - return (n == null)? null : n.key; + return (n == null) ? null : n.key; } /** @@ -2169,7 +2107,7 @@ public class ConcurrentSkipListMap extends AbstractMap */ public K higherKey(K key) { Node n = findNear(key, GT); - return (n == null)? null : n.key; + return (n == null) ? null : n.key; } /** @@ -2342,7 +2280,8 @@ public class ConcurrentSkipListMap extends AbstractMap return list; } - static final class KeySet extends AbstractSet implements NavigableSet { + static final class KeySet + extends AbstractSet implements NavigableSet { private final ConcurrentNavigableMap m; KeySet(ConcurrentNavigableMap map) { m = map; } public int size() { return m.size(); } @@ -2359,11 +2298,11 @@ public class ConcurrentSkipListMap extends AbstractMap public E last() { return m.lastKey(); } public E pollFirst() { Map.Entry e = m.pollFirstEntry(); - return e == null? null : e.getKey(); + return (e == null) ? null : e.getKey(); } public E pollLast() { Map.Entry e = m.pollLastEntry(); - return e == null? null : e.getKey(); + return (e == null) ? null : e.getKey(); } public Iterator iterator() { if (m instanceof ConcurrentSkipListMap) @@ -2710,9 +2649,9 @@ public class ConcurrentSkipListMap extends AbstractMap rel &= ~m.LT; } if (tooLow(key)) - return ((rel & m.LT) != 0)? null : lowestEntry(); + return ((rel & m.LT) != 0) ? null : lowestEntry(); if (tooHigh(key)) - return ((rel & m.LT) != 0)? highestEntry() : null; + return ((rel & m.LT) != 0) ? highestEntry() : null; for (;;) { Node n = m.findNear(key, rel); if (n == null || !inBounds(n.key)) @@ -2783,7 +2722,7 @@ public class ConcurrentSkipListMap extends AbstractMap public V remove(Object key) { K k = (K)key; - return (!inBounds(k))? null : m.remove(k); + return (!inBounds(k)) ? null : m.remove(k); } public int size() { @@ -2794,7 +2733,7 @@ public class ConcurrentSkipListMap extends AbstractMap if (n.getValidValue() != null) ++count; } - return count >= Integer.MAX_VALUE? Integer.MAX_VALUE : (int)count; + return count >= Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)count; } public boolean isEmpty() { @@ -2972,27 +2911,27 @@ public class ConcurrentSkipListMap extends AbstractMap } public K firstKey() { - return isDescending? highestKey() : lowestKey(); + return isDescending ? highestKey() : lowestKey(); } public K lastKey() { - return isDescending? lowestKey() : highestKey(); + return isDescending ? lowestKey() : highestKey(); } public Map.Entry firstEntry() { - return isDescending? highestEntry() : lowestEntry(); + return isDescending ? highestEntry() : lowestEntry(); } public Map.Entry lastEntry() { - return isDescending? lowestEntry() : highestEntry(); + return isDescending ? lowestEntry() : highestEntry(); } public Map.Entry pollFirstEntry() { - return isDescending? removeHighest() : removeLowest(); + return isDescending ? removeHighest() : removeLowest(); } public Map.Entry pollLastEntry() { - return isDescending? removeLowest() : removeHighest(); + return isDescending ? removeLowest() : removeHighest(); } /* ---------------- Submap Views -------------- */ @@ -3141,4 +3080,22 @@ public class ConcurrentSkipListMap extends AbstractMap } } } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long headOffset = + objectFieldOffset(UNSAFE, "head", ConcurrentSkipListMap.class); + + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, + String field, Class klazz) { + try { + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); + } catch (NoSuchFieldException e) { + // Convert Exception to corresponding Error + NoSuchFieldError error = new NoSuchFieldError(field); + error.initCause(e); + throw error; + } + } + } diff --git a/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java b/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java index 465426ff823..8c5193538fa 100644 --- a/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java +++ b/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java @@ -832,7 +832,7 @@ public class CopyOnWriteArrayList } /** - * Save the state of the list to a stream (i.e., serialize it). + * Saves the state of the list to a stream (that is, serializes it). * * @serialData The length of the array backing the list is emitted * (int), followed by all of its elements (each an Object) @@ -842,27 +842,25 @@ public class CopyOnWriteArrayList private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ - // Write out element count, and any hidden stuff s.defaultWriteObject(); Object[] elements = getArray(); - int len = elements.length; // Write out array length - s.writeInt(len); + s.writeInt(elements.length); // Write out all elements in the proper order. - for (int i = 0; i < len; i++) - s.writeObject(elements[i]); + for (Object element : elements) + s.writeObject(element); } /** - * Reconstitute the list from a stream (i.e., deserialize it). + * Reconstitutes the list from a stream (that is, deserializes it). + * * @param s the stream */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { - // Read in size, and any hidden stuff s.defaultReadObject(); // bind to new lock diff --git a/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java index 263552a93ea..22938fe4ba9 100644 --- a/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java @@ -525,8 +525,8 @@ public class ForkJoinPool extends AbstractExecutorService { */ private volatile long eventWaiters; - private static final int EVENT_COUNT_SHIFT = 32; - private static final long WAITER_ID_MASK = (1L << 16) - 1L; + private static final int EVENT_COUNT_SHIFT = 32; + private static final int WAITER_ID_MASK = (1 << 16) - 1; /** * A counter for events that may wake up worker threads: @@ -615,7 +615,7 @@ public class ForkJoinPool extends AbstractExecutorService { // are usually manually inlined by callers /** - * Increments running count part of workerCounts + * Increments running count part of workerCounts. */ final void incrementRunningCount() { int c; @@ -625,7 +625,17 @@ public class ForkJoinPool extends AbstractExecutorService { } /** - * Tries to decrement running count unless already zero + * Tries to increment running count part of workerCounts. + */ + final boolean tryIncrementRunningCount() { + int c; + return UNSAFE.compareAndSwapInt(this, workerCountsOffset, + c = workerCounts, + c + ONE_RUNNING); + } + + /** + * Tries to decrement running count unless already zero. */ final boolean tryDecrementRunningCount() { int wc = workerCounts; @@ -698,10 +708,11 @@ public class ForkJoinPool extends AbstractExecutorService { for (k = 0; k < n && ws[k] != null; ++k) ; if (k == n) - ws = Arrays.copyOf(ws, n << 1); + ws = workers = Arrays.copyOf(ws, n << 1); } ws[k] = w; - workers = ws; // volatile array write ensures slot visibility + int c = eventCount; // advance event count to ensure visibility + UNSAFE.compareAndSwapInt(this, eventCountOffset, c, c+1); } finally { lock.unlock(); } @@ -734,7 +745,7 @@ public class ForkJoinPool extends AbstractExecutorService { */ final void workerTerminated(ForkJoinWorkerThread w) { forgetWorker(w); - decrementWorkerCounts(w.isTrimmed()? 0 : ONE_RUNNING, ONE_TOTAL); + decrementWorkerCounts(w.isTrimmed() ? 0 : ONE_RUNNING, ONE_TOTAL); while (w.stealCount != 0) // collect final count tryAccumulateStealCount(w); tryTerminate(false); @@ -746,24 +757,23 @@ public class ForkJoinPool extends AbstractExecutorService { * Releases workers blocked on a count not equal to current count. * Normally called after precheck that eventWaiters isn't zero to * avoid wasted array checks. Gives up upon a change in count or - * upon releasing two workers, letting others take over. + * upon releasing four workers, letting others take over. */ private void releaseEventWaiters() { ForkJoinWorkerThread[] ws = workers; int n = ws.length; long h = eventWaiters; int ec = eventCount; - boolean releasedOne = false; + int releases = 4; ForkJoinWorkerThread w; int id; - while ((id = ((int)(h & WAITER_ID_MASK)) - 1) >= 0 && + while ((id = (((int)h) & WAITER_ID_MASK) - 1) >= 0 && (int)(h >>> EVENT_COUNT_SHIFT) != ec && id < n && (w = ws[id]) != null) { if (UNSAFE.compareAndSwapLong(this, eventWaitersOffset, h, w.nextWaiter)) { LockSupport.unpark(w); - if (releasedOne) // exit on second release + if (--releases == 0) break; - releasedOne = true; } if (eventCount != ec) break; @@ -793,7 +803,7 @@ public class ForkJoinPool extends AbstractExecutorService { long nh = (((long)ec) << EVENT_COUNT_SHIFT) | ((long)(w.poolIndex+1)); long h; while ((runState < SHUTDOWN || !tryTerminate(false)) && - (((int)((h = eventWaiters) & WAITER_ID_MASK)) == 0 || + (((int)(h = eventWaiters) & WAITER_ID_MASK) == 0 || (int)(h >>> EVENT_COUNT_SHIFT) == ec) && eventCount == ec) { if (UNSAFE.compareAndSwapLong(this, eventWaitersOffset, @@ -820,9 +830,9 @@ public class ForkJoinPool extends AbstractExecutorService { if (tryAccumulateStealCount(w)) { // transfer while idle boolean untimed = (w.nextWaiter != 0L || (workerCounts & RUNNING_COUNT_MASK) <= 1); - long startTime = untimed? 0 : System.nanoTime(); + long startTime = untimed ? 0 : System.nanoTime(); Thread.interrupted(); // clear/ignore interrupt - if (eventCount != ec || w.isTerminating()) + if (w.isTerminating() || eventCount != ec) break; // recheck after clear if (untimed) LockSupport.park(w); @@ -860,7 +870,8 @@ public class ForkJoinPool extends AbstractExecutorService { if ((sw = spareWaiters) != 0 && (id = (sw & SPARE_ID_MASK) - 1) >= 0 && id < n && (w = ws[id]) != null && - (workerCounts & RUNNING_COUNT_MASK) < parallelism && + (runState >= TERMINATING || + (workerCounts & RUNNING_COUNT_MASK) < parallelism) && spareWaiters == sw && UNSAFE.compareAndSwapInt(this, spareWaitersOffset, sw, w.nextSpare)) { @@ -914,12 +925,8 @@ public class ForkJoinPool extends AbstractExecutorService { break; } w.start(recordWorker(w), ueh); - if ((workerCounts >>> TOTAL_COUNT_SHIFT) >= pc) { - int c; // advance event count - UNSAFE.compareAndSwapInt(this, eventCountOffset, - c = eventCount, c+1); + if ((workerCounts >>> TOTAL_COUNT_SHIFT) >= pc) break; // add at most one unless total below target - } } } if (eventWaiters != 0L) @@ -955,7 +962,7 @@ public class ForkJoinPool extends AbstractExecutorService { } else if ((h = eventWaiters) != 0L) { long nh; - int id = ((int)(h & WAITER_ID_MASK)) - 1; + int id = (((int)h) & WAITER_ID_MASK) - 1; if (id >= 0 && id < n && (w = ws[id]) != null && (nh = w.nextWaiter) != 0L && // keep at least one worker UNSAFE.compareAndSwapLong(this, eventWaitersOffset, h, nh)) @@ -1003,24 +1010,31 @@ public class ForkJoinPool extends AbstractExecutorService { int pc = parallelism; while (w.runState == 0) { int rs = runState; - if (rs >= TERMINATING) { // propagate shutdown + if (rs >= TERMINATING) { // propagate shutdown w.shutdown(); break; } if ((inactivate || (active && (rs & ACTIVE_COUNT_MASK) >= pc)) && - UNSAFE.compareAndSwapInt(this, runStateOffset, rs, rs - 1)) + UNSAFE.compareAndSwapInt(this, runStateOffset, rs, --rs)) { inactivate = active = w.active = false; - int wc = workerCounts; + if (rs == SHUTDOWN) { // all inactive and shut down + tryTerminate(false); + continue; + } + } + int wc = workerCounts; // try to suspend as spare if ((wc & RUNNING_COUNT_MASK) > pc) { if (!(inactivate |= active) && // must inactivate to suspend - workerCounts == wc && // try to suspend as spare + workerCounts == wc && UNSAFE.compareAndSwapInt(this, workerCountsOffset, wc, wc - ONE_RUNNING)) w.suspendAsSpare(); } else if ((wc >>> TOTAL_COUNT_SHIFT) < pc) helpMaintainParallelism(); // not enough workers - else if (!ran) { + else if (ran) + break; + else { long h = eventWaiters; int ec = eventCount; if (h != 0L && (int)(h >>> EVENT_COUNT_SHIFT) != ec) @@ -1032,8 +1046,6 @@ public class ForkJoinPool extends AbstractExecutorService { else if (!(inactivate |= active)) eventSync(w, wec); // must inactivate before sync } - else - break; } } @@ -1043,35 +1055,67 @@ public class ForkJoinPool extends AbstractExecutorService { * * @param joinMe the task to join * @param worker the current worker thread + * @param timed true if wait should time out + * @param nanos timeout value if timed */ - final void awaitJoin(ForkJoinTask joinMe, ForkJoinWorkerThread worker) { + final void awaitJoin(ForkJoinTask joinMe, ForkJoinWorkerThread worker, + boolean timed, long nanos) { + long startTime = timed ? System.nanoTime() : 0L; int retries = 2 + (parallelism >> 2); // #helpJoins before blocking + boolean running = true; // false when count decremented while (joinMe.status >= 0) { - int wc; - worker.helpJoinTask(joinMe); + if (runState >= TERMINATING) { + joinMe.cancelIgnoringExceptions(); + break; + } + running = worker.helpJoinTask(joinMe, running); if (joinMe.status < 0) break; - else if (retries > 0) + if (retries > 0) { --retries; - else if (((wc = workerCounts) & RUNNING_COUNT_MASK) != 0 && - UNSAFE.compareAndSwapInt(this, workerCountsOffset, - wc, wc - ONE_RUNNING)) { - int stat, c; long h; - while ((stat = joinMe.status) >= 0 && - (h = eventWaiters) != 0L && // help release others - (int)(h >>> EVENT_COUNT_SHIFT) != eventCount) - releaseEventWaiters(); - if (stat >= 0 && - ((workerCounts & RUNNING_COUNT_MASK) == 0 || - (stat = - joinMe.internalAwaitDone(JOIN_TIMEOUT_MILLIS)) >= 0)) - helpMaintainParallelism(); // timeout or no running workers - do {} while (!UNSAFE.compareAndSwapInt - (this, workerCountsOffset, - c = workerCounts, c + ONE_RUNNING)); - if (stat < 0) - break; // else restart + continue; } + int wc = workerCounts; + if ((wc & RUNNING_COUNT_MASK) != 0) { + if (running) { + if (!UNSAFE.compareAndSwapInt(this, workerCountsOffset, + wc, wc - ONE_RUNNING)) + continue; + running = false; + } + long h = eventWaiters; + if (h != 0L && (int)(h >>> EVENT_COUNT_SHIFT) != eventCount) + releaseEventWaiters(); + if ((workerCounts & RUNNING_COUNT_MASK) != 0) { + long ms; int ns; + if (!timed) { + ms = JOIN_TIMEOUT_MILLIS; + ns = 0; + } + else { // at most JOIN_TIMEOUT_MILLIS per wait + long nt = nanos - (System.nanoTime() - startTime); + if (nt <= 0L) + break; + ms = nt / 1000000; + if (ms > JOIN_TIMEOUT_MILLIS) { + ms = JOIN_TIMEOUT_MILLIS; + ns = 0; + } + else + ns = (int) (nt % 1000000); + } + joinMe.internalAwaitDone(ms, ns); + } + if (joinMe.status < 0) + break; + } + helpMaintainParallelism(); + } + if (!running) { + int c; + do {} while (!UNSAFE.compareAndSwapInt + (this, workerCountsOffset, + c = workerCounts, c + ONE_RUNNING)); } } @@ -1082,9 +1126,10 @@ public class ForkJoinPool extends AbstractExecutorService { throws InterruptedException { while (!blocker.isReleasable()) { int wc = workerCounts; - if ((wc & RUNNING_COUNT_MASK) != 0 && - UNSAFE.compareAndSwapInt(this, workerCountsOffset, - wc, wc - ONE_RUNNING)) { + if ((wc & RUNNING_COUNT_MASK) == 0) + helpMaintainParallelism(); + else if (UNSAFE.compareAndSwapInt(this, workerCountsOffset, + wc, wc - ONE_RUNNING)) { try { while (!blocker.isReleasable()) { long h = eventWaiters; @@ -1129,12 +1174,11 @@ public class ForkJoinPool extends AbstractExecutorService { // Finish now if all threads terminated; else in some subsequent call if ((workerCounts >>> TOTAL_COUNT_SHIFT) == 0) { advanceRunLevel(TERMINATED); - termination.arrive(); + termination.forceTermination(); } return true; } - /** * Actions on transition to TERMINATING * @@ -1325,17 +1369,13 @@ public class ForkJoinPool extends AbstractExecutorService { // Execution methods /** - * Common code for execute, invoke and submit + * Submits task and creates, starts, or resumes some workers if necessary */ private void doSubmit(ForkJoinTask task) { - if (task == null) - throw new NullPointerException(); - if (runState >= SHUTDOWN) - throw new RejectedExecutionException(); submissionQueue.offer(task); int c; // try to increment event count -- CAS failure OK UNSAFE.compareAndSwapInt(this, eventCountOffset, c = eventCount, c+1); - helpMaintainParallelism(); // create, start, or resume some workers + helpMaintainParallelism(); } /** @@ -1348,8 +1388,33 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public T invoke(ForkJoinTask task) { - doSubmit(task); - return task.join(); + if (task == null) + throw new NullPointerException(); + if (runState >= SHUTDOWN) + throw new RejectedExecutionException(); + Thread t = Thread.currentThread(); + if ((t instanceof ForkJoinWorkerThread) && + ((ForkJoinWorkerThread)t).pool == this) + return task.invoke(); // bypass submit if in same pool + else { + doSubmit(task); + return task.join(); + } + } + + /** + * Unless terminating, forks task if within an ongoing FJ + * computation in the current pool, else submits as external task. + */ + private void forkOrSubmit(ForkJoinTask task) { + if (runState >= SHUTDOWN) + throw new RejectedExecutionException(); + Thread t = Thread.currentThread(); + if ((t instanceof ForkJoinWorkerThread) && + ((ForkJoinWorkerThread)t).pool == this) + task.fork(); + else + doSubmit(task); } /** @@ -1361,7 +1426,9 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public void execute(ForkJoinTask task) { - doSubmit(task); + if (task == null) + throw new NullPointerException(); + forkOrSubmit(task); } // AbstractExecutorService methods @@ -1372,12 +1439,14 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public void execute(Runnable task) { + if (task == null) + throw new NullPointerException(); ForkJoinTask job; if (task instanceof ForkJoinTask) // avoid re-wrap job = (ForkJoinTask) task; else job = ForkJoinTask.adapt(task, null); - doSubmit(job); + forkOrSubmit(job); } /** @@ -1390,7 +1459,9 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public ForkJoinTask submit(ForkJoinTask task) { - doSubmit(task); + if (task == null) + throw new NullPointerException(); + forkOrSubmit(task); return task; } @@ -1400,8 +1471,10 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public ForkJoinTask submit(Callable task) { + if (task == null) + throw new NullPointerException(); ForkJoinTask job = ForkJoinTask.adapt(task); - doSubmit(job); + forkOrSubmit(job); return job; } @@ -1411,8 +1484,10 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public ForkJoinTask submit(Runnable task, T result) { + if (task == null) + throw new NullPointerException(); ForkJoinTask job = ForkJoinTask.adapt(task, result); - doSubmit(job); + forkOrSubmit(job); return job; } @@ -1422,12 +1497,14 @@ public class ForkJoinPool extends AbstractExecutorService { * scheduled for execution */ public ForkJoinTask submit(Runnable task) { + if (task == null) + throw new NullPointerException(); ForkJoinTask job; if (task instanceof ForkJoinTask) // avoid re-wrap job = (ForkJoinTask) task; else job = ForkJoinTask.adapt(task, null); - doSubmit(job); + forkOrSubmit(job); return job; } @@ -1725,8 +1802,11 @@ public class ForkJoinPool extends AbstractExecutorService { * commenced but not yet completed. This method may be useful for * debugging. A return of {@code true} reported a sufficient * period after shutdown may indicate that submitted tasks have - * ignored or suppressed interruption, causing this executor not - * to properly terminate. + * ignored or suppressed interruption, or are waiting for IO, + * causing this executor not to properly terminate. (See the + * advisory notes for class {@link ForkJoinTask} stating that + * tasks should not normally entail blocking operations. But if + * they do, they must abort them on interrupt.) * * @return {@code true} if terminating but not yet terminated */ @@ -1764,10 +1844,11 @@ public class ForkJoinPool extends AbstractExecutorService { public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { try { - return termination.awaitAdvanceInterruptibly(0, timeout, unit) > 0; + termination.awaitAdvanceInterruptibly(0, timeout, unit); } catch (TimeoutException ex) { return false; } + return true; } /** diff --git a/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java b/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java index cd18360f83d..b02323ffd6d 100644 --- a/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java +++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java @@ -42,6 +42,16 @@ import java.util.List; import java.util.RandomAccess; import java.util.Map; import java.util.WeakHashMap; +import java.util.concurrent.Callable; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.RunnableFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; /** * Abstract base class for tasks that run within a {@link ForkJoinPool}. @@ -129,6 +139,16 @@ import java.util.WeakHashMap; * result in exceptions or errors, possibly including * {@code ClassCastException}. * + *

Method {@link #join} and its variants are appropriate for use + * only when completion dependencies are acyclic; that is, the + * parallel computation can be described as a directed acyclic graph + * (DAG). Otherwise, executions may encounter a form of deadlock as + * tasks cyclically wait for each other. However, this framework + * supports other methods and techniques (for example the use of + * {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that + * may be of use in constructing custom subclasses for problems that + * are not statically structured as DAGs. + * *

Most base support methods are {@code final}, to prevent * overriding of implementations that are intrinsically tied to the * underlying lightweight task scheduling framework. Developers @@ -143,9 +163,10 @@ import java.util.WeakHashMap; * computation. Large tasks should be split into smaller subtasks, * usually via recursive decomposition. As a very rough rule of thumb, * a task should perform more than 100 and less than 10000 basic - * computational steps. If tasks are too big, then parallelism cannot - * improve throughput. If too small, then memory and internal task - * maintenance overhead may overwhelm processing. + * computational steps, and should avoid indefinite looping. If tasks + * are too big, then parallelism cannot improve throughput. If too + * small, then memory and internal task maintenance overhead may + * overwhelm processing. * *

This class provides {@code adapt} methods for {@link Runnable} * and {@link Callable}, that may be of use when mixing execution of @@ -241,66 +262,84 @@ public abstract class ForkJoinTask implements Future, Serializable { setCompletion(EXCEPTIONAL); } - /** - * Blocks a worker thread until completion. Called only by - * pool. Currently unused -- pool-based waits use timeout - * version below. - */ - final void internalAwaitDone() { - int s; // the odd construction reduces lock bias effects - while ((s = status) >= 0) { - try { - synchronized (this) { - if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL)) - wait(); - } - } catch (InterruptedException ie) { - cancelIfTerminating(); - } - } - } - /** * Blocks a worker thread until completed or timed out. Called * only by pool. - * - * @return status on exit */ - final int internalAwaitDone(long millis) { - int s; - if ((s = status) >= 0) { - try { + final void internalAwaitDone(long millis, int nanos) { + int s = status; + if ((s == 0 && + UNSAFE.compareAndSwapInt(this, statusOffset, 0, SIGNAL)) || + s > 0) { + try { // the odd construction reduces lock bias effects synchronized (this) { - if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL)) - wait(millis, 0); + if (status > 0) + wait(millis, nanos); + else + notifyAll(); } } catch (InterruptedException ie) { cancelIfTerminating(); } - s = status; } - return s; } /** * Blocks a non-worker-thread until completion. */ private void externalAwaitDone() { - int s; - while ((s = status) >= 0) { + if (status >= 0) { + boolean interrupted = false; synchronized (this) { - if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)){ - boolean interrupted = false; - while (status >= 0) { + for (;;) { + int s = status; + if (s == 0) + UNSAFE.compareAndSwapInt(this, statusOffset, + 0, SIGNAL); + else if (s < 0) { + notifyAll(); + break; + } + else { try { wait(); } catch (InterruptedException ie) { interrupted = true; } } - if (interrupted) - Thread.currentThread().interrupt(); - break; + } + } + if (interrupted) + Thread.currentThread().interrupt(); + } + } + + /** + * Blocks a non-worker-thread until completion or interruption or timeout. + */ + private void externalInterruptibleAwaitDone(boolean timed, long nanos) + throws InterruptedException { + if (Thread.interrupted()) + throw new InterruptedException(); + if (status >= 0) { + long startTime = timed ? System.nanoTime() : 0L; + synchronized (this) { + for (;;) { + long nt; + int s = status; + if (s == 0) + UNSAFE.compareAndSwapInt(this, statusOffset, + 0, SIGNAL); + else if (s < 0) { + notifyAll(); + break; + } + else if (!timed) + wait(); + else if ((nt = nanos - (System.nanoTime()-startTime)) > 0L) + wait(nt / 1000000, (int)(nt % 1000000)); + else + break; } } } @@ -335,7 +374,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * #isDone} returning {@code true}. * *

This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -349,10 +388,13 @@ public abstract class ForkJoinTask implements Future, Serializable { } /** - * Returns the result of the computation when it {@link #isDone is done}. - * This method differs from {@link #get()} in that + * Returns the result of the computation when it {@link #isDone is + * done}. This method differs from {@link #get()} in that * abnormal completion results in {@code RuntimeException} or - * {@code Error}, not {@code ExecutionException}. + * {@code Error}, not {@code ExecutionException}, and that + * interrupts of the calling thread do not cause the + * method to abruptly return by throwing {@code + * InterruptedException}. * * @return the computed result */ @@ -394,7 +436,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * unprocessed. * *

This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -422,7 +464,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * normally or exceptionally, or left unprocessed. * *

This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -477,7 +519,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * unprocessed. * *

This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -529,25 +571,28 @@ public abstract class ForkJoinTask implements Future, Serializable { /** * Attempts to cancel execution of this task. This attempt will - * fail if the task has already completed, has already been - * cancelled, or could not be cancelled for some other reason. If - * successful, and this task has not started when cancel is - * called, execution of this task is suppressed, {@link - * #isCancelled} will report true, and {@link #join} will result - * in a {@code CancellationException} being thrown. + * fail if the task has already completed or could not be + * cancelled for some other reason. If successful, and this task + * has not started when {@code cancel} is called, execution of + * this task is suppressed. After this method returns + * successfully, unless there is an intervening call to {@link + * #reinitialize}, subsequent calls to {@link #isCancelled}, + * {@link #isDone}, and {@code cancel} will return {@code true} + * and calls to {@link #join} and related methods will result in + * {@code CancellationException}. * *

This method may be overridden in subclasses, but if so, must - * still ensure that these minimal properties hold. In particular, - * the {@code cancel} method itself must not throw exceptions. + * still ensure that these properties hold. In particular, the + * {@code cancel} method itself must not throw exceptions. * *

This method is designed to be invoked by other * tasks. To terminate the current task, you can just return or * throw an unchecked exception from its computation method, or * invoke {@link #completeExceptionally}. * - * @param mayInterruptIfRunning this value is ignored in the - * default implementation because tasks are not - * cancelled via interruption + * @param mayInterruptIfRunning this value has no effect in the + * default implementation because interrupts are not used to + * control cancellation. * * @return {@code true} if this task is now cancelled */ @@ -681,23 +726,13 @@ public abstract class ForkJoinTask implements Future, Serializable { * member of a ForkJoinPool and was interrupted while waiting */ public final V get() throws InterruptedException, ExecutionException { - int s; - if (Thread.currentThread() instanceof ForkJoinWorkerThread) { + Thread t = Thread.currentThread(); + if (t instanceof ForkJoinWorkerThread) quietlyJoin(); - s = status; - } - else { - while ((s = status) >= 0) { - synchronized (this) { // interruptible form of awaitDone - if (UNSAFE.compareAndSwapInt(this, statusOffset, - s, SIGNAL)) { - while (status >= 0) - wait(); - } - } - } - } - if (s < NORMAL) { + else + externalInterruptibleAwaitDone(false, 0L); + int s = status; + if (s != NORMAL) { Throwable ex; if (s == CANCELLED) throw new CancellationException(); @@ -723,72 +758,18 @@ public abstract class ForkJoinTask implements Future, Serializable { */ public final V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - Thread t = Thread.currentThread(); - ForkJoinPool pool; - if (t instanceof ForkJoinWorkerThread) { - ForkJoinWorkerThread w = (ForkJoinWorkerThread) t; - if (status >= 0 && w.unpushTask(this)) - quietlyExec(); - pool = w.pool; - } - else - pool = null; - /* - * Timed wait loop intermixes cases for FJ (pool != null) and - * non FJ threads. For FJ, decrement pool count but don't try - * for replacement; increment count on completion. For non-FJ, - * deal with interrupts. This is messy, but a little less so - * than is splitting the FJ and nonFJ cases. - */ - boolean interrupted = false; - boolean dec = false; // true if pool count decremented long nanos = unit.toNanos(timeout); - for (;;) { - if (pool == null && Thread.interrupted()) { - interrupted = true; - break; - } - int s = status; - if (s < 0) - break; - if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)) { - long startTime = System.nanoTime(); - long nt; // wait time - while (status >= 0 && - (nt = nanos - (System.nanoTime() - startTime)) > 0) { - if (pool != null && !dec) - dec = pool.tryDecrementRunningCount(); - else { - long ms = nt / 1000000; - int ns = (int) (nt % 1000000); - try { - synchronized (this) { - if (status >= 0) - wait(ms, ns); - } - } catch (InterruptedException ie) { - if (pool != null) - cancelIfTerminating(); - else { - interrupted = true; - break; - } - } - } - } - break; - } - } - if (pool != null && dec) - pool.incrementRunningCount(); - if (interrupted) - throw new InterruptedException(); - int es = status; - if (es != NORMAL) { + Thread t = Thread.currentThread(); + if (t instanceof ForkJoinWorkerThread) + ((ForkJoinWorkerThread)t).joinTask(this, true, nanos); + else + externalInterruptibleAwaitDone(true, nanos); + int s = status; + if (s != NORMAL) { Throwable ex; - if (es == CANCELLED) + if (s == CANCELLED) throw new CancellationException(); - if (es == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null) + if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null) throw new ExecutionException(ex); throw new TimeoutException(); } @@ -819,7 +800,7 @@ public abstract class ForkJoinTask implements Future, Serializable { return; } } - w.joinTask(this); + w.joinTask(this, false, 0L); } } else @@ -855,7 +836,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * processed. * *

This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -874,6 +855,12 @@ public abstract class ForkJoinTask implements Future, Serializable { * under any other usage conditions are not guaranteed. * This method may be useful when executing * pre-constructed trees of subtasks in loops. + * + *

Upon completion of this method, {@code isDone()} reports + * {@code false}, and {@code getException()} reports {@code + * null}. However, the value returned by {@code getRawResult} is + * unaffected. To clear this value, you can invoke {@code + * setRawResult(null)}. */ public void reinitialize() { if (status == EXCEPTIONAL) @@ -895,11 +882,12 @@ public abstract class ForkJoinTask implements Future, Serializable { } /** - * Returns {@code true} if the current thread is executing as a - * ForkJoinPool computation. + * Returns {@code true} if the current thread is a {@link + * ForkJoinWorkerThread} executing as a ForkJoinPool computation. * - * @return {@code true} if the current thread is executing as a - * ForkJoinPool computation, or false otherwise + * @return {@code true} if the current thread is a {@link + * ForkJoinWorkerThread} executing as a ForkJoinPool computation, + * or {@code false} otherwise */ public static boolean inForkJoinPool() { return Thread.currentThread() instanceof ForkJoinWorkerThread; @@ -914,7 +902,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * were not, stolen. * *

This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -933,7 +921,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * fork other tasks. * *

This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -956,7 +944,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * exceeded. * *

This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -1014,7 +1002,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * otherwise. * *

This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -1033,7 +1021,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * be useful otherwise. * *

This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. @@ -1056,7 +1044,7 @@ public abstract class ForkJoinTask implements Future, Serializable { * otherwise. * *

This method may be invoked only from within {@code - * ForkJoinTask} computations (as may be determined using method + * ForkJoinPool} computations (as may be determined using method * {@link #inForkJoinPool}). Attempts to invoke in other contexts * result in exceptions or errors, possibly including {@code * ClassCastException}. diff --git a/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java b/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java index 4dcfbbd571c..7d79c5190e2 100644 --- a/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java +++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java @@ -38,16 +38,18 @@ package java.util.concurrent; import java.util.Random; import java.util.Collection; import java.util.concurrent.locks.LockSupport; +import java.util.concurrent.RejectedExecutionException; /** - * A thread managed by a {@link ForkJoinPool}. This class is - * subclassable solely for the sake of adding functionality -- there - * are no overridable methods dealing with scheduling or execution. - * However, you can override initialization and termination methods - * surrounding the main task processing loop. If you do create such a - * subclass, you will also need to supply a custom {@link - * ForkJoinPool.ForkJoinWorkerThreadFactory} to use it in a {@code - * ForkJoinPool}. + * A thread managed by a {@link ForkJoinPool}, which executes + * {@link ForkJoinTask}s. + * This class is subclassable solely for the sake of adding + * functionality -- there are no overridable methods dealing with + * scheduling or execution. However, you can override initialization + * and termination methods surrounding the main task processing loop. + * If you do create such a subclass, you will also need to supply a + * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to use it + * in a {@code ForkJoinPool}. * * @since 1.7 * @author Doug Lea @@ -376,7 +378,7 @@ public class ForkJoinWorkerThread extends Thread { /** * Initializes internal state after construction but before * processing any tasks. If you override this method, you must - * invoke @code{super.onStart()} at the beginning of the method. + * invoke {@code super.onStart()} at the beginning of the method. * Initialization requires care: Most fields must have legal * default values, to ensure that attempted accesses from other * threads work correctly even before this thread starts @@ -384,7 +386,7 @@ public class ForkJoinWorkerThread extends Thread { */ protected void onStart() { int rs = seedGenerator.nextInt(); - seed = rs == 0? 1 : rs; // seed must be nonzero + seed = (rs == 0) ? 1 : rs; // seed must be nonzero // Allocate name string and arrays in this thread String pid = Integer.toString(pool.getPoolNumber()); @@ -426,7 +428,7 @@ public class ForkJoinWorkerThread extends Thread { /** * This method is required to be public, but should never be * called explicitly. It performs the main run loop to execute - * ForkJoinTasks. + * {@link ForkJoinTask}s. */ public void run() { Throwable exception = null; @@ -628,6 +630,19 @@ public class ForkJoinWorkerThread extends Thread { if (t == null) // lost to stealer break; if (UNSAFE.compareAndSwapObject(q, u, t, null)) { + /* + * Note: here and in related methods, as a + * performance (not correctness) issue, we'd like + * to encourage compiler not to arbitrarily + * postpone setting sp after successful CAS. + * Currently there is no intrinsic for arranging + * this, but using Unsafe putOrderedInt may be a + * preferable strategy on some compilers even + * though its main effect is a pre-, not post- + * fence. To simplify possible changes, the option + * is left in comments next to the associated + * assignments. + */ sp = s; // putOrderedInt may encourage more timely write // UNSAFE.putOrderedInt(this, spOffset, s); return t; @@ -777,10 +792,10 @@ public class ForkJoinWorkerThread extends Thread { // Run State management // status check methods used mainly by ForkJoinPool - final boolean isRunning() { return runState == 0; } - final boolean isTerminated() { return (runState & TERMINATED) != 0; } - final boolean isSuspended() { return (runState & SUSPENDED) != 0; } - final boolean isTrimmed() { return (runState & TRIMMED) != 0; } + final boolean isRunning() { return runState == 0; } + final boolean isTerminated() { return (runState & TERMINATED) != 0; } + final boolean isSuspended() { return (runState & SUSPENDED) != 0; } + final boolean isTrimmed() { return (runState & TRIMMED) != 0; } final boolean isTerminating() { if ((runState & TERMINATING) != 0) @@ -884,8 +899,7 @@ public class ForkJoinWorkerThread extends Thread { */ final void cancelTasks() { ForkJoinTask cj = currentJoin; // try to cancel ongoing tasks - if (cj != null) { - currentJoin = null; + if (cj != null && cj.status >= 0) { cj.cancelIgnoringExceptions(); try { this.interrupt(); // awaken wait @@ -893,10 +907,8 @@ public class ForkJoinWorkerThread extends Thread { } } ForkJoinTask cs = currentSteal; - if (cs != null) { - currentSteal = null; + if (cs != null && cs.status >= 0) cs.cancelIgnoringExceptions(); - } while (base != sp) { ForkJoinTask t = deqTask(); if (t != null) @@ -959,57 +971,23 @@ public class ForkJoinWorkerThread extends Thread { * Possibly runs some tasks and/or blocks, until task is done. * * @param joinMe the task to join + * @param timed true if use timed wait + * @param nanos wait time if timed */ - final void joinTask(ForkJoinTask joinMe) { + final void joinTask(ForkJoinTask joinMe, boolean timed, long nanos) { // currentJoin only written by this thread; only need ordered store ForkJoinTask prevJoin = currentJoin; UNSAFE.putOrderedObject(this, currentJoinOffset, joinMe); - if (sp != base) - localHelpJoinTask(joinMe); - if (joinMe.status >= 0) - pool.awaitJoin(joinMe, this); + pool.awaitJoin(joinMe, this, timed, nanos); UNSAFE.putOrderedObject(this, currentJoinOffset, prevJoin); } /** - * Run tasks in local queue until given task is done. - * - * @param joinMe the task to join - */ - private void localHelpJoinTask(ForkJoinTask joinMe) { - int s; - ForkJoinTask[] q; - while (joinMe.status >= 0 && (s = sp) != base && (q = queue) != null) { - int i = (q.length - 1) & --s; - long u = (i << qShift) + qBase; // raw offset - ForkJoinTask t = q[i]; - if (t == null) // lost to a stealer - break; - if (UNSAFE.compareAndSwapObject(q, u, t, null)) { - /* - * This recheck (and similarly in helpJoinTask) - * handles cases where joinMe is independently - * cancelled or forced even though there is other work - * available. Back out of the pop by putting t back - * into slot before we commit by writing sp. - */ - if (joinMe.status < 0) { - UNSAFE.putObjectVolatile(q, u, t); - break; - } - sp = s; - // UNSAFE.putOrderedInt(this, spOffset, s); - t.quietlyExec(); - } - } - } - - /** - * Unless terminating, tries to locate and help perform tasks for - * a stealer of the given task, or in turn one of its stealers. - * Traces currentSteal->currentJoin links looking for a thread - * working on a descendant of the given task and with a non-empty - * queue to steal back and execute tasks from. + * Tries to locate and help perform tasks for a stealer of the + * given task, or in turn one of its stealers. Traces + * currentSteal->currentJoin links looking for a thread working on + * a descendant of the given task and with a non-empty queue to + * steal back and execute tasks from. * * The implementation is very branchy to cope with potential * inconsistencies or loops encountering chains that are stale, @@ -1019,77 +997,127 @@ public class ForkJoinWorkerThread extends Thread { * don't work out. * * @param joinMe the task to join + * @param running if false, then must update pool count upon + * running a task + * @return value of running on exit */ - final void helpJoinTask(ForkJoinTask joinMe) { - ForkJoinWorkerThread[] ws; - int n; - if (joinMe.status < 0) // already done - return; - if ((runState & TERMINATING) != 0) { // cancel if shutting down - joinMe.cancelIgnoringExceptions(); - return; + final boolean helpJoinTask(ForkJoinTask joinMe, boolean running) { + /* + * Initial checks to (1) abort if terminating; (2) clean out + * old cancelled tasks from local queue; (3) if joinMe is next + * task, run it; (4) omit scan if local queue nonempty (since + * it may contain non-descendents of joinMe). + */ + ForkJoinPool p = pool; + for (;;) { + ForkJoinTask[] q; + int s; + if (joinMe.status < 0) + return running; + else if ((runState & TERMINATING) != 0) { + joinMe.cancelIgnoringExceptions(); + return running; + } + else if ((s = sp) == base || (q = queue) == null) + break; // queue empty + else { + int i = (q.length - 1) & --s; + long u = (i << qShift) + qBase; // raw offset + ForkJoinTask t = q[i]; + if (t == null) + break; // lost to a stealer + else if (t != joinMe && t.status >= 0) + return running; // cannot safely help + else if ((running || + (running = p.tryIncrementRunningCount())) && + UNSAFE.compareAndSwapObject(q, u, t, null)) { + sp = s; // putOrderedInt may encourage more timely write + // UNSAFE.putOrderedInt(this, spOffset, s); + t.quietlyExec(); + } + } } - if ((ws = pool.workers) == null || (n = ws.length) <= 1) - return; // need at least 2 workers - ForkJoinTask task = joinMe; // base of chain - ForkJoinWorkerThread thread = this; // thread with stolen task - for (int d = 0; d < MAX_HELP_DEPTH; ++d) { // chain length - // Try to find v, the stealer of task, by first using hint - ForkJoinWorkerThread v = ws[thread.stealHint & (n - 1)]; - if (v == null || v.currentSteal != task) { - for (int j = 0; ; ++j) { // search array - if (j < n) { - ForkJoinTask vs; - if ((v = ws[j]) != null && - (vs = v.currentSteal) != null) { - if (joinMe.status < 0 || task.status < 0) - return; // stale or done - if (vs == task) { - thread.stealHint = j; - break; // save hint for next time + int n; // worker array size + ForkJoinWorkerThread[] ws = p.workers; + if (ws != null && (n = ws.length) > 1) { // need at least 2 workers + ForkJoinTask task = joinMe; // base of chain + ForkJoinWorkerThread thread = this; // thread with stolen task + + outer:for (int d = 0; d < MAX_HELP_DEPTH; ++d) { // chain length + // Try to find v, the stealer of task, by first using hint + ForkJoinWorkerThread v = ws[thread.stealHint & (n - 1)]; + if (v == null || v.currentSteal != task) { + for (int j = 0; ; ++j) { // search array + if (j < n) { + ForkJoinTask vs; + if ((v = ws[j]) != null && + (vs = v.currentSteal) != null) { + if (joinMe.status < 0) + break outer; + if (vs == task) { + if (task.status < 0) + break outer; // stale + thread.stealHint = j; + break; // save hint for next time + } } } + else + break outer; // no stealer } - else - return; // no stealer } - } - for (;;) { // Try to help v, using specialized form of deqTask - if (joinMe.status < 0) - return; - int b = v.base; - ForkJoinTask[] q = v.queue; - if (b == v.sp || q == null) - break; - int i = (q.length - 1) & b; - long u = (i << qShift) + qBase; - ForkJoinTask t = q[i]; - int pid = poolIndex; - ForkJoinTask ps = currentSteal; - if (task.status < 0) - return; // stale or done - if (t != null && v.base == b++ && - UNSAFE.compareAndSwapObject(q, u, t, null)) { - if (joinMe.status < 0) { - UNSAFE.putObjectVolatile(q, u, t); - return; // back out on cancel + + // Try to help v, using specialized form of deqTask + for (;;) { + if (joinMe.status < 0) + break outer; + int b = v.base; + ForkJoinTask[] q = v.queue; + if (b == v.sp || q == null) + break; // empty + int i = (q.length - 1) & b; + long u = (i << qShift) + qBase; + ForkJoinTask t = q[i]; + if (task.status < 0) + break outer; // stale + if (t != null && + (running || + (running = p.tryIncrementRunningCount())) && + v.base == b++ && + UNSAFE.compareAndSwapObject(q, u, t, null)) { + if (t != joinMe && joinMe.status < 0) { + UNSAFE.putObjectVolatile(q, u, t); + break outer; // joinMe cancelled; back out + } + v.base = b; + if (t.status >= 0) { + ForkJoinTask ps = currentSteal; + int pid = poolIndex; + v.stealHint = pid; + UNSAFE.putOrderedObject(this, + currentStealOffset, t); + t.quietlyExec(); + UNSAFE.putOrderedObject(this, + currentStealOffset, ps); + } + } + else if ((runState & TERMINATING) != 0) { + joinMe.cancelIgnoringExceptions(); + break outer; } - v.base = b; - v.stealHint = pid; - UNSAFE.putOrderedObject(this, currentStealOffset, t); - t.quietlyExec(); - UNSAFE.putOrderedObject(this, currentStealOffset, ps); } + + // Try to descend to find v's stealer + ForkJoinTask next = v.currentJoin; + if (task.status < 0 || next == null || next == task || + joinMe.status < 0) + break; // done, stale, dead-end, or cyclic + task = next; + thread = v; } - // Try to descend to find v's stealer - ForkJoinTask next = v.currentJoin; - if (task.status < 0 || next == null || next == task || - joinMe.status < 0) - return; - task = next; - thread = v; } + return running; } /** diff --git a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java index 8051ccaa848..f5d9da1cb17 100644 --- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -1029,6 +1029,8 @@ public class LinkedBlockingDeque * elements as they existed upon construction of the iterator, and * may (but is not guaranteed to) reflect any modifications * subsequent to construction. + * + * @return an iterator over the elements in this deque in reverse order */ public Iterator descendingIterator() { return new DescendingItr(); diff --git a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java index 9746b7dedec..5f62e79ce56 100644 --- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java +++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java @@ -189,14 +189,14 @@ public class LinkedBlockingQueue extends AbstractQueue } /** - * Creates a node and links it at end of queue. + * Links node at end of queue. * - * @param x the item + * @param node the node */ - private void enqueue(E x) { + private void enqueue(Node node) { // assert putLock.isHeldByCurrentThread(); // assert last.next == null; - last = last.next = new Node(x); + last = last.next = node; } /** @@ -282,7 +282,7 @@ public class LinkedBlockingQueue extends AbstractQueue throw new NullPointerException(); if (n == capacity) throw new IllegalStateException("Queue full"); - enqueue(e); + enqueue(new Node(e)); ++n; } count.set(n); @@ -332,6 +332,7 @@ public class LinkedBlockingQueue extends AbstractQueue // Note: convention in all put/take/etc is to preset local var // holding count negative to indicate failure unless set. int c = -1; + Node node = new Node(e); final ReentrantLock putLock = this.putLock; final AtomicInteger count = this.count; putLock.lockInterruptibly(); @@ -347,7 +348,7 @@ public class LinkedBlockingQueue extends AbstractQueue while (count.get() == capacity) { notFull.await(); } - enqueue(e); + enqueue(node); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); @@ -382,7 +383,7 @@ public class LinkedBlockingQueue extends AbstractQueue return false; nanos = notFull.awaitNanos(nanos); } - enqueue(e); + enqueue(new Node(e)); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); @@ -411,11 +412,12 @@ public class LinkedBlockingQueue extends AbstractQueue if (count.get() == capacity) return false; int c = -1; + Node node = new Node(e); final ReentrantLock putLock = this.putLock; putLock.lock(); try { if (count.get() < capacity) { - enqueue(e); + enqueue(node); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); @@ -559,6 +561,27 @@ public class LinkedBlockingQueue extends AbstractQueue } } + /** + * Returns {@code true} if this queue contains the specified element. + * More formally, returns {@code true} if and only if this queue contains + * at least one element {@code e} such that {@code o.equals(e)}. + * + * @param o object to be checked for containment in this queue + * @return {@code true} if this queue contains the specified element + */ + public boolean contains(Object o) { + if (o == null) return false; + fullyLock(); + try { + for (Node p = head.next; p != null; p = p.next) + if (o.equals(p.item)) + return true; + return false; + } finally { + fullyUnlock(); + } + } + /** * Returns an array containing all of the elements in this queue, in * proper sequence. @@ -645,7 +668,20 @@ public class LinkedBlockingQueue extends AbstractQueue public String toString() { fullyLock(); try { - return super.toString(); + Node p = head.next; + if (p == null) + return "[]"; + + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (;;) { + E e = p.item; + sb.append(e == this ? "(this Collection)" : e); + p = p.next; + if (p == null) + return sb.append(']').toString(); + sb.append(',').append(' '); + } } finally { fullyUnlock(); } @@ -727,12 +763,14 @@ public class LinkedBlockingQueue extends AbstractQueue /** * Returns an iterator over the elements in this queue in proper sequence. - * The returned {@code Iterator} is a "weakly consistent" iterator that + * The elements will be returned in order from first (head) to last (tail). + * + *

The returned iterator is a "weakly consistent" iterator that * will never throw {@link java.util.ConcurrentModificationException - * ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. + * ConcurrentModificationException}, and guarantees to traverse + * elements as they existed upon construction of the iterator, and + * may (but is not guaranteed to) reflect any modifications + * subsequent to construction. * * @return an iterator over the elements in this queue in proper sequence */ diff --git a/jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java b/jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java index 82bed929072..fec92a8b189 100644 --- a/jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java +++ b/jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java @@ -37,10 +37,10 @@ package java.util.concurrent; import java.util.AbstractQueue; import java.util.Collection; -import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Queue; +import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; /** @@ -450,7 +450,7 @@ public class LinkedTransferQueue extends AbstractQueue } final boolean casItem(Object cmp, Object val) { - // assert cmp == null || cmp.getClass() != Node.class; + // assert cmp == null || cmp.getClass() != Node.class; return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val); } @@ -516,7 +516,7 @@ public class LinkedTransferQueue extends AbstractQueue * Tries to artificially match a data node -- used by remove. */ final boolean tryMatchData() { - // assert isData; + // assert isData; Object x = item; if (x != null && x != this && casItem(x, null)) { LockSupport.unpark(waiter); @@ -569,7 +569,7 @@ public class LinkedTransferQueue extends AbstractQueue @SuppressWarnings("unchecked") static E cast(Object item) { - // assert item == null || item.getClass() != Node.class; + // assert item == null || item.getClass() != Node.class; return (E) item; } @@ -588,7 +588,8 @@ public class LinkedTransferQueue extends AbstractQueue throw new NullPointerException(); Node s = null; // the node to append, if needed - retry: for (;;) { // restart on append race + retry: + for (;;) { // restart on append race for (Node h = head, p = h; p != null;) { // find & match first node boolean isData = p.isData; @@ -599,7 +600,7 @@ public class LinkedTransferQueue extends AbstractQueue if (p.casItem(item, e)) { // match for (Node q = p; q != h;) { Node n = q.next; // update by 2 unless singleton - if (head == h && casHead(h, n == null? q : n)) { + if (head == h && casHead(h, n == null ? q : n)) { h.forgetNext(); break; } // advance and retry @@ -684,7 +685,7 @@ public class LinkedTransferQueue extends AbstractQueue for (;;) { Object item = s.item; if (item != e) { // matched - // assert item != s; + // assert item != s; s.forgetContents(); // avoid garbage return this.cast(item); } @@ -809,22 +810,61 @@ public class LinkedTransferQueue extends AbstractQueue * Moves to next node after prev, or first node if prev null. */ private void advance(Node prev) { - lastPred = lastRet; - lastRet = prev; - for (Node p = (prev == null) ? head : succ(prev); - p != null; p = succ(p)) { - Object item = p.item; - if (p.isData) { - if (item != null && item != p) { - nextItem = LinkedTransferQueue.this.cast(item); - nextNode = p; + /* + * To track and avoid buildup of deleted nodes in the face + * of calls to both Queue.remove and Itr.remove, we must + * include variants of unsplice and sweep upon each + * advance: Upon Itr.remove, we may need to catch up links + * from lastPred, and upon other removes, we might need to + * skip ahead from stale nodes and unsplice deleted ones + * found while advancing. + */ + + Node r, b; // reset lastPred upon possible deletion of lastRet + if ((r = lastRet) != null && !r.isMatched()) + lastPred = r; // next lastPred is old lastRet + else if ((b = lastPred) == null || b.isMatched()) + lastPred = null; // at start of list + else { + Node s, n; // help with removal of lastPred.next + while ((s = b.next) != null && + s != b && s.isMatched() && + (n = s.next) != null && n != s) + b.casNext(s, n); + } + + this.lastRet = prev; + + for (Node p = prev, s, n;;) { + s = (p == null) ? head : p.next; + if (s == null) + break; + else if (s == p) { + p = null; + continue; + } + Object item = s.item; + if (s.isData) { + if (item != null && item != s) { + nextItem = LinkedTransferQueue.cast(item); + nextNode = s; return; } } else if (item == null) break; + // assert s.isMatched(); + if (p == null) + p = s; + else if ((n = s.next) == null) + break; + else if (s == n) + p = null; + else + p.casNext(s, n); } nextNode = null; + nextItem = null; } Itr() { @@ -844,10 +884,12 @@ public class LinkedTransferQueue extends AbstractQueue } public final void remove() { - Node p = lastRet; - if (p == null) throw new IllegalStateException(); - if (p.tryMatchData()) - unsplice(lastPred, p); + final Node lastRet = this.lastRet; + if (lastRet == null) + throw new IllegalStateException(); + this.lastRet = null; + if (lastRet.tryMatchData()) + unsplice(lastPred, lastRet); } } @@ -997,8 +1039,7 @@ public class LinkedTransferQueue extends AbstractQueue * Inserts the specified element at the tail of this queue. * As the queue is unbounded, this method will never return {@code false}. * - * @return {@code true} (as specified by - * {@link BlockingQueue#offer(Object) BlockingQueue.offer}) + * @return {@code true} (as specified by {@link Queue#offer}) * @throws NullPointerException if the specified element is null */ public boolean offer(E e) { @@ -1130,15 +1171,15 @@ public class LinkedTransferQueue extends AbstractQueue } /** - * Returns an iterator over the elements in this queue in proper - * sequence, from head to tail. + * Returns an iterator over the elements in this queue in proper sequence. + * The elements will be returned in order from first (head) to last (tail). * *

The returned iterator is a "weakly consistent" iterator that - * will never throw - * {@link ConcurrentModificationException ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed - * to) reflect any modifications subsequent to construction. + * will never throw {@link java.util.ConcurrentModificationException + * ConcurrentModificationException}, and guarantees to traverse + * elements as they existed upon construction of the iterator, and + * may (but is not guaranteed to) reflect any modifications + * subsequent to construction. * * @return an iterator over the elements in this queue in proper sequence */ @@ -1202,6 +1243,28 @@ public class LinkedTransferQueue extends AbstractQueue return findAndRemove(o); } + /** + * Returns {@code true} if this queue contains the specified element. + * More formally, returns {@code true} if and only if this queue contains + * at least one element {@code e} such that {@code o.equals(e)}. + * + * @param o object to be checked for containment in this queue + * @return {@code true} if this queue contains the specified element + */ + public boolean contains(Object o) { + if (o == null) return false; + for (Node p = head; p != null; p = succ(p)) { + Object item = p.item; + if (p.isData) { + if (item != null && item != p && o.equals(item)) + return true; + } + else if (item == null) + break; + } + return false; + } + /** * Always returns {@code Integer.MAX_VALUE} because a * {@code LinkedTransferQueue} is not capacity constrained. diff --git a/jdk/src/share/classes/java/util/concurrent/Phaser.java b/jdk/src/share/classes/java/util/concurrent/Phaser.java index 623f46e41ed..d5725b3e1a2 100644 --- a/jdk/src/share/classes/java/util/concurrent/Phaser.java +++ b/jdk/src/share/classes/java/util/concurrent/Phaser.java @@ -35,6 +35,8 @@ package java.util.concurrent; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.LockSupport; @@ -61,38 +63,38 @@ import java.util.concurrent.locks.LockSupport; * Phaser} may be repeatedly awaited. Method {@link * #arriveAndAwaitAdvance} has effect analogous to {@link * java.util.concurrent.CyclicBarrier#await CyclicBarrier.await}. Each - * generation of a {@code Phaser} has an associated phase number. The - * phase number starts at zero, and advances when all parties arrive - * at the barrier, wrapping around to zero after reaching {@code + * generation of a phaser has an associated phase number. The phase + * number starts at zero, and advances when all parties arrive at the + * phaser, wrapping around to zero after reaching {@code * Integer.MAX_VALUE}. The use of phase numbers enables independent - * control of actions upon arrival at a barrier and upon awaiting + * control of actions upon arrival at a phaser and upon awaiting * others, via two kinds of methods that may be invoked by any * registered party: * *

    * *
  • Arrival. Methods {@link #arrive} and - * {@link #arriveAndDeregister} record arrival at a - * barrier. These methods do not block, but return an associated - * arrival phase number; that is, the phase number of - * the barrier to which the arrival applied. When the final - * party for a given phase arrives, an optional barrier action - * is performed and the phase advances. Barrier actions, - * performed by the party triggering a phase advance, are - * arranged by overriding method {@link #onAdvance(int, int)}, - * which also controls termination. Overriding this method is - * similar to, but more flexible than, providing a barrier - * action to a {@code CyclicBarrier}. + * {@link #arriveAndDeregister} record arrival. These methods + * do not block, but return an associated arrival phase + * number; that is, the phase number of the phaser to which + * the arrival applied. When the final party for a given phase + * arrives, an optional action is performed and the phase + * advances. These actions are performed by the party + * triggering a phase advance, and are arranged by overriding + * method {@link #onAdvance(int, int)}, which also controls + * termination. Overriding this method is similar to, but more + * flexible than, providing a barrier action to a {@code + * CyclicBarrier}. * *
  • Waiting. Method {@link #awaitAdvance} requires an * argument indicating an arrival phase number, and returns when - * the barrier advances to (or is already at) a different phase. + * the phaser advances to (or is already at) a different phase. * Unlike similar constructions using {@code CyclicBarrier}, * method {@code awaitAdvance} continues to wait even if the * waiting thread is interrupted. Interruptible and timeout * versions are also available, but exceptions encountered while * tasks wait interruptibly or with timeout do not change the - * state of the barrier. If necessary, you can perform any + * state of the phaser. If necessary, you can perform any * associated recovery within handlers of those exceptions, * often after invoking {@code forceTermination}. Phasers may * also be used by tasks executing in a {@link ForkJoinPool}, @@ -101,26 +103,39 @@ import java.util.concurrent.locks.LockSupport; * *
* - *

Termination. A {@code Phaser} may enter a - * termination state in which all synchronization methods - * immediately return without updating phaser state or waiting for - * advance, and indicating (via a negative phase value) that execution - * is complete. Termination is triggered when an invocation of {@code - * onAdvance} returns {@code true}. As illustrated below, when - * phasers control actions with a fixed number of iterations, it is - * often convenient to override this method to cause termination when - * the current phase number reaches a threshold. Method {@link - * #forceTermination} is also available to abruptly release waiting - * threads and allow them to terminate. + *

Termination. A phaser may enter a termination + * state, that may be checked using method {@link #isTerminated}. Upon + * termination, all synchronization methods immediately return without + * waiting for advance, as indicated by a negative return value. + * Similarly, attempts to register upon termination have no effect. + * Termination is triggered when an invocation of {@code onAdvance} + * returns {@code true}. The default implementation returns {@code + * true} if a deregistration has caused the number of registered + * parties to become zero. As illustrated below, when phasers control + * actions with a fixed number of iterations, it is often convenient + * to override this method to cause termination when the current phase + * number reaches a threshold. Method {@link #forceTermination} is + * also available to abruptly release waiting threads and allow them + * to terminate. * - *

Tiering. Phasers may be tiered (i.e., arranged - * in tree structures) to reduce contention. Phasers with large - * numbers of parties that would otherwise experience heavy + *

Tiering. Phasers may be tiered (i.e., + * constructed in tree structures) to reduce contention. Phasers with + * large numbers of parties that would otherwise experience heavy * synchronization contention costs may instead be set up so that * groups of sub-phasers share a common parent. This may greatly * increase throughput even though it incurs greater per-operation * overhead. * + *

In a tree of tiered phasers, registration and deregistration of + * child phasers with their parent are managed automatically. + * Whenever the number of registered parties of a child phaser becomes + * non-zero (as established in the {@link #Phaser(Phaser,int)} + * constructor, {@link #register}, or {@link #bulkRegister}), the + * child phaser is registered with its parent. Whenever the number of + * registered parties becomes zero as the result of an invocation of + * {@link #arriveAndDeregister}, the child phaser is deregistered + * from its parent. + * *

Monitoring. While synchronization methods may be invoked * only by registered parties, the current state of a phaser may be * monitored by any caller. At any given moment there are {@link @@ -136,9 +151,9 @@ import java.util.concurrent.locks.LockSupport; *

Sample usages: * *

A {@code Phaser} may be used instead of a {@code CountDownLatch} - * to control a one-shot action serving a variable number of - * parties. The typical idiom is for the method setting this up to - * first register, then start the actions, then deregister, as in: + * to control a one-shot action serving a variable number of parties. + * The typical idiom is for the method setting this up to first + * register, then start the actions, then deregister, as in: * *

 {@code
  * void runTasks(List tasks) {
@@ -208,34 +223,32 @@ import java.util.concurrent.locks.LockSupport;
  * }}
* * - *

To create a set of tasks using a tree of phasers, - * you could use code of the following form, assuming a - * Task class with a constructor accepting a phaser that - * it registers for upon construction: + *

To create a set of {@code n} tasks using a tree of phasers, you + * could use code of the following form, assuming a Task class with a + * constructor accepting a {@code Phaser} that it registers with upon + * construction. After invocation of {@code build(new Task[n], 0, n, + * new Phaser())}, these tasks could then be started, for example by + * submitting to a pool: * *

 {@code
- * void build(Task[] actions, int lo, int hi, Phaser ph) {
+ * void build(Task[] tasks, int lo, int hi, Phaser ph) {
  *   if (hi - lo > TASKS_PER_PHASER) {
  *     for (int i = lo; i < hi; i += TASKS_PER_PHASER) {
  *       int j = Math.min(i + TASKS_PER_PHASER, hi);
- *       build(actions, i, j, new Phaser(ph));
+ *       build(tasks, i, j, new Phaser(ph));
  *     }
  *   } else {
  *     for (int i = lo; i < hi; ++i)
- *       actions[i] = new Task(ph);
+ *       tasks[i] = new Task(ph);
  *       // assumes new Task(ph) performs ph.register()
  *   }
- * }
- * // .. initially called, for n tasks via
- * build(new Task[n], 0, n, new Phaser());}
+ * }} * * The best value of {@code TASKS_PER_PHASER} depends mainly on - * expected barrier synchronization rates. A value as low as four may - * be appropriate for extremely small per-barrier task bodies (thus + * expected synchronization rates. A value as low as four may + * be appropriate for extremely small per-phase task bodies (thus * high rates), or up to hundreds for extremely large ones. * - * - * *

Implementation notes: This implementation restricts the * maximum number of parties to 65535. Attempts to register additional * parties result in {@code IllegalStateException}. However, you can and @@ -253,60 +266,66 @@ public class Phaser { */ /** - * Barrier state representation. Conceptually, a barrier contains - * four values: + * Primary state representation, holding four bit-fields: * - * * parties -- the number of parties to wait (16 bits) - * * unarrived -- the number of parties yet to hit barrier (16 bits) - * * phase -- the generation of the barrier (31 bits) - * * terminated -- set if barrier is terminated (1 bit) + * unarrived -- the number of parties yet to hit barrier (bits 0-15) + * parties -- the number of parties to wait (bits 16-31) + * phase -- the generation of the barrier (bits 32-62) + * terminated -- set if barrier is terminated (bit 63 / sign) * - * However, to efficiently maintain atomicity, these values are - * packed into a single (atomic) long. Termination uses the sign - * bit of 32 bit representation of phase, so phase is set to -1 on - * termination. Good performance relies on keeping state decoding - * and encoding simple, and keeping race windows short. + * Except that a phaser with no registered parties is + * distinguished by the otherwise illegal state of having zero + * parties and one unarrived parties (encoded as EMPTY below). * - * Note: there are some cheats in arrive() that rely on unarrived - * count being lowest 16 bits. + * To efficiently maintain atomicity, these values are packed into + * a single (atomic) long. Good performance relies on keeping + * state decoding and encoding simple, and keeping race windows + * short. + * + * All state updates are performed via CAS except initial + * registration of a sub-phaser (i.e., one with a non-null + * parent). In this (relatively rare) case, we use built-in + * synchronization to lock while first registering with its + * parent. + * + * The phase of a subphaser is allowed to lag that of its + * ancestors until it is actually accessed -- see method + * reconcileState. */ private volatile long state; - private static final int ushortMask = 0xffff; - private static final int phaseMask = 0x7fffffff; + private static final int MAX_PARTIES = 0xffff; + private static final int MAX_PHASE = Integer.MAX_VALUE; + private static final int PARTIES_SHIFT = 16; + private static final int PHASE_SHIFT = 32; + private static final int UNARRIVED_MASK = 0xffff; // to mask ints + private static final long PARTIES_MASK = 0xffff0000L; // to mask longs + private static final long TERMINATION_BIT = 1L << 63; + + // some special values + private static final int ONE_ARRIVAL = 1; + private static final int ONE_PARTY = 1 << PARTIES_SHIFT; + private static final int EMPTY = 1; + + // The following unpacking methods are usually manually inlined private static int unarrivedOf(long s) { - return (int) (s & ushortMask); + int counts = (int)s; + return (counts == EMPTY) ? 0 : counts & UNARRIVED_MASK; } private static int partiesOf(long s) { - return ((int) s) >>> 16; + return (int)s >>> PARTIES_SHIFT; } private static int phaseOf(long s) { - return (int) (s >>> 32); + return (int)(s >>> PHASE_SHIFT); } private static int arrivedOf(long s) { - return partiesOf(s) - unarrivedOf(s); - } - - private static long stateFor(int phase, int parties, int unarrived) { - return ((((long) phase) << 32) | (((long) parties) << 16) | - (long) unarrived); - } - - private static long trippedStateFor(int phase, int parties) { - long lp = (long) parties; - return (((long) phase) << 32) | (lp << 16) | lp; - } - - /** - * Returns message string for bad bounds exceptions. - */ - private static String badBounds(int parties, int unarrived) { - return ("Attempt to set " + unarrived + - " unarrived of " + parties + " parties"); + int counts = (int)s; + return (counts == EMPTY) ? 0 : + (counts >>> PARTIES_SHIFT) - (counts & UNARRIVED_MASK); } /** @@ -315,70 +334,180 @@ public class Phaser { private final Phaser parent; /** - * The root of phaser tree. Equals this if not in a tree. Used to - * support faster state push-down. + * The root of phaser tree. Equals this if not in a tree. */ private final Phaser root; - // Wait queues - /** * Heads of Treiber stacks for waiting threads. To eliminate - * contention while releasing some threads while adding others, we + * contention when releasing some threads while adding others, we * use two of them, alternating across even and odd phases. + * Subphasers share queues with root to speed up releases. */ - private final AtomicReference evenQ = new AtomicReference(); - private final AtomicReference oddQ = new AtomicReference(); + private final AtomicReference evenQ; + private final AtomicReference oddQ; private AtomicReference queueFor(int phase) { return ((phase & 1) == 0) ? evenQ : oddQ; } /** - * Returns current state, first resolving lagged propagation from - * root if necessary. + * Returns message string for bounds exceptions on arrival. */ - private long getReconciledState() { - return (parent == null) ? state : reconcileState(); + private String badArrive(long s) { + return "Attempted arrival of unregistered party for " + + stateToString(s); } /** - * Recursively resolves state. + * Returns message string for bounds exceptions on registration. */ - private long reconcileState() { - Phaser p = parent; - long s = state; - if (p != null) { - while (unarrivedOf(s) == 0 && phaseOf(s) != phaseOf(root.state)) { - long parentState = p.getReconciledState(); - int parentPhase = phaseOf(parentState); - int phase = phaseOf(s = state); - if (phase != parentPhase) { - long next = trippedStateFor(parentPhase, partiesOf(s)); - if (casState(s, next)) { - releaseWaiters(phase); - s = next; + private String badRegister(long s) { + return "Attempt to register more than " + + MAX_PARTIES + " parties for " + stateToString(s); + } + + /** + * Main implementation for methods arrive and arriveAndDeregister. + * Manually tuned to speed up and minimize race windows for the + * common case of just decrementing unarrived field. + * + * @param deregister false for arrive, true for arriveAndDeregister + */ + private int doArrive(boolean deregister) { + int adj = deregister ? ONE_ARRIVAL|ONE_PARTY : ONE_ARRIVAL; + final Phaser root = this.root; + for (;;) { + long s = (root == this) ? state : reconcileState(); + int phase = (int)(s >>> PHASE_SHIFT); + int counts = (int)s; + int unarrived = (counts & UNARRIVED_MASK) - 1; + if (phase < 0) + return phase; + else if (counts == EMPTY || unarrived < 0) { + if (root == this || reconcileState() == s) + throw new IllegalStateException(badArrive(s)); + } + else if (UNSAFE.compareAndSwapLong(this, stateOffset, s, s-=adj)) { + if (unarrived == 0) { + long n = s & PARTIES_MASK; // base of next state + int nextUnarrived = (int)n >>> PARTIES_SHIFT; + if (root != this) + return parent.doArrive(nextUnarrived == 0); + if (onAdvance(phase, nextUnarrived)) + n |= TERMINATION_BIT; + else if (nextUnarrived == 0) + n |= EMPTY; + else + n |= nextUnarrived; + n |= (long)((phase + 1) & MAX_PHASE) << PHASE_SHIFT; + UNSAFE.compareAndSwapLong(this, stateOffset, s, n); + releaseWaiters(phase); + } + return phase; + } + } + } + + /** + * Implementation of register, bulkRegister + * + * @param registrations number to add to both parties and + * unarrived fields. Must be greater than zero. + */ + private int doRegister(int registrations) { + // adjustment to state + long adj = ((long)registrations << PARTIES_SHIFT) | registrations; + final Phaser parent = this.parent; + int phase; + for (;;) { + long s = state; + int counts = (int)s; + int parties = counts >>> PARTIES_SHIFT; + int unarrived = counts & UNARRIVED_MASK; + if (registrations > MAX_PARTIES - parties) + throw new IllegalStateException(badRegister(s)); + else if ((phase = (int)(s >>> PHASE_SHIFT)) < 0) + break; + else if (counts != EMPTY) { // not 1st registration + if (parent == null || reconcileState() == s) { + if (unarrived == 0) // wait out advance + root.internalAwaitAdvance(phase, null); + else if (UNSAFE.compareAndSwapLong(this, stateOffset, + s, s + adj)) + break; + } + } + else if (parent == null) { // 1st root registration + long next = ((long)phase << PHASE_SHIFT) | adj; + if (UNSAFE.compareAndSwapLong(this, stateOffset, s, next)) + break; + } + else { + synchronized (this) { // 1st sub registration + if (state == s) { // recheck under lock + parent.doRegister(1); + do { // force current phase + phase = (int)(root.state >>> PHASE_SHIFT); + // assert phase < 0 || (int)state == EMPTY; + } while (!UNSAFE.compareAndSwapLong + (this, stateOffset, state, + ((long)phase << PHASE_SHIFT) | adj)); + break; } } } } + return phase; + } + + /** + * Resolves lagged phase propagation from root if necessary. + * Reconciliation normally occurs when root has advanced but + * subphasers have not yet done so, in which case they must finish + * their own advance by setting unarrived to parties (or if + * parties is zero, resetting to unregistered EMPTY state). + * However, this method may also be called when "floating" + * subphasers with possibly some unarrived parties are merely + * catching up to current phase, in which case counts are + * unaffected. + * + * @return reconciled state + */ + private long reconcileState() { + final Phaser root = this.root; + long s = state; + if (root != this) { + int phase, u, p; + // CAS root phase with current parties; possibly trip unarrived + while ((phase = (int)(root.state >>> PHASE_SHIFT)) != + (int)(s >>> PHASE_SHIFT) && + !UNSAFE.compareAndSwapLong + (this, stateOffset, s, + s = (((long)phase << PHASE_SHIFT) | + (s & PARTIES_MASK) | + ((p = (int)s >>> PARTIES_SHIFT) == 0 ? EMPTY : + (u = (int)s & UNARRIVED_MASK) == 0 ? p : u)))) + s = state; + } return s; } /** - * Creates a new phaser without any initially registered parties, - * initial phase number 0, and no parent. Any thread using this + * Creates a new phaser with no initially registered parties, no + * parent, and initial phase number 0. Any thread using this * phaser will need to first register for it. */ public Phaser() { - this(null); + this(null, 0); } /** - * Creates a new phaser with the given numbers of registered - * unarrived parties, initial phase number 0, and no parent. + * Creates a new phaser with the given number of registered + * unarrived parties, no parent, and initial phase number 0. * - * @param parties the number of parties required to trip barrier + * @param parties the number of parties required to advance to the + * next phase * @throws IllegalArgumentException if parties less than zero * or greater than the maximum number of parties supported */ @@ -387,54 +516,62 @@ public class Phaser { } /** - * Creates a new phaser with the given parent, without any - * initially registered parties. If parent is non-null this phaser - * is registered with the parent and its initial phase number is - * the same as that of parent phaser. + * Equivalent to {@link #Phaser(Phaser, int) Phaser(parent, 0)}. * * @param parent the parent phaser */ public Phaser(Phaser parent) { - int phase = 0; - this.parent = parent; - if (parent != null) { - this.root = parent.root; - phase = parent.register(); - } - else - this.root = this; - this.state = trippedStateFor(phase, 0); + this(parent, 0); } /** - * Creates a new phaser with the given parent and numbers of - * registered unarrived parties. If parent is non-null, this phaser - * is registered with the parent and its initial phase number is - * the same as that of parent phaser. + * Creates a new phaser with the given parent and number of + * registered unarrived parties. When the given parent is non-null + * and the given number of parties is greater than zero, this + * child phaser is registered with its parent. * * @param parent the parent phaser - * @param parties the number of parties required to trip barrier + * @param parties the number of parties required to advance to the + * next phase * @throws IllegalArgumentException if parties less than zero * or greater than the maximum number of parties supported */ public Phaser(Phaser parent, int parties) { - if (parties < 0 || parties > ushortMask) + if (parties >>> PARTIES_SHIFT != 0) throw new IllegalArgumentException("Illegal number of parties"); int phase = 0; this.parent = parent; if (parent != null) { - this.root = parent.root; - phase = parent.register(); + final Phaser root = parent.root; + this.root = root; + this.evenQ = root.evenQ; + this.oddQ = root.oddQ; + if (parties != 0) + phase = parent.doRegister(1); } - else + else { this.root = this; - this.state = trippedStateFor(phase, parties); + this.evenQ = new AtomicReference(); + this.oddQ = new AtomicReference(); + } + this.state = (parties == 0) ? (long)EMPTY : + ((long)phase << PHASE_SHIFT) | + ((long)parties << PARTIES_SHIFT) | + ((long)parties); } /** - * Adds a new unarrived party to this phaser. + * Adds a new unarrived party to this phaser. If an ongoing + * invocation of {@link #onAdvance} is in progress, this method + * may await its completion before returning. If this phaser has + * a parent, and this phaser previously had no registered parties, + * this child phaser is also registered with its parent. If + * this phaser is terminated, the attempt to register has + * no effect, and a negative value is returned. * - * @return the arrival phase number to which this registration applied + * @return the arrival phase number to which this registration + * applied. If this value is negative, then this phaser has + * terminated, in which case registration has no effect. * @throws IllegalStateException if attempting to register more * than the maximum supported number of parties */ @@ -444,11 +581,22 @@ public class Phaser { /** * Adds the given number of new unarrived parties to this phaser. + * If an ongoing invocation of {@link #onAdvance} is in progress, + * this method may await its completion before returning. If this + * phaser has a parent, and the given number of parties is greater + * than zero, and this phaser previously had no registered + * parties, this child phaser is also registered with its parent. + * If this phaser is terminated, the attempt to register has no + * effect, and a negative value is returned. * - * @param parties the number of parties required to trip barrier - * @return the arrival phase number to which this registration applied + * @param parties the number of additional parties required to + * advance to the next phase + * @return the arrival phase number to which this registration + * applied. If this value is negative, then this phaser has + * terminated, in which case registration has no effect. * @throws IllegalStateException if attempting to register more * than the maximum supported number of parties + * @throws IllegalArgumentException if {@code parties < 0} */ public int bulkRegister(int parties) { if (parties < 0) @@ -459,258 +607,210 @@ public class Phaser { } /** - * Shared code for register, bulkRegister - */ - private int doRegister(int registrations) { - int phase; - for (;;) { - long s = getReconciledState(); - phase = phaseOf(s); - int unarrived = unarrivedOf(s) + registrations; - int parties = partiesOf(s) + registrations; - if (phase < 0) - break; - if (parties > ushortMask || unarrived > ushortMask) - throw new IllegalStateException(badBounds(parties, unarrived)); - if (phase == phaseOf(root.state) && - casState(s, stateFor(phase, parties, unarrived))) - break; - } - return phase; - } - - /** - * Arrives at the barrier, but does not wait for others. (You can - * in turn wait for others via {@link #awaitAdvance}). It is an - * unenforced usage error for an unregistered party to invoke this - * method. + * Arrives at this phaser, without waiting for others to arrive. + * + *

It is a usage error for an unregistered party to invoke this + * method. However, this error may result in an {@code + * IllegalStateException} only upon some subsequent operation on + * this phaser, if ever. * * @return the arrival phase number, or a negative value if terminated * @throws IllegalStateException if not terminated and the number * of unarrived parties would become negative */ public int arrive() { - int phase; - for (;;) { - long s = state; - phase = phaseOf(s); - if (phase < 0) - break; - int parties = partiesOf(s); - int unarrived = unarrivedOf(s) - 1; - if (unarrived > 0) { // Not the last arrival - if (casState(s, s - 1)) // s-1 adds one arrival - break; - } - else if (unarrived == 0) { // the last arrival - Phaser par = parent; - if (par == null) { // directly trip - if (casState - (s, - trippedStateFor(onAdvance(phase, parties) ? -1 : - ((phase + 1) & phaseMask), parties))) { - releaseWaiters(phase); - break; - } - } - else { // cascade to parent - if (casState(s, s - 1)) { // zeroes unarrived - par.arrive(); - reconcileState(); - break; - } - } - } - else if (phase != phaseOf(root.state)) // or if unreconciled - reconcileState(); - else - throw new IllegalStateException(badBounds(parties, unarrived)); - } - return phase; + return doArrive(false); } /** - * Arrives at the barrier and deregisters from it without waiting - * for others. Deregistration reduces the number of parties - * required to trip the barrier in future phases. If this phaser + * Arrives at this phaser and deregisters from it without waiting + * for others to arrive. Deregistration reduces the number of + * parties required to advance in future phases. If this phaser * has a parent, and deregistration causes this phaser to have - * zero parties, this phaser also arrives at and is deregistered - * from its parent. It is an unenforced usage error for an - * unregistered party to invoke this method. + * zero parties, this phaser is also deregistered from its parent. + * + *

It is a usage error for an unregistered party to invoke this + * method. However, this error may result in an {@code + * IllegalStateException} only upon some subsequent operation on + * this phaser, if ever. * * @return the arrival phase number, or a negative value if terminated * @throws IllegalStateException if not terminated and the number * of registered or unarrived parties would become negative */ public int arriveAndDeregister() { - // similar code to arrive, but too different to merge - Phaser par = parent; - int phase; - for (;;) { - long s = state; - phase = phaseOf(s); - if (phase < 0) - break; - int parties = partiesOf(s) - 1; - int unarrived = unarrivedOf(s) - 1; - if (parties >= 0) { - if (unarrived > 0 || (unarrived == 0 && par != null)) { - if (casState - (s, - stateFor(phase, parties, unarrived))) { - if (unarrived == 0) { - par.arriveAndDeregister(); - reconcileState(); - } - break; - } - continue; - } - if (unarrived == 0) { - if (casState - (s, - trippedStateFor(onAdvance(phase, parties) ? -1 : - ((phase + 1) & phaseMask), parties))) { - releaseWaiters(phase); - break; - } - continue; - } - if (par != null && phase != phaseOf(root.state)) { - reconcileState(); - continue; - } - } - throw new IllegalStateException(badBounds(parties, unarrived)); - } - return phase; + return doArrive(true); } /** - * Arrives at the barrier and awaits others. Equivalent in effect + * Arrives at this phaser and awaits others. Equivalent in effect * to {@code awaitAdvance(arrive())}. If you need to await with * interruption or timeout, you can arrange this with an analogous - * construction using one of the other forms of the awaitAdvance - * method. If instead you need to deregister upon arrival use - * {@code arriveAndDeregister}. It is an unenforced usage error - * for an unregistered party to invoke this method. + * construction using one of the other forms of the {@code + * awaitAdvance} method. If instead you need to deregister upon + * arrival, use {@code awaitAdvance(arriveAndDeregister())}. * - * @return the arrival phase number, or a negative number if terminated + *

It is a usage error for an unregistered party to invoke this + * method. However, this error may result in an {@code + * IllegalStateException} only upon some subsequent operation on + * this phaser, if ever. + * + * @return the arrival phase number, or the (negative) + * {@linkplain #getPhase() current phase} if terminated * @throws IllegalStateException if not terminated and the number * of unarrived parties would become negative */ public int arriveAndAwaitAdvance() { - return awaitAdvance(arrive()); + // Specialization of doArrive+awaitAdvance eliminating some reads/paths + final Phaser root = this.root; + for (;;) { + long s = (root == this) ? state : reconcileState(); + int phase = (int)(s >>> PHASE_SHIFT); + int counts = (int)s; + int unarrived = (counts & UNARRIVED_MASK) - 1; + if (phase < 0) + return phase; + else if (counts == EMPTY || unarrived < 0) { + if (reconcileState() == s) + throw new IllegalStateException(badArrive(s)); + } + else if (UNSAFE.compareAndSwapLong(this, stateOffset, s, + s -= ONE_ARRIVAL)) { + if (unarrived != 0) + return root.internalAwaitAdvance(phase, null); + if (root != this) + return parent.arriveAndAwaitAdvance(); + long n = s & PARTIES_MASK; // base of next state + int nextUnarrived = (int)n >>> PARTIES_SHIFT; + if (onAdvance(phase, nextUnarrived)) + n |= TERMINATION_BIT; + else if (nextUnarrived == 0) + n |= EMPTY; + else + n |= nextUnarrived; + int nextPhase = (phase + 1) & MAX_PHASE; + n |= (long)nextPhase << PHASE_SHIFT; + if (!UNSAFE.compareAndSwapLong(this, stateOffset, s, n)) + return (int)(state >>> PHASE_SHIFT); // terminated + releaseWaiters(phase); + return nextPhase; + } + } } /** - * Awaits the phase of the barrier to advance from the given phase - * value, returning immediately if the current phase of the - * barrier is not equal to the given phase value or this barrier - * is terminated. It is an unenforced usage error for an - * unregistered party to invoke this method. + * Awaits the phase of this phaser to advance from the given phase + * value, returning immediately if the current phase is not equal + * to the given phase value or this phaser is terminated. * * @param phase an arrival phase number, or negative value if * terminated; this argument is normally the value returned by a - * previous call to {@code arrive} or its variants - * @return the next arrival phase number, or a negative value - * if terminated or argument is negative + * previous call to {@code arrive} or {@code arriveAndDeregister}. + * @return the next arrival phase number, or the argument if it is + * negative, or the (negative) {@linkplain #getPhase() current phase} + * if terminated */ public int awaitAdvance(int phase) { + final Phaser root = this.root; + long s = (root == this) ? state : reconcileState(); + int p = (int)(s >>> PHASE_SHIFT); if (phase < 0) return phase; - long s = getReconciledState(); - int p = phaseOf(s); - if (p != phase) - return p; - if (unarrivedOf(s) == 0 && parent != null) - parent.awaitAdvance(phase); - // Fall here even if parent waited, to reconcile and help release - return untimedWait(phase); + if (p == phase) + return root.internalAwaitAdvance(phase, null); + return p; } /** - * Awaits the phase of the barrier to advance from the given phase + * Awaits the phase of this phaser to advance from the given phase * value, throwing {@code InterruptedException} if interrupted - * while waiting, or returning immediately if the current phase of - * the barrier is not equal to the given phase value or this - * barrier is terminated. It is an unenforced usage error for an - * unregistered party to invoke this method. + * while waiting, or returning immediately if the current phase is + * not equal to the given phase value or this phaser is + * terminated. * * @param phase an arrival phase number, or negative value if * terminated; this argument is normally the value returned by a - * previous call to {@code arrive} or its variants - * @return the next arrival phase number, or a negative value - * if terminated or argument is negative + * previous call to {@code arrive} or {@code arriveAndDeregister}. + * @return the next arrival phase number, or the argument if it is + * negative, or the (negative) {@linkplain #getPhase() current phase} + * if terminated * @throws InterruptedException if thread interrupted while waiting */ public int awaitAdvanceInterruptibly(int phase) throws InterruptedException { + final Phaser root = this.root; + long s = (root == this) ? state : reconcileState(); + int p = (int)(s >>> PHASE_SHIFT); if (phase < 0) return phase; - long s = getReconciledState(); - int p = phaseOf(s); - if (p != phase) - return p; - if (unarrivedOf(s) == 0 && parent != null) - parent.awaitAdvanceInterruptibly(phase); - return interruptibleWait(phase); + if (p == phase) { + QNode node = new QNode(this, phase, true, false, 0L); + p = root.internalAwaitAdvance(phase, node); + if (node.wasInterrupted) + throw new InterruptedException(); + } + return p; } /** - * Awaits the phase of the barrier to advance from the given phase + * Awaits the phase of this phaser to advance from the given phase * value or the given timeout to elapse, throwing {@code * InterruptedException} if interrupted while waiting, or - * returning immediately if the current phase of the barrier is - * not equal to the given phase value or this barrier is - * terminated. It is an unenforced usage error for an - * unregistered party to invoke this method. + * returning immediately if the current phase is not equal to the + * given phase value or this phaser is terminated. * * @param phase an arrival phase number, or negative value if * terminated; this argument is normally the value returned by a - * previous call to {@code arrive} or its variants + * previous call to {@code arrive} or {@code arriveAndDeregister}. * @param timeout how long to wait before giving up, in units of * {@code unit} * @param unit a {@code TimeUnit} determining how to interpret the * {@code timeout} parameter - * @return the next arrival phase number, or a negative value - * if terminated or argument is negative + * @return the next arrival phase number, or the argument if it is + * negative, or the (negative) {@linkplain #getPhase() current phase} + * if terminated * @throws InterruptedException if thread interrupted while waiting * @throws TimeoutException if timed out while waiting */ public int awaitAdvanceInterruptibly(int phase, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException { + long nanos = unit.toNanos(timeout); + final Phaser root = this.root; + long s = (root == this) ? state : reconcileState(); + int p = (int)(s >>> PHASE_SHIFT); if (phase < 0) return phase; - long s = getReconciledState(); - int p = phaseOf(s); - if (p != phase) - return p; - if (unarrivedOf(s) == 0 && parent != null) - parent.awaitAdvanceInterruptibly(phase, timeout, unit); - return timedWait(phase, unit.toNanos(timeout)); + if (p == phase) { + QNode node = new QNode(this, phase, true, true, nanos); + p = root.internalAwaitAdvance(phase, node); + if (node.wasInterrupted) + throw new InterruptedException(); + else if (p == phase) + throw new TimeoutException(); + } + return p; } /** - * Forces this barrier to enter termination state. Counts of - * arrived and registered parties are unaffected. If this phaser - * has a parent, it too is terminated. This method may be useful - * for coordinating recovery after one or more tasks encounter + * Forces this phaser to enter termination state. Counts of + * registered parties are unaffected. If this phaser is a member + * of a tiered set of phasers, then all of the phasers in the set + * are terminated. If this phaser is already terminated, this + * method has no effect. This method may be useful for + * coordinating recovery after one or more tasks encounter * unexpected exceptions. */ public void forceTermination() { - for (;;) { - long s = getReconciledState(); - int phase = phaseOf(s); - int parties = partiesOf(s); - int unarrived = unarrivedOf(s); - if (phase < 0 || - casState(s, stateFor(-1, parties, unarrived))) { + // Only need to change root state + final Phaser root = this.root; + long s; + while ((s = root.state) >= 0) { + if (UNSAFE.compareAndSwapLong(root, stateOffset, + s, s | TERMINATION_BIT)) { + // signal all threads releaseWaiters(0); releaseWaiters(1); - if (parent != null) - parent.forceTermination(); return; } } @@ -719,16 +819,18 @@ public class Phaser { /** * Returns the current phase number. The maximum phase number is * {@code Integer.MAX_VALUE}, after which it restarts at - * zero. Upon termination, the phase number is negative. + * zero. Upon termination, the phase number is negative, + * in which case the prevailing phase prior to termination + * may be obtained via {@code getPhase() + Integer.MIN_VALUE}. * * @return the phase number, or a negative value if terminated */ public final int getPhase() { - return phaseOf(getReconciledState()); + return (int)(root.state >>> PHASE_SHIFT); } /** - * Returns the number of parties registered at this barrier. + * Returns the number of parties registered at this phaser. * * @return the number of parties */ @@ -738,22 +840,24 @@ public class Phaser { /** * Returns the number of registered parties that have arrived at - * the current phase of this barrier. + * the current phase of this phaser. If this phaser has terminated, + * the returned value is meaningless and arbitrary. * * @return the number of arrived parties */ public int getArrivedParties() { - return arrivedOf(state); + return arrivedOf(reconcileState()); } /** * Returns the number of registered parties that have not yet - * arrived at the current phase of this barrier. + * arrived at the current phase of this phaser. If this phaser has + * terminated, the returned value is meaningless and arbitrary. * * @return the number of unarrived parties */ public int getUnarrivedParties() { - return unarrivedOf(state); + return unarrivedOf(reconcileState()); } /** @@ -776,52 +880,56 @@ public class Phaser { } /** - * Returns {@code true} if this barrier has been terminated. + * Returns {@code true} if this phaser has been terminated. * - * @return {@code true} if this barrier has been terminated + * @return {@code true} if this phaser has been terminated */ public boolean isTerminated() { - return getPhase() < 0; + return root.state < 0L; } /** * Overridable method to perform an action upon impending phase * advance, and to control termination. This method is invoked - * upon arrival of the party tripping the barrier (when all other + * upon arrival of the party advancing this phaser (when all other * waiting parties are dormant). If this method returns {@code - * true}, then, rather than advance the phase number, this barrier - * will be set to a final termination state, and subsequent calls - * to {@link #isTerminated} will return true. Any (unchecked) - * Exception or Error thrown by an invocation of this method is - * propagated to the party attempting to trip the barrier, in - * which case no advance occurs. + * true}, this phaser will be set to a final termination state + * upon advance, and subsequent calls to {@link #isTerminated} + * will return true. Any (unchecked) Exception or Error thrown by + * an invocation of this method is propagated to the party + * attempting to advance this phaser, in which case no advance + * occurs. * *

The arguments to this method provide the state of the phaser - * prevailing for the current transition. (When called from within - * an implementation of {@code onAdvance} the values returned by - * methods such as {@code getPhase} may or may not reliably - * indicate the state to which this transition applies.) + * prevailing for the current transition. The effects of invoking + * arrival, registration, and waiting methods on this phaser from + * within {@code onAdvance} are unspecified and should not be + * relied on. * - *

The default version returns {@code true} when the number of - * registered parties is zero. Normally, overrides that arrange - * termination for other reasons should also preserve this - * property. + *

If this phaser is a member of a tiered set of phasers, then + * {@code onAdvance} is invoked only for its root phaser on each + * advance. * - *

You may override this method to perform an action with side - * effects visible to participating tasks, but it is only sensible - * to do so in designs where all parties register before any - * arrive, and all {@link #awaitAdvance} at each phase. - * Otherwise, you cannot ensure lack of interference from other - * parties during the invocation of this method. Additionally, - * method {@code onAdvance} may be invoked more than once per - * transition if registrations are intermixed with arrivals. + *

To support the most common use cases, the default + * implementation of this method returns {@code true} when the + * number of registered parties has become zero as the result of a + * party invoking {@code arriveAndDeregister}. You can disable + * this behavior, thus enabling continuation upon future + * registrations, by overriding this method to always return + * {@code false}: * - * @param phase the phase number on entering the barrier + *

 {@code
+     * Phaser phaser = new Phaser() {
+     *   protected boolean onAdvance(int phase, int parties) { return false; }
+     * }}
+ * + * @param phase the current phase number on entry to this method, + * before this phaser is advanced * @param registeredParties the current number of registered parties - * @return {@code true} if this barrier should terminate + * @return {@code true} if this phaser should terminate */ protected boolean onAdvance(int phase, int registeredParties) { - return registeredParties <= 0; + return registeredParties == 0; } /** @@ -831,17 +939,138 @@ public class Phaser { * followed by the number of registered parties, and {@code * "arrived = "} followed by the number of arrived parties. * - * @return a string identifying this barrier, as well as its state + * @return a string identifying this phaser, as well as its state */ public String toString() { - long s = getReconciledState(); + return stateToString(reconcileState()); + } + + /** + * Implementation of toString and string-based error messages + */ + private String stateToString(long s) { return super.toString() + "[phase = " + phaseOf(s) + " parties = " + partiesOf(s) + " arrived = " + arrivedOf(s) + "]"; } - // methods for waiting + // Waiting mechanics + + /** + * Removes and signals threads from queue for phase. + */ + private void releaseWaiters(int phase) { + QNode q; // first element of queue + Thread t; // its thread + AtomicReference head = (phase & 1) == 0 ? evenQ : oddQ; + while ((q = head.get()) != null && + q.phase != (int)(root.state >>> PHASE_SHIFT)) { + if (head.compareAndSet(q, q.next) && + (t = q.thread) != null) { + q.thread = null; + LockSupport.unpark(t); + } + } + } + + /** + * Variant of releaseWaiters that additionally tries to remove any + * nodes no longer waiting for advance due to timeout or + * interrupt. Currently, nodes are removed only if they are at + * head of queue, which suffices to reduce memory footprint in + * most usages. + * + * @return current phase on exit + */ + private int abortWait(int phase) { + AtomicReference head = (phase & 1) == 0 ? evenQ : oddQ; + for (;;) { + Thread t; + QNode q = head.get(); + int p = (int)(root.state >>> PHASE_SHIFT); + if (q == null || ((t = q.thread) != null && q.phase == p)) + return p; + if (head.compareAndSet(q, q.next) && t != null) { + q.thread = null; + LockSupport.unpark(t); + } + } + } + + /** The number of CPUs, for spin control */ + private static final int NCPU = Runtime.getRuntime().availableProcessors(); + + /** + * The number of times to spin before blocking while waiting for + * advance, per arrival while waiting. On multiprocessors, fully + * blocking and waking up a large number of threads all at once is + * usually a very slow process, so we use rechargeable spins to + * avoid it when threads regularly arrive: When a thread in + * internalAwaitAdvance notices another arrival before blocking, + * and there appear to be enough CPUs available, it spins + * SPINS_PER_ARRIVAL more times before blocking. The value trades + * off good-citizenship vs big unnecessary slowdowns. + */ + static final int SPINS_PER_ARRIVAL = (NCPU < 2) ? 1 : 1 << 8; + + /** + * Possibly blocks and waits for phase to advance unless aborted. + * Call only from root node. + * + * @param phase current phase + * @param node if non-null, the wait node to track interrupt and timeout; + * if null, denotes noninterruptible wait + * @return current phase + */ + private int internalAwaitAdvance(int phase, QNode node) { + releaseWaiters(phase-1); // ensure old queue clean + boolean queued = false; // true when node is enqueued + int lastUnarrived = 0; // to increase spins upon change + int spins = SPINS_PER_ARRIVAL; + long s; + int p; + while ((p = (int)((s = state) >>> PHASE_SHIFT)) == phase) { + if (node == null) { // spinning in noninterruptible mode + int unarrived = (int)s & UNARRIVED_MASK; + if (unarrived != lastUnarrived && + (lastUnarrived = unarrived) < NCPU) + spins += SPINS_PER_ARRIVAL; + boolean interrupted = Thread.interrupted(); + if (interrupted || --spins < 0) { // need node to record intr + node = new QNode(this, phase, false, false, 0L); + node.wasInterrupted = interrupted; + } + } + else if (node.isReleasable()) // done or aborted + break; + else if (!queued) { // push onto queue + AtomicReference head = (phase & 1) == 0 ? evenQ : oddQ; + QNode q = node.next = head.get(); + if ((q == null || q.phase == phase) && + (int)(state >>> PHASE_SHIFT) == phase) // avoid stale enq + queued = head.compareAndSet(q, node); + } + else { + try { + ForkJoinPool.managedBlock(node); + } catch (InterruptedException ie) { + node.wasInterrupted = true; + } + } + } + + if (node != null) { + if (node.thread != null) + node.thread = null; // avoid need for unpark() + if (node.wasInterrupted && !node.interruptible) + Thread.currentThread().interrupt(); + if (p == phase && (p = (int)(state >>> PHASE_SHIFT)) == phase) + return abortWait(phase); // possibly clean up on abort + } + releaseWaiters(phase); + return p; + } /** * Wait nodes for Treiber stack representing wait queue @@ -849,186 +1078,69 @@ public class Phaser { static final class QNode implements ForkJoinPool.ManagedBlocker { final Phaser phaser; final int phase; - final long startTime; - final long nanos; - final boolean timed; final boolean interruptible; - volatile boolean wasInterrupted = false; + final boolean timed; + boolean wasInterrupted; + long nanos; + long lastTime; volatile Thread thread; // nulled to cancel wait QNode next; + QNode(Phaser phaser, int phase, boolean interruptible, - boolean timed, long startTime, long nanos) { + boolean timed, long nanos) { this.phaser = phaser; this.phase = phase; - this.timed = timed; this.interruptible = interruptible; - this.startTime = startTime; this.nanos = nanos; + this.timed = timed; + this.lastTime = timed ? System.nanoTime() : 0L; thread = Thread.currentThread(); } + public boolean isReleasable() { - return (thread == null || - phaser.getPhase() != phase || - (interruptible && wasInterrupted) || - (timed && (nanos - (System.nanoTime() - startTime)) <= 0)); - } - public boolean block() { - if (Thread.interrupted()) { - wasInterrupted = true; - if (interruptible) - return true; - } - if (!timed) - LockSupport.park(this); - else { - long waitTime = nanos - (System.nanoTime() - startTime); - if (waitTime <= 0) - return true; - LockSupport.parkNanos(this, waitTime); - } - return isReleasable(); - } - void signal() { - Thread t = thread; - if (t != null) { + if (thread == null) + return true; + if (phaser.getPhase() != phase) { thread = null; - LockSupport.unpark(t); + return true; } - } - boolean doWait() { - if (thread != null) { - try { - ForkJoinPool.managedBlock(this); - } catch (InterruptedException ie) { + if (Thread.interrupted()) + wasInterrupted = true; + if (wasInterrupted && interruptible) { + thread = null; + return true; + } + if (timed) { + if (nanos > 0L) { + long now = System.nanoTime(); + nanos -= now - lastTime; + lastTime = now; + } + if (nanos <= 0L) { + thread = null; + return true; } } - return wasInterrupted; + return false; } - } - - /** - * Removes and signals waiting threads from wait queue. - */ - private void releaseWaiters(int phase) { - AtomicReference head = queueFor(phase); - QNode q; - while ((q = head.get()) != null) { - if (head.compareAndSet(q, q.next)) - q.signal(); + public boolean block() { + if (isReleasable()) + return true; + else if (!timed) + LockSupport.park(this); + else if (nanos > 0) + LockSupport.parkNanos(this, nanos); + return isReleasable(); } } - /** - * Tries to enqueue given node in the appropriate wait queue. - * - * @return true if successful - */ - private boolean tryEnqueue(QNode node) { - AtomicReference head = queueFor(node.phase); - return head.compareAndSet(node.next = head.get(), node); - } - - /** - * Enqueues node and waits unless aborted or signalled. - * - * @return current phase - */ - private int untimedWait(int phase) { - QNode node = null; - boolean queued = false; - boolean interrupted = false; - int p; - while ((p = getPhase()) == phase) { - if (Thread.interrupted()) - interrupted = true; - else if (node == null) - node = new QNode(this, phase, false, false, 0, 0); - else if (!queued) - queued = tryEnqueue(node); - else - interrupted = node.doWait(); - } - if (node != null) - node.thread = null; - releaseWaiters(phase); - if (interrupted) - Thread.currentThread().interrupt(); - return p; - } - - /** - * Interruptible version - * @return current phase - */ - private int interruptibleWait(int phase) throws InterruptedException { - QNode node = null; - boolean queued = false; - boolean interrupted = false; - int p; - while ((p = getPhase()) == phase && !interrupted) { - if (Thread.interrupted()) - interrupted = true; - else if (node == null) - node = new QNode(this, phase, true, false, 0, 0); - else if (!queued) - queued = tryEnqueue(node); - else - interrupted = node.doWait(); - } - if (node != null) - node.thread = null; - if (p != phase || (p = getPhase()) != phase) - releaseWaiters(phase); - if (interrupted) - throw new InterruptedException(); - return p; - } - - /** - * Timeout version. - * @return current phase - */ - private int timedWait(int phase, long nanos) - throws InterruptedException, TimeoutException { - long startTime = System.nanoTime(); - QNode node = null; - boolean queued = false; - boolean interrupted = false; - int p; - while ((p = getPhase()) == phase && !interrupted) { - if (Thread.interrupted()) - interrupted = true; - else if (nanos - (System.nanoTime() - startTime) <= 0) - break; - else if (node == null) - node = new QNode(this, phase, true, true, startTime, nanos); - else if (!queued) - queued = tryEnqueue(node); - else - interrupted = node.doWait(); - } - if (node != null) - node.thread = null; - if (p != phase || (p = getPhase()) != phase) - releaseWaiters(phase); - if (interrupted) - throw new InterruptedException(); - if (p == phase) - throw new TimeoutException(); - return p; - } - // Unsafe mechanics private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); private static final long stateOffset = objectFieldOffset("state", Phaser.class); - private final boolean casState(long cmp, long val) { - return UNSAFE.compareAndSwapLong(this, stateOffset, cmp, val); - } - private static long objectFieldOffset(String field, Class klazz) { try { return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); diff --git a/jdk/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java b/jdk/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java index fec463e3d38..60928ac8a74 100644 --- a/jdk/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java +++ b/jdk/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java @@ -43,11 +43,11 @@ import java.util.*; * the same ordering rules as class {@link PriorityQueue} and supplies * blocking retrieval operations. While this queue is logically * unbounded, attempted additions may fail due to resource exhaustion - * (causing OutOfMemoryError). This class does not permit - * null elements. A priority queue relying on {@linkplain + * (causing {@code OutOfMemoryError}). This class does not permit + * {@code null} elements. A priority queue relying on {@linkplain * Comparable natural ordering} also does not permit insertion of * non-comparable objects (doing so results in - * ClassCastException). + * {@code ClassCastException}). * *

This class and its iterator implement all of the * optional methods of the {@link Collection} and {@link @@ -55,7 +55,7 @@ import java.util.*; * #iterator()} is not guaranteed to traverse the elements of * the PriorityBlockingQueue in any particular order. If you need * ordered traversal, consider using - * Arrays.sort(pq.toArray()). Also, method drainTo + * {@code Arrays.sort(pq.toArray())}. Also, method {@code drainTo} * can be used to remove some or all elements in priority * order and place them in another collection. * @@ -65,12 +65,12 @@ import java.util.*; * secondary key to break ties in primary priority values. For * example, here is a class that applies first-in-first-out * tie-breaking to comparable elements. To use it, you would insert a - * new FIFOEntry(anEntry) instead of a plain entry object. + * {@code new FIFOEntry(anEntry)} instead of a plain entry object. * - *

- * class FIFOEntry<E extends Comparable<? super E>>
- *     implements Comparable<FIFOEntry<E>> {
- *   final static AtomicLong seq = new AtomicLong();
+ *  
 {@code
+ * class FIFOEntry>
+ *     implements Comparable> {
+ *   static final AtomicLong seq = new AtomicLong(0);
  *   final long seqNum;
  *   final E entry;
  *   public FIFOEntry(E entry) {
@@ -78,13 +78,13 @@ import java.util.*;
  *     this.entry = entry;
  *   }
  *   public E getEntry() { return entry; }
- *   public int compareTo(FIFOEntry<E> other) {
+ *   public int compareTo(FIFOEntry other) {
  *     int res = entry.compareTo(other.entry);
- *     if (res == 0 && other.entry != this.entry)
- *       res = (seqNum < other.seqNum ? -1 : 1);
+ *     if (res == 0 && other.entry != this.entry)
+ *       res = (seqNum < other.seqNum ? -1 : 1);
  *     return res;
  *   }
- * }
+ * }}
* *

This class is a member of the * @@ -98,34 +98,102 @@ public class PriorityBlockingQueue extends AbstractQueue implements BlockingQueue, java.io.Serializable { private static final long serialVersionUID = 5595510919245408276L; - private final PriorityQueue q; - private final ReentrantLock lock = new ReentrantLock(true); - private final Condition notEmpty = lock.newCondition(); + /* + * The implementation uses an array-based binary heap, with public + * operations protected with a single lock. However, allocation + * during resizing uses a simple spinlock (used only while not + * holding main lock) in order to allow takes to operate + * concurrently with allocation. This avoids repeated + * postponement of waiting consumers and consequent element + * build-up. The need to back away from lock during allocation + * makes it impossible to simply wrap delegated + * java.util.PriorityQueue operations within a lock, as was done + * in a previous version of this class. To maintain + * interoperability, a plain PriorityQueue is still used during + * serialization, which maintains compatibility at the espense of + * transiently doubling overhead. + */ /** - * Creates a PriorityBlockingQueue with the default + * Default array capacity. + */ + private static final int DEFAULT_INITIAL_CAPACITY = 11; + + /** + * The maximum size of array to allocate. + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + + /** + * Priority queue represented as a balanced binary heap: the two + * children of queue[n] are queue[2*n+1] and queue[2*(n+1)]. The + * priority queue is ordered by comparator, or by the elements' + * natural ordering, if comparator is null: For each node n in the + * heap and each descendant d of n, n <= d. The element with the + * lowest value is in queue[0], assuming the queue is nonempty. + */ + private transient Object[] queue; + + /** + * The number of elements in the priority queue. + */ + private transient int size; + + /** + * The comparator, or null if priority queue uses elements' + * natural ordering. + */ + private transient Comparator comparator; + + /** + * Lock used for all public operations + */ + private final ReentrantLock lock; + + /** + * Condition for blocking when empty + */ + private final Condition notEmpty; + + /** + * Spinlock for allocation, acquired via CAS. + */ + private transient volatile int allocationSpinLock; + + /** + * A plain PriorityQueue used only for serialization, + * to maintain compatibility with previous versions + * of this class. Non-null only during serialization/deserialization. + */ + private PriorityQueue q; + + /** + * Creates a {@code PriorityBlockingQueue} with the default * initial capacity (11) that orders its elements according to * their {@linkplain Comparable natural ordering}. */ public PriorityBlockingQueue() { - q = new PriorityQueue(); + this(DEFAULT_INITIAL_CAPACITY, null); } /** - * Creates a PriorityBlockingQueue with the specified + * Creates a {@code PriorityBlockingQueue} with the specified * initial capacity that orders its elements according to their * {@linkplain Comparable natural ordering}. * * @param initialCapacity the initial capacity for this priority queue - * @throws IllegalArgumentException if initialCapacity is less + * @throws IllegalArgumentException if {@code initialCapacity} is less * than 1 */ public PriorityBlockingQueue(int initialCapacity) { - q = new PriorityQueue(initialCapacity, null); + this(initialCapacity, null); } /** - * Creates a PriorityBlockingQueue with the specified initial + * Creates a {@code PriorityBlockingQueue} with the specified initial * capacity that orders its elements according to the specified * comparator. * @@ -133,16 +201,21 @@ public class PriorityBlockingQueue extends AbstractQueue * @param comparator the comparator that will be used to order this * priority queue. If {@code null}, the {@linkplain Comparable * natural ordering} of the elements will be used. - * @throws IllegalArgumentException if initialCapacity is less + * @throws IllegalArgumentException if {@code initialCapacity} is less * than 1 */ public PriorityBlockingQueue(int initialCapacity, Comparator comparator) { - q = new PriorityQueue(initialCapacity, comparator); + if (initialCapacity < 1) + throw new IllegalArgumentException(); + this.lock = new ReentrantLock(); + this.notEmpty = lock.newCondition(); + this.comparator = comparator; + this.queue = new Object[initialCapacity]; } /** - * Creates a PriorityBlockingQueue containing the elements + * Creates a {@code PriorityBlockingQueue} containing the elements * in the specified collection. If the specified collection is a * {@link SortedSet} or a {@link PriorityQueue}, this * priority queue will be ordered according to the same ordering. @@ -158,14 +231,215 @@ public class PriorityBlockingQueue extends AbstractQueue * of its elements are null */ public PriorityBlockingQueue(Collection c) { - q = new PriorityQueue(c); + this.lock = new ReentrantLock(); + this.notEmpty = lock.newCondition(); + boolean heapify = true; // true if not known to be in heap order + boolean screen = true; // true if must screen for nulls + if (c instanceof SortedSet) { + SortedSet ss = (SortedSet) c; + this.comparator = (Comparator) ss.comparator(); + heapify = false; + } + else if (c instanceof PriorityBlockingQueue) { + PriorityBlockingQueue pq = + (PriorityBlockingQueue) c; + this.comparator = (Comparator) pq.comparator(); + screen = false; + if (pq.getClass() == PriorityBlockingQueue.class) // exact match + heapify = false; + } + Object[] a = c.toArray(); + int n = a.length; + // If c.toArray incorrectly doesn't return Object[], copy it. + if (a.getClass() != Object[].class) + a = Arrays.copyOf(a, n, Object[].class); + if (screen && (n == 1 || this.comparator != null)) { + for (int i = 0; i < n; ++i) + if (a[i] == null) + throw new NullPointerException(); + } + this.queue = a; + this.size = n; + if (heapify) + heapify(); + } + + /** + * Tries to grow array to accommodate at least one more element + * (but normally expand by about 50%), giving up (allowing retry) + * on contention (which we expect to be rare). Call only while + * holding lock. + * + * @param array the heap array + * @param oldCap the length of the array + */ + private void tryGrow(Object[] array, int oldCap) { + lock.unlock(); // must release and then re-acquire main lock + Object[] newArray = null; + if (allocationSpinLock == 0 && + UNSAFE.compareAndSwapInt(this, allocationSpinLockOffset, + 0, 1)) { + try { + int newCap = oldCap + ((oldCap < 64) ? + (oldCap + 2) : // grow faster if small + (oldCap >> 1)); + if (newCap - MAX_ARRAY_SIZE > 0) { // possible overflow + int minCap = oldCap + 1; + if (minCap < 0 || minCap > MAX_ARRAY_SIZE) + throw new OutOfMemoryError(); + newCap = MAX_ARRAY_SIZE; + } + if (newCap > oldCap && queue == array) + newArray = new Object[newCap]; + } finally { + allocationSpinLock = 0; + } + } + if (newArray == null) // back off if another thread is allocating + Thread.yield(); + lock.lock(); + if (newArray != null && queue == array) { + queue = newArray; + System.arraycopy(array, 0, newArray, 0, oldCap); + } + } + + /** + * Mechanics for poll(). Call only while holding lock. + */ + private E extract() { + E result; + int n = size - 1; + if (n < 0) + result = null; + else { + Object[] array = queue; + result = (E) array[0]; + E x = (E) array[n]; + array[n] = null; + Comparator cmp = comparator; + if (cmp == null) + siftDownComparable(0, x, array, n); + else + siftDownUsingComparator(0, x, array, n, cmp); + size = n; + } + return result; + } + + /** + * Inserts item x at position k, maintaining heap invariant by + * promoting x up the tree until it is greater than or equal to + * its parent, or is the root. + * + * To simplify and speed up coercions and comparisons. the + * Comparable and Comparator versions are separated into different + * methods that are otherwise identical. (Similarly for siftDown.) + * These methods are static, with heap state as arguments, to + * simplify use in light of possible comparator exceptions. + * + * @param k the position to fill + * @param x the item to insert + * @param array the heap array + * @param n heap size + */ + private static void siftUpComparable(int k, T x, Object[] array) { + Comparable key = (Comparable) x; + while (k > 0) { + int parent = (k - 1) >>> 1; + Object e = array[parent]; + if (key.compareTo((T) e) >= 0) + break; + array[k] = e; + k = parent; + } + array[k] = key; + } + + private static void siftUpUsingComparator(int k, T x, Object[] array, + Comparator cmp) { + while (k > 0) { + int parent = (k - 1) >>> 1; + Object e = array[parent]; + if (cmp.compare(x, (T) e) >= 0) + break; + array[k] = e; + k = parent; + } + array[k] = x; + } + + /** + * Inserts item x at position k, maintaining heap invariant by + * demoting x down the tree repeatedly until it is less than or + * equal to its children or is a leaf. + * + * @param k the position to fill + * @param x the item to insert + * @param array the heap array + * @param n heap size + */ + private static void siftDownComparable(int k, T x, Object[] array, + int n) { + Comparable key = (Comparable)x; + int half = n >>> 1; // loop while a non-leaf + while (k < half) { + int child = (k << 1) + 1; // assume left child is least + Object c = array[child]; + int right = child + 1; + if (right < n && + ((Comparable) c).compareTo((T) array[right]) > 0) + c = array[child = right]; + if (key.compareTo((T) c) <= 0) + break; + array[k] = c; + k = child; + } + array[k] = key; + } + + private static void siftDownUsingComparator(int k, T x, Object[] array, + int n, + Comparator cmp) { + int half = n >>> 1; + while (k < half) { + int child = (k << 1) + 1; + Object c = array[child]; + int right = child + 1; + if (right < n && cmp.compare((T) c, (T) array[right]) > 0) + c = array[child = right]; + if (cmp.compare(x, (T) c) <= 0) + break; + array[k] = c; + k = child; + } + array[k] = x; + } + + /** + * Establishes the heap invariant (described above) in the entire tree, + * assuming nothing about the order of the elements prior to the call. + */ + private void heapify() { + Object[] array = queue; + int n = size; + int half = (n >>> 1) - 1; + Comparator cmp = comparator; + if (cmp == null) { + for (int i = half; i >= 0; i--) + siftDownComparable(i, (E) array[i], array, n); + } + else { + for (int i = half; i >= 0; i--) + siftDownUsingComparator(i, (E) array[i], array, n, cmp); + } } /** * Inserts the specified element into this priority queue. * * @param e the element to add - * @return true (as specified by {@link Collection#add}) + * @return {@code true} (as specified by {@link Collection#add}) * @throws ClassCastException if the specified element cannot be compared * with elements currently in the priority queue according to the * priority queue's ordering @@ -177,30 +451,41 @@ public class PriorityBlockingQueue extends AbstractQueue /** * Inserts the specified element into this priority queue. + * As the queue is unbounded, this method will never return {@code false}. * * @param e the element to add - * @return true (as specified by {@link Queue#offer}) + * @return {@code true} (as specified by {@link Queue#offer}) * @throws ClassCastException if the specified element cannot be compared * with elements currently in the priority queue according to the * priority queue's ordering * @throws NullPointerException if the specified element is null */ public boolean offer(E e) { + if (e == null) + throw new NullPointerException(); final ReentrantLock lock = this.lock; lock.lock(); + int n, cap; + Object[] array; + while ((n = size) >= (cap = (array = queue).length)) + tryGrow(array, cap); try { - boolean ok = q.offer(e); - assert ok; + Comparator cmp = comparator; + if (cmp == null) + siftUpComparable(n, e, array); + else + siftUpUsingComparator(n, e, array, cmp); + size = n + 1; notEmpty.signal(); - return true; } finally { lock.unlock(); } + return true; } /** - * Inserts the specified element into this priority queue. As the queue is - * unbounded this method will never block. + * Inserts the specified element into this priority queue. + * As the queue is unbounded, this method will never block. * * @param e the element to add * @throws ClassCastException if the specified element cannot be compared @@ -213,13 +498,15 @@ public class PriorityBlockingQueue extends AbstractQueue } /** - * Inserts the specified element into this priority queue. As the queue is - * unbounded this method will never block. + * Inserts the specified element into this priority queue. + * As the queue is unbounded, this method will never block or + * return {@code false}. * * @param e the element to add * @param timeout This parameter is ignored as the method never blocks * @param unit This parameter is ignored as the method never blocks - * @return true + * @return {@code true} (as specified by + * {@link BlockingQueue#offer(Object,long,TimeUnit) BlockingQueue.offer}) * @throws ClassCastException if the specified element cannot be compared * with elements currently in the priority queue according to the * priority queue's ordering @@ -232,97 +519,123 @@ public class PriorityBlockingQueue extends AbstractQueue public E poll() { final ReentrantLock lock = this.lock; lock.lock(); + E result; try { - return q.poll(); + result = extract(); } finally { lock.unlock(); } + return result; } public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); + E result; try { - try { - while (q.size() == 0) - notEmpty.await(); - } catch (InterruptedException ie) { - notEmpty.signal(); // propagate to non-interrupted thread - throw ie; - } - E x = q.poll(); - assert x != null; - return x; + while ( (result = extract()) == null) + notEmpty.await(); } finally { lock.unlock(); } + return result; } public E poll(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); + E result; try { - for (;;) { - E x = q.poll(); - if (x != null) - return x; - if (nanos <= 0) - return null; - try { - nanos = notEmpty.awaitNanos(nanos); - } catch (InterruptedException ie) { - notEmpty.signal(); // propagate to non-interrupted thread - throw ie; - } - } + while ( (result = extract()) == null && nanos > 0) + nanos = notEmpty.awaitNanos(nanos); } finally { lock.unlock(); } + return result; } public E peek() { final ReentrantLock lock = this.lock; lock.lock(); + E result; try { - return q.peek(); + result = size > 0 ? (E) queue[0] : null; } finally { lock.unlock(); } + return result; } /** * Returns the comparator used to order the elements in this queue, - * or null if this queue uses the {@linkplain Comparable + * or {@code null} if this queue uses the {@linkplain Comparable * natural ordering} of its elements. * * @return the comparator used to order the elements in this queue, - * or null if this queue uses the natural + * or {@code null} if this queue uses the natural * ordering of its elements */ public Comparator comparator() { - return q.comparator(); + return comparator; } public int size() { final ReentrantLock lock = this.lock; lock.lock(); try { - return q.size(); + return size; } finally { lock.unlock(); } } /** - * Always returns Integer.MAX_VALUE because - * a PriorityBlockingQueue is not capacity constrained. - * @return Integer.MAX_VALUE + * Always returns {@code Integer.MAX_VALUE} because + * a {@code PriorityBlockingQueue} is not capacity constrained. + * @return {@code Integer.MAX_VALUE} always */ public int remainingCapacity() { return Integer.MAX_VALUE; } + private int indexOf(Object o) { + if (o != null) { + Object[] array = queue; + int n = size; + for (int i = 0; i < n; i++) + if (o.equals(array[i])) + return i; + } + return -1; + } + + /** + * Removes the ith element from queue. + */ + private void removeAt(int i) { + Object[] array = queue; + int n = size - 1; + if (n == i) // removed last element + array[i] = null; + else { + E moved = (E) array[n]; + array[n] = null; + Comparator cmp = comparator; + if (cmp == null) + siftDownComparable(i, moved, array, n); + else + siftDownUsingComparator(i, moved, array, n, cmp); + if (array[i] == moved) { + if (cmp == null) + siftUpComparable(i, moved, array); + else + siftUpUsingComparator(i, moved, array, cmp); + } + } + size = n; + } + /** * Removes a single instance of the specified element from this queue, * if it is present. More formally, removes an element {@code e} such @@ -332,13 +645,40 @@ public class PriorityBlockingQueue extends AbstractQueue * result of the call). * * @param o element to be removed from this queue, if present - * @return true if this queue changed as a result of the call + * @return {@code true} if this queue changed as a result of the call */ public boolean remove(Object o) { + boolean removed = false; final ReentrantLock lock = this.lock; lock.lock(); try { - return q.remove(o); + int i = indexOf(o); + if (i != -1) { + removeAt(i); + removed = true; + } + } finally { + lock.unlock(); + } + return removed; + } + + + /** + * Identity-based version for use in Itr.remove + */ + private void removeEQ(Object o) { + final ReentrantLock lock = this.lock; + lock.lock(); + try { + Object[] array = queue; + int n = size; + for (int i = 0; i < n; i++) { + if (o == array[i]) { + removeAt(i); + break; + } + } } finally { lock.unlock(); } @@ -350,16 +690,18 @@ public class PriorityBlockingQueue extends AbstractQueue * at least one element {@code e} such that {@code o.equals(e)}. * * @param o object to be checked for containment in this queue - * @return true if this queue contains the specified element + * @return {@code true} if this queue contains the specified element */ public boolean contains(Object o) { + int index; final ReentrantLock lock = this.lock; lock.lock(); try { - return q.contains(o); + index = indexOf(o); } finally { lock.unlock(); } + return index != -1; } /** @@ -379,7 +721,7 @@ public class PriorityBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - return q.toArray(); + return Arrays.copyOf(queue, size); } finally { lock.unlock(); } @@ -390,7 +732,18 @@ public class PriorityBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - return q.toString(); + int n = size; + if (n == 0) + return "[]"; + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (int i = 0; i < n; ++i) { + E e = (E)queue[i]; + sb.append(e == this ? "(this Collection)" : e); + if (i != n - 1) + sb.append(',').append(' '); + } + return sb.append(']').toString(); } finally { lock.unlock(); } @@ -412,7 +765,7 @@ public class PriorityBlockingQueue extends AbstractQueue try { int n = 0; E e; - while ( (e = q.poll()) != null) { + while ( (e = extract()) != null) { c.add(e); ++n; } @@ -440,7 +793,7 @@ public class PriorityBlockingQueue extends AbstractQueue try { int n = 0; E e; - while (n < maxElements && (e = q.poll()) != null) { + while (n < maxElements && (e = extract()) != null) { c.add(e); ++n; } @@ -458,7 +811,11 @@ public class PriorityBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - q.clear(); + Object[] array = queue; + int n = size; + size = 0; + for (int i = 0; i < n; i++) + array[i] = null; } finally { lock.unlock(); } @@ -475,22 +832,22 @@ public class PriorityBlockingQueue extends AbstractQueue *

If this queue fits in the specified array with room to spare * (i.e., the array has more elements than this queue), the element in * the array immediately following the end of the queue is set to - * null. + * {@code null}. * *

Like the {@link #toArray()} method, this method acts as bridge between * array-based and collection-based APIs. Further, this method allows * precise control over the runtime type of the output array, and may, * under certain circumstances, be used to save allocation costs. * - *

Suppose x is a queue known to contain only strings. + *

Suppose {@code x} is a queue known to contain only strings. * The following code can be used to dump the queue into a newly - * allocated array of String: + * allocated array of {@code String}: * *

      *     String[] y = x.toArray(new String[0]);
* - * Note that toArray(new Object[0]) is identical in function to - * toArray(). + * Note that {@code toArray(new Object[0])} is identical in function to + * {@code toArray()}. * * @param a the array into which the elements of the queue are to * be stored, if it is big enough; otherwise, a new array of the @@ -505,7 +862,14 @@ public class PriorityBlockingQueue extends AbstractQueue final ReentrantLock lock = this.lock; lock.lock(); try { - return q.toArray(a); + int n = size; + if (a.length < n) + // Make a new array of a's runtime type, but my contents: + return (T[]) Arrays.copyOf(queue, size, a.getClass()); + System.arraycopy(queue, 0, a, 0, n); + if (a.length > n) + a[n] = null; + return a; } finally { lock.unlock(); } @@ -514,8 +878,9 @@ public class PriorityBlockingQueue extends AbstractQueue /** * Returns an iterator over the elements in this queue. The * iterator does not return the elements in any particular order. - * The returned Iterator is a "weakly consistent" - * iterator that will never throw {@link + * + *

The returned iterator is a "weakly consistent" iterator that + * will never throw {@link java.util.ConcurrentModificationException * ConcurrentModificationException}, and guarantees to traverse * elements as they existed upon construction of the iterator, and * may (but is not guaranteed to) reflect any modifications @@ -530,7 +895,7 @@ public class PriorityBlockingQueue extends AbstractQueue /** * Snapshot iterator that works off copy of underlying q array. */ - private class Itr implements Iterator { + final class Itr implements Iterator { final Object[] array; // Array of all elements int cursor; // index of next element to return; int lastRet; // index of last element, or -1 if no such @@ -554,39 +919,65 @@ public class PriorityBlockingQueue extends AbstractQueue public void remove() { if (lastRet < 0) throw new IllegalStateException(); - Object x = array[lastRet]; + removeEQ(array[lastRet]); lastRet = -1; - // Traverse underlying queue to find == element, - // not just a .equals element. - lock.lock(); - try { - for (Iterator it = q.iterator(); it.hasNext(); ) { - if (it.next() == x) { - it.remove(); - return; - } - } - } finally { - lock.unlock(); - } } } /** - * Saves the state to a stream (that is, serializes it). This - * merely wraps default serialization within lock. The - * serialization strategy for items is left to underlying - * Queue. Note that locking is not needed on deserialization, so - * readObject is not defined, just relying on default. + * Saves the state to a stream (that is, serializes it). For + * compatibility with previous version of this class, + * elements are first copied to a java.util.PriorityQueue, + * which is then serialized. */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { lock.lock(); try { + int n = size; // avoid zero capacity argument + q = new PriorityQueue(n == 0 ? 1 : n, comparator); + q.addAll(this); s.defaultWriteObject(); } finally { + q = null; lock.unlock(); } } + /** + * Reconstitutes the {@code PriorityBlockingQueue} instance from a stream + * (that is, deserializes it). + * + * @param s the stream + */ + private void readObject(java.io.ObjectInputStream s) + throws java.io.IOException, ClassNotFoundException { + try { + s.defaultReadObject(); + this.queue = new Object[q.size()]; + comparator = q.comparator(); + addAll(q); + } finally { + q = null; + } + } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long allocationSpinLockOffset = + objectFieldOffset(UNSAFE, "allocationSpinLock", + PriorityBlockingQueue.class); + + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, + String field, Class klazz) { + try { + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); + } catch (NoSuchFieldException e) { + // Convert Exception to corresponding Error + NoSuchFieldError error = new NoSuchFieldError(field); + error.initCause(e); + throw error; + } + } + } diff --git a/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java b/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java index 46961b7aa40..f1731420897 100644 --- a/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java +++ b/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java @@ -360,8 +360,12 @@ public class ScheduledThreadPoolExecutor getExecuteExistingDelayedTasksAfterShutdownPolicy(); boolean keepPeriodic = getContinueExistingPeriodicTasksAfterShutdownPolicy(); - if (!keepDelayed && !keepPeriodic) + if (!keepDelayed && !keepPeriodic) { + for (Object e : q.toArray()) + if (e instanceof RunnableScheduledFuture) + ((RunnableScheduledFuture) e).cancel(false); q.clear(); + } else { // Traverse snapshot to avoid iterator exceptions for (Object e : q.toArray()) { diff --git a/jdk/src/share/classes/java/util/concurrent/SynchronousQueue.java b/jdk/src/share/classes/java/util/concurrent/SynchronousQueue.java index f39f1a906e6..47b352f9e35 100644 --- a/jdk/src/share/classes/java/util/concurrent/SynchronousQueue.java +++ b/jdk/src/share/classes/java/util/concurrent/SynchronousQueue.java @@ -163,7 +163,7 @@ public class SynchronousQueue extends AbstractQueue /** * Shared internal API for dual stacks and queues. */ - static abstract class Transferer { + abstract static class Transferer { /** * Performs a put or take. * @@ -190,7 +190,7 @@ public class SynchronousQueue extends AbstractQueue * seems not to vary with number of CPUs (beyond 2) so is just * a constant. */ - static final int maxTimedSpins = (NCPUS < 2)? 0 : 32; + static final int maxTimedSpins = (NCPUS < 2) ? 0 : 32; /** * The number of times to spin before blocking in untimed waits. @@ -241,19 +241,11 @@ public class SynchronousQueue extends AbstractQueue this.item = item; } - static final AtomicReferenceFieldUpdater - nextUpdater = AtomicReferenceFieldUpdater.newUpdater - (SNode.class, SNode.class, "next"); - boolean casNext(SNode cmp, SNode val) { - return (cmp == next && - nextUpdater.compareAndSet(this, cmp, val)); + return cmp == next && + UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); } - static final AtomicReferenceFieldUpdater - matchUpdater = AtomicReferenceFieldUpdater.newUpdater - (SNode.class, SNode.class, "match"); - /** * Tries to match node s to this node, if so, waking up thread. * Fulfillers call tryMatch to identify their waiters. @@ -264,7 +256,7 @@ public class SynchronousQueue extends AbstractQueue */ boolean tryMatch(SNode s) { if (match == null && - matchUpdater.compareAndSet(this, null, s)) { + UNSAFE.compareAndSwapObject(this, matchOffset, null, s)) { Thread w = waiter; if (w != null) { // waiters need at most one unpark waiter = null; @@ -279,23 +271,28 @@ public class SynchronousQueue extends AbstractQueue * Tries to cancel a wait by matching node to itself. */ void tryCancel() { - matchUpdater.compareAndSet(this, null, this); + UNSAFE.compareAndSwapObject(this, matchOffset, null, this); } boolean isCancelled() { return match == this; } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long nextOffset = + objectFieldOffset(UNSAFE, "next", SNode.class); + private static final long matchOffset = + objectFieldOffset(UNSAFE, "match", SNode.class); + } /** The head (top) of the stack */ volatile SNode head; - static final AtomicReferenceFieldUpdater - headUpdater = AtomicReferenceFieldUpdater.newUpdater - (TransferStack.class, SNode.class, "head"); - boolean casHead(SNode h, SNode nh) { - return h == head && headUpdater.compareAndSet(this, h, nh); + return h == head && + UNSAFE.compareAndSwapObject(this, headOffset, h, nh); } /** @@ -338,7 +335,7 @@ public class SynchronousQueue extends AbstractQueue */ SNode s = null; // constructed/reused as needed - int mode = (e == null)? REQUEST : DATA; + int mode = (e == null) ? REQUEST : DATA; for (;;) { SNode h = head; @@ -356,7 +353,7 @@ public class SynchronousQueue extends AbstractQueue } if ((h = head) != null && h.next == s) casHead(h, s.next); // help s's fulfiller - return mode == REQUEST? m.item : s.item; + return (mode == REQUEST) ? m.item : s.item; } } else if (!isFulfilling(h.mode)) { // try to fulfill if (h.isCancelled()) // already cancelled @@ -372,7 +369,7 @@ public class SynchronousQueue extends AbstractQueue SNode mn = m.next; if (m.tryMatch(s)) { casHead(s, mn); // pop both s and m - return (mode == REQUEST)? m.item : s.item; + return (mode == REQUEST) ? m.item : s.item; } else // lost match s.casNext(m, mn); // help unlink } @@ -423,11 +420,11 @@ public class SynchronousQueue extends AbstractQueue * and don't wait at all, so are trapped in transfer * method rather than calling awaitFulfill. */ - long lastTime = (timed)? System.nanoTime() : 0; + long lastTime = timed ? System.nanoTime() : 0; Thread w = Thread.currentThread(); SNode h = head; - int spins = (shouldSpin(s)? - (timed? maxTimedSpins : maxUntimedSpins) : 0); + int spins = (shouldSpin(s) ? + (timed ? maxTimedSpins : maxUntimedSpins) : 0); for (;;) { if (w.isInterrupted()) s.tryCancel(); @@ -444,7 +441,7 @@ public class SynchronousQueue extends AbstractQueue } } if (spins > 0) - spins = shouldSpin(s)? (spins-1) : 0; + spins = shouldSpin(s) ? (spins-1) : 0; else if (s.waiter == null) s.waiter = w; // establish waiter so can park next iter else if (!timed) @@ -499,6 +496,12 @@ public class SynchronousQueue extends AbstractQueue p = n; } } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long headOffset = + objectFieldOffset(UNSAFE, "head", TransferStack.class); + } /** Dual Queue */ @@ -524,29 +527,21 @@ public class SynchronousQueue extends AbstractQueue this.isData = isData; } - static final AtomicReferenceFieldUpdater - nextUpdater = AtomicReferenceFieldUpdater.newUpdater - (QNode.class, QNode.class, "next"); - boolean casNext(QNode cmp, QNode val) { - return (next == cmp && - nextUpdater.compareAndSet(this, cmp, val)); + return next == cmp && + UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); } - static final AtomicReferenceFieldUpdater - itemUpdater = AtomicReferenceFieldUpdater.newUpdater - (QNode.class, Object.class, "item"); - boolean casItem(Object cmp, Object val) { - return (item == cmp && - itemUpdater.compareAndSet(this, cmp, val)); + return item == cmp && + UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val); } /** * Tries to cancel by CAS'ing ref to this as item. */ void tryCancel(Object cmp) { - itemUpdater.compareAndSet(this, cmp, this); + UNSAFE.compareAndSwapObject(this, itemOffset, cmp, this); } boolean isCancelled() { @@ -561,6 +556,13 @@ public class SynchronousQueue extends AbstractQueue boolean isOffList() { return next == this; } + + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long nextOffset = + objectFieldOffset(UNSAFE, "next", QNode.class); + private static final long itemOffset = + objectFieldOffset(UNSAFE, "item", QNode.class); } /** Head of queue */ @@ -580,41 +582,30 @@ public class SynchronousQueue extends AbstractQueue tail = h; } - static final AtomicReferenceFieldUpdater - headUpdater = AtomicReferenceFieldUpdater.newUpdater - (TransferQueue.class, QNode.class, "head"); - /** * Tries to cas nh as new head; if successful, unlink * old head's next node to avoid garbage retention. */ void advanceHead(QNode h, QNode nh) { - if (h == head && headUpdater.compareAndSet(this, h, nh)) + if (h == head && + UNSAFE.compareAndSwapObject(this, headOffset, h, nh)) h.next = h; // forget old next } - static final AtomicReferenceFieldUpdater - tailUpdater = AtomicReferenceFieldUpdater.newUpdater - (TransferQueue.class, QNode.class, "tail"); - /** * Tries to cas nt as new tail. */ void advanceTail(QNode t, QNode nt) { if (tail == t) - tailUpdater.compareAndSet(this, t, nt); + UNSAFE.compareAndSwapObject(this, tailOffset, t, nt); } - static final AtomicReferenceFieldUpdater - cleanMeUpdater = AtomicReferenceFieldUpdater.newUpdater - (TransferQueue.class, QNode.class, "cleanMe"); - /** * Tries to CAS cleanMe slot. */ boolean casCleanMe(QNode cmp, QNode val) { - return (cleanMe == cmp && - cleanMeUpdater.compareAndSet(this, cmp, val)); + return cleanMe == cmp && + UNSAFE.compareAndSwapObject(this, cleanMeOffset, cmp, val); } /** @@ -683,7 +674,7 @@ public class SynchronousQueue extends AbstractQueue s.item = s; s.waiter = null; } - return (x != null)? x : e; + return (x != null) ? x : e; } else { // complementary-mode QNode m = h.next; // node to fulfill @@ -700,7 +691,7 @@ public class SynchronousQueue extends AbstractQueue advanceHead(h, m); // successfully fulfilled LockSupport.unpark(m.waiter); - return (x != null)? x : e; + return (x != null) ? x : e; } } } @@ -716,10 +707,10 @@ public class SynchronousQueue extends AbstractQueue */ Object awaitFulfill(QNode s, Object e, boolean timed, long nanos) { /* Same idea as TransferStack.awaitFulfill */ - long lastTime = (timed)? System.nanoTime() : 0; + long lastTime = timed ? System.nanoTime() : 0; Thread w = Thread.currentThread(); int spins = ((head.next == s) ? - (timed? maxTimedSpins : maxUntimedSpins) : 0); + (timed ? maxTimedSpins : maxUntimedSpins) : 0); for (;;) { if (w.isInterrupted()) s.tryCancel(e); @@ -799,6 +790,16 @@ public class SynchronousQueue extends AbstractQueue return; // Postpone cleaning s } } + + // unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long headOffset = + objectFieldOffset(UNSAFE, "head", TransferQueue.class); + private static final long tailOffset = + objectFieldOffset(UNSAFE, "tail", TransferQueue.class); + private static final long cleanMeOffset = + objectFieldOffset(UNSAFE, "cleanMe", TransferQueue.class); + } /** @@ -824,7 +825,7 @@ public class SynchronousQueue extends AbstractQueue * access; otherwise the order is unspecified. */ public SynchronousQueue(boolean fair) { - transferer = (fair)? new TransferQueue() : new TransferStack(); + transferer = fair ? new TransferQueue() : new TransferStack(); } /** @@ -1141,4 +1142,17 @@ public class SynchronousQueue extends AbstractQueue transferer = new TransferStack(); } + // Unsafe mechanics + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, + String field, Class klazz) { + try { + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); + } catch (NoSuchFieldException e) { + // Convert Exception to corresponding Error + NoSuchFieldError error = new NoSuchFieldError(field); + error.initCause(e); + throw error; + } + } + } diff --git a/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java b/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java index bfd3b8381f8..841a5804430 100644 --- a/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java +++ b/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java @@ -1841,6 +1841,43 @@ public class ThreadPoolExecutor extends AbstractExecutorService { } } + /** + * Returns a string identifying this pool, as well as its state, + * including indications of run state and estimated worker and + * task counts. + * + * @return a string identifying this pool, as well as its state + */ + public String toString() { + long ncompleted; + int nworkers, nactive; + final ReentrantLock mainLock = this.mainLock; + mainLock.lock(); + try { + ncompleted = completedTaskCount; + nactive = 0; + nworkers = workers.size(); + for (Worker w : workers) { + ncompleted += w.completedTasks; + if (w.isLocked()) + ++nactive; + } + } finally { + mainLock.unlock(); + } + int c = ctl.get(); + String rs = (runStateLessThan(c, SHUTDOWN) ? "Running" : + (runStateAtLeast(c, TERMINATED) ? "Terminated" : + "Shutting down")); + return super.toString() + + "[" + rs + + ", pool size = " + nworkers + + ", active threads = " + nactive + + ", queued tasks = " + workQueue.size() + + ", completed tasks = " + ncompleted + + "]"; + } + /* Extension hooks */ /** @@ -1961,7 +1998,9 @@ public class ThreadPoolExecutor extends AbstractExecutorService { * @throws RejectedExecutionException always. */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { - throw new RejectedExecutionException(); + throw new RejectedExecutionException("Task " + r.toString() + + " rejected from " + + e.toString()); } } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java index 2a9b8a80db0..54b9488ab51 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java @@ -48,28 +48,37 @@ import java.util.*; public class AtomicIntegerArray implements java.io.Serializable { private static final long serialVersionUID = 2862133569453604235L; - // setup to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final int base = unsafe.arrayBaseOffset(int[].class); - private static final int scale = unsafe.arrayIndexScale(int[].class); + private static final int shift; private final int[] array; - private long rawIndex(int i) { + static { + int scale = unsafe.arrayIndexScale(int[].class); + if ((scale & (scale - 1)) != 0) + throw new Error("data type scale not a power of two"); + shift = 31 - Integer.numberOfLeadingZeros(scale); + } + + private long checkedByteOffset(int i) { if (i < 0 || i >= array.length) throw new IndexOutOfBoundsException("index " + i); - return base + (long) i * scale; + + return byteOffset(i); + } + + private static long byteOffset(int i) { + return ((long) i << shift) + base; } /** - * Creates a new AtomicIntegerArray of given length. + * Creates a new AtomicIntegerArray of the given length, with all + * elements initially zero. * * @param length the length of the array */ public AtomicIntegerArray(int length) { array = new int[length]; - // must perform at least one volatile write to conform to JMM - if (length > 0) - unsafe.putIntVolatile(array, rawIndex(0), 0); } /** @@ -80,17 +89,8 @@ public class AtomicIntegerArray implements java.io.Serializable { * @throws NullPointerException if array is null */ public AtomicIntegerArray(int[] array) { - if (array == null) - throw new NullPointerException(); - int length = array.length; - this.array = new int[length]; - if (length > 0) { - int last = length-1; - for (int i = 0; i < last; ++i) - this.array[i] = array[i]; - // Do the last write as volatile - unsafe.putIntVolatile(this.array, rawIndex(last), array[last]); - } + // Visibility guaranteed by final field guarantees + this.array = array.clone(); } /** @@ -109,7 +109,11 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the current value */ public final int get(int i) { - return unsafe.getIntVolatile(array, rawIndex(i)); + return getRaw(checkedByteOffset(i)); + } + + private int getRaw(long offset) { + return unsafe.getIntVolatile(array, offset); } /** @@ -119,7 +123,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @param newValue the new value */ public final void set(int i, int newValue) { - unsafe.putIntVolatile(array, rawIndex(i), newValue); + unsafe.putIntVolatile(array, checkedByteOffset(i), newValue); } /** @@ -130,7 +134,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @since 1.6 */ public final void lazySet(int i, int newValue) { - unsafe.putOrderedInt(array, rawIndex(i), newValue); + unsafe.putOrderedInt(array, checkedByteOffset(i), newValue); } /** @@ -142,9 +146,10 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the previous value */ public final int getAndSet(int i, int newValue) { + long offset = checkedByteOffset(i); while (true) { - int current = get(i); - if (compareAndSet(i, current, newValue)) + int current = getRaw(offset); + if (compareAndSetRaw(offset, current, newValue)) return current; } } @@ -160,8 +165,11 @@ public class AtomicIntegerArray implements java.io.Serializable { * the actual value was not equal to the expected value. */ public final boolean compareAndSet(int i, int expect, int update) { - return unsafe.compareAndSwapInt(array, rawIndex(i), - expect, update); + return compareAndSetRaw(checkedByteOffset(i), expect, update); + } + + private boolean compareAndSetRaw(long offset, int expect, int update) { + return unsafe.compareAndSwapInt(array, offset, expect, update); } /** @@ -188,12 +196,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the previous value */ public final int getAndIncrement(int i) { - while (true) { - int current = get(i); - int next = current + 1; - if (compareAndSet(i, current, next)) - return current; - } + return getAndAdd(i, 1); } /** @@ -203,12 +206,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the previous value */ public final int getAndDecrement(int i) { - while (true) { - int current = get(i); - int next = current - 1; - if (compareAndSet(i, current, next)) - return current; - } + return getAndAdd(i, -1); } /** @@ -219,10 +217,10 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the previous value */ public final int getAndAdd(int i, int delta) { + long offset = checkedByteOffset(i); while (true) { - int current = get(i); - int next = current + delta; - if (compareAndSet(i, current, next)) + int current = getRaw(offset); + if (compareAndSetRaw(offset, current, current + delta)) return current; } } @@ -234,12 +232,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the updated value */ public final int incrementAndGet(int i) { - while (true) { - int current = get(i); - int next = current + 1; - if (compareAndSet(i, current, next)) - return next; - } + return addAndGet(i, 1); } /** @@ -249,12 +242,7 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the updated value */ public final int decrementAndGet(int i) { - while (true) { - int current = get(i); - int next = current - 1; - if (compareAndSet(i, current, next)) - return next; - } + return addAndGet(i, -1); } /** @@ -265,22 +253,32 @@ public class AtomicIntegerArray implements java.io.Serializable { * @return the updated value */ public final int addAndGet(int i, int delta) { + long offset = checkedByteOffset(i); while (true) { - int current = get(i); + int current = getRaw(offset); int next = current + delta; - if (compareAndSet(i, current, next)) + if (compareAndSetRaw(offset, current, next)) return next; } } /** * Returns the String representation of the current values of array. - * @return the String representation of the current values of array. + * @return the String representation of the current values of array */ public String toString() { - if (array.length > 0) // force volatile read - get(0); - return Arrays.toString(array); + int iMax = array.length - 1; + if (iMax == -1) + return "[]"; + + StringBuilder b = new StringBuilder(); + b.append('['); + for (int i = 0; ; i++) { + b.append(getRaw(byteOffset(i))); + if (i == iMax) + return b.append(']').toString(); + b.append(',').append(' '); + } } } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java index d1f404ca69b..f1873c54d7a 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java @@ -47,28 +47,37 @@ import java.util.*; public class AtomicLongArray implements java.io.Serializable { private static final long serialVersionUID = -2308431214976778248L; - // setup to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final int base = unsafe.arrayBaseOffset(long[].class); - private static final int scale = unsafe.arrayIndexScale(long[].class); + private static final int shift; private final long[] array; - private long rawIndex(int i) { + static { + int scale = unsafe.arrayIndexScale(long[].class); + if ((scale & (scale - 1)) != 0) + throw new Error("data type scale not a power of two"); + shift = 31 - Integer.numberOfLeadingZeros(scale); + } + + private long checkedByteOffset(int i) { if (i < 0 || i >= array.length) throw new IndexOutOfBoundsException("index " + i); - return base + (long) i * scale; + + return byteOffset(i); + } + + private static long byteOffset(int i) { + return ((long) i << shift) + base; } /** - * Creates a new AtomicLongArray of given length. + * Creates a new AtomicLongArray of the given length, with all + * elements initially zero. * * @param length the length of the array */ public AtomicLongArray(int length) { array = new long[length]; - // must perform at least one volatile write to conform to JMM - if (length > 0) - unsafe.putLongVolatile(array, rawIndex(0), 0); } /** @@ -79,17 +88,8 @@ public class AtomicLongArray implements java.io.Serializable { * @throws NullPointerException if array is null */ public AtomicLongArray(long[] array) { - if (array == null) - throw new NullPointerException(); - int length = array.length; - this.array = new long[length]; - if (length > 0) { - int last = length-1; - for (int i = 0; i < last; ++i) - this.array[i] = array[i]; - // Do the last write as volatile - unsafe.putLongVolatile(this.array, rawIndex(last), array[last]); - } + // Visibility guaranteed by final field guarantees + this.array = array.clone(); } /** @@ -108,7 +108,11 @@ public class AtomicLongArray implements java.io.Serializable { * @return the current value */ public final long get(int i) { - return unsafe.getLongVolatile(array, rawIndex(i)); + return getRaw(checkedByteOffset(i)); + } + + private long getRaw(long offset) { + return unsafe.getLongVolatile(array, offset); } /** @@ -118,7 +122,7 @@ public class AtomicLongArray implements java.io.Serializable { * @param newValue the new value */ public final void set(int i, long newValue) { - unsafe.putLongVolatile(array, rawIndex(i), newValue); + unsafe.putLongVolatile(array, checkedByteOffset(i), newValue); } /** @@ -129,7 +133,7 @@ public class AtomicLongArray implements java.io.Serializable { * @since 1.6 */ public final void lazySet(int i, long newValue) { - unsafe.putOrderedLong(array, rawIndex(i), newValue); + unsafe.putOrderedLong(array, checkedByteOffset(i), newValue); } @@ -142,16 +146,17 @@ public class AtomicLongArray implements java.io.Serializable { * @return the previous value */ public final long getAndSet(int i, long newValue) { + long offset = checkedByteOffset(i); while (true) { - long current = get(i); - if (compareAndSet(i, current, newValue)) + long current = getRaw(offset); + if (compareAndSetRaw(offset, current, newValue)) return current; } } /** - * Atomically sets the value to the given updated value - * if the current value {@code ==} the expected value. + * Atomically sets the element at position {@code i} to the given + * updated value if the current value {@code ==} the expected value. * * @param i the index * @param expect the expected value @@ -160,13 +165,16 @@ public class AtomicLongArray implements java.io.Serializable { * the actual value was not equal to the expected value. */ public final boolean compareAndSet(int i, long expect, long update) { - return unsafe.compareAndSwapLong(array, rawIndex(i), - expect, update); + return compareAndSetRaw(checkedByteOffset(i), expect, update); + } + + private boolean compareAndSetRaw(long offset, long expect, long update) { + return unsafe.compareAndSwapLong(array, offset, expect, update); } /** - * Atomically sets the value to the given updated value - * if the current value {@code ==} the expected value. + * Atomically sets the element at position {@code i} to the given + * updated value if the current value {@code ==} the expected value. * *

May fail spuriously * and does not provide ordering guarantees, so is only rarely an @@ -188,12 +196,7 @@ public class AtomicLongArray implements java.io.Serializable { * @return the previous value */ public final long getAndIncrement(int i) { - while (true) { - long current = get(i); - long next = current + 1; - if (compareAndSet(i, current, next)) - return current; - } + return getAndAdd(i, 1); } /** @@ -203,12 +206,7 @@ public class AtomicLongArray implements java.io.Serializable { * @return the previous value */ public final long getAndDecrement(int i) { - while (true) { - long current = get(i); - long next = current - 1; - if (compareAndSet(i, current, next)) - return current; - } + return getAndAdd(i, -1); } /** @@ -219,10 +217,10 @@ public class AtomicLongArray implements java.io.Serializable { * @return the previous value */ public final long getAndAdd(int i, long delta) { + long offset = checkedByteOffset(i); while (true) { - long current = get(i); - long next = current + delta; - if (compareAndSet(i, current, next)) + long current = getRaw(offset); + if (compareAndSetRaw(offset, current, current + delta)) return current; } } @@ -234,12 +232,7 @@ public class AtomicLongArray implements java.io.Serializable { * @return the updated value */ public final long incrementAndGet(int i) { - while (true) { - long current = get(i); - long next = current + 1; - if (compareAndSet(i, current, next)) - return next; - } + return addAndGet(i, 1); } /** @@ -249,12 +242,7 @@ public class AtomicLongArray implements java.io.Serializable { * @return the updated value */ public final long decrementAndGet(int i) { - while (true) { - long current = get(i); - long next = current - 1; - if (compareAndSet(i, current, next)) - return next; - } + return addAndGet(i, -1); } /** @@ -265,22 +253,32 @@ public class AtomicLongArray implements java.io.Serializable { * @return the updated value */ public long addAndGet(int i, long delta) { + long offset = checkedByteOffset(i); while (true) { - long current = get(i); + long current = getRaw(offset); long next = current + delta; - if (compareAndSet(i, current, next)) + if (compareAndSetRaw(offset, current, next)) return next; } } /** * Returns the String representation of the current values of array. - * @return the String representation of the current values of array. + * @return the String representation of the current values of array */ public String toString() { - if (array.length > 0) // force volatile read - get(0); - return Arrays.toString(array); + int iMax = array.length - 1; + if (iMax == -1) + return "[]"; + + StringBuilder b = new StringBuilder(); + b.append('['); + for (int i = 0; ; i++) { + b.append(getRaw(byteOffset(i))); + if (i == iMax) + return b.append(']').toString(); + b.append(',').append(' '); + } } } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java index ca1ca6507a0..e898758f522 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java @@ -38,8 +38,8 @@ package java.util.concurrent.atomic; /** * An {@code AtomicMarkableReference} maintains an object reference * along with a mark bit, that can be updated atomically. - *

- *

Implementation note. This implementation maintains markable + * + *

Implementation note: This implementation maintains markable * references by creating internal objects representing "boxed" * [reference, boolean] pairs. * @@ -47,17 +47,21 @@ package java.util.concurrent.atomic; * @author Doug Lea * @param The type of object referred to by this reference */ -public class AtomicMarkableReference { +public class AtomicMarkableReference { - private static class ReferenceBooleanPair { - private final T reference; - private final boolean bit; - ReferenceBooleanPair(T r, boolean i) { - reference = r; bit = i; + private static class Pair { + final T reference; + final boolean mark; + private Pair(T reference, boolean mark) { + this.reference = reference; + this.mark = mark; + } + static Pair of(T reference, boolean mark) { + return new Pair(reference, mark); } } - private final AtomicReference> atomicRef; + private volatile Pair pair; /** * Creates a new {@code AtomicMarkableReference} with the given @@ -67,7 +71,7 @@ public class AtomicMarkableReference { * @param initialMark the initial mark */ public AtomicMarkableReference(V initialRef, boolean initialMark) { - atomicRef = new AtomicReference> (new ReferenceBooleanPair(initialRef, initialMark)); + pair = Pair.of(initialRef, initialMark); } /** @@ -76,7 +80,7 @@ public class AtomicMarkableReference { * @return the current value of the reference */ public V getReference() { - return atomicRef.get().reference; + return pair.reference; } /** @@ -85,7 +89,7 @@ public class AtomicMarkableReference { * @return the current value of the mark */ public boolean isMarked() { - return atomicRef.get().bit; + return pair.mark; } /** @@ -97,9 +101,9 @@ public class AtomicMarkableReference { * @return the current value of the reference */ public V get(boolean[] markHolder) { - ReferenceBooleanPair p = atomicRef.get(); - markHolder[0] = p.bit; - return p.reference; + Pair pair = this.pair; + markHolder[0] = pair.mark; + return pair.reference; } /** @@ -122,13 +126,8 @@ public class AtomicMarkableReference { V newReference, boolean expectedMark, boolean newMark) { - ReferenceBooleanPair current = atomicRef.get(); - return expectedReference == current.reference && - expectedMark == current.bit && - ((newReference == current.reference && newMark == current.bit) || - atomicRef.weakCompareAndSet(current, - new ReferenceBooleanPair(newReference, - newMark))); + return compareAndSet(expectedReference, newReference, + expectedMark, newMark); } /** @@ -147,13 +146,13 @@ public class AtomicMarkableReference { V newReference, boolean expectedMark, boolean newMark) { - ReferenceBooleanPair current = atomicRef.get(); - return expectedReference == current.reference && - expectedMark == current.bit && - ((newReference == current.reference && newMark == current.bit) || - atomicRef.compareAndSet(current, - new ReferenceBooleanPair(newReference, - newMark))); + Pair current = pair; + return + expectedReference == current.reference && + expectedMark == current.mark && + ((newReference == current.reference && + newMark == current.mark) || + casPair(current, Pair.of(newReference, newMark))); } /** @@ -163,9 +162,9 @@ public class AtomicMarkableReference { * @param newMark the new value for the mark */ public void set(V newReference, boolean newMark) { - ReferenceBooleanPair current = atomicRef.get(); - if (newReference != current.reference || newMark != current.bit) - atomicRef.set(new ReferenceBooleanPair(newReference, newMark)); + Pair current = pair; + if (newReference != current.reference || newMark != current.mark) + this.pair = Pair.of(newReference, newMark); } /** @@ -182,11 +181,32 @@ public class AtomicMarkableReference { * @return true if successful */ public boolean attemptMark(V expectedReference, boolean newMark) { - ReferenceBooleanPair current = atomicRef.get(); - return expectedReference == current.reference && - (newMark == current.bit || - atomicRef.compareAndSet - (current, new ReferenceBooleanPair(expectedReference, - newMark))); + Pair current = pair; + return + expectedReference == current.reference && + (newMark == current.mark || + casPair(current, Pair.of(expectedReference, newMark))); + } + + // Unsafe mechanics + + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long pairOffset = + objectFieldOffset(UNSAFE, "pair", AtomicMarkableReference.class); + + private boolean casPair(Pair cmp, Pair val) { + return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); + } + + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, + String field, Class klazz) { + try { + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); + } catch (NoSuchFieldException e) { + // Convert Exception to corresponding Error + NoSuchFieldError error = new NoSuchFieldError(field); + error.initCause(e); + throw error; + } } } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java index 6aca62c5cc7..b5fd65ab48f 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java @@ -51,24 +51,35 @@ public class AtomicReferenceArray implements java.io.Serializable { private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final int base = unsafe.arrayBaseOffset(Object[].class); - private static final int scale = unsafe.arrayIndexScale(Object[].class); + private static final int shift; private final Object[] array; - private long rawIndex(int i) { + static { + int scale = unsafe.arrayIndexScale(Object[].class); + if ((scale & (scale - 1)) != 0) + throw new Error("data type scale not a power of two"); + shift = 31 - Integer.numberOfLeadingZeros(scale); + } + + private long checkedByteOffset(int i) { if (i < 0 || i >= array.length) throw new IndexOutOfBoundsException("index " + i); - return base + (long) i * scale; + + return byteOffset(i); + } + + private static long byteOffset(int i) { + return ((long) i << shift) + base; } /** - * Creates a new AtomicReferenceArray of given length. + * Creates a new AtomicReferenceArray of the given length, with all + * elements initially null. + * * @param length the length of the array */ public AtomicReferenceArray(int length) { array = new Object[length]; - // must perform at least one volatile write to conform to JMM - if (length > 0) - unsafe.putObjectVolatile(array, rawIndex(0), null); } /** @@ -79,18 +90,8 @@ public class AtomicReferenceArray implements java.io.Serializable { * @throws NullPointerException if array is null */ public AtomicReferenceArray(E[] array) { - if (array == null) - throw new NullPointerException(); - int length = array.length; - this.array = new Object[length]; - if (length > 0) { - int last = length-1; - for (int i = 0; i < last; ++i) - this.array[i] = array[i]; - // Do the last write as volatile - E e = array[last]; - unsafe.putObjectVolatile(this.array, rawIndex(last), e); - } + // Visibility guaranteed by final field guarantees + this.array = array.clone(); } /** @@ -109,7 +110,11 @@ public class AtomicReferenceArray implements java.io.Serializable { * @return the current value */ public final E get(int i) { - return (E) unsafe.getObjectVolatile(array, rawIndex(i)); + return getRaw(checkedByteOffset(i)); + } + + private E getRaw(long offset) { + return (E) unsafe.getObjectVolatile(array, offset); } /** @@ -119,7 +124,7 @@ public class AtomicReferenceArray implements java.io.Serializable { * @param newValue the new value */ public final void set(int i, E newValue) { - unsafe.putObjectVolatile(array, rawIndex(i), newValue); + unsafe.putObjectVolatile(array, checkedByteOffset(i), newValue); } /** @@ -130,7 +135,7 @@ public class AtomicReferenceArray implements java.io.Serializable { * @since 1.6 */ public final void lazySet(int i, E newValue) { - unsafe.putOrderedObject(array, rawIndex(i), newValue); + unsafe.putOrderedObject(array, checkedByteOffset(i), newValue); } @@ -143,9 +148,10 @@ public class AtomicReferenceArray implements java.io.Serializable { * @return the previous value */ public final E getAndSet(int i, E newValue) { + long offset = checkedByteOffset(i); while (true) { - E current = get(i); - if (compareAndSet(i, current, newValue)) + E current = (E) getRaw(offset); + if (compareAndSetRaw(offset, current, newValue)) return current; } } @@ -153,6 +159,7 @@ public class AtomicReferenceArray implements java.io.Serializable { /** * Atomically sets the element at position {@code i} to the given * updated value if the current value {@code ==} the expected value. + * * @param i the index * @param expect the expected value * @param update the new value @@ -160,8 +167,11 @@ public class AtomicReferenceArray implements java.io.Serializable { * the actual value was not equal to the expected value. */ public final boolean compareAndSet(int i, E expect, E update) { - return unsafe.compareAndSwapObject(array, rawIndex(i), - expect, update); + return compareAndSetRaw(checkedByteOffset(i), expect, update); + } + + private boolean compareAndSetRaw(long offset, E expect, E update) { + return unsafe.compareAndSwapObject(array, offset, expect, update); } /** @@ -183,12 +193,21 @@ public class AtomicReferenceArray implements java.io.Serializable { /** * Returns the String representation of the current values of array. - * @return the String representation of the current values of array. + * @return the String representation of the current values of array */ public String toString() { - if (array.length > 0) // force volatile read - get(0); - return Arrays.toString(array); + int iMax = array.length - 1; + if (iMax == -1) + return "[]"; + + StringBuilder b = new StringBuilder(); + b.append('['); + for (int i = 0; ; i++) { + b.append(getRaw(byteOffset(i))); + if (i == iMax) + return b.append(']').toString(); + b.append(',').append(' '); + } } } diff --git a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java index 854c02c12a3..412eca36eb3 100644 --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java @@ -39,7 +39,7 @@ package java.util.concurrent.atomic; * An {@code AtomicStampedReference} maintains an object reference * along with an integer "stamp", that can be updated atomically. * - *

Implementation note. This implementation maintains stamped + *

Implementation note: This implementation maintains stamped * references by creating internal objects representing "boxed" * [reference, integer] pairs. * @@ -47,17 +47,21 @@ package java.util.concurrent.atomic; * @author Doug Lea * @param The type of object referred to by this reference */ -public class AtomicStampedReference { +public class AtomicStampedReference { - private static class ReferenceIntegerPair { - private final T reference; - private final int integer; - ReferenceIntegerPair(T r, int i) { - reference = r; integer = i; + private static class Pair { + final T reference; + final int stamp; + private Pair(T reference, int stamp) { + this.reference = reference; + this.stamp = stamp; + } + static Pair of(T reference, int stamp) { + return new Pair(reference, stamp); } } - private final AtomicReference> atomicRef; + private volatile Pair pair; /** * Creates a new {@code AtomicStampedReference} with the given @@ -67,8 +71,7 @@ public class AtomicStampedReference { * @param initialStamp the initial stamp */ public AtomicStampedReference(V initialRef, int initialStamp) { - atomicRef = new AtomicReference> - (new ReferenceIntegerPair(initialRef, initialStamp)); + pair = Pair.of(initialRef, initialStamp); } /** @@ -77,7 +80,7 @@ public class AtomicStampedReference { * @return the current value of the reference */ public V getReference() { - return atomicRef.get().reference; + return pair.reference; } /** @@ -86,7 +89,7 @@ public class AtomicStampedReference { * @return the current value of the stamp */ public int getStamp() { - return atomicRef.get().integer; + return pair.stamp; } /** @@ -98,9 +101,9 @@ public class AtomicStampedReference { * @return the current value of the reference */ public V get(int[] stampHolder) { - ReferenceIntegerPair p = atomicRef.get(); - stampHolder[0] = p.integer; - return p.reference; + Pair pair = this.pair; + stampHolder[0] = pair.stamp; + return pair.reference; } /** @@ -119,18 +122,12 @@ public class AtomicStampedReference { * @param newStamp the new value for the stamp * @return true if successful */ - public boolean weakCompareAndSet(V expectedReference, - V newReference, - int expectedStamp, - int newStamp) { - ReferenceIntegerPair current = atomicRef.get(); - return expectedReference == current.reference && - expectedStamp == current.integer && - ((newReference == current.reference && - newStamp == current.integer) || - atomicRef.weakCompareAndSet(current, - new ReferenceIntegerPair(newReference, - newStamp))); + public boolean weakCompareAndSet(V expectedReference, + V newReference, + int expectedStamp, + int newStamp) { + return compareAndSet(expectedReference, newReference, + expectedStamp, newStamp); } /** @@ -145,18 +142,17 @@ public class AtomicStampedReference { * @param newStamp the new value for the stamp * @return true if successful */ - public boolean compareAndSet(V expectedReference, - V newReference, - int expectedStamp, - int newStamp) { - ReferenceIntegerPair current = atomicRef.get(); - return expectedReference == current.reference && - expectedStamp == current.integer && + public boolean compareAndSet(V expectedReference, + V newReference, + int expectedStamp, + int newStamp) { + Pair current = pair; + return + expectedReference == current.reference && + expectedStamp == current.stamp && ((newReference == current.reference && - newStamp == current.integer) || - atomicRef.compareAndSet(current, - new ReferenceIntegerPair(newReference, - newStamp))); + newStamp == current.stamp) || + casPair(current, Pair.of(newReference, newStamp))); } @@ -167,9 +163,9 @@ public class AtomicStampedReference { * @param newStamp the new value for the stamp */ public void set(V newReference, int newStamp) { - ReferenceIntegerPair current = atomicRef.get(); - if (newReference != current.reference || newStamp != current.integer) - atomicRef.set(new ReferenceIntegerPair(newReference, newStamp)); + Pair current = pair; + if (newReference != current.reference || newStamp != current.stamp) + this.pair = Pair.of(newReference, newStamp); } /** @@ -186,11 +182,32 @@ public class AtomicStampedReference { * @return true if successful */ public boolean attemptStamp(V expectedReference, int newStamp) { - ReferenceIntegerPair current = atomicRef.get(); - return expectedReference == current.reference && - (newStamp == current.integer || - atomicRef.compareAndSet(current, - new ReferenceIntegerPair(expectedReference, - newStamp))); + Pair current = pair; + return + expectedReference == current.reference && + (newStamp == current.stamp || + casPair(current, Pair.of(expectedReference, newStamp))); + } + + // Unsafe mechanics + + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long pairOffset = + objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class); + + private boolean casPair(Pair cmp, Pair val) { + return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val); + } + + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, + String field, Class klazz) { + try { + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); + } catch (NoSuchFieldException e) { + // Convert Exception to corresponding Error + NoSuchFieldError error = new NoSuchFieldError(field); + error.initCause(e); + throw error; + } } } diff --git a/jdk/src/share/classes/java/util/concurrent/locks/Condition.java b/jdk/src/share/classes/java/util/concurrent/locks/Condition.java index c1774bc25dd..f3fb607a47e 100644 --- a/jdk/src/share/classes/java/util/concurrent/locks/Condition.java +++ b/jdk/src/share/classes/java/util/concurrent/locks/Condition.java @@ -308,18 +308,21 @@ public interface Condition { * condition still does not hold. Typical uses of this method take * the following form: * - *

-     * synchronized boolean aMethod(long timeout, TimeUnit unit) {
-     *   long nanosTimeout = unit.toNanos(timeout);
-     *   while (!conditionBeingWaitedFor) {
-     *     if (nanosTimeout > 0)
-     *         nanosTimeout = theCondition.awaitNanos(nanosTimeout);
-     *      else
-     *        return false;
+     *  
 {@code
+     * boolean aMethod(long timeout, TimeUnit unit) {
+     *   long nanos = unit.toNanos(timeout);
+     *   lock.lock();
+     *   try {
+     *     while (!conditionBeingWaitedFor()) {
+     *       if (nanos <= 0L)
+     *         return false;
+     *       nanos = theCondition.awaitNanos(nanos);
+     *     }
+     *     // ...
+     *   } finally {
+     *     lock.unlock();
      *   }
-     *   // ...
-     * }
-     * 
+ * }}
* *

Design note: This method requires a nanosecond argument so * as to avoid truncation errors in reporting remaining times. @@ -408,18 +411,21 @@ public interface Condition { * *

The return value indicates whether the deadline has elapsed, * which can be used as follows: - *

-     * synchronized boolean aMethod(Date deadline) {
+     *  
 {@code
+     * boolean aMethod(Date deadline) {
      *   boolean stillWaiting = true;
-     *   while (!conditionBeingWaitedFor) {
-     *     if (stillWaiting)
-     *         stillWaiting = theCondition.awaitUntil(deadline);
-     *      else
-     *        return false;
+     *   lock.lock();
+     *   try {
+     *     while (!conditionBeingWaitedFor()) {
+     *       if (!stillWaiting)
+     *         return false;
+     *       stillWaiting = theCondition.awaitUntil(deadline);
+     *     }
+     *     // ...
+     *   } finally {
+     *     lock.unlock();
      *   }
-     *   // ...
-     * }
-     * 
+ * }}
* *

Implementation Considerations * @@ -450,6 +456,15 @@ public interface Condition { *

If any threads are waiting on this condition then one * is selected for waking up. That thread must then re-acquire the * lock before returning from {@code await}. + * + *

Implementation Considerations + * + *

An implementation may (and typically does) require that the + * current thread hold the lock associated with this {@code + * Condition} when this method is called. Implementations must + * document this precondition and any actions taken if the lock is + * not held. Typically, an exception such as {@link + * IllegalMonitorStateException} will be thrown. */ void signal(); @@ -459,6 +474,15 @@ public interface Condition { *

If any threads are waiting on this condition then they are * all woken up. Each thread must re-acquire the lock before it can * return from {@code await}. + * + *

Implementation Considerations + * + *

An implementation may (and typically does) require that the + * current thread hold the lock associated with this {@code + * Condition} when this method is called. Implementations must + * document this precondition and any actions taken if the lock is + * not held. Typically, an exception such as {@link + * IllegalMonitorStateException} will be thrown. */ void signalAll(); } diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 365de2bc17b..ced686efd87 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -734,8 +734,8 @@ java/util/concurrent/locks/Lock/TimedAcquireLeak.java generic-all # Fails on solaris-sparc -server (Set not equal to copy. 1) java/util/EnumSet/EnumSetBash.java solaris-sparc -# Need to be marked othervm, or changed to be samevm safe -java/util/WeakHashMap/GCDuringIteration.java generic-all +# Fails on solaris-sparc, see 7011857 +java/util/concurrent/Phaser/FickleRegister.java solaris-sparc ############################################################################ diff --git a/jdk/test/java/util/WeakHashMap/GCDuringIteration.java b/jdk/test/java/util/WeakHashMap/GCDuringIteration.java index 938322b7db2..482d04426ca 100644 --- a/jdk/test/java/util/WeakHashMap/GCDuringIteration.java +++ b/jdk/test/java/util/WeakHashMap/GCDuringIteration.java @@ -33,18 +33,17 @@ import java.util.*; import java.util.concurrent.CountDownLatch; public class GCDuringIteration { - static void finalizeTillYouDrop() { - System.gc(); // Enqueue all finalizables + private static void waitForFinalizersToRun() { + for (int i = 0; i < 2; i++) + tryWaitForFinalizersToRun(); + } - System.runFinalization(); // Drain finalizer queue - - // There may be a straggler finalizable object still being - // finalized by the dedicated finalizer thread. Enqueue one - // more finalizable object, and wait for it to be finalized. - final CountDownLatch latch = new CountDownLatch(1); - new Object() { protected void finalize() { latch.countDown(); }}; + private static void tryWaitForFinalizersToRun() { System.gc(); - try { latch.await(); } + final CountDownLatch fin = new CountDownLatch(1); + new Object() { protected void finalize() { fin.countDown(); }}; + System.gc(); + try { fin.await(); } catch (InterruptedException ie) { throw new Error(ie); } } @@ -101,7 +100,9 @@ public class GCDuringIteration { { int first = firstValue(map); final Iterator> it = map.entrySet().iterator(); - foos[first] = null; finalizeTillYouDrop(); + foos[first] = null; + for (int i = 0; i < 10 && map.size() != first; i++) + tryWaitForFinalizersToRun(); equal(map.size(), first); checkIterator(it, first-1); equal(map.size(), first); @@ -113,11 +114,14 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.next(); // protects first entry System.out.println(map.values()); - foos[first] = null; finalizeTillYouDrop(); + foos[first] = null; + tryWaitForFinalizersToRun() equal(map.size(), first+1); System.out.println(map.values()); checkIterator(it, first-1); - finalizeTillYouDrop(); // first entry no longer protected + // first entry no longer protected + for (int i = 0; i < 10 && map.size() != first; i++) + tryWaitForFinalizersToRun(); equal(map.size(), first); equal(firstValue(map), first-1); } @@ -127,12 +131,15 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.next(); // protects first entry System.out.println(map.values()); - foos[first] = foos[first-1] = null; finalizeTillYouDrop(); + foos[first] = foos[first-1] = null; + tryWaitForFinalizersToRun(); equal(map.size(), first); equal(firstValue(map), first); System.out.println(map.values()); checkIterator(it, first-2); - finalizeTillYouDrop(); // first entry no longer protected + // first entry no longer protected + for (int i = 0; i < 10 && map.size() != first-1; i++) + tryWaitForFinalizersToRun(); equal(map.size(), first-1); equal(firstValue(map), first-2); } @@ -143,12 +150,15 @@ public class GCDuringIteration { it.next(); // protects first entry it.hasNext(); // protects second entry System.out.println(map.values()); - foos[first] = foos[first-1] = null; finalizeTillYouDrop(); + foos[first] = foos[first-1] = null; + tryWaitForFinalizersToRun(); equal(firstValue(map), first); equal(map.size(), first+1); System.out.println(map.values()); checkIterator(it, first-1); - finalizeTillYouDrop(); // first entry no longer protected + // first entry no longer protected + for (int i = 0; i < 10 && map.size() != first-1; i++) + tryWaitForFinalizersToRun(); equal(map.size(), first-1); equal(firstValue(map), first-2); } @@ -158,13 +168,16 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.next(); // protects first entry System.out.println(map.values()); - foos[first] = foos[first-1] = null; finalizeTillYouDrop(); + foos[first] = foos[first-1] = null; + tryWaitForFinalizersToRun(); it.remove(); equal(firstValue(map), first-2); equal(map.size(), first-1); System.out.println(map.values()); checkIterator(it, first-2); - finalizeTillYouDrop(); + // first entry no longer protected + for (int i = 0; i < 10 && map.size() != first-1; i++) + tryWaitForFinalizersToRun(); equal(map.size(), first-1); equal(firstValue(map), first-2); } @@ -176,12 +189,14 @@ public class GCDuringIteration { it.remove(); it.hasNext(); // protects second entry System.out.println(map.values()); - foos[first] = foos[first-1] = null; finalizeTillYouDrop(); + foos[first] = foos[first-1] = null; + tryWaitForFinalizersToRun(); equal(firstValue(map), first-1); equal(map.size(), first); System.out.println(map.values()); checkIterator(it, first-1); - finalizeTillYouDrop(); + for (int i = 0; i < 10 && map.size() != first-1; i++) + tryWaitForFinalizersToRun(); equal(map.size(), first-1); equal(firstValue(map), first-2); } @@ -191,12 +206,13 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.hasNext(); // protects first entry Arrays.fill(foos, null); - finalizeTillYouDrop(); + tryWaitForFinalizersToRun(); equal(map.size(), 1); System.out.println(map.values()); equal(it.next().getValue(), first); check(! it.hasNext()); - finalizeTillYouDrop(); + for (int i = 0; i < 10 && map.size() != 0; i++) + tryWaitForFinalizersToRun(); equal(map.size(), 0); check(map.isEmpty()); } diff --git a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java index c12a57ec708..34f0722d8bd 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java @@ -34,7 +34,7 @@ /* * @test * @bug 4486658 - * @compile CancelledProducerConsumerLoops.java + * @compile -source 1.5 CancelledProducerConsumerLoops.java * @run main/timeout=7000 CancelledProducerConsumerLoops * @summary Checks for responsiveness of blocking queues to cancellation. * Runs under the assumption that ITERS computations require more than @@ -119,48 +119,24 @@ public class CancelledProducerConsumerLoops { } } - static final class LTQasSQ extends LinkedTransferQueue { - LTQasSQ() { super(); } - public void put(T x) { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - private final static long serialVersionUID = 42; - } - - static final class HalfSyncLTQ extends LinkedTransferQueue { - HalfSyncLTQ() { super(); } - public void put(T x) { - if (ThreadLocalRandom.current().nextBoolean()) - super.put(x); - else { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - } - private final static long serialVersionUID = 42; - } - static void oneTest(int pairs, int iters) throws Exception { oneRun(new ArrayBlockingQueue(CAPACITY), pairs, iters); oneRun(new LinkedBlockingQueue(CAPACITY), pairs, iters); oneRun(new LinkedBlockingDeque(CAPACITY), pairs, iters); + oneRun(new LinkedTransferQueue(), pairs, iters); oneRun(new SynchronousQueue(), pairs, iters / 8); - /* TODO: unbounded queue implementations are prone to OOME + /* PriorityBlockingQueue is unbounded oneRun(new PriorityBlockingQueue(iters / 2 * pairs), pairs, iters / 4); - oneRun(new LinkedTransferQueue(), pairs, iters); - oneRun(new LTQasSQ(), pairs, iters); - oneRun(new HalfSyncLTQ(), pairs, iters); */ } - static abstract class Stage implements Callable { + abstract static class Stage implements Callable { final BlockingQueue queue; final CyclicBarrier barrier; final int iters; - Stage (BlockingQueue q, CyclicBarrier b, int iters) { + Stage(BlockingQueue q, CyclicBarrier b, int iters) { queue = q; barrier = b; this.iters = iters; diff --git a/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java index 1f85c511e59..d57939fc374 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java @@ -34,7 +34,7 @@ /* * @test * @bug 4486658 - * @compile MultipleProducersSingleConsumerLoops.java + * @compile -source 1.5 MultipleProducersSingleConsumerLoops.java * @run main/timeout=3600 MultipleProducersSingleConsumerLoops * @summary multiple producers and single consumer using blocking queues */ @@ -87,35 +87,11 @@ public class MultipleProducersSingleConsumerLoops { throw new Error(); } - static final class LTQasSQ extends LinkedTransferQueue { - LTQasSQ() { super(); } - public void put(T x) { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - private final static long serialVersionUID = 42; - } - - static final class HalfSyncLTQ extends LinkedTransferQueue { - HalfSyncLTQ() { super(); } - public void put(T x) { - if (ThreadLocalRandom.current().nextBoolean()) - super.put(x); - else { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - } - private final static long serialVersionUID = 42; - } - static void oneTest(int producers, int iters) throws Exception { oneRun(new ArrayBlockingQueue(CAPACITY), producers, iters); oneRun(new LinkedBlockingQueue(CAPACITY), producers, iters); oneRun(new LinkedBlockingDeque(CAPACITY), producers, iters); oneRun(new LinkedTransferQueue(), producers, iters); - oneRun(new LTQasSQ(), producers, iters); - oneRun(new HalfSyncLTQ(), producers, iters); // Don't run PBQ since can legitimately run out of memory // if (print) @@ -129,11 +105,11 @@ public class MultipleProducersSingleConsumerLoops { oneRun(new ArrayBlockingQueue(CAPACITY, true), producers, iters); } - static abstract class Stage implements Runnable { + abstract static class Stage implements Runnable { final int iters; final BlockingQueue queue; final CyclicBarrier barrier; - Stage (BlockingQueue q, CyclicBarrier b, int iters) { + Stage(BlockingQueue q, CyclicBarrier b, int iters) { queue = q; barrier = b; this.iters = iters; diff --git a/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java index f2b4a5b334d..9f18ab53c89 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java @@ -34,7 +34,7 @@ /* * @test * @bug 4486658 - * @compile ProducerConsumerLoops.java + * @compile -source 1.5 ProducerConsumerLoops.java * @run main/timeout=3600 ProducerConsumerLoops * @summary multiple producers and consumers using blocking queues */ @@ -87,35 +87,11 @@ public class ProducerConsumerLoops { throw new Error(); } - static final class LTQasSQ extends LinkedTransferQueue { - LTQasSQ() { super(); } - public void put(T x) { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - private final static long serialVersionUID = 42; - } - - static final class HalfSyncLTQ extends LinkedTransferQueue { - HalfSyncLTQ() { super(); } - public void put(T x) { - if (ThreadLocalRandom.current().nextBoolean()) - super.put(x); - else { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - } - private final static long serialVersionUID = 42; - } - static void oneTest(int pairs, int iters) throws Exception { oneRun(new ArrayBlockingQueue(CAPACITY), pairs, iters); oneRun(new LinkedBlockingQueue(CAPACITY), pairs, iters); oneRun(new LinkedBlockingDeque(CAPACITY), pairs, iters); oneRun(new LinkedTransferQueue(), pairs, iters); - oneRun(new LTQasSQ(), pairs, iters); - oneRun(new HalfSyncLTQ(), pairs, iters); oneRun(new PriorityBlockingQueue(), pairs, iters); oneRun(new SynchronousQueue(), pairs, iters); @@ -126,11 +102,11 @@ public class ProducerConsumerLoops { oneRun(new ArrayBlockingQueue(CAPACITY, true), pairs, iters); } - static abstract class Stage implements Runnable { + abstract static class Stage implements Runnable { final int iters; final BlockingQueue queue; final CyclicBarrier barrier; - Stage (BlockingQueue q, CyclicBarrier b, int iters) { + Stage(BlockingQueue q, CyclicBarrier b, int iters) { queue = q; barrier = b; this.iters = iters; diff --git a/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java index 1550bb22277..85699bc7d56 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java @@ -34,7 +34,7 @@ /* * @test * @bug 4486658 - * @compile SingleProducerMultipleConsumerLoops.java + * @compile -source 1.5 SingleProducerMultipleConsumerLoops.java * @run main/timeout=600 SingleProducerMultipleConsumerLoops * @summary check ordering for blocking queues with 1 producer and multiple consumers */ @@ -73,35 +73,11 @@ public class SingleProducerMultipleConsumerLoops { throw new Error(); } - static final class LTQasSQ extends LinkedTransferQueue { - LTQasSQ() { super(); } - public void put(T x) { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - private final static long serialVersionUID = 42; - } - - static final class HalfSyncLTQ extends LinkedTransferQueue { - HalfSyncLTQ() { super(); } - public void put(T x) { - if (ThreadLocalRandom.current().nextBoolean()) - super.put(x); - else { - try { super.transfer(x); } - catch (InterruptedException ex) { throw new Error(); } - } - } - private final static long serialVersionUID = 42; - } - static void oneTest(int consumers, int iters) throws Exception { oneRun(new ArrayBlockingQueue(CAPACITY), consumers, iters); oneRun(new LinkedBlockingQueue(CAPACITY), consumers, iters); oneRun(new LinkedBlockingDeque(CAPACITY), consumers, iters); oneRun(new LinkedTransferQueue(), consumers, iters); - oneRun(new LTQasSQ(), consumers, iters); - oneRun(new HalfSyncLTQ(), consumers, iters); oneRun(new PriorityBlockingQueue(), consumers, iters); oneRun(new SynchronousQueue(), consumers, iters); if (print) @@ -110,12 +86,12 @@ public class SingleProducerMultipleConsumerLoops { oneRun(new ArrayBlockingQueue(CAPACITY, true), consumers, iters); } - static abstract class Stage implements Runnable { + abstract static class Stage implements Runnable { final int iters; final BlockingQueue queue; final CyclicBarrier barrier; volatile int result; - Stage (BlockingQueue q, CyclicBarrier b, int iters) { + Stage(BlockingQueue q, CyclicBarrier b, int iters) { queue = q; barrier = b; this.iters = iters; diff --git a/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java index 78ce8d71194..dabb2b9de2a 100644 --- a/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java +++ b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java @@ -53,7 +53,9 @@ public class IteratorWeakConsistency { test(new LinkedTransferQueue()); // Other concurrent queues (e.g. ArrayBlockingQueue) do not // currently have weakly consistent iterators. - // test(new ArrayBlockingQueue(20)); + // As of 2010-09, ArrayBlockingQueue passes this test, but + // does not fully implement weak consistency. + test(new ArrayBlockingQueue(20)); } void test(Queue q) { diff --git a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java index e6f7c1a3d5a..fb4976ff878 100644 --- a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java +++ b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java @@ -24,6 +24,7 @@ /* * @test * @bug 6399443 + * @run main/othervm AutoShutdown * @summary Check for auto-shutdown and gc of singleThreadExecutors * @author Martin Buchholz */ diff --git a/jdk/test/java/util/concurrent/Phaser/Basic.java b/jdk/test/java/util/concurrent/Phaser/Basic.java index e394cee94f6..a358873c2ec 100644 --- a/jdk/test/java/util/concurrent/Phaser/Basic.java +++ b/jdk/test/java/util/concurrent/Phaser/Basic.java @@ -52,15 +52,16 @@ public class Basic { check(phaser.isTerminated()); int unarriverParties = phaser.getUnarrivedParties(); int registeredParties = phaser.getRegisteredParties(); - equal(phaser.arrive(), -1); - equal(phaser.arriveAndDeregister(), -1); - equal(phaser.arriveAndAwaitAdvance(), -1); - equal(phaser.bulkRegister(10), -1); - equal(phaser.getPhase(), -1); - equal(phaser.register(), -1); + int phase = phaser.getPhase(); + check(phase < 0); + equal(phase, phaser.arrive()); + equal(phase, phaser.arriveAndDeregister()); + equal(phase, phaser.arriveAndAwaitAdvance()); + equal(phase, phaser.bulkRegister(10)); + equal(phase, phaser.register()); try { - equal(phaser.awaitAdvanceInterruptibly(0), -1); - equal(phaser.awaitAdvanceInterruptibly(0, 10, SECONDS), -1); + equal(phase, phaser.awaitAdvanceInterruptibly(0)); + equal(phase, phaser.awaitAdvanceInterruptibly(0, 10, SECONDS)); } catch (Exception ie) { unexpected(ie); } @@ -94,10 +95,9 @@ public class Basic { } int phase = atTheStartingGate.getPhase(); equal(phase, atTheStartingGate.arrive()); - int AwaitPhase = atTheStartingGate.awaitAdvanceInterruptibly(phase, - 10, - SECONDS); - if (expectNextPhase) check(AwaitPhase == (phase + 1)); + int awaitPhase = atTheStartingGate.awaitAdvanceInterruptibly + (phase, 10, SECONDS); + if (expectNextPhase) check(awaitPhase == (phase + 1)); pass(); } catch (Throwable t) { @@ -271,18 +271,19 @@ public class Basic { // Phaser is terminated while threads are waiting //---------------------------------------------------------------- try { - Phaser phaser = new Phaser(3); - Iterator awaiters = awaiterIterator(phaser); for (int i = 0; i < 4; i++) { + Phaser phaser = new Phaser(3); + Iterator awaiters = awaiterIterator(phaser); Arriver a1 = awaiters.next(); a1.start(); Arriver a2 = awaiters.next(); a2.start(); toTheStartingGate(); while (phaser.getArrivedParties() < 2) Thread.yield(); + equal(0, phaser.getPhase()); phaser.forceTermination(); a1.join(); a2.join(); - check(a1.phase == -1); - check(a2.phase == -1); + equal(0 + Integer.MIN_VALUE, a1.phase); + equal(0 + Integer.MIN_VALUE, a2.phase); int arrivedParties = phaser.getArrivedParties(); checkTerminated(phaser); equal(phaser.getArrivedParties(), arrivedParties); diff --git a/jdk/test/java/util/concurrent/Phaser/FickleRegister.java b/jdk/test/java/util/concurrent/Phaser/FickleRegister.java new file mode 100644 index 00000000000..9ce91c5de44 --- /dev/null +++ b/jdk/test/java/util/concurrent/Phaser/FickleRegister.java @@ -0,0 +1,150 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain + */ + +/* + * @test + * @summary stress test for register/arriveAndDeregister + * @run main FickleRegister 300 + */ + +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.*; + +public class FickleRegister { + final AtomicLong count = new AtomicLong(0); + final long testDurationMillisDefault = 10L * 1000L; + final long testDurationMillis; + final long quittingTimeNanos; + final int chunkSize = 1000; + + FickleRegister(String[] args) { + testDurationMillis = (args.length > 0) ? + Long.valueOf(args[0]) : testDurationMillisDefault; + quittingTimeNanos = System.nanoTime() + + testDurationMillis * 1000L * 1000L; + } + + class Runner extends CheckedRunnable { + final Phaser p; + Runner(Phaser phaser) { p = phaser; } + public void realRun() { + int prevPhase = -1; + for (int k = 1;; k++) { + for (int i = 0; i < chunkSize; i++) { + int phase = p.register(); + if (phase < 0) break; + check(phase > prevPhase); + prevPhase = phase; + equal(phase, p.arriveAndDeregister()); + check(phase < p.awaitAdvance(phase)); + } + if (System.nanoTime() - quittingTimeNanos > 0) { + count.getAndAdd(k * chunkSize); + break; + } + } + } + } + + void test(String[] args) throws Throwable { + final Phaser parent = new Phaser() { + protected boolean onAdvance(int phase, int parties) { + return false; + } + }; + + final Phaser child1 = new Phaser(parent); + final Phaser child2 = new Phaser(parent); + final Phaser subchild1 = new Phaser(child1); + final Phaser subchild2 = new Phaser(child2); + final Phaser[] phasers = { + parent, child1, child2, subchild1, subchild2 + }; + + int reps = 4; + ArrayList threads = new ArrayList(); + for (int j = 0; j < reps; ++j) { + threads.add(new Thread(new Runner(subchild1))); + threads.add(new Thread(new Runner(child1))); + threads.add(new Thread(new Runner(parent))); + threads.add(new Thread(new Runner(child2))); + threads.add(new Thread(new Runner(subchild2))); + } + + for (Thread thread : threads) + thread.start(); + + for (Thread thread : threads) + thread.join(); + + System.out.println("Parent: " + parent); + System.out.println("Child1: " + child1); + System.out.println("Child2: " + child2); + System.out.println("Subchild1: " + subchild1); + System.out.println("Subchild2: " + subchild2); + System.out.println("Iterations:" + count.get()); + + for (Phaser phaser : phasers) { + check(phaser.getPhase() > 0); + equal(0, phaser.getRegisteredParties()); + equal(0, phaser.getUnarrivedParties()); + equal(parent.getPhase(), phaser.getPhase()); + } + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new FickleRegister(args).instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + + abstract class CheckedRunnable implements Runnable { + protected abstract void realRun() throws Throwable; + + public final void run() { + try {realRun();} catch (Throwable t) {unexpected(t);} + } + } +} diff --git a/jdk/test/java/util/concurrent/Phaser/PhaseOverflow.java b/jdk/test/java/util/concurrent/Phaser/PhaseOverflow.java new file mode 100644 index 00000000000..da8b5367072 --- /dev/null +++ b/jdk/test/java/util/concurrent/Phaser/PhaseOverflow.java @@ -0,0 +1,158 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Martin Buchholz and Doug Lea with assistance from + * members of JCP JSR-166 Expert Group and released to the public + * domain, as explained at + * http://creativecommons.org/licenses/publicdomain + */ + +/* + * @test + * @summary Test Phaser phase integer overflow behavior + */ + +import java.util.concurrent.Phaser; +import java.lang.reflect.Field; + +public class PhaseOverflow { + Field stateField; + + void checkState(Phaser phaser, + int phase, int parties, int unarrived) { + equal(phase, phaser.getPhase()); + equal(parties, phaser.getRegisteredParties()); + equal(unarrived, phaser.getUnarrivedParties()); + } + + void test(String[] args) throws Throwable { + stateField = Phaser.class.getDeclaredField("state"); + stateField.setAccessible(true); + testLeaf(); + testTiered(); + } + + void testLeaf() throws Throwable { + Phaser phaser = new Phaser(); + // this is extremely dependent on internal representation + stateField.setLong(phaser, ((Integer.MAX_VALUE - 1L) << 32) | 1L); + checkState(phaser, Integer.MAX_VALUE - 1, 0, 0); + phaser.register(); + checkState(phaser, Integer.MAX_VALUE - 1, 1, 1); + phaser.arrive(); + checkState(phaser, Integer.MAX_VALUE, 1, 1); + phaser.arrive(); + checkState(phaser, 0, 1, 1); + phaser.arrive(); + checkState(phaser, 1, 1, 1); + } + + int phaseInc(int phase) { return (phase + 1) & Integer.MAX_VALUE; } + + void testTiered() throws Throwable { + Phaser root = new Phaser(); + // this is extremely dependent on internal representation + stateField.setLong(root, ((Integer.MAX_VALUE - 1L) << 32) | 1L); + checkState(root, Integer.MAX_VALUE - 1, 0, 0); + Phaser p1 = new Phaser(root, 1); + checkState(root, Integer.MAX_VALUE - 1, 1, 1); + checkState(p1, Integer.MAX_VALUE - 1, 1, 1); + Phaser p2 = new Phaser(root, 2); + checkState(root, Integer.MAX_VALUE - 1, 2, 2); + checkState(p2, Integer.MAX_VALUE - 1, 2, 2); + int ph = Integer.MAX_VALUE - 1; + for (int k = 0; k < 5; k++) { + checkState(root, ph, 2, 2); + checkState(p1, ph, 1, 1); + checkState(p2, ph, 2, 2); + p1.arrive(); + checkState(root, ph, 2, 1); + checkState(p1, ph, 1, 0); + checkState(p2, ph, 2, 2); + p2.arrive(); + checkState(root, ph, 2, 1); + checkState(p1, ph, 1, 0); + checkState(p2, ph, 2, 1); + p2.arrive(); + ph = phaseInc(ph); + checkState(root, ph, 2, 2); + checkState(p1, ph, 1, 1); + checkState(p2, ph, 2, 2); + } + equal(3, ph); + } + + void xtestTiered() throws Throwable { + Phaser root = new Phaser(); + stateField.setLong(root, ((Integer.MAX_VALUE - 1L) << 32) | 1L); + checkState(root, Integer.MAX_VALUE - 1, 0, 0); + Phaser p1 = new Phaser(root, 1); + checkState(root, Integer.MAX_VALUE - 1, 1, 1); + checkState(p1, Integer.MAX_VALUE - 1, 1, 1); + Phaser p2 = new Phaser(root, 2); + checkState(root, Integer.MAX_VALUE - 1, 2, 2); + checkState(p2, Integer.MAX_VALUE - 1, 2, 2); + int ph = Integer.MAX_VALUE - 1; + for (int k = 0; k < 5; k++) { + checkState(root, ph, 2, 2); + checkState(p1, ph, 1, 1); + checkState(p2, ph, 2, 2); + p1.arrive(); + checkState(root, ph, 2, 1); + checkState(p1, ph, 1, 0); + checkState(p2, ph, 2, 2); + p2.arrive(); + checkState(root, ph, 2, 1); + checkState(p1, ph, 1, 0); + checkState(p2, ph, 2, 1); + p2.arrive(); + ph = phaseInc(ph); + checkState(root, ph, 2, 2); + checkState(p1, ph, 1, 1); + checkState(p2, ph, 2, 2); + } + equal(3, ph); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new PhaseOverflow().instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/jdk/test/java/util/concurrent/Phaser/TieredArriveLoops.java b/jdk/test/java/util/concurrent/Phaser/TieredArriveLoops.java new file mode 100644 index 00000000000..33a03f08dab --- /dev/null +++ b/jdk/test/java/util/concurrent/Phaser/TieredArriveLoops.java @@ -0,0 +1,117 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain + */ + +/* + * @test + * @summary stress test for arrivals in a tiered phaser + * @run main TieredArriveLoops 300 + */ +import java.util.*; +import java.util.concurrent.*; + +public class TieredArriveLoops { + final long testDurationMillisDefault = 10L * 1000L; + final long testDurationMillis; + final long quittingTimeNanos; + + TieredArriveLoops(String[] args) { + testDurationMillis = (args.length > 0) ? + Long.valueOf(args[0]) : testDurationMillisDefault; + quittingTimeNanos = System.nanoTime() + + testDurationMillis * 1000L * 1000L; + } + + Runnable runner(final Phaser p) { + return new CheckedRunnable() { public void realRun() { + int prevPhase = p.register(); + while (!p.isTerminated()) { + int phase = p.awaitAdvance(p.arrive()); + if (phase < 0) + return; + equal(phase, (prevPhase + 1) & Integer.MAX_VALUE); + int ph = p.getPhase(); + check(ph < 0 || ph == phase); + prevPhase = phase; + } + }}; + } + + void test(String[] args) throws Throwable { + final Phaser parent = new Phaser(); + final Phaser child1 = new Phaser(parent); + final Phaser child2 = new Phaser(parent); + + Thread t1 = new Thread(runner(child1)); + Thread t2 = new Thread(runner(child2)); + t1.start(); + t2.start(); + + for (int prevPhase = 0, phase; ; prevPhase = phase) { + phase = child2.getPhase(); + check(phase >= prevPhase); + if (System.nanoTime() - quittingTimeNanos > 0) { + System.err.printf("phase=%d%n", phase); + child1.forceTermination(); + break; + } + } + + t1.join(); + t2.join(); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new TieredArriveLoops(args).instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + + abstract class CheckedRunnable implements Runnable { + protected abstract void realRun() throws Throwable; + + public final void run() { + try {realRun();} catch (Throwable t) {unexpected(t);} + } + } +} diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java index 6bd37fe7035..547cd2130f0 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java @@ -31,47 +31,79 @@ import java.util.concurrent.*; public class CoreThreadTimeOut { - static volatile int passed = 0, failed = 0; - static void pass() { passed++; } - static void fail() { failed++; Thread.dumpStack(); } - static void unexpected(Throwable t) { failed++; t.printStackTrace(); } - static void check(boolean cond) { if (cond) pass(); else fail(); } - static void equal(Object x, Object y) { - if (x == null ? y == null : x.equals(y)) pass(); - else {System.out.println(x + " not equal to " + y); fail(); }} - static int countExecutorThreads() { + static class IdentifiableThreadFactory implements ThreadFactory { + static ThreadFactory defaultThreadFactory + = Executors.defaultThreadFactory(); + + public Thread newThread(Runnable r) { + Thread t = defaultThreadFactory.newThread(r); + t.setName("CoreThreadTimeOut-" + t.getName()); + return t; + } + } + + int countExecutorThreads() { Thread[] threads = new Thread[Thread.activeCount()+100]; Thread.enumerate(threads); int count = 0; for (Thread t : threads) - if (t != null && t.getName().matches("pool-[0-9]+-thread-[0-9]+")) + if (t != null && + t.getName().matches + ("CoreThreadTimeOut-pool-[0-9]+-thread-[0-9]+")) count++; return count; } - public static void main(String[] args) throws Throwable { + long millisElapsedSince(long t0) { + return (System.nanoTime() - t0) / (1000L * 1000L); + } + + void test(String[] args) throws Throwable { final int threadCount = 10; + final int timeoutMillis = 30; BlockingQueue q = new ArrayBlockingQueue(2*threadCount); ThreadPoolExecutor tpe = new ThreadPoolExecutor(threadCount, threadCount, - 30, TimeUnit.MILLISECONDS, - q); + timeoutMillis, TimeUnit.MILLISECONDS, + q, new IdentifiableThreadFactory()); equal(tpe.getCorePoolSize(), threadCount); check(! tpe.allowsCoreThreadTimeOut()); tpe.allowCoreThreadTimeOut(true); check(tpe.allowsCoreThreadTimeOut()); equal(countExecutorThreads(), 0); + long t0 = System.nanoTime(); for (int i = 0; i < threadCount; i++) tpe.submit(new Runnable() { public void run() {}}); - equal(countExecutorThreads(), threadCount); - Thread.sleep(500); + int count = countExecutorThreads(); + if (millisElapsedSince(t0) < timeoutMillis) + equal(count, threadCount); + while (countExecutorThreads() > 0 && + millisElapsedSince(t0) < 10 * 1000); equal(countExecutorThreads(), 0); tpe.shutdown(); check(tpe.allowsCoreThreadTimeOut()); + check(tpe.awaitTermination(10, TimeUnit.SECONDS)); System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new Exception("Some tests failed"); } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new CoreThreadTimeOut().instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} } From 058b35d369d7bde44c9bfea0aa70a6533bbe19db Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Wed, 12 Jan 2011 15:05:10 +0000 Subject: [PATCH 033/152] 6829919: URLClassLoader.close() doesn't close resource file if getResourceAsStream(...) was called before Reviewed-by: chegar --- .../classes/java/net/URLClassLoader.java | 115 ++++++++++++++---- .../URLClassLoader/closetest/CloseTest.java | 89 +------------- .../net/URLClassLoader/closetest/Common.java | 115 ++++++++++++++++++ .../closetest/GetResourceAsStream.java | 108 ++++++++++++++++ .../net/URLClassLoader/closetest/build2.sh | 58 +++++++++ 5 files changed, 373 insertions(+), 112 deletions(-) create mode 100644 jdk/test/java/net/URLClassLoader/closetest/Common.java create mode 100644 jdk/test/java/net/URLClassLoader/closetest/GetResourceAsStream.java create mode 100644 jdk/test/java/net/URLClassLoader/closetest/build2.sh diff --git a/jdk/src/share/classes/java/net/URLClassLoader.java b/jdk/src/share/classes/java/net/URLClassLoader.java index 00b8abc76dd..70dc45585fb 100644 --- a/jdk/src/share/classes/java/net/URLClassLoader.java +++ b/jdk/src/share/classes/java/net/URLClassLoader.java @@ -27,19 +27,15 @@ package java.net; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.io.File; -import java.io.FilePermission; -import java.io.InputStream; -import java.io.IOException; -import java.io.Closeable; +import java.lang.ref.*; +import java.io.*; import java.net.URL; import java.net.URLConnection; import java.net.URLStreamHandlerFactory; import java.util.Enumeration; -import java.util.List; -import java.util.NoSuchElementException; -import java.util.StringTokenizer; +import java.util.*; import java.util.jar.Manifest; +import java.util.jar.JarFile; import java.util.jar.Attributes; import java.util.jar.Attributes.Name; import java.security.CodeSigner; @@ -194,6 +190,65 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { acc = AccessController.getContext(); } + /* A map (used as a set) to keep track of closeable local resources + * (either JarFiles or FileInputStreams). We don't care about + * Http resources since they don't need to be closed. + * + * If the resource is coming from a jar file + * we keep a (weak) reference to the JarFile object which can + * be closed if URLClassLoader.close() called. Due to jar file + * caching there will typically be only one JarFile object + * per underlying jar file. + * + * For file resources, which is probably a less common situation + * we have to keep a weak reference to each stream. + */ + + private WeakHashMap + closeables = new WeakHashMap<>(); + + /** + * Returns an input stream for reading the specified resource. + * If this loader is closed, then any resources opened by this method + * will be closed. + * + *

The search order is described in the documentation for {@link + * #getResource(String)}.

+ * + * @param name + * The resource name + * + * @return An input stream for reading the resource, or null + * if the resource could not be found + * + * @since 1.7 + */ + public InputStream getResourceAsStream(String name) { + URL url = getResource(name); + try { + if (url == null) { + return null; + } + URLConnection urlc = url.openConnection(); + InputStream is = urlc.getInputStream(); + if (urlc instanceof JarURLConnection) { + JarURLConnection juc = (JarURLConnection)urlc; + JarFile jar = juc.getJarFile(); + synchronized (closeables) { + if (!closeables.containsKey(jar)) { + closeables.put(jar, null); + } + } + } else if (urlc instanceof sun.net.www.protocol.file.FileURLConnection) { + synchronized (closeables) { + closeables.put(is, null); + } + } + return is; + } catch (IOException e) { + return null; + } + } /** * Closes this URLClassLoader, so that it can no longer be used to load @@ -202,8 +257,8 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { * delegation hierarchy are still accessible. Also, any classes or resources * that are already loaded, are still accessible. *

- * In the case of jar: and file: URLs, it also closes any class files, - * or JAR files that were opened by it. If another thread is loading a + * In the case of jar: and file: URLs, it also closes any files + * that were opened by it. If another thread is loading a * class when the {@code close} method is invoked, then the result of * that load is undefined. *

@@ -213,10 +268,10 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { * loader has no effect. *

* @throws IOException if closing any file opened by this class loader - * resulted in an IOException. Any such exceptions are caught, and a - * single IOException is thrown after the last file has been closed. - * If only one exception was thrown, it will be set as the cause - * of this IOException. + * resulted in an IOException. Any such exceptions are caught internally. + * If only one is caught, then it is re-thrown. If more than one exception + * is caught, then the second and following exceptions are added + * as suppressed exceptions of the first one caught, which is then re-thrown. * * @throws SecurityException if a security manager is set, and it denies * {@link RuntimePermission}("closeClassLoader") @@ -229,21 +284,33 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { security.checkPermission(new RuntimePermission("closeClassLoader")); } List errors = ucp.closeLoaders(); + + // now close any remaining streams. + + synchronized (closeables) { + Set keys = closeables.keySet(); + for (Closeable c : keys) { + try { + c.close(); + } catch (IOException ioex) { + errors.add(ioex); + } + } + closeables.clear(); + } + if (errors.isEmpty()) { return; } - if (errors.size() == 1) { - throw new IOException ( - "Error closing URLClassLoader resource", - errors.get(0) - ); - } - // Several exceptions. So, just combine the error messages - String errormsg = "Error closing resources: "; + + IOException firstex = errors.remove(0); + + // Suppress any remaining exceptions + for (IOException error: errors) { - errormsg = errormsg + "[" + error.toString() + "] "; + firstex.addSuppressed(error); } - throw new IOException (errormsg); + throw firstex; } /** diff --git a/jdk/test/java/net/URLClassLoader/closetest/CloseTest.java b/jdk/test/java/net/URLClassLoader/closetest/CloseTest.java index 20937085958..fcd8b6b1363 100644 --- a/jdk/test/java/net/URLClassLoader/closetest/CloseTest.java +++ b/jdk/test/java/net/URLClassLoader/closetest/CloseTest.java @@ -36,94 +36,7 @@ import java.net.*; import java.lang.reflect.*; import com.sun.net.httpserver.*; -public class CloseTest { - - static void copyFile (String src, String dst) { - copyFile (new File(src), new File(dst)); - } - - static void copyDir (String src, String dst) { - copyDir (new File(src), new File(dst)); - } - - static void copyFile (File src, File dst) { - try { - if (!src.isFile()) { - throw new RuntimeException ("File not found: " + src.toString()); - } - dst.delete(); - dst.createNewFile(); - FileInputStream i = new FileInputStream (src); - FileOutputStream o = new FileOutputStream (dst); - byte[] buf = new byte [1024]; - int count; - while ((count=i.read(buf)) >= 0) { - o.write (buf, 0, count); - } - i.close(); - o.close(); - } catch (IOException e) { - throw new RuntimeException (e); - } - } - - static void rm_minus_rf (File path) { - if (!path.exists()) { - return; - } - if (path.isFile()) { - if (!path.delete()) { - throw new RuntimeException ("Could not delete " + path); - } - } else if (path.isDirectory ()) { - String[] names = path.list(); - File[] files = path.listFiles(); - for (int i=0; i= 0) { + o.write (buf, 0, count); + } + i.close(); + o.close(); + } catch (IOException e) { + throw new RuntimeException (e); + } + } + + static void rm_minus_rf (File path) { + if (!path.exists()) { + return; + } + if (path.isFile()) { + if (!path.delete()) { + throw new RuntimeException ("Could not delete " + path); + } + } else if (path.isDirectory ()) { + String[] names = path.list(); + File[] files = path.listFiles(); + for (int i=0; i ${TESTCLASSES}/test3/hello.txt +echo "Bye world" > ${TESTCLASSES}/test3/bye.txt +cp ${TESTSRC}/test1/com/foo/TestClass.java ${TESTCLASSES}/test3 +cd ${TESTCLASSES}/test3 +${JAVAC} -d . TestClass.java + +${JAR} cvf foo.jar hello.txt bye.txt com/foo/TestClass.class +rm -f ../foo.jar +mv foo.jar .. From b6d2068ee206af0a6032915cb167355f60965d7e Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Wed, 12 Jan 2011 15:44:16 +0000 Subject: [PATCH 034/152] 6994753: Implement optional hook to a Java method at VM startup Reviewed-by: mchung, acorn --- .../share/vm/classfile/systemDictionary.hpp | 4 +++- hotspot/src/share/vm/classfile/vmSymbols.hpp | 3 ++- hotspot/src/share/vm/prims/jvm.h | 5 +++-- hotspot/src/share/vm/runtime/arguments.cpp | 6 ++---- hotspot/src/share/vm/runtime/java.cpp | 5 +++-- hotspot/src/share/vm/runtime/java.hpp | 13 ++++++++---- hotspot/src/share/vm/runtime/thread.cpp | 21 +++++++++++++++++++ 7 files changed, 43 insertions(+), 14 deletions(-) diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp index a83c8d55120..9dc5b933f80 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.hpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -172,6 +172,8 @@ class SymbolPropertyTable; \ template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \ \ + template(sun_misc_PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt) \ + \ /* Preload boxing klasses */ \ template(Boolean_klass, java_lang_Boolean, Pre) \ template(Character_klass, java_lang_Character, Pre) \ diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index 59168b8c544..6a9ef12a525 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -111,6 +111,7 @@ template(sun_jkernel_DownloadManager, "sun/jkernel/DownloadManager") \ template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \ template(setBootClassLoaderHook_name, "setBootClassLoaderHook") \ + template(sun_misc_PostVMInitHook, "sun/misc/PostVMInitHook") \ \ /* class file format tags */ \ template(tag_source_file, "SourceFile") \ diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index 1c5000af4eb..ec8ca4049a6 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -1649,7 +1649,8 @@ typedef struct { * the new bit is also added in the main/baseline. */ unsigned int thread_park_blocker : 1; - unsigned int : 31; + unsigned int post_vm_init_hook_enabled : 1; + unsigned int : 30; unsigned int : 32; unsigned int : 32; } jdk_version_info; diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 09b41b5b0b1..b106d08fc60 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -918,9 +918,7 @@ bool Arguments::add_property(const char* prop) { } else if (strcmp(key, "sun.java.command") == 0) { _java_command = value; - // don't add this property to the properties exposed to the java application - FreeHeap(key); - return true; + // Record value in Arguments, but let it get passed to Java. } else if (strcmp(key, "sun.java.launcher.pid") == 0) { // launcher.pid property is private and is processed // in process_sun_java_launcher_properties(); diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index f6b20a7b79e..42cfd6a0018 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -663,7 +663,8 @@ void JDK_Version::initialize() { } _current = JDK_Version(major, minor, micro, info.update_version, info.special_update_version, build, - info.thread_park_blocker == 1); + info.thread_park_blocker == 1, + info.post_vm_init_hook_enabled == 1); } } diff --git a/hotspot/src/share/vm/runtime/java.hpp b/hotspot/src/share/vm/runtime/java.hpp index b6062da448b..aabc63116c1 100644 --- a/hotspot/src/share/vm/runtime/java.hpp +++ b/hotspot/src/share/vm/runtime/java.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,6 +92,7 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC { bool _partially_initialized; bool _thread_park_blocker; + bool _post_vm_init_hook_enabled; bool is_valid() const { return (_major != 0 || _partially_initialized); @@ -113,14 +114,15 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC { JDK_Version() : _major(0), _minor(0), _micro(0), _update(0), _special(0), _build(0), _partially_initialized(false), - _thread_park_blocker(false) {} + _thread_park_blocker(false), _post_vm_init_hook_enabled(false) {} JDK_Version(uint8_t major, uint8_t minor = 0, uint8_t micro = 0, uint8_t update = 0, uint8_t special = 0, uint8_t build = 0, - bool thread_park_blocker = false) : + bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false) : _major(major), _minor(minor), _micro(micro), _update(update), _special(special), _build(build), _partially_initialized(false), - _thread_park_blocker(thread_park_blocker) {} + _thread_park_blocker(thread_park_blocker), + _post_vm_init_hook_enabled(post_vm_init_hook_enabled) {} // Returns the current running JDK version static JDK_Version current() { return _current; } @@ -144,6 +146,9 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC { bool supports_thread_park_blocker() const { return _thread_park_blocker; } + bool post_vm_init_hook_enabled() const { + return _post_vm_init_hook_enabled; + } // Performs a full ordering comparison using all fields (update, build, etc.) int compare(const JDK_Version& other) const; diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index ee26bf4ac2e..0349c658495 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -978,6 +978,19 @@ static void set_jkernel_boot_classloader_hook(TRAPS) { } #endif // KERNEL +// General purpose hook into Java code, run once when the VM is initialized. +// The Java library method itself may be changed independently from the VM. +static void call_postVMInitHook(TRAPS) { + klassOop k = SystemDictionary::sun_misc_PostVMInitHook_klass(); + instanceKlassHandle klass (THREAD, k); + if (klass.not_null()) { + JavaValue result(T_VOID); + JavaCalls::call_static(&result, klass, vmSymbolHandles::run_method_name(), + vmSymbolHandles::void_method_signature(), + CHECK); + } +} + static void reset_vm_info_property(TRAPS) { // the vm info string ResourceMark rm(THREAD); @@ -3346,6 +3359,14 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { BiasedLocking::init(); + if (JDK_Version::current().post_vm_init_hook_enabled()) { + call_postVMInitHook(THREAD); + // The Java side of PostVMInitHook.run must deal with all + // exceptions and provide means of diagnosis. + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + } + } // Start up the WatcherThread if there are any periodic tasks // NOTE: All PeriodicTasks should be registered by now. If they From 8867f6b29823704312740f5c3bc8b46c9f151814 Mon Sep 17 00:00:00 2001 From: Keith McGuigan Date: Wed, 12 Jan 2011 11:47:35 -0500 Subject: [PATCH 035/152] 6436034: Instance filter doesn't filter event if it occurs in native method Use 'GetLocalInstance' JVMTI extension if it exists Reviewed-by: coleenp, dcubed --- jdk/src/share/back/debugInit.c | 65 +++++++--- jdk/src/share/back/eventFilter.c | 44 ++++++- jdk/src/share/instrument/JPLISAgent.c | 4 +- jdk/src/share/javavm/export/jvmti.h | 18 ++- .../com/sun/jdi/NativeInstanceFilter.java | 122 ++++++++++++++++++ .../com/sun/jdi/NativeInstanceFilterTarg.java | 56 ++++++++ 6 files changed, 284 insertions(+), 25 deletions(-) create mode 100644 jdk/test/com/sun/jdi/NativeInstanceFilter.java create mode 100644 jdk/test/com/sun/jdi/NativeInstanceFilterTarg.java diff --git a/jdk/src/share/back/debugInit.c b/jdk/src/share/back/debugInit.c index e09971b0a06..39c6ad53fba 100644 --- a/jdk/src/share/back/debugInit.c +++ b/jdk/src/share/back/debugInit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -133,27 +133,60 @@ set_event_notification(jvmtiEventMode mode, EventIndex ei) return error; } +typedef struct { + int major; + int minor; +} version_type; + +typedef struct { + version_type runtime; + version_type compiletime; +} compatible_versions_type; + +/* + * List of explicitly compatible JVMTI versions, specified as + * { runtime version, compile-time version } pairs. -1 is a wildcard. + */ +static int nof_compatible_versions = 3; +static compatible_versions_type compatible_versions_list[] = { + /* + * FIXUP: Allow version 0 to be compatible with anything + * Special check for FCS of 1.0. + */ + { { 0, -1 }, { -1, -1 } }, + { { -1, -1 }, { 0, -1 } }, + /* + * 1.2 is runtime compatible with 1.1 -- just make sure to check the + * version before using any new 1.2 features + */ + { { 1, 1 }, { 1, 2 } } +}; + + /* Logic to determine JVMTI version compatibility */ static jboolean compatible_versions(jint major_runtime, jint minor_runtime, jint major_compiletime, jint minor_compiletime) { -#if 1 /* FIXUP: We allow version 0 to be compatible with anything */ - /* Special check for FCS of 1.0. */ - if ( major_runtime == 0 || major_compiletime == 0 ) { - return JNI_TRUE; + /* + * First check to see if versions are explicitly compatible via the + * list specified above. + */ + int i; + for (i = 0; i < nof_compatible_versions; ++i) { + version_type runtime = compatible_versions_list[i].runtime; + version_type comptime = compatible_versions_list[i].compiletime; + + if ((major_runtime == runtime.major || runtime.major == -1) && + (minor_runtime == runtime.minor || runtime.minor == -1) && + (major_compiletime == comptime.major || comptime.major == -1) && + (minor_compiletime == comptime.minor || comptime.minor == -1)) { + return JNI_TRUE; + } } -#endif - /* Runtime major version must match. */ - if ( major_runtime != major_compiletime ) { - return JNI_FALSE; - } - /* Runtime minor version must be >= the version compiled with. */ - if ( minor_runtime < minor_compiletime ) { - return JNI_FALSE; - } - /* Assumed compatible */ - return JNI_TRUE; + + return major_runtime == major_compiletime && + minor_runtime >= minor_compiletime; } /* OnLoad startup: diff --git a/jdk/src/share/back/eventFilter.c b/jdk/src/share/back/eventFilter.c index b0c2bd19b98..3d816d37019 100644 --- a/jdk/src/share/back/eventFilter.c +++ b/jdk/src/share/back/eventFilter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ #include "stepControl.h" #include "threadControl.h" #include "SDE.h" +#include "jvmti.h" typedef struct ClassFilter { jclass clazz; @@ -275,6 +276,24 @@ patternStringMatch(char *classname, const char *pattern) } } +static jboolean isVersionGte12x() { + jint version; + jvmtiError err = + JVMTI_FUNC_PTR(gdata->jvmti,GetVersionNumber)(gdata->jvmti, &version); + + if (err == JVMTI_ERROR_NONE) { + jint major, minor; + + major = (version & JVMTI_VERSION_MASK_MAJOR) + >> JVMTI_VERSION_SHIFT_MAJOR; + minor = (version & JVMTI_VERSION_MASK_MINOR) + >> JVMTI_VERSION_SHIFT_MINOR; + return (major > 1 || major == 1 && minor >= 2); + } else { + return JNI_FALSE; + } +} + /* Return the object instance in which the event occurred */ /* Return NULL if static or if an error occurs */ static jobject @@ -286,6 +305,14 @@ eventInstance(EventInfo *evinfo) jint modifiers = 0; jvmtiError error; + static jboolean got_version = JNI_FALSE; + static jboolean is_version_gte_12x = JNI_FALSE; + + if (!got_version) { + is_version_gte_12x = isVersionGte12x(); + got_version = JNI_TRUE; + } + switch (evinfo->ei) { case EI_SINGLE_STEP: case EI_BREAKPOINT: @@ -314,11 +341,18 @@ eventInstance(EventInfo *evinfo) /* fail if error or static (0x8) */ if (error == JVMTI_ERROR_NONE && thread!=NULL && (modifiers & 0x8) == 0) { FrameNumber fnum = 0; - /* get slot zero object "this" */ - error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject) - (gdata->jvmti, thread, fnum, 0, &object); - if (error != JVMTI_ERROR_NONE) + if (is_version_gte_12x) { + /* Use new 1.2.x function, GetLocalInstance */ + error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInstance) + (gdata->jvmti, thread, fnum, &object); + } else { + /* get slot zero object "this" */ + error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject) + (gdata->jvmti, thread, fnum, 0, &object); + } + if (error != JVMTI_ERROR_NONE) { object = NULL; + } } return object; diff --git a/jdk/src/share/instrument/JPLISAgent.c b/jdk/src/share/instrument/JPLISAgent.c index adc9cf13355..7f6b2a0b67c 100644 --- a/jdk/src/share/instrument/JPLISAgent.c +++ b/jdk/src/share/instrument/JPLISAgent.c @@ -209,7 +209,7 @@ createNewJPLISAgent(JavaVM * vm, JPLISAgent **agent_ptr) { *agent_ptr = NULL; jnierror = (*vm)->GetEnv( vm, (void **) &jvmtienv, - JVMTI_VERSION); + JVMTI_VERSION_1_1); if ( jnierror != JNI_OK ) { initerror = JPLIS_INIT_ERROR_CANNOT_CREATE_NATIVE_AGENT; } else { @@ -990,7 +990,7 @@ retransformableEnvironment(JPLISAgent * agent) { } jnierror = (*agent->mJVM)->GetEnv( agent->mJVM, (void **) &retransformerEnv, - JVMTI_VERSION); + JVMTI_VERSION_1_1); if ( jnierror != JNI_OK ) { return NULL; } diff --git a/jdk/src/share/javavm/export/jvmti.h b/jdk/src/share/javavm/export/jvmti.h index c235f16376b..7e9f2216b55 100644 --- a/jdk/src/share/javavm/export/jvmti.h +++ b/jdk/src/share/javavm/export/jvmti.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,8 +41,9 @@ enum { JVMTI_VERSION_1 = 0x30010000, JVMTI_VERSION_1_0 = 0x30010000, JVMTI_VERSION_1_1 = 0x30010100, + JVMTI_VERSION_1_2 = 0x30010200, - JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (1 * 0x100) + 102 /* version: 1.1.102 */ + JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (2 * 0x100) + 1 /* version: 1.2.1 */ }; JNIEXPORT jint JNICALL @@ -1774,6 +1775,12 @@ typedef struct jvmtiInterface_1_ { jobject object, jlong* size_ptr); + /* 155 : Get Local Instance */ + jvmtiError (JNICALL *GetLocalInstance) (jvmtiEnv* env, + jthread thread, + jint depth, + jobject* value_ptr); + } jvmtiInterface_1; struct _jvmtiEnv { @@ -2031,6 +2038,12 @@ struct _jvmtiEnv { return functions->GetLocalObject(this, thread, depth, slot, value_ptr); } + jvmtiError GetLocalInstance(jthread thread, + jint depth, + jobject* value_ptr) { + return functions->GetLocalInstance(this, thread, depth, value_ptr); + } + jvmtiError GetLocalInt(jthread thread, jint depth, jint slot, @@ -2518,3 +2531,4 @@ struct _jvmtiEnv { #endif /* __cplusplus */ #endif /* !_JAVA_JVMTI_H_ */ + diff --git a/jdk/test/com/sun/jdi/NativeInstanceFilter.java b/jdk/test/com/sun/jdi/NativeInstanceFilter.java new file mode 100644 index 00000000000..90e714e6889 --- /dev/null +++ b/jdk/test/com/sun/jdi/NativeInstanceFilter.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6426034 + * @summary Instance filter doesn't filter event if it occurs in native method + * + * @author Keith McGuigan + * + * @library scaffold + * @run build JDIScaffold VMConnection + * @compile -XDignore.symbol.file NativeInstanceFilterTarg.java + * @run main/othervm NativeInstanceFilter + */ + +/* + * This test tests instance filters for events generated from a native method + */ + +import java.util.*; +import com.sun.jdi.*; +import com.sun.jdi.event.*; +import com.sun.jdi.request.*; + +public class NativeInstanceFilter extends JDIScaffold { + + static int unfilteredEvents = 0; + + public static void main(String args[]) throws Exception { + new NativeInstanceFilter().startTests(); + } + + public NativeInstanceFilter() { + super(); + } + + static EventRequestManager requestManager = null; + static MethodExitRequest request = null; + + private void listen() { + TargetAdapter adapter = new TargetAdapter() { + EventSet set = null; + ObjectReference instance = null; + + public boolean eventSetReceived(EventSet set) { + this.set = set; + return false; + } + + public boolean methodExited(MethodExitEvent event) { + String name = event.method().name(); + if (instance == null && name.equals("latch")) { + // Grab the instance (return value) and set up as filter + System.out.println("Setting up instance filter"); + instance = (ObjectReference)event.returnValue(); + requestManager.deleteEventRequest(request); + request = requestManager.createMethodExitRequest(); + request.addInstanceFilter(instance); + request.enable(); + } else if (instance != null && name.equals("intern")) { + // If not for the filter, this will be called twice + System.out.println("method exit event (String.intern())"); + ++unfilteredEvents; + } + set.resume(); + return false; + } + }; + addListener(adapter); + } + + + protected void runTests() throws Exception { + String[] args = new String[2]; + args[0] = "-connect"; + args[1] = "com.sun.jdi.CommandLineLaunch:main=NativeInstanceFilterTarg"; + + connect(args); + waitForVMStart(); + + // VM has started, but hasn't started running the test program yet. + requestManager = vm().eventRequestManager(); + ReferenceType referenceType = + resumeToPrepareOf("NativeInstanceFilterTarg").referenceType(); + + request = requestManager.createMethodExitRequest(); + request.enable(); + + listen(); + + vm().resume(); + + waitForVMDeath(); + + if (unfilteredEvents != 1) { + throw new Exception( + "Failed: Event from native frame not filtered out."); + } + System.out.println("Passed: Event filtered out."); + } +} diff --git a/jdk/test/com/sun/jdi/NativeInstanceFilterTarg.java b/jdk/test/com/sun/jdi/NativeInstanceFilterTarg.java new file mode 100644 index 00000000000..48a21b43aba --- /dev/null +++ b/jdk/test/com/sun/jdi/NativeInstanceFilterTarg.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.misc.Version; + +public class NativeInstanceFilterTarg { + + public static void main(String args[]) { + boolean runTest = jvmSupportsJVMTI_12x(); + String s1 = "abc"; + String s2 = "def"; + latch(s1); + s1.intern(); + if (runTest) { + s2.intern(); // this is the call that generates events that ought + // to be filtered out. + } else { + System.out.println("Neutering test since JVMTI 1.2 not supported"); + } + } + + // Used by debugger to get an instance to filter with + public static String latch(String s) { return s; } + + public static boolean jvmSupportsJVMTI_12x() { + // This fix requires the JVM to support JVMTI 1.2, which doesn't + // happen until HSX 20.0, build 05. + int major = Version.jvmMajorVersion(); + int minor = Version.jvmMinorVersion(); + int micro = Version.jvmMicroVersion(); + int build = Version.jvmBuildNumber(); + + return (major > 20 || major == 20 && + (minor > 0 || micro > 0 || build >= 5)); + } +} From 5f21cb1b9b98f0589f6347805588599751afc827 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Wed, 12 Jan 2011 13:06:00 -0500 Subject: [PATCH 036/152] 7007068: G1: refine the BOT during evac failure handling During evacuation failure handling we refine the BOT to reflect the location of all the objects in the regions we scan. The changeset includes some minor cleanup: a) non-product print_on() method on the G1 BOT class, b) added more complete BOT verification during heap / region verification, c) slight modification to the BOT set up for humongous regions to be more consistent with the BOT set up during evac failure handling, and d) removed a couple of unused methods. Reviewed-by: johnc, ysr --- .../g1/g1BlockOffsetTable.cpp | 116 +++++------ .../g1/g1BlockOffsetTable.hpp | 19 +- .../gc_implementation/g1/g1CollectedHeap.cpp | 37 ++-- .../gc_implementation/g1/g1CollectedHeap.hpp | 3 +- .../vm/gc_implementation/g1/heapRegion.cpp | 190 +++++++++++------- .../vm/gc_implementation/g1/heapRegion.hpp | 49 ++++- .../vm/gc_implementation/g1/heapRegionSeq.cpp | 4 +- 7 files changed, 249 insertions(+), 169 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp index 270e1fa3d62..d16685a7ebc 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -222,7 +222,7 @@ void G1BlockOffsetArray::split_block(HeapWord* blk, size_t blk_size, // Action_mark - update the BOT for the block [blk_start, blk_end). // Current typical use is for splitting a block. -// Action_single - udpate the BOT for an allocation. +// Action_single - update the BOT for an allocation. // Action_verify - BOT verification. void G1BlockOffsetArray::do_block_internal(HeapWord* blk_start, HeapWord* blk_end, @@ -331,47 +331,6 @@ G1BlockOffsetArray::mark_block(HeapWord* blk_start, HeapWord* blk_end) { do_block_internal(blk_start, blk_end, Action_mark); } -void G1BlockOffsetArray::join_blocks(HeapWord* blk1, HeapWord* blk2) { - HeapWord* blk1_start = Universe::heap()->block_start(blk1); - HeapWord* blk2_start = Universe::heap()->block_start(blk2); - assert(blk1 == blk1_start && blk2 == blk2_start, - "Must be block starts."); - assert(blk1 + _sp->block_size(blk1) == blk2, "Must be contiguous."); - size_t blk1_start_index = _array->index_for(blk1); - size_t blk2_start_index = _array->index_for(blk2); - assert(blk1_start_index <= blk2_start_index, "sanity"); - HeapWord* blk2_card_start = _array->address_for_index(blk2_start_index); - if (blk2 == blk2_card_start) { - // blk2 starts a card. Does blk1 start on the prevous card, or futher - // back? - assert(blk1_start_index < blk2_start_index, "must be lower card."); - if (blk1_start_index + 1 == blk2_start_index) { - // previous card; new value for blk2 card is size of blk1. - _array->set_offset_array(blk2_start_index, (u_char) _sp->block_size(blk1)); - } else { - // Earlier card; go back a card. - _array->set_offset_array(blk2_start_index, N_words); - } - } else { - // blk2 does not start a card. Does it cross a card? If not, nothing - // to do. - size_t blk2_end_index = - _array->index_for(blk2 + _sp->block_size(blk2) - 1); - assert(blk2_end_index >= blk2_start_index, "sanity"); - if (blk2_end_index > blk2_start_index) { - // Yes, it crosses a card. The value for the next card must change. - if (blk1_start_index + 1 == blk2_start_index) { - // previous card; new value for second blk2 card is size of blk1. - _array->set_offset_array(blk2_start_index + 1, - (u_char) _sp->block_size(blk1)); - } else { - // Earlier card; go back a card. - _array->set_offset_array(blk2_start_index + 1, N_words); - } - } - } -} - HeapWord* G1BlockOffsetArray::block_start_unsafe(const void* addr) { assert(_bottom <= addr && addr < _end, "addr must be covered by this Array"); @@ -580,16 +539,51 @@ void G1BlockOffsetArray::alloc_block_work2(HeapWord** threshold_, size_t* index_ #endif } -void -G1BlockOffsetArray::set_for_starts_humongous(HeapWord* new_end) { - assert(_end == new_end, "_end should have already been updated"); - - // The first BOT entry should have offset 0. - _array->set_offset_array(_array->index_for(_bottom), 0); - // The rest should point to the first one. - set_remainder_to_point_to_start(_bottom + N_words, new_end); +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"]", + block_start, card, card_addr, + _array->offset_array(card), + obj_start, word_size, first_card, last_card); + return false; + } + } + return true; } +#ifndef PRODUCT +void +G1BlockOffsetArray::print_on(outputStream* out) { + size_t from_index = _array->index_for(_bottom); + size_t to_index = _array->index_for(_end); + out->print_cr(">> BOT for area ["PTR_FORMAT","PTR_FORMAT") " + "cards ["SIZE_FORMAT","SIZE_FORMAT")", + _bottom, _end, from_index, to_index); + for (size_t i = from_index; i < to_index; ++i) { + out->print_cr(" entry "SIZE_FORMAT_W(8)" | "PTR_FORMAT" : %3u", + i, _array->address_for_index(i), + (uint) _array->offset_array(i)); + } +} +#endif // !PRODUCT + ////////////////////////////////////////////////////////////////////// // G1BlockOffsetArrayContigSpace ////////////////////////////////////////////////////////////////////// @@ -641,10 +635,20 @@ void G1BlockOffsetArrayContigSpace::zero_bottom_entry() { } void -G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_end) { - G1BlockOffsetArray::set_for_starts_humongous(new_end); +G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_top) { + assert(new_top <= _end, "_end should have already been updated"); - // Make sure _next_offset_threshold and _next_offset_index point to new_end. - _next_offset_threshold = new_end; - _next_offset_index = _array->index_for(new_end); + // The first BOT entry should have offset 0. + zero_bottom_entry(); + initialize_threshold(); + alloc_block(_bottom, new_top); + } + +#ifndef PRODUCT +void +G1BlockOffsetArrayContigSpace::print_on(outputStream* out) { + G1BlockOffsetArray::print_on(out); + out->print_cr(" next offset threshold: "PTR_FORMAT, _next_offset_threshold); + out->print_cr(" next offset index: "SIZE_FORMAT, _next_offset_index); } +#endif // !PRODUCT diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp index 82568dddd8c..b6a42c73eba 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -352,11 +352,6 @@ public: // The following methods are useful and optimized for a // general, non-contiguous space. - // The given arguments are required to be the starts of adjacent ("blk1" - // before "blk2") well-formed blocks covered by "this". After this call, - // they should be considered to form one block. - virtual void join_blocks(HeapWord* blk1, HeapWord* blk2); - // Given a block [blk_start, blk_start + full_blk_size), and // a left_blk_size < full_blk_size, adjust the BOT to show two // blocks [blk_start, blk_start + left_blk_size) and @@ -429,6 +424,12 @@ public: verify_single_block(blk, blk + size); } + // 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; + // Verify that the given block is before _unallocated_block inline void verify_not_unallocated(HeapWord* blk_start, HeapWord* blk_end) const { @@ -444,7 +445,7 @@ public: void check_all_cards(size_t left_card, size_t right_card) const; - virtual void set_for_starts_humongous(HeapWord* new_end); + virtual void print_on(outputStream* out) PRODUCT_RETURN; }; // A subtype of BlockOffsetArray that takes advantage of the fact @@ -494,7 +495,9 @@ class G1BlockOffsetArrayContigSpace: public G1BlockOffsetArray { HeapWord* block_start_unsafe(const void* addr); HeapWord* block_start_unsafe_const(const void* addr) const; - virtual void set_for_starts_humongous(HeapWord* new_end); + void set_for_starts_humongous(HeapWord* new_top); + + virtual void print_on(outputStream* out) PRODUCT_RETURN; }; #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 030aecade77..a91b0679b26 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -3856,13 +3856,15 @@ private: size_t _next_marked_bytes; OopsInHeapRegionClosure *_cl; public: - RemoveSelfPointerClosure(G1CollectedHeap* g1, OopsInHeapRegionClosure* cl) : - _g1(g1), _cm(_g1->concurrent_mark()), _prev_marked_bytes(0), + RemoveSelfPointerClosure(G1CollectedHeap* g1, HeapRegion* hr, + OopsInHeapRegionClosure* cl) : + _g1(g1), _hr(hr), _cm(_g1->concurrent_mark()), _prev_marked_bytes(0), _next_marked_bytes(0), _cl(cl) {} size_t prev_marked_bytes() { return _prev_marked_bytes; } size_t next_marked_bytes() { return _next_marked_bytes; } + // // The original idea here was to coalesce evacuated and dead objects. // However that caused complications with the block offset table (BOT). // In particular if there were two TLABs, one of them partially refined. @@ -3871,15 +3873,24 @@ public: // of TLAB_2. If the last object of the TLAB_1 and the first object // of TLAB_2 are coalesced, then the cards of the unrefined part // would point into middle of the filler object. - // // The current approach is to not coalesce and leave the BOT contents intact. + // + // + // We now reset the BOT when we start the object iteration over the + // region and refine its entries for every object we come across. So + // the above comment is not really relevant and we should be able + // to coalesce dead objects if we want to. void do_object(oop obj) { + HeapWord* obj_addr = (HeapWord*) obj; + assert(_hr->is_in(obj_addr), "sanity"); + size_t obj_size = obj->size(); + _hr->update_bot_for_object(obj_addr, obj_size); if (obj->is_forwarded() && obj->forwardee() == obj) { // The object failed to move. assert(!_g1->is_obj_dead(obj), "We should not be preserving dead objs."); _cm->markPrev(obj); assert(_cm->isPrevMarked(obj), "Should be marked!"); - _prev_marked_bytes += (obj->size() * HeapWordSize); + _prev_marked_bytes += (obj_size * HeapWordSize); if (_g1->mark_in_progress() && !_g1->is_obj_ill(obj)) { _cm->markAndGrayObjectIfNecessary(obj); } @@ -3901,7 +3912,7 @@ public: } else { // The object has been either evacuated or is dead. Fill it with a // dummy object. - MemRegion mr((HeapWord*)obj, obj->size()); + MemRegion mr((HeapWord*)obj, obj_size); CollectedHeap::fill_with_object(mr); _cm->clearRangeBothMaps(mr); } @@ -3921,10 +3932,13 @@ void G1CollectedHeap::remove_self_forwarding_pointers() { HeapRegion* cur = g1_policy()->collection_set(); while (cur != NULL) { assert(g1_policy()->assertMarkedBytesDataOK(), "Should be!"); + assert(!cur->isHumongous(), "sanity"); - RemoveSelfPointerClosure rspc(_g1h, cl); if (cur->evacuation_failed()) { assert(cur->in_collection_set(), "bad CS"); + RemoveSelfPointerClosure rspc(_g1h, cur, cl); + + cur->reset_bot(); cl->set_region(cur); cur->object_iterate(&rspc); @@ -3989,15 +4003,6 @@ void G1CollectedHeap::drain_evac_failure_scan_stack() { } } -void G1CollectedHeap::handle_evacuation_failure(oop old) { - markOop m = old->mark(); - // forward to self - assert(!old->is_forwarded(), "precondition"); - - old->forward_to(old); - handle_evacuation_failure_common(old, m); -} - oop G1CollectedHeap::handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop old) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 0cec92564fe..54827d1fa86 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -826,7 +826,6 @@ protected: void finalize_for_evac_failure(); // An attempt to evacuate "obj" has failed; take necessary steps. - void handle_evacuation_failure(oop obj); oop handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop obj); void handle_evacuation_failure_common(oop obj, markOop m); diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index ab022668384..dc2799e667d 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -386,26 +386,27 @@ void HeapRegion::calc_gc_efficiency() { } // -void HeapRegion::set_startsHumongous(HeapWord* new_end) { +void HeapRegion::set_startsHumongous(HeapWord* new_top, HeapWord* new_end) { assert(end() == _orig_end, "Should be normal before the humongous object allocation"); assert(top() == bottom(), "should be empty"); + assert(bottom() <= new_top && new_top <= new_end, "pre-condition"); _humongous_type = StartsHumongous; _humongous_start_region = this; set_end(new_end); - _offsets.set_for_starts_humongous(new_end); + _offsets.set_for_starts_humongous(new_top); } -void HeapRegion::set_continuesHumongous(HeapRegion* start) { +void HeapRegion::set_continuesHumongous(HeapRegion* first_hr) { assert(end() == _orig_end, "Should be normal before the humongous object allocation"); assert(top() == bottom(), "should be empty"); - assert(start->startsHumongous(), "pre-condition"); + assert(first_hr->startsHumongous(), "pre-condition"); _humongous_type = ContinuesHumongous; - _humongous_start_region = start; + _humongous_start_region = first_hr; } bool HeapRegion::claimHeapRegion(jint claimValue) { @@ -782,9 +783,6 @@ void HeapRegion::verify(bool allow_dirty) const { verify(allow_dirty, /* use_prev_marking */ true, /* failures */ &dummy); } -#define OBJ_SAMPLE_INTERVAL 0 -#define BLOCK_SAMPLE_INTERVAL 100 - // This really ought to be commoned up into OffsetTableContigSpace somehow. // We would need a mechanism to make that code skip dead objects. @@ -795,83 +793,125 @@ void HeapRegion::verify(bool allow_dirty, *failures = false; HeapWord* p = bottom(); HeapWord* prev_p = NULL; - int objs = 0; - int blocks = 0; VerifyLiveClosure vl_cl(g1, use_prev_marking); bool is_humongous = isHumongous(); + bool do_bot_verify = !is_young(); size_t object_num = 0; while (p < top()) { - size_t size = oop(p)->size(); - if (is_humongous != g1->isHumongous(size)) { + oop obj = oop(p); + size_t obj_size = obj->size(); + object_num += 1; + + if (is_humongous != g1->isHumongous(obj_size)) { gclog_or_tty->print_cr("obj "PTR_FORMAT" is of %shumongous size (" SIZE_FORMAT" words) in a %shumongous region", - p, g1->isHumongous(size) ? "" : "non-", - size, is_humongous ? "" : "non-"); + p, g1->isHumongous(obj_size) ? "" : "non-", + obj_size, is_humongous ? "" : "non-"); *failures = true; + return; } - object_num += 1; - if (blocks == BLOCK_SAMPLE_INTERVAL) { - HeapWord* res = block_start_const(p + (size/2)); - if (p != res) { - gclog_or_tty->print_cr("offset computation 1 for "PTR_FORMAT" and " - SIZE_FORMAT" returned "PTR_FORMAT, - p, size, res); - *failures = true; - return; - } - blocks = 0; - } else { - blocks++; + + // If it returns false, verify_for_object() will output the + // appropriate messasge. + if (do_bot_verify && !_offsets.verify_for_object(p, obj_size)) { + *failures = true; + return; } - if (objs == OBJ_SAMPLE_INTERVAL) { - oop obj = oop(p); - if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) { - if (obj->is_oop()) { - klassOop klass = obj->klass(); - if (!klass->is_perm()) { - gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" " - "not in perm", klass, obj); - *failures = true; - return; - } else if (!klass->is_klass()) { - gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" " - "not a klass", klass, obj); - *failures = true; - return; - } else { - vl_cl.set_containing_obj(obj); - obj->oop_iterate(&vl_cl); - if (vl_cl.failures()) { - *failures = true; - } - if (G1MaxVerifyFailures >= 0 && - vl_cl.n_failures() >= G1MaxVerifyFailures) { - return; - } - } - } else { - gclog_or_tty->print_cr(PTR_FORMAT" no an oop", obj); + + if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) { + if (obj->is_oop()) { + klassOop klass = obj->klass(); + if (!klass->is_perm()) { + gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" " + "not in perm", klass, obj); *failures = true; return; + } else if (!klass->is_klass()) { + gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" " + "not a klass", klass, obj); + *failures = true; + return; + } else { + vl_cl.set_containing_obj(obj); + obj->oop_iterate(&vl_cl); + if (vl_cl.failures()) { + *failures = true; + } + if (G1MaxVerifyFailures >= 0 && + vl_cl.n_failures() >= G1MaxVerifyFailures) { + return; + } } - } - objs = 0; - } else { - objs++; - } - prev_p = p; - p += size; - } - HeapWord* rend = end(); - HeapWord* rtop = top(); - if (rtop < rend) { - HeapWord* res = block_start_const(rtop + (rend - rtop) / 2); - if (res != rtop) { - gclog_or_tty->print_cr("offset computation 2 for "PTR_FORMAT" and " - PTR_FORMAT" returned "PTR_FORMAT, - rtop, rend, res); + } else { + gclog_or_tty->print_cr(PTR_FORMAT" no an oop", obj); *failures = true; return; + } + } + prev_p = p; + p += obj_size; + } + + if (p != top()) { + gclog_or_tty->print_cr("end of last object "PTR_FORMAT" " + "does not match top "PTR_FORMAT, p, top()); + *failures = true; + return; + } + + HeapWord* the_end = end(); + assert(p == top(), "it should still hold"); + // Do some extra BOT consistency checking for addresses in the + // range [top, end). BOT look-ups in this range should yield + // top. No point in doing that if top == end (there's nothing there). + if (p < the_end) { + // Look up top + HeapWord* addr_1 = p; + HeapWord* b_start_1 = _offsets.block_start_const(addr_1); + if (b_start_1 != p) { + gclog_or_tty->print_cr("BOT look up for top: "PTR_FORMAT" " + " yielded "PTR_FORMAT", expecting "PTR_FORMAT, + addr_1, b_start_1, p); + *failures = true; + return; + } + + // Look up top + 1 + HeapWord* addr_2 = p + 1; + if (addr_2 < the_end) { + HeapWord* b_start_2 = _offsets.block_start_const(addr_2); + if (b_start_2 != p) { + gclog_or_tty->print_cr("BOT look up for top + 1: "PTR_FORMAT" " + " yielded "PTR_FORMAT", expecting "PTR_FORMAT, + addr_2, b_start_2, p); + *failures = true; + return; + } + } + + // Look up an address between top and end + size_t diff = pointer_delta(the_end, p) / 2; + HeapWord* addr_3 = p + diff; + if (addr_3 < the_end) { + HeapWord* b_start_3 = _offsets.block_start_const(addr_3); + if (b_start_3 != p) { + gclog_or_tty->print_cr("BOT look up for top + diff: "PTR_FORMAT" " + " yielded "PTR_FORMAT", expecting "PTR_FORMAT, + addr_3, b_start_3, p); + *failures = true; + return; + } + } + + // Loook up end - 1 + HeapWord* addr_4 = the_end - 1; + HeapWord* b_start_4 = _offsets.block_start_const(addr_4); + if (b_start_4 != p) { + gclog_or_tty->print_cr("BOT look up for end - 1: "PTR_FORMAT" " + " yielded "PTR_FORMAT", expecting "PTR_FORMAT, + addr_4, b_start_4, p); + *failures = true; + return; } } @@ -880,12 +920,6 @@ void HeapRegion::verify(bool allow_dirty, "but has "SIZE_FORMAT", objects", bottom(), end(), object_num); *failures = true; - } - - if (p != top()) { - gclog_or_tty->print_cr("end of last object "PTR_FORMAT" " - "does not match top "PTR_FORMAT, p, top()); - *failures = true; return; } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index f11c6a3a3ec..4e5f2224b61 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -173,6 +173,19 @@ class G1OffsetTableContigSpace: public ContiguousSpace { virtual HeapWord* cross_threshold(HeapWord* start, HeapWord* end); virtual void print() const; + + void reset_bot() { + _offsets.zero_bottom_entry(); + _offsets.initialize_threshold(); + } + + void update_bot_for_object(HeapWord* start, size_t word_size) { + _offsets.alloc_block(start, word_size); + } + + void print_bot_on(outputStream* out) { + _offsets.print_on(out); + } }; class HeapRegion: public G1OffsetTableContigSpace { @@ -404,13 +417,35 @@ class HeapRegion: public G1OffsetTableContigSpace { return _humongous_start_region; } - // Causes the current region to represent a humongous object spanning "n" - // regions. - void set_startsHumongous(HeapWord* new_end); + // Makes the current region be a "starts humongous" region, i.e., + // the first region in a series of one or more contiguous regions + // that will contain a single "humongous" object. The two parameters + // are as follows: + // + // new_top : The new value of the top field of this region which + // points to the end of the humongous object that's being + // allocated. If there is more than one region in the series, top + // will lie beyond this region's original end field and on the last + // region in the series. + // + // new_end : The new value of the end field of this region which + // points to the end of the last region in the series. If there is + // one region in the series (namely: this one) end will be the same + // as the original end of this region. + // + // Updating top and end as described above makes this region look as + // if it spans the entire space taken up by all the regions in the + // series and an single allocation moved its top to new_top. This + // ensures that the space (capacity / allocated) taken up by all + // humongous regions can be calculated by just looking at the + // "starts humongous" regions and by ignoring the "continues + // humongous" regions. + void set_startsHumongous(HeapWord* new_top, HeapWord* new_end); - // The regions that continue a humongous sequence should be added using - // this method, in increasing address order. - void set_continuesHumongous(HeapRegion* start); + // Makes the current region be a "continues humongous' + // region. first_hr is the "start humongous" region of the series + // which this region will be part of. + void set_continuesHumongous(HeapRegion* first_hr); // If the region has a remembered set, return a pointer to it. HeapRegionRemSet* rem_set() const { diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp index 336ba21c4f2..a116d9d815b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -144,7 +144,7 @@ HeapRegionSeq::alloc_obj_from_region_index(int ind, size_t word_size) { // will also update the BOT covering all the regions to reflect // that there is a single object that starts at the bottom of the // first region. - first_hr->set_startsHumongous(new_end); + first_hr->set_startsHumongous(new_top, new_end); // Then, if there are any, we will set up the "continues // humongous" regions. From bc1df68513c40e526ff8452865a0d8b227efa2f2 Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Wed, 12 Jan 2011 16:34:25 -0500 Subject: [PATCH 037/152] 6994297: G1: do first-level slow-path allocations with a CAS First attempt to allocate out the current alloc region using a CAS instead of taking the Heap_lock (first level of G1's slow allocation path). Only if that fails and it's necessary to replace the current alloc region take the Heap_lock (that's the second level of G1's slow allocation path). Reviewed-by: johnc, brutisso, ysr --- .../gc_implementation/g1/g1CollectedHeap.cpp | 137 +++++++++++------- .../gc_implementation/g1/g1CollectedHeap.hpp | 43 ++++-- .../g1/g1CollectedHeap.inline.hpp | 89 +++++++++--- .../vm/gc_implementation/g1/heapRegion.hpp | 9 ++ 4 files changed, 189 insertions(+), 89 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index a91b0679b26..3fddd0b1e31 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -610,6 +610,39 @@ G1CollectedHeap::retire_cur_alloc_region(HeapRegion* cur_alloc_region) { // of the free region list is revamped as part of CR 6977804. wait_for_cleanup_complete(); + // Other threads might still be trying to allocate using CASes out + // of the region we are retiring, as they can do so without holding + // the Heap_lock. So we first have to make sure that noone else can + // allocate in it by doing a maximal allocation. Even if our CAS + // attempt fails a few times, we'll succeed sooner or later given + // that a failed CAS attempt mean that the region is getting closed + // to being full (someone else succeeded in allocating into it). + size_t free_word_size = cur_alloc_region->free() / HeapWordSize; + + // This is the minimum free chunk we can turn into a dummy + // object. If the free space falls below this, then noone can + // allocate in this region anyway (all allocation requests will be + // of a size larger than this) so we won't have to perform the dummy + // allocation. + size_t min_word_size_to_fill = CollectedHeap::min_fill_size(); + + while (free_word_size >= min_word_size_to_fill) { + HeapWord* dummy = + cur_alloc_region->par_allocate_no_bot_updates(free_word_size); + if (dummy != NULL) { + // If the allocation was successful we should fill in the space. + CollectedHeap::fill_with_object(dummy, free_word_size); + break; + } + + free_word_size = cur_alloc_region->free() / HeapWordSize; + // It's also possible that someone else beats us to the + // allocation and they fill up the region. In that case, we can + // just get out of the loop + } + assert(cur_alloc_region->free() / HeapWordSize < min_word_size_to_fill, + "sanity"); + retire_cur_alloc_region_common(cur_alloc_region); assert(_cur_alloc_region == NULL, "post-condition"); } @@ -661,27 +694,29 @@ G1CollectedHeap::replace_cur_alloc_region_and_allocate(size_t word_size, // young type. OrderAccess::storestore(); - // Now allocate out of the new current alloc region. We could - // have re-used allocate_from_cur_alloc_region() but its - // operation is slightly different to what we need here. First, - // allocate_from_cur_alloc_region() is only called outside a - // safepoint and will always unlock the Heap_lock if it returns - // a non-NULL result. Second, it assumes that the current alloc - // region is what's already assigned in _cur_alloc_region. What - // we want here is to actually do the allocation first before we - // assign the new region to _cur_alloc_region. This ordering is - // not currently important, but it will be essential when we - // change the code to support CAS allocation in the future (see - // CR 6994297). - // - // This allocate method does BOT updates and we don't need them in - // the young generation. This will be fixed in the near future by - // CR 6994297. - HeapWord* result = new_cur_alloc_region->allocate(word_size); + // Now, perform the allocation out of the region we just + // allocated. Note that noone else can access that region at + // this point (as _cur_alloc_region has not been updated yet), + // so we can just go ahead and do the allocation without any + // atomics (and we expect this allocation attempt to + // suceeded). Given that other threads can attempt an allocation + // with a CAS and without needing the Heap_lock, if we assigned + // the new region to _cur_alloc_region before first allocating + // into it other threads might have filled up the new region + // before we got a chance to do the allocation ourselves. In + // that case, we would have needed to retire the region, grab a + // new one, and go through all this again. Allocating out of the + // new region before assigning it to _cur_alloc_region avoids + // all this. + HeapWord* result = + new_cur_alloc_region->allocate_no_bot_updates(word_size); assert(result != NULL, "we just allocate out of an empty region " "so allocation should have been successful"); assert(is_in(result), "result should be in the heap"); + // Now make sure that the store to _cur_alloc_region does not + // float above the store to top. + OrderAccess::storestore(); _cur_alloc_region = new_cur_alloc_region; if (!at_safepoint) { @@ -718,6 +753,9 @@ G1CollectedHeap::attempt_allocation_slow(size_t word_size) { for (int try_count = 1; /* we'll return or break */; try_count += 1) { bool succeeded = true; + // Every time we go round the loop we should be holding the Heap_lock. + assert_heap_locked(); + { // We may have concurrent cleanup working at the time. Wait for // it to complete. In the future we would probably want to make @@ -734,7 +772,8 @@ G1CollectedHeap::attempt_allocation_slow(size_t word_size) { // attempt as it's redundant (we only reach here after an // allocation attempt has been unsuccessful). wait_for_cleanup_complete(); - HeapWord* result = attempt_allocation(word_size); + + HeapWord* result = attempt_allocation_locked(word_size); if (result != NULL) { assert_heap_not_locked(); return result; @@ -748,7 +787,6 @@ G1CollectedHeap::attempt_allocation_slow(size_t word_size) { if (g1_policy()->can_expand_young_list()) { // Yes, we are allowed to expand the young gen. Let's try to // allocate a new current alloc region. - HeapWord* result = replace_cur_alloc_region_and_allocate(word_size, false, /* at_safepoint */ @@ -771,20 +809,23 @@ G1CollectedHeap::attempt_allocation_slow(size_t word_size) { // rather than causing more, now probably unnecessary, GC attempts. JavaThread* jthr = JavaThread::current(); assert(jthr != NULL, "sanity"); - if (!jthr->in_critical()) { - MutexUnlocker mul(Heap_lock); - GC_locker::stall_until_clear(); - - // We'll then fall off the end of the ("if GC locker active") - // if-statement and retry the allocation further down in the - // loop. - } else { + if (jthr->in_critical()) { if (CheckJNICalls) { fatal("Possible deadlock due to allocating while" " in jni critical section"); } + // We are returning NULL so the protocol is that we're still + // holding the Heap_lock. + assert_heap_locked(); return NULL; } + + Heap_lock->unlock(); + GC_locker::stall_until_clear(); + + // No need to relock the Heap_lock. We'll fall off to the code + // below the else-statement which assumes that we are not + // holding the Heap_lock. } else { // We are not locked out. So, let's try to do a GC. The VM op // will retry the allocation before it completes. @@ -805,11 +846,10 @@ G1CollectedHeap::attempt_allocation_slow(size_t word_size) { dirty_young_block(result, word_size); return result; } - - Heap_lock->lock(); } - assert_heap_locked(); + // Both paths that get us here from above unlock the Heap_lock. + assert_heap_not_locked(); // We can reach here when we were unsuccessful in doing a GC, // because another thread beat us to it, or because we were locked @@ -948,10 +988,8 @@ HeapWord* G1CollectedHeap::attempt_allocation_at_safepoint(size_t word_size, if (!expect_null_cur_alloc_region) { HeapRegion* cur_alloc_region = _cur_alloc_region; if (cur_alloc_region != NULL) { - // This allocate method does BOT updates and we don't need them in - // the young generation. This will be fixed in the near future by - // CR 6994297. - HeapWord* result = cur_alloc_region->allocate(word_size); + // We are at a safepoint so no reason to use the MT-safe version. + HeapWord* result = cur_alloc_region->allocate_no_bot_updates(word_size); if (result != NULL) { assert(is_in(result), "result should be in the heap"); @@ -983,20 +1021,17 @@ HeapWord* G1CollectedHeap::allocate_new_tlab(size_t word_size) { assert_heap_not_locked_and_not_at_safepoint(); assert(!isHumongous(word_size), "we do not allow TLABs of humongous size"); - Heap_lock->lock(); - - // First attempt: try allocating out of the current alloc region or - // after replacing the current alloc region. + // First attempt: Try allocating out of the current alloc region + // using a CAS. If that fails, take the Heap_lock and retry the + // allocation, potentially replacing the current alloc region. HeapWord* result = attempt_allocation(word_size); if (result != NULL) { assert_heap_not_locked(); return result; } - assert_heap_locked(); - - // Second attempt: go into the even slower path where we might - // try to schedule a collection. + // Second attempt: Go to the slower path where we might try to + // schedule a collection. result = attempt_allocation_slow(word_size); if (result != NULL) { assert_heap_not_locked(); @@ -1004,6 +1039,7 @@ HeapWord* G1CollectedHeap::allocate_new_tlab(size_t word_size) { } assert_heap_locked(); + // Need to unlock the Heap_lock before returning. Heap_lock->unlock(); return NULL; } @@ -1022,11 +1058,10 @@ G1CollectedHeap::mem_allocate(size_t word_size, for (int try_count = 1; /* we'll return */; try_count += 1) { unsigned int gc_count_before; { - Heap_lock->lock(); - if (!isHumongous(word_size)) { - // First attempt: try allocating out of the current alloc - // region or after replacing the current alloc region. + // First attempt: Try allocating out of the current alloc region + // using a CAS. If that fails, take the Heap_lock and retry the + // allocation, potentially replacing the current alloc region. HeapWord* result = attempt_allocation(word_size); if (result != NULL) { assert_heap_not_locked(); @@ -1035,14 +1070,17 @@ G1CollectedHeap::mem_allocate(size_t word_size, assert_heap_locked(); - // Second attempt: go into the even slower path where we might - // try to schedule a collection. + // Second attempt: Go to the slower path where we might try to + // schedule a collection. result = attempt_allocation_slow(word_size); if (result != NULL) { assert_heap_not_locked(); return result; } } else { + // attempt_allocation_humongous() requires the Heap_lock to be held. + Heap_lock->lock(); + HeapWord* result = attempt_allocation_humongous(word_size, false /* at_safepoint */); if (result != NULL) { @@ -1054,7 +1092,8 @@ G1CollectedHeap::mem_allocate(size_t word_size, assert_heap_locked(); // Read the gc count while the heap lock is held. gc_count_before = SharedHeap::heap()->total_collections(); - // We cannot be at a safepoint, so it is safe to unlock the Heap_lock + + // Release the Heap_lock before attempting the collection. Heap_lock->unlock(); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 54827d1fa86..35eb571388a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -430,7 +430,8 @@ protected: bool* gc_overhead_limit_was_exceeded); // The following methods, allocate_from_cur_allocation_region(), - // attempt_allocation(), replace_cur_alloc_region_and_allocate(), + // attempt_allocation(), attempt_allocation_locked(), + // replace_cur_alloc_region_and_allocate(), // attempt_allocation_slow(), and attempt_allocation_humongous() // have very awkward pre- and post-conditions with respect to // locking: @@ -481,20 +482,30 @@ protected: // successfully manage to allocate it, or NULL. // It tries to satisfy an allocation request out of the current - // allocating region, which is passed as a parameter. It assumes - // that the caller has checked that the current allocating region is - // not NULL. Given that the caller has to check the current - // allocating region for at least NULL, it might as well pass it as - // the first parameter so that the method doesn't have to read it - // from the _cur_alloc_region field again. + // alloc region, which is passed as a parameter. It assumes that the + // caller has checked that the current alloc region is not NULL. + // Given that the caller has to check the current alloc region for + // at least NULL, it might as well pass it as the first parameter so + // that the method doesn't have to read it from the + // _cur_alloc_region field again. It is called from both + // attempt_allocation() and attempt_allocation_locked() and the + // with_heap_lock parameter indicates whether the caller was holding + // the heap lock when it called it or not. inline HeapWord* allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region, - size_t word_size); + size_t word_size, + bool with_heap_lock); - // It attempts to allocate out of the current alloc region. If that - // fails, it retires the current alloc region (if there is one), - // tries to get a new one and retries the allocation. + // First-level of allocation slow path: it attempts to allocate out + // of the current alloc region in a lock-free manner using a CAS. If + // that fails it takes the Heap_lock and calls + // attempt_allocation_locked() for the second-level slow path. inline HeapWord* attempt_allocation(size_t word_size); + // Second-level of allocation slow path: while holding the Heap_lock + // it tries to allocate out of the current alloc region and, if that + // fails, tries to allocate out of a new current alloc region. + inline HeapWord* attempt_allocation_locked(size_t word_size); + // It assumes that the current alloc region has been retired and // tries to allocate a new one. If it's successful, it performs the // allocation out of the new current alloc region and updates @@ -506,11 +517,11 @@ protected: bool do_dirtying, bool can_expand); - // The slow path when we are unable to allocate a new current alloc - // region to satisfy an allocation request (i.e., when - // attempt_allocation() fails). It will try to do an evacuation - // pause, which might stall due to the GC locker, and retry the - // allocation attempt when appropriate. + // Third-level of allocation slow path: when we are unable to + // allocate a new current alloc region to satisfy an allocation + // request (i.e., when attempt_allocation_locked() fails). It will + // try to do an evacuation pause, which might stall due to the GC + // locker, and retry the allocation attempt when appropriate. HeapWord* attempt_allocation_slow(size_t word_size); // The method that tries to satisfy a humongous allocation diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp index 85812877f87..4d38cc76830 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -63,10 +63,12 @@ inline bool G1CollectedHeap::obj_in_cs(oop obj) { // assumptions of this method (and other related ones). inline HeapWord* G1CollectedHeap::allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region, - size_t word_size) { - assert_heap_locked_and_not_at_safepoint(); + size_t word_size, + bool with_heap_lock) { + assert_not_at_safepoint(); + assert(with_heap_lock == Heap_lock->owned_by_self(), + "with_heap_lock and Heap_lock->owned_by_self() should be a tautology"); assert(cur_alloc_region != NULL, "pre-condition of the method"); - assert(cur_alloc_region == _cur_alloc_region, "pre-condition of the method"); assert(cur_alloc_region->is_young(), "we only support young current alloc regions"); assert(!isHumongous(word_size), "allocate_from_cur_alloc_region() " @@ -76,20 +78,24 @@ G1CollectedHeap::allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region, assert(!cur_alloc_region->is_empty(), err_msg("region ["PTR_FORMAT","PTR_FORMAT"] should not be empty", cur_alloc_region->bottom(), cur_alloc_region->end())); - // This allocate method does BOT updates and we don't need them in - // the young generation. This will be fixed in the near future by - // CR 6994297. - HeapWord* result = cur_alloc_region->allocate(word_size); + HeapWord* result = cur_alloc_region->par_allocate_no_bot_updates(word_size); if (result != NULL) { assert(is_in(result), "result should be in the heap"); - Heap_lock->unlock(); + if (with_heap_lock) { + Heap_lock->unlock(); + } + assert_heap_not_locked(); // Do the dirtying after we release the Heap_lock. dirty_young_block(result, word_size); return result; } - assert_heap_locked(); + if (with_heap_lock) { + assert_heap_locked(); + } else { + assert_heap_not_locked(); + } return NULL; } @@ -97,31 +103,27 @@ G1CollectedHeap::allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region, // assumptions of this method (and other related ones). inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size) { - assert_heap_locked_and_not_at_safepoint(); + assert_heap_not_locked_and_not_at_safepoint(); assert(!isHumongous(word_size), "attempt_allocation() should not be called " "for humongous allocation requests"); HeapRegion* cur_alloc_region = _cur_alloc_region; if (cur_alloc_region != NULL) { HeapWord* result = allocate_from_cur_alloc_region(cur_alloc_region, - word_size); + word_size, + false /* with_heap_lock */); + assert_heap_not_locked(); if (result != NULL) { - assert_heap_not_locked(); return result; } - - assert_heap_locked(); - - // Since we couldn't successfully allocate into it, retire the - // current alloc region. - retire_cur_alloc_region(cur_alloc_region); } - // Try to get a new region and allocate out of it - HeapWord* result = replace_cur_alloc_region_and_allocate(word_size, - false, /* at_safepoint */ - true, /* do_dirtying */ - false /* can_expand */); + // Our attempt to allocate lock-free failed as the current + // allocation region is either NULL or full. So, we'll now take the + // Heap_lock and retry. + Heap_lock->lock(); + + HeapWord* result = attempt_allocation_locked(word_size); if (result != NULL) { assert_heap_not_locked(); return result; @@ -145,6 +147,45 @@ G1CollectedHeap::retire_cur_alloc_region_common(HeapRegion* cur_alloc_region) { _cur_alloc_region = NULL; } +inline HeapWord* +G1CollectedHeap::attempt_allocation_locked(size_t word_size) { + assert_heap_locked_and_not_at_safepoint(); + assert(!isHumongous(word_size), "attempt_allocation_locked() " + "should not be called for humongous allocation requests"); + + // First, reread the current alloc region and retry the allocation + // in case somebody replaced it while we were waiting to get the + // Heap_lock. + HeapRegion* cur_alloc_region = _cur_alloc_region; + if (cur_alloc_region != NULL) { + HeapWord* result = allocate_from_cur_alloc_region( + cur_alloc_region, word_size, + true /* with_heap_lock */); + if (result != NULL) { + assert_heap_not_locked(); + return result; + } + + // We failed to allocate out of the current alloc region, so let's + // retire it before getting a new one. + retire_cur_alloc_region(cur_alloc_region); + } + + assert_heap_locked(); + // Try to get a new region and allocate out of it + HeapWord* result = replace_cur_alloc_region_and_allocate(word_size, + false, /* at_safepoint */ + true, /* do_dirtying */ + false /* can_expand */); + if (result != NULL) { + assert_heap_not_locked(); + return result; + } + + assert_heap_locked(); + return NULL; +} + // It dirties the cards that cover the block so that so that the post // write barrier never queues anything when updating objects on this // block. It is assumed (and in fact we assert) that the block diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index 4e5f2224b61..18e1777aeba 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -372,6 +372,15 @@ class HeapRegion: public G1OffsetTableContigSpace { Allocated }; + inline HeapWord* par_allocate_no_bot_updates(size_t word_size) { + assert(is_young(), "we can only skip BOT updates on young regions"); + return ContiguousSpace::par_allocate(word_size); + } + inline HeapWord* allocate_no_bot_updates(size_t word_size) { + assert(is_young(), "we can only skip BOT updates on young regions"); + return ContiguousSpace::allocate(word_size); + } + // If this region is a member of a HeapRegionSeq, the index in that // sequence, otherwise -1. int hrs_index() const { return _hrs_index; } From 07549260db3653825d1393e1104eae654716b883 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Wed, 12 Jan 2011 13:52:09 -0800 Subject: [PATCH 038/152] 7008713: diamond conversion of kerberos5 and security tools Reviewed-by: weijun --- .../classes/sun/security/krb5/Config.java | 21 ++++++++-------- .../classes/sun/security/krb5/KdcComm.java | 6 ++--- .../sun/security/krb5/PrincipalName.java | 4 +-- .../classes/sun/security/krb5/Realm.java | 4 +-- .../security/krb5/internal/Authenticator.java | 2 +- .../krb5/internal/AuthorizationData.java | 3 +-- .../security/krb5/internal/EncAPRepPart.java | 2 +- .../security/krb5/internal/HostAddresses.java | 5 ++-- .../sun/security/krb5/internal/KDCReq.java | 2 +- .../security/krb5/internal/KDCReqBody.java | 6 ++--- .../sun/security/krb5/internal/KRBCred.java | 2 +- .../sun/security/krb5/internal/KRBError.java | 2 +- .../security/krb5/internal/KrbCredInfo.java | 2 +- .../sun/security/krb5/internal/LastReq.java | 2 +- .../internal/ccache/FileCredentialsCache.java | 2 +- .../security/krb5/internal/crypto/EType.java | 2 +- .../security/krb5/internal/ktab/KeyTab.java | 4 +-- .../classes/sun/security/tools/JarSigner.java | 25 ++++++++----------- .../classes/sun/security/tools/KeyTool.java | 19 +++++++------- .../security/tools/policytool/PolicyTool.java | 10 +++----- jdk/test/sun/security/krb5/IPv6.java | 4 +-- .../sun/security/krb5/auto/CleanState.java | 4 +-- jdk/test/sun/security/krb5/auto/Context.java | 6 ++--- .../krb5/auto/HttpNegotiateServer.java | 4 +-- jdk/test/sun/security/krb5/auto/KDC.java | 10 ++++---- .../krb5/auto/LoginModuleOptions.java | 4 +-- .../sun/security/krb5/tools/KtabCheck.java | 2 +- 27 files changed, 75 insertions(+), 84 deletions(-) diff --git a/jdk/src/share/classes/sun/security/krb5/Config.java b/jdk/src/share/classes/sun/security/krb5/Config.java index 272c3b1e6ca..09017bf7a3e 100644 --- a/jdk/src/share/classes/sun/security/krb5/Config.java +++ b/jdk/src/share/classes/sun/security/krb5/Config.java @@ -528,7 +528,7 @@ public class Config { } }))); String Line; - Vector v = new Vector (); + Vector v = new Vector<>(); String previous = null; while ((Line = br.readLine()) != null) { // ignore comments and blank line in the configuration file. @@ -589,7 +589,7 @@ public class Config { throw new KrbException("I/O error while reading" + " configuration file."); } - Hashtable table = new Hashtable (); + Hashtable table = new Hashtable<>(); for (int i = 0; i < v.size(); i++) { String line = v.elementAt(i).trim(); if (line.equalsIgnoreCase("[realms]")) { @@ -598,7 +598,7 @@ public class Config { if ((count == v.size()) || (v.elementAt(count).startsWith("["))) { Hashtable>> temp = - new Hashtable>>(); + new Hashtable<>(); temp = parseRealmField(v, i + 1, count); table.put("realms", temp); i = count - 1; @@ -611,7 +611,7 @@ public class Config { if ((count == v.size()) || (v.elementAt(count).startsWith("["))) { Hashtable>> temp = - new Hashtable>>(); + new Hashtable<>(); temp = parseRealmField(v, i + 1, count); table.put("capaths", temp); i = count - 1; @@ -729,7 +729,7 @@ public class Config { * Parses key-value pairs under a stanza name. */ private Hashtable parseField(Vector v, int start, int end) { - Hashtable table = new Hashtable (); + Hashtable table = new Hashtable<>(); String line; for (int i = start; i < end; i++) { line = v.elementAt(i); @@ -751,7 +751,7 @@ public class Config { * information for the realm given within a pair of braces. */ private Hashtable>> parseRealmField(Vector v, int start, int end) { - Hashtable>> table = new Hashtable>> (); + Hashtable>> table = new Hashtable<>(); String line; for (int i = start; i < end; i++) { line = v.elementAt(i).trim(); @@ -791,10 +791,9 @@ public class Config { * Parses key-value pairs within each braces under [realms]. */ private Hashtable> parseRealmFieldEx(Vector v, int start, int end) { - Hashtable> table = - new Hashtable> (); - Vector keyVector = new Vector (); - Vector nameVector = new Vector (); + Hashtable> table = new Hashtable<>(); + Vector keyVector = new Vector<>(); + Vector nameVector = new Vector<>(); String line = ""; String key; for (int i = start; i < end; i++) { @@ -899,7 +898,7 @@ public class Config { } st = new StringTokenizer(default_enctypes, delim); int len = st.countTokens(); - ArrayList ls = new ArrayList (len); + ArrayList ls = new ArrayList<>(len); int type; for (int i = 0; i < len; i++) { type = getType(st.nextToken()); diff --git a/jdk/src/share/classes/sun/security/krb5/KdcComm.java b/jdk/src/share/classes/sun/security/krb5/KdcComm.java index 22e54afe5e8..bb113392db1 100644 --- a/jdk/src/share/classes/sun/security/krb5/KdcComm.java +++ b/jdk/src/share/classes/sun/security/krb5/KdcComm.java @@ -462,7 +462,7 @@ public final class KdcComm { */ static class KdcAccessibility { // Known bad KDCs - private static Set bads = new HashSet(); + private static Set bads = new HashSet<>(); private static synchronized void addBad(String kdc) { if (DEBUG) { @@ -492,9 +492,9 @@ public final class KdcComm { // Returns a preferred KDC list by putting the bad ones at the end private static synchronized String[] list(String kdcList) { StringTokenizer st = new StringTokenizer(kdcList); - List list = new ArrayList(); + List list = new ArrayList<>(); if (badPolicy == BpType.TRY_LAST) { - List badkdcs = new ArrayList(); + List badkdcs = new ArrayList<>(); while (st.hasMoreTokens()) { String t = st.nextToken(); if (bads.contains(t)) badkdcs.add(t); diff --git a/jdk/src/share/classes/sun/security/krb5/PrincipalName.java b/jdk/src/share/classes/sun/security/krb5/PrincipalName.java index 647f7199b3f..11d11dbfa0e 100644 --- a/jdk/src/share/classes/sun/security/krb5/PrincipalName.java +++ b/jdk/src/share/classes/sun/security/krb5/PrincipalName.java @@ -244,7 +244,7 @@ public class PrincipalName if (subDer.getTag() != DerValue.tag_SequenceOf) { throw new Asn1Exception(Krb5.ASN1_BAD_ID); } - Vector v = new Vector (); + Vector v = new Vector<>(); DerValue subSubDer; while(subDer.getData().available() > 0) { subSubDer = subDer.getData().getDerValue(); @@ -299,7 +299,7 @@ public class PrincipalName // Code repetition, realm parsed again by class Realm protected static String[] parseName(String name) { - Vector tempStrings = new Vector (); + Vector tempStrings = new Vector<>(); String temp = name; int i = 0; int componentStart = 0; diff --git a/jdk/src/share/classes/sun/security/krb5/Realm.java b/jdk/src/share/classes/sun/security/krb5/Realm.java index 88f679de7a5..f7b450ec6be 100644 --- a/jdk/src/share/classes/sun/security/krb5/Realm.java +++ b/jdk/src/share/classes/sun/security/krb5/Realm.java @@ -359,12 +359,12 @@ public class Realm implements Cloneable { } String tempTarget = null, tempRealm = null; - Stack iStack = new Stack (); + Stack iStack = new Stack<>(); /* * I don't expect any more than a handful of intermediaries. */ - Vector tempList = new Vector (8, 8); + Vector tempList = new Vector<>(8, 8); /* * The initiator at first location. diff --git a/jdk/src/share/classes/sun/security/krb5/internal/Authenticator.java b/jdk/src/share/classes/sun/security/krb5/internal/Authenticator.java index 28a44cc514c..67f70387a99 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/Authenticator.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/Authenticator.java @@ -176,7 +176,7 @@ public class Authenticator { * @exception IOException if an I/O error occurs while reading encoded data. */ public byte[] asn1Encode() throws Asn1Exception, IOException { - Vector v = new Vector(); + Vector v = new Vector<>(); DerOutputStream temp = new DerOutputStream(); temp.putInteger(BigInteger.valueOf(authenticator_vno)); v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x00), temp.toByteArray())); diff --git a/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationData.java b/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationData.java index bbec348c146..9a9de81932f 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationData.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationData.java @@ -99,8 +99,7 @@ public class AuthorizationData implements Cloneable { * @exception IOException if an I/O error occurs while reading encoded data. */ public AuthorizationData(DerValue der) throws Asn1Exception, IOException { - Vector v = - new Vector(); + Vector v = new Vector<>(); if (der.getTag() != DerValue.tag_Sequence) { throw new Asn1Exception(Krb5.ASN1_BAD_ID); } diff --git a/jdk/src/share/classes/sun/security/krb5/internal/EncAPRepPart.java b/jdk/src/share/classes/sun/security/krb5/internal/EncAPRepPart.java index f8fb0aead5b..fdebf1de980 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/EncAPRepPart.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/EncAPRepPart.java @@ -133,7 +133,7 @@ public class EncAPRepPart { * @exception IOException if an I/O error occurs while reading encoded data. */ public byte[] asn1Encode() throws Asn1Exception, IOException { - Vector v = new Vector(); + Vector v = new Vector<>(); DerOutputStream temp = new DerOutputStream(); v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x00), ctime.asn1Encode())); diff --git a/jdk/src/share/classes/sun/security/krb5/internal/HostAddresses.java b/jdk/src/share/classes/sun/security/krb5/internal/HostAddresses.java index df51f3a3536..1cd1e4ac44f 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/HostAddresses.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/HostAddresses.java @@ -179,7 +179,7 @@ public class HostAddresses implements Cloneable { */ public HostAddresses(DerValue encoding) throws Asn1Exception, IOException { - Vector tempAddresses = new Vector (); + Vector tempAddresses = new Vector<>(); DerValue der = null; while (encoding.getData().available() > 0) { der = encoding.getData().getDerValue(); @@ -265,8 +265,7 @@ public class HostAddresses implements Cloneable { if (addresses == null || addresses.length == 0) return null; - ArrayList ipAddrs = - new ArrayList (addresses.length); + ArrayList ipAddrs = new ArrayList<>(addresses.length); for (int i = 0; i < addresses.length; i++) { try { diff --git a/jdk/src/share/classes/sun/security/krb5/internal/KDCReq.java b/jdk/src/share/classes/sun/security/krb5/internal/KDCReq.java index 0dfd3ccf904..16591e80404 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/KDCReq.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/KDCReq.java @@ -150,7 +150,7 @@ public class KDCReq { if (subsubDer.getTag() != DerValue.tag_SequenceOf) { throw new Asn1Exception(Krb5.ASN1_BAD_ID); } - Vector v = new Vector(); + Vector v = new Vector<>(); while (subsubDer.getData().available() > 0) { v.addElement(new PAData(subsubDer.getData().getDerValue())); } diff --git a/jdk/src/share/classes/sun/security/krb5/internal/KDCReqBody.java b/jdk/src/share/classes/sun/security/krb5/internal/KDCReqBody.java index 4af4dad0c13..a23d452885d 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/KDCReqBody.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/KDCReqBody.java @@ -158,7 +158,7 @@ public class KDCReqBody { throw new Asn1Exception(Krb5.ASN1_BAD_ID); } der = encoding.getData().getDerValue(); - Vector v = new Vector (); + Vector v = new Vector<>(); if ((der.getTag() & (byte)0x1F) == (byte)0x08) { subDer = der.getData().getDerValue(); @@ -183,7 +183,7 @@ public class KDCReqBody { encAuthorizationData = EncryptedData.parse(encoding.getData(), (byte)0x0A, true); } if (encoding.getData().available() > 0) { - Vector tempTickets = new Vector (); + Vector tempTickets = new Vector<>(); der = encoding.getData().getDerValue(); if ((der.getTag() & (byte)0x1F) == (byte)0x0B) { subDer = der.getData().getDerValue(); @@ -216,7 +216,7 @@ public class KDCReqBody { * */ public byte[] asn1Encode(int msgType) throws Asn1Exception, IOException { - Vector v = new Vector (); + Vector v = new Vector<>(); v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), kdcOptions.asn1Encode())); if (msgType == Krb5.KRB_AS_REQ) { if (cname != null) { diff --git a/jdk/src/share/classes/sun/security/krb5/internal/KRBCred.java b/jdk/src/share/classes/sun/security/krb5/internal/KRBCred.java index 5fbe7ad8e03..ff719f432c2 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/KRBCred.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/KRBCred.java @@ -134,7 +134,7 @@ public class KRBCred { if (subsubDer.getTag() != DerValue.tag_SequenceOf) { throw new Asn1Exception(Krb5.ASN1_BAD_ID); } - Vector v = new Vector(); + Vector v = new Vector<>(); while (subsubDer.getData().available() > 0) { v.addElement(new Ticket(subsubDer.getData().getDerValue())); } diff --git a/jdk/src/share/classes/sun/security/krb5/internal/KRBError.java b/jdk/src/share/classes/sun/security/krb5/internal/KRBError.java index ac8667f0686..ed17cd8212a 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/KRBError.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/KRBError.java @@ -260,7 +260,7 @@ public class KRBError implements java.io.Serializable { private void parsePAData(byte[] data) throws IOException, Asn1Exception { DerValue derPA = new DerValue(data); - List paList = new ArrayList(); + List paList = new ArrayList<>(); while (derPA.data.available() > 0) { // read the PA-DATA DerValue tmp = derPA.data.getDerValue(); diff --git a/jdk/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java b/jdk/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java index 7c2fbff849d..63ebe03d3c6 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java @@ -157,7 +157,7 @@ public class KrbCredInfo { * @exception IOException if an I/O error occurs while reading encoded data. */ public byte[] asn1Encode() throws Asn1Exception, IOException { - Vector v = new Vector (); + Vector v = new Vector<>(); v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), key.asn1Encode())); if (prealm != null) v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), prealm.asn1Encode())); diff --git a/jdk/src/share/classes/sun/security/krb5/internal/LastReq.java b/jdk/src/share/classes/sun/security/krb5/internal/LastReq.java index 578d955f45b..45ff8a81274 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/LastReq.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/LastReq.java @@ -77,7 +77,7 @@ public class LastReq { */ public LastReq(DerValue encoding) throws Asn1Exception, IOException { - Vector v= new Vector (); + Vector v= new Vector<>(); if (encoding.getTag() != DerValue.tag_Sequence) { throw new Asn1Exception(Krb5.ASN1_BAD_ID); } diff --git a/jdk/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java b/jdk/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java index 4f874903f79..46e5985f76f 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java @@ -490,7 +490,7 @@ public class FileCredentialsCache extends CredentialsCache private static String exec(String c) { StringTokenizer st = new StringTokenizer(c); - Vector v = new Vector (); + Vector v = new Vector<>(); while (st.hasMoreTokens()) { v.addElement(st.nextToken()); } diff --git a/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java b/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java index 90c0be67dae..85ba264944d 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java @@ -257,7 +257,7 @@ public abstract class EType { + configName); } - List list = new ArrayList (answer.length); + List list = new ArrayList<>(answer.length); for (int i = 0; i < answer.length; i++) { if (EncryptionKey.findKey(answer[i], keys) != null) { list.add(answer[i]); diff --git a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java index e0624e4db03..3c680fde166 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java @@ -57,7 +57,7 @@ public class KeyTab implements KeyTabConstants { private static KeyTab singleton = null; private static final boolean DEBUG = Krb5.DEBUG; private static String name; - private Vector entries = new Vector (); + private Vector entries = new Vector<>(); private KeyTab(String filename) throws IOException, RealmException { init(filename); @@ -240,7 +240,7 @@ public class KeyTab implements KeyTabConstants { KeyTabEntry entry; EncryptionKey key; int size = entries.size(); - ArrayList keys = new ArrayList (size); + ArrayList keys = new ArrayList<>(size); for (int i = size-1; i >= 0; i--) { entry = entries.elementAt(i); diff --git a/jdk/src/share/classes/sun/security/tools/JarSigner.java b/jdk/src/share/classes/sun/security/tools/JarSigner.java index 03809d37812..42d3bf57fd8 100644 --- a/jdk/src/share/classes/sun/security/tools/JarSigner.java +++ b/jdk/src/share/classes/sun/security/tools/JarSigner.java @@ -123,19 +123,19 @@ public class JarSigner { // or the default keystore, never null String keystore; // key store file - List crlfiles = new ArrayList(); // CRL files to add + List crlfiles = new ArrayList<>(); // CRL files to add boolean nullStream = false; // null keystore input stream (NONE) boolean token = false; // token-based keystore String jarfile; // jar files to sign or verify String alias; // alias to sign jar with - List ckaliases = new ArrayList(); // aliases in -verify + List ckaliases = new ArrayList<>(); // aliases in -verify char[] storepass; // keystore password boolean protectedPath; // protected authentication path String storetype; // keystore type String providerName; // provider name Vector providers = null; // list of providers // arguments for provider constructors - HashMap providerArgs = new HashMap(); + HashMap providerArgs = new HashMap<>(); char[] keypass; // private key password String sigfile; // name of .SF file String sigalg; // name of signature algorithm @@ -236,7 +236,7 @@ public class JarSigner { if (crlfiles.size() > 0 || autoCRL) { CertificateFactory fac = CertificateFactory.getInstance("X509"); - List list = new ArrayList(); + List list = new ArrayList<>(); for (String file: crlfiles) { Collection tmp = KeyTool.loadCRLs(file); for (CRL crl: tmp) { @@ -606,7 +606,7 @@ public class JarSigner { try { jf = new JarFile(jarName, true); - Vector entriesVec = new Vector(); + Vector entriesVec = new Vector<>(); byte[] buffer = new byte[8192]; Enumeration entries = jf.entries(); @@ -633,8 +633,7 @@ public class JarSigner { // The map to record display info, only used when -verbose provided // key: signer info string // value: the list of files with common key - Map> output = - new LinkedHashMap>(); + Map> output = new LinkedHashMap<>(); if (man != null) { if (verbose != null) System.out.println(); @@ -1000,8 +999,7 @@ public class JarSigner { .append(signTimeForm.format(source)).append("]").toString(); } - private Map cacheForInKS = - new IdentityHashMap(); + private Map cacheForInKS = new IdentityHashMap<>(); private int inKeyStoreForOneSigner(CodeSigner signer) { if (cacheForInKS.containsKey(signer)) { @@ -1044,8 +1042,7 @@ public class JarSigner { return result; } - Hashtable storeHash = - new Hashtable(); + Hashtable storeHash = new Hashtable<>(); int inKeyStore(CodeSigner[] signers) { @@ -1175,7 +1172,7 @@ public class JarSigner { * generated one. (This may invalidate existing signatures!) */ BASE64Encoder encoder = new JarBASE64Encoder(); - Vector mfFiles = new Vector(); + Vector mfFiles = new Vector<>(); boolean wasSigned = false; @@ -1531,7 +1528,7 @@ public class JarSigner { return false; } - Map cacheForSignerInfo = new IdentityHashMap(); + Map cacheForSignerInfo = new IdentityHashMap<>(); /** * Returns a string of singer info, with a newline at the end @@ -1655,7 +1652,7 @@ public class JarSigner { } } } - Set tas = new HashSet(); + Set tas = new HashSet<>(); try { KeyStore caks = KeyTool.getCacertsKeyStore(); if (caks != null) { diff --git a/jdk/src/share/classes/sun/security/tools/KeyTool.java b/jdk/src/share/classes/sun/security/tools/KeyTool.java index 5ce08316f35..897d407a1c2 100644 --- a/jdk/src/share/classes/sun/security/tools/KeyTool.java +++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java @@ -153,11 +153,11 @@ public final class KeyTool { private KeyStore caks = null; // "cacerts" keystore private char[] srcstorePass = null; private String srcstoretype = null; - private Set passwords = new HashSet (); + private Set passwords = new HashSet<>(); private String startDate = null; - private List ids = new ArrayList (); // used in GENCRL - private List v3ext = new ArrayList (); + private List ids = new ArrayList<>(); // used in GENCRL + private List v3ext = new ArrayList<>(); enum Command { CERTREQ("Generates.a.certificate.request", @@ -2091,7 +2091,7 @@ public final class KeyTool { */ public static List readCRLsFromCert(X509Certificate cert) throws Exception { - List crls = new ArrayList(); + List crls = new ArrayList<>(); CRLDistributionPointsExtension ext = X509CertImpl.toImpl(cert).getCRLDistributionPointsExtension(); if (ext == null) return crls; @@ -2258,7 +2258,7 @@ public final class KeyTool { if (jarfile != null) { JarFile jf = new JarFile(jarfile, true); Enumeration entries = jf.entries(); - Set ss = new HashSet(); + Set ss = new HashSet<>(); byte[] buffer = new byte[8192]; int pos = 0; while (entries.hasMoreElements()) { @@ -3347,7 +3347,7 @@ public final class KeyTool { } // start building chain - Vector chain = new Vector(2); + Vector chain = new Vector<>(2); if (buildChain((X509Certificate)certToVerify, chain, certs)) { Certificate[] newChain = new Certificate[chain.size()]; // buildChain() returns chain with self-signed root-cert first and @@ -3873,8 +3873,7 @@ public final class KeyTool { break; case 2: // EKU if(value != null) { - Vector v = - new Vector (); + Vector v = new Vector<>(); for (String s: value.split(",")) { int p = oneOf(s, "anyExtendedKeyUsage", @@ -3944,7 +3943,7 @@ public final class KeyTool { } if(value != null) { List accessDescriptions = - new ArrayList(); + new ArrayList<>(); String[] ps = value.split(","); for(String item: ps) { colonpos = item.indexOf(':'); @@ -4228,7 +4227,7 @@ class Pair { } public static Pair of(A a, B b) { - return new Pair(a,b); + return new Pair<>(a,b); } } diff --git a/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java b/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java index f310504a204..cc40a08e594 100644 --- a/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java +++ b/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java @@ -643,7 +643,7 @@ public class PolicyTool { Class pc = Class.forName(type, true, Thread.currentThread().getContextClassLoader()); Constructor c = null; - Vector objects = new Vector(2); + Vector objects = new Vector<>(2); if (name != null) objects.add(name); if (actions != null) objects.add(actions); switch (objects.size()) { @@ -1722,8 +1722,7 @@ class ToolDialog extends Dialog { new PolicyParser.GrantEntry(signedby, codebase); // get the new Principals - LinkedList prins = - new LinkedList(); + LinkedList prins = new LinkedList<>(); TaggedList prinList = (TaggedList)getComponent(PE_PRIN_LIST); for (int i = 0; i < prinList.getItemCount(); i++) { prins.add((PolicyParser.PrincipalEntry)prinList.getObject(i)); @@ -1731,8 +1730,7 @@ class ToolDialog extends Dialog { ge.principals = prins; // get the new Permissions - Vector perms = - new Vector(); + Vector perms = new Vector<>(); TaggedList permList = (TaggedList)getComponent(PE_PERM_LIST); for (int i = 0; i < permList.getItemCount(); i++) { perms.addElement((PolicyParser.PermissionEntry)permList.getObject(i)); @@ -3649,7 +3647,7 @@ class NoDisplayException extends RuntimeException { * This is a java.awt.List that bind an Object to each String it holds. */ class TaggedList extends List { - private java.util.List data = new LinkedList(); + private java.util.List data = new LinkedList<>(); public TaggedList(int i, boolean b) { super(i, b); } diff --git a/jdk/test/sun/security/krb5/IPv6.java b/jdk/test/sun/security/krb5/IPv6.java index 58abbe9739e..4b4f2a88767 100644 --- a/jdk/test/sun/security/krb5/IPv6.java +++ b/jdk/test/sun/security/krb5/IPv6.java @@ -78,8 +78,8 @@ public class IPv6 { try { Subject subject = new Subject(); Krb5LoginModule krb5 = new Krb5LoginModule(); - Map map = new HashMap(); - Map shared = new HashMap(); + Map map = new HashMap<>(); + Map shared = new HashMap<>(); map.put("debug", "true"); map.put("doNotPrompt", "true"); diff --git a/jdk/test/sun/security/krb5/auto/CleanState.java b/jdk/test/sun/security/krb5/auto/CleanState.java index cc6e7e54322..316a730edfe 100644 --- a/jdk/test/sun/security/krb5/auto/CleanState.java +++ b/jdk/test/sun/security/krb5/auto/CleanState.java @@ -49,11 +49,11 @@ public class CleanState { final char[] password = OneKDC.PASS; char[] badpassword = "hellokitty".toCharArray(); - Map map = new HashMap(); + Map map = new HashMap<>(); map.put("useTicketCache", "false"); map.put("doNotPrompt", "false"); map.put("tryFirstPass", "true"); - Map shared = new HashMap(); + Map shared = new HashMap<>(); shared.put("javax.security.auth.login.name", name); shared.put("javax.security.auth.login.password", badpassword); diff --git a/jdk/test/sun/security/krb5/auto/Context.java b/jdk/test/sun/security/krb5/auto/Context.java index 86726e3f7b9..4c67109121f 100644 --- a/jdk/test/sun/security/krb5/auto/Context.java +++ b/jdk/test/sun/security/krb5/auto/Context.java @@ -117,8 +117,8 @@ public class Context { out.name = user; out.s = new Subject(); Krb5LoginModule krb5 = new Krb5LoginModule(); - Map map = new HashMap(); - Map shared = new HashMap(); + Map map = new HashMap<>(); + Map shared = new HashMap<>(); if (pass != null) { map.put("useFirstPass", "true"); @@ -151,7 +151,7 @@ public class Context { out.name = user; out.s = new Subject(); Krb5LoginModule krb5 = new Krb5LoginModule(); - Map map = new HashMap(); + Map map = new HashMap<>(); map.put("doNotPrompt", "true"); map.put("useTicketCache", "false"); diff --git a/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java b/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java index 96323b76553..e25e60d6ab5 100644 --- a/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java +++ b/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java @@ -297,8 +297,8 @@ public class HttpNegotiateServer { } Krb5LoginModule krb5 = new Krb5LoginModule(); - Map map = new HashMap(); - Map shared = new HashMap(); + Map map = new HashMap<>(); + Map shared = new HashMap<>(); map.put("storeKey", "true"); map.put("isInitiator", "false"); diff --git a/jdk/test/sun/security/krb5/auto/KDC.java b/jdk/test/sun/security/krb5/auto/KDC.java index 796415bb03e..36dc08b4ae6 100644 --- a/jdk/test/sun/security/krb5/auto/KDC.java +++ b/jdk/test/sun/security/krb5/auto/KDC.java @@ -132,7 +132,7 @@ public class KDC { // Principal db. principal -> pass. A case-insensitive TreeMap is used // so that even if the client provides a name with different case, the KDC // can still locate the principal and give back correct salt. - private TreeMap passwords = new TreeMap + private TreeMap passwords = new TreeMap<> (String.CASE_INSENSITIVE_ORDER); // Realm name @@ -142,9 +142,9 @@ public class KDC { // Service port number private int port; // The request/response job queue - private BlockingQueue q = new ArrayBlockingQueue(100); + private BlockingQueue q = new ArrayBlockingQueue<>(100); // Options - private Map options = new HashMap(); + private Map options = new HashMap<>(); private Thread thread1, thread2, thread3; DatagramSocket u1 = null; @@ -537,7 +537,7 @@ public class KDC { } } - private Map policies = new HashMap(); + private Map policies = new HashMap<>(); public void setPolicy(String rule, String value) { if (value == null) { @@ -760,7 +760,7 @@ public class KDC { private byte[] processAsReq(byte[] in) throws Exception { ASReq asReq = new ASReq(in); int[] eTypes = null; - List outPAs = new ArrayList(); + List outPAs = new ArrayList<>(); try { System.out.println(realm + "> " + asReq.reqBody.cname + diff --git a/jdk/test/sun/security/krb5/auto/LoginModuleOptions.java b/jdk/test/sun/security/krb5/auto/LoginModuleOptions.java index 44c4a414d0d..f22f774316f 100644 --- a/jdk/test/sun/security/krb5/auto/LoginModuleOptions.java +++ b/jdk/test/sun/security/krb5/auto/LoginModuleOptions.java @@ -135,8 +135,8 @@ public class LoginModuleOptions { throws Exception { Krb5LoginModule krb5 = new Krb5LoginModule(); Subject subject = new Subject(); - Map map = new HashMap(); - Map shared = new HashMap(); + Map map = new HashMap<>(); + Map shared = new HashMap<>(); int count = options.length / 2; for (int i = 0; i < count; i++) { diff --git a/jdk/test/sun/security/krb5/tools/KtabCheck.java b/jdk/test/sun/security/krb5/tools/KtabCheck.java index 0fe8b783168..e82b83ac740 100644 --- a/jdk/test/sun/security/krb5/tools/KtabCheck.java +++ b/jdk/test/sun/security/krb5/tools/KtabCheck.java @@ -39,7 +39,7 @@ public class KtabCheck { public static void main(String[] args) throws Exception { System.out.println("Checking " + Arrays.toString(args)); KeyTab ktab = KeyTab.getInstance(args[0]); - Set expected = new HashSet(); + Set expected = new HashSet<>(); for (int i=1; i Date: Wed, 12 Jan 2011 13:59:18 -0800 Subject: [PATCH 039/152] 7009828: Fix for 6938627 breaks visualvm monitoring when -Djava.io.tmpdir is defined Change get_temp_directory() back to /tmp and %TEMP% like it always was and where the tools expect it to be. Reviewed-by: phh, dcubed, kamg, alanb --- hotspot/src/os/linux/vm/os_linux.cpp | 7 +++---- hotspot/src/os/solaris/vm/os_solaris.cpp | 7 +++---- hotspot/src/os/windows/vm/os_windows.cpp | 4 ++-- hotspot/src/share/vm/utilities/vmError.cpp | 10 ++++++---- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 330e347a7e5..5d34fc50c7d 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -1610,10 +1610,9 @@ int os::current_process_id() { const char* os::dll_file_extension() { return ".so"; } -const char* os::get_temp_directory() { - const char *prop = Arguments::get_property("java.io.tmpdir"); - return prop == NULL ? "/tmp" : prop; -} +// This must be hard coded because it's the system's temporary +// directory not the java application's temp directory, ala java.io.tmpdir. +const char* os::get_temp_directory() { return "/tmp"; } static bool file_exists(const char* filename) { struct stat statbuf; diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index f6f816cf3ad..80c7c4d5058 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -1884,10 +1884,9 @@ void os::set_error_file(const char *logfile) {} const char* os::dll_file_extension() { return ".so"; } -const char* os::get_temp_directory() { - const char *prop = Arguments::get_property("java.io.tmpdir"); - return prop == NULL ? "/tmp" : prop; -} +// This must be hard coded because it's the system's temporary +// directory not the java application's temp directory, ala java.io.tmpdir. +const char* os::get_temp_directory() { return "/tmp"; } static bool file_exists(const char* filename) { struct stat statbuf; diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 0422063c50e..2eeb3d33392 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -1044,9 +1044,9 @@ os::closedir(DIR *dirp) return 0; } +// This must be hard coded because it's the system's temporary +// directory not the java application's temp directory, ala java.io.tmpdir. const char* os::get_temp_directory() { - const char *prop = Arguments::get_property("java.io.tmpdir"); - if (prop != 0) return prop; static char path_buf[MAX_PATH]; if (GetTempPath(MAX_PATH, path_buf)>0) return path_buf; diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index 4b8e055d496..662e5a7c91a 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -874,11 +874,13 @@ void VMError::report_and_die() { } if (fd == -1) { - // try temp directory const char * tmpdir = os::get_temp_directory(); - jio_snprintf(buffer, sizeof(buffer), "%s%shs_err_pid%u.log", - tmpdir, os::file_separator(), os::current_process_id()); - fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666); + // try temp directory if it exists. + if (tmpdir != NULL && tmpdir[0] != '\0') { + jio_snprintf(buffer, sizeof(buffer), "%s%shs_err_pid%u.log", + tmpdir, os::file_separator(), os::current_process_id()); + fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666); + } } if (fd != -1) { From efefa140388e224dc30e3597e7fde824a26feaff Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 12 Jan 2011 15:58:15 -0800 Subject: [PATCH 040/152] 6958221: java.awt.Font.getFamily() leads to JVM crash on Linux on JDK7 for "custom" fonts Reviewed-by: igor, jgodinez --- jdk/make/sun/awt/mapfile-mawt-vers | 3 +- jdk/make/sun/awt/mapfile-vers-linux | 3 +- jdk/make/sun/headless/mapfile-vers | 1 - jdk/make/sun/xawt/mapfile-vers | 3 +- .../classes/sun/awt/X11FontManager.java | 26 ++----- .../classes/sun/awt/motif/MToolkit.java | 7 -- jdk/src/solaris/native/sun/awt/fontpath.c | 74 ++----------------- .../awt/FontClass/X11FontPathCrashTest.java | 41 ++++++++++ 8 files changed, 58 insertions(+), 100 deletions(-) create mode 100644 jdk/test/java/awt/FontClass/X11FontPathCrashTest.java diff --git a/jdk/make/sun/awt/mapfile-mawt-vers b/jdk/make/sun/awt/mapfile-mawt-vers index b80f30fed50..f1b7143e948 100644 --- a/jdk/make/sun/awt/mapfile-mawt-vers +++ b/jdk/make/sun/awt/mapfile-mawt-vers @@ -515,8 +515,7 @@ SUNWprivate_1.1 { getDefaultConfig; Java_sun_font_FontConfigManager_getFontConfig; Java_sun_font_FontConfigManager_getFontConfigAASettings; - Java_sun_awt_X11FontManager_getFontPath; - Java_sun_awt_X11FontManager_setNativeFontPath; + Java_sun_awt_X11FontManager_getFontPathNative; Java_sun_font_SunFontManager_populateFontFileNameMap; # CDE private entry point diff --git a/jdk/make/sun/awt/mapfile-vers-linux b/jdk/make/sun/awt/mapfile-vers-linux index 60fa9ccef69..d2fbf560c9b 100644 --- a/jdk/make/sun/awt/mapfile-vers-linux +++ b/jdk/make/sun/awt/mapfile-vers-linux @@ -537,8 +537,7 @@ SUNWprivate_1.1 { getDefaultConfig; Java_sun_font_FontConfigManager_getFontConfig; Java_sun_font_FontConfigManager_getFontConfigAASettings; - Java_sun_awt_X11FontManager_getFontPath; - Java_sun_awt_X11FontManager_setNativeFontPath; + Java_sun_awt_X11FontManager_getFontPathNative; Java_sun_font_SunFontManager_populateFontFileNameMap; # CDE private entry point diff --git a/jdk/make/sun/headless/mapfile-vers b/jdk/make/sun/headless/mapfile-vers index c82b6116fcc..d04e70700f0 100644 --- a/jdk/make/sun/headless/mapfile-vers +++ b/jdk/make/sun/headless/mapfile-vers @@ -65,7 +65,6 @@ SUNWprivate_1.1 { Java_sun_font_FontConfigManager_getFontConfig; Java_sun_font_FontConfigManager_getFontConfigAASettings; Java_sun_font_FontConfigManager_getFontConfigVersion; - Java_sun_awt_X11FontManager_getFontPath; Java_sun_awt_FontDescriptor_initIDs; Java_sun_awt_PlatformFont_initIDs; diff --git a/jdk/make/sun/xawt/mapfile-vers b/jdk/make/sun/xawt/mapfile-vers index 7eac730927d..479a55a800d 100644 --- a/jdk/make/sun/xawt/mapfile-vers +++ b/jdk/make/sun/xawt/mapfile-vers @@ -188,8 +188,7 @@ SUNWprivate_1.1 { Java_sun_font_FontConfigManager_getFontConfig; Java_sun_font_FontConfigManager_getFontConfigAASettings; Java_sun_font_FontConfigManager_getFontConfigVersion; - Java_sun_awt_X11FontManager_getFontPath; - Java_sun_font_X11FontManager_setNativeFontPath; + Java_sun_awt_X11FontManager_getFontPathNative; Java_sun_awt_X11GraphicsEnvironment_initDisplay; Java_sun_awt_X11GraphicsEnvironment_initGLX; Java_sun_awt_X11GraphicsEnvironment_initXRender; diff --git a/jdk/src/solaris/classes/sun/awt/X11FontManager.java b/jdk/src/solaris/classes/sun/awt/X11FontManager.java index fea46ff56c3..36eeb15d607 100644 --- a/jdk/src/solaris/classes/sun/awt/X11FontManager.java +++ b/jdk/src/solaris/classes/sun/awt/X11FontManager.java @@ -718,25 +718,6 @@ public class X11FontManager extends SunFontManager { fontdirs = (String[])fontConfigDirs.toArray(new String[0]); } - /* Called by MToolkit to set the X11 font path */ - public static void setNativeFontPath() { - if (fontdirs == null) { - return; - } - - // need to register these individually rather than by one call - // to ensure that one bad directory doesn't cause all to be rejected - for (int i=0; iSolaris the paths needed by the JRE should - * also be available to the server, although we have no way to check this - * for sure. - * So set the font path if we think its safe to do so: - * All Solaris X servers at least back to 2.6 and up to Solaris 10 - * define the exact same vendor string. - * The version number for Solaris 2.6 is 3600, for 2.7 is 3610 and - * for Solaris 8 6410 - * we want to set the font path only for 2.8 and onwards. Earlier releases - * are unlikely to have the right fonts and can't install "all locales" - * as needed to be sure. Also Solaris 8 is the earliest release supported - * by 1.5. - */ -#ifndef HEADLESS -static int isSunXServer() { -#ifdef __solaris__ - return ((strncmp(ServerVendor(awt_display), "Sun Microsystems, Inc.", 22) == 0) || - (strncmp(ServerVendor(awt_display), "Oracle Corporation", 18) == 0) && - VendorRelease(awt_display) >= 6410); -#else - return 0; -#endif /* __solaris__ */ -} - -/* Avoid re-doing work for every call to setNativeFontPath */ -static int doSetFontPath = -1; -static int shouldSetXFontPath(JNIEnv *env) { - if (doSetFontPath == -1) { - doSetFontPath = - awt_display != NULL && (isDisplayLocal(env) || isSunXServer()); - } - return doSetFontPath; -} -#endif /* !HEADLESS */ - -JNIEXPORT void JNICALL Java_sun_font_X11FontManager_setNativeFontPath -(JNIEnv *env, jclass obj, jstring theString) { -#ifdef HEADLESS - return; -#else - fDirRecord fDir; - const char *theChars; - - if (awt_display == NULL) { - return; - } - AWT_LOCK(); - if (shouldSetXFontPath(env)) { - theChars = (*env)->GetStringUTFChars (env, theString, 0); - fDir.num = 1; - fDir.name[0] = theChars; - /* printf ("Registering the font path here %s \n", theChars ); */ - AddFontsToX11FontPath ( &fDir ); - if (theChars) { - (*env)->ReleaseStringUTFChars (env, - theString, (const char*)theChars); - } - } - AWT_UNLOCK(); - -#endif -} - #include #ifndef __linux__ /* i.e. is solaris */ #include diff --git a/jdk/test/java/awt/FontClass/X11FontPathCrashTest.java b/jdk/test/java/awt/FontClass/X11FontPathCrashTest.java new file mode 100644 index 00000000000..cbc762a36ed --- /dev/null +++ b/jdk/test/java/awt/FontClass/X11FontPathCrashTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2011, 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 6958221 + * @summary Test no crashing getting fonts on X11 + * @run main X11FontPathCrashTest + */ + +import java.awt.*; +import java.awt.font.*; +import java.awt.geom.*; + + +public class X11FontPathCrashTest { + public static void main(String[] args) { + new Font("nonexistentfont", Font.PLAIN, 12).getFamily(); + } +} + From 18619a6ed64bd8587656b7a17e17c4e106d083c4 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Wed, 12 Jan 2011 18:33:25 -0800 Subject: [PATCH 041/152] 7011627: C1: call_RT must support targets that don't fit in wdisp30 Make both compilers emit near and far calls when necessary. Reviewed-by: never, kvn, phh --- hotspot/src/cpu/sparc/vm/assembler_sparc.hpp | 20 ++++++++++---- .../cpu/sparc/vm/assembler_sparc.inline.hpp | 17 ++++++------ hotspot/src/cpu/sparc/vm/sparc.ad | 27 +++++++------------ 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index 253193868f2..54989c335c1 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -823,15 +823,23 @@ class Assembler : public AbstractAssembler { }; // test if x is within signed immediate range for nbits - static bool is_simm(int x, int nbits) { return -( 1 << nbits-1 ) <= x && x < ( 1 << nbits-1 ); } + static bool is_simm(intptr_t x, int nbits) { return -( intptr_t(1) << nbits-1 ) <= x && x < ( intptr_t(1) << nbits-1 ); } // test if -4096 <= x <= 4095 - static bool is_simm13(int x) { return is_simm(x, 13); } + static bool is_simm13(intptr_t x) { return is_simm(x, 13); } + + static bool is_in_wdisp_range(address a, address b, int nbits) { + intptr_t d = intptr_t(b) - intptr_t(a); + return is_simm(d, nbits + 2); + } // test if label is in simm16 range in words (wdisp16). bool is_in_wdisp16_range(Label& L) { - intptr_t d = intptr_t(pc()) - intptr_t(target(L)); - return is_simm(d, 18); + return is_in_wdisp_range(target(L), pc(), 16); + } + // test if the distance between two addresses fits in simm30 range in words + static bool is_in_wdisp30_range(address a, address b) { + return is_in_wdisp_range(a, b, 30); } enum ASIs { // page 72, v9 @@ -1843,6 +1851,8 @@ class MacroAssembler: public Assembler { inline void jmp( Register s1, Register s2 ); inline void jmp( Register s1, int simm13a, RelocationHolder const& rspec = RelocationHolder() ); + // Check if the call target is out of wdisp30 range (relative to the code cache) + static inline bool is_far_target(address d); inline void call( address d, relocInfo::relocType rt = relocInfo::runtime_call_type ); inline void call( Label& L, relocInfo::relocType rt = relocInfo::runtime_call_type ); inline void callr( Register s1, Register s2 ); diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp index 106aa14e5b0..9b292b0ad81 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -588,10 +588,13 @@ inline void MacroAssembler::fbp( Condition c, bool a, CC cc, Predict p, Label& L inline void MacroAssembler::jmp( Register s1, Register s2 ) { jmpl( s1, s2, G0 ); } inline void MacroAssembler::jmp( Register s1, int simm13a, RelocationHolder const& rspec ) { jmpl( s1, simm13a, G0, rspec); } +inline bool MacroAssembler::is_far_target(address d) { + return !is_in_wdisp30_range(d, CodeCache::low_bound()) || !is_in_wdisp30_range(d, CodeCache::high_bound()); +} + // Call with a check to see if we need to deal with the added // expense of relocation and if we overflow the displacement -// of the quick call instruction./ -// Check to see if we have to deal with relocations +// of the quick call instruction. inline void MacroAssembler::call( address d, relocInfo::relocType rt ) { #ifdef _LP64 intptr_t disp; @@ -603,14 +606,12 @@ inline void MacroAssembler::call( address d, relocInfo::relocType rt ) { // Is this address within range of the call instruction? // If not, use the expensive instruction sequence - disp = (intptr_t)d - (intptr_t)pc(); - if ( disp != (intptr_t)(int32_t)disp ) { + if (is_far_target(d)) { relocate(rt); AddressLiteral dest(d); jumpl_to(dest, O7, O7); - } - else { - Assembler::call( d, rt ); + } else { + Assembler::call(d, rt); } #else Assembler::call( d, rt ); diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 25117f205b2..422b83f1476 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1998, 2011, 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 @@ -575,7 +575,11 @@ int MachCallDynamicJavaNode::ret_addr_offset() { int MachCallRuntimeNode::ret_addr_offset() { #ifdef _LP64 - return NativeFarCall::instruction_size; // farcall; delay slot + if (MacroAssembler::is_far_target(entry_point())) { + return NativeFarCall::instruction_size; + } else { + return NativeCall::instruction_size; + } #else return NativeCall::instruction_size; // call; delay slot #endif @@ -941,7 +945,7 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, const MachNode* n, int primary, int te #endif } -void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocType rtype, bool preserve_g2 = false, bool force_far_call = false) { +void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocType rtype, bool preserve_g2 = false) { // The method which records debug information at every safepoint // expects the call to be the first instruction in the snippet as // it creates a PcDesc structure which tracks the offset of a call @@ -963,20 +967,7 @@ void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocTyp int startpos = __ offset(); #endif /* ASSERT */ -#ifdef _LP64 - // Calls to the runtime or native may not be reachable from compiled code, - // so we generate the far call sequence on 64 bit sparc. - // This code sequence is relocatable to any address, even on LP64. - if ( force_far_call ) { - __ relocate(rtype); - AddressLiteral dest(entry_point); - __ jumpl_to(dest, O7, O7); - } - else -#endif - { - __ call((address)entry_point, rtype); - } + __ call((address)entry_point, rtype); if (preserve_g2) __ delayed()->mov(G2, L7); else __ delayed()->nop(); @@ -2507,7 +2498,7 @@ encode %{ // CALL directly to the runtime // The user of this is responsible for ensuring that R_L7 is empty (killed). emit_call_reloc(cbuf, $meth$$method, relocInfo::runtime_call_type, - /*preserve_g2=*/true, /*force far call*/true); + /*preserve_g2=*/true); %} enc_class preserve_SP %{ From de3e3830d21d0c8961c88fcbb08d2bca02e9b279 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Thu, 13 Jan 2011 11:01:30 +0000 Subject: [PATCH 042/152] 6896088: URLClassLoader.close() apparently not working for JAR URLs on Windows Reviewed-by: chegar --- .../share/classes/sun/misc/URLClassPath.java | 18 ++- .../java/net/URLClassLoader/B6896088.java | 130 ++++++++++++++++++ 2 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/net/URLClassLoader/B6896088.java diff --git a/jdk/src/share/classes/sun/misc/URLClassPath.java b/jdk/src/share/classes/sun/misc/URLClassPath.java index c828ab3e16e..d7664f1be7b 100644 --- a/jdk/src/share/classes/sun/misc/URLClassPath.java +++ b/jdk/src/share/classes/sun/misc/URLClassPath.java @@ -466,6 +466,7 @@ public class URLClassPath { */ private static class Loader implements Closeable { private final URL base; + private JarFile jarfile; // if this points to a jar file /* * Creates a new Loader for the specified URL. @@ -530,6 +531,17 @@ public class URLClassPath { } uc = url.openConnection(); InputStream in = uc.getInputStream(); + if (uc instanceof JarURLConnection) { + /* JarURLConnection.getInputStream() returns a separate + * instance on each call. So we have to close this here. + * The jar file cache will keep the file open. + * Also, need to remember the jar file so it can be closed + * in a hurry. + */ + JarURLConnection juc = (JarURLConnection)uc; + jarfile = juc.getJarFile(); + in.close(); + } } catch (Exception e) { return null; } @@ -559,7 +571,11 @@ public class URLClassPath { * close this loader and release all resources * method overridden in sub-classes */ - public void close () throws IOException {} + public void close () throws IOException { + if (jarfile != null) { + jarfile.close(); + } + } /* * Returns the local class path for this loader, or null if none. diff --git a/jdk/test/java/net/URLClassLoader/B6896088.java b/jdk/test/java/net/URLClassLoader/B6896088.java new file mode 100644 index 00000000000..4e0792b0345 --- /dev/null +++ b/jdk/test/java/net/URLClassLoader/B6896088.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2011, 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 6896088 + * @run main/othervm B6896088 + * @summary URLClassLoader.close() apparently not working for JAR URLs on Windows + */ + +import java.net.*; +import java.io.*; +import java.nio.file.Path; + +public class B6896088 { + + public static void main(String[] args) throws Exception { + + String dir = System.getProperty ("test.classes"); + File jarf = new File (dir, "foo.jar"); + FileOutputStream fos = new FileOutputStream (jarf); + fos.write(bytes(nums)); + fos.close(); + + // Create URL using JAR protocol + String jarName = (jarf.toURI()).toString(); + URL url = new URL("jar", "", jarName + "!/"); + + // Create URLClassLoader from the URL + URLClassLoader loader = new URLClassLoader(new URL[]{url}); + Class c = loader.loadClass("Foo"); + + // Close the URLClassLoader so we can delete/update the jar file + loader.close(); + + // Now try to delete the jar file + + if (jarf.delete() && !jarf.exists()) { + System.out.println(jarf.getName()+" File Deleted"); + } else { + System.out.println(jarf.getName()+" File Not Deleted"); + throw new RuntimeException ("File not deleted"); + } + } + + static byte[] bytes (int[] i) { + byte[] buf = new byte [i.length]; + + for (int j=0; j Date: Thu, 13 Jan 2011 04:43:30 -0800 Subject: [PATCH 043/152] 6941122: G1: UseLargePages does not work with G1 garbage collector Pass the value of UseLargePages instead of false as the "large" parameter when reserving the G1 heap. Reviewed-by: tonyp, johnc, phh --- .../src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 3fddd0b1e31..2fa2fdb8f0b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1907,7 +1907,7 @@ jint G1CollectedHeap::initialize() { ReservedSpace heap_rs(max_byte_size + pgs->max_size(), HeapRegion::GrainBytes, - false /*ism*/, addr); + UseLargePages, addr); if (UseCompressedOops) { if (addr != NULL && !heap_rs.is_reserved()) { @@ -1916,13 +1916,13 @@ jint G1CollectedHeap::initialize() { // Try again to reserver heap higher. addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop); ReservedSpace heap_rs0(total_reserved, HeapRegion::GrainBytes, - false /*ism*/, addr); + UseLargePages, addr); if (addr != NULL && !heap_rs0.is_reserved()) { // Failed to reserve at specified address again - give up. addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop); assert(addr == NULL, ""); ReservedSpace heap_rs1(total_reserved, HeapRegion::GrainBytes, - false /*ism*/, addr); + UseLargePages, addr); heap_rs = heap_rs1; } else { heap_rs = heap_rs0; From ab0fe3d421664d083b77a7702c051a7fb43d02e8 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Thu, 13 Jan 2011 13:24:58 +0000 Subject: [PATCH 044/152] 6964547: Impossible to set useV4 in SocksSocketImpl Add socksProxyVersion property Reviewed-by: alanb, michaelm --- jdk/make/sun/net/FILES_java.gmk | 1 + .../share/classes/java/io/PrintStream.java | 2 +- .../classes/java/net/SocksSocketImpl.java | 13 ++- .../java/net/doc-files/net-properties.html | 7 +- jdk/src/share/classes/sun/net/SocksProxy.java | 49 ++++++++++ .../sun/net/spi/DefaultProxySelector.java | 20 +++- .../java/net/Socks/SocksProxyVersion.java | 98 +++++++++++++++++++ 7 files changed, 182 insertions(+), 8 deletions(-) create mode 100644 jdk/src/share/classes/sun/net/SocksProxy.java create mode 100644 jdk/test/java/net/Socks/SocksProxyVersion.java diff --git a/jdk/make/sun/net/FILES_java.gmk b/jdk/make/sun/net/FILES_java.gmk index 23c94b42ab0..576159c4799 100644 --- a/jdk/make/sun/net/FILES_java.gmk +++ b/jdk/make/sun/net/FILES_java.gmk @@ -33,6 +33,7 @@ FILES_java = \ sun/net/ProgressEvent.java \ sun/net/ProgressListener.java \ sun/net/ProgressMeteringPolicy.java \ + sun/net/SocksProxy.java \ sun/net/TelnetInputStream.java \ sun/net/TelnetOutputStream.java \ sun/net/TelnetProtocolException.java \ diff --git a/jdk/src/share/classes/java/io/PrintStream.java b/jdk/src/share/classes/java/io/PrintStream.java index 87d425bfeb0..9ed3ff6f910 100644 --- a/jdk/src/share/classes/java/io/PrintStream.java +++ b/jdk/src/share/classes/java/io/PrintStream.java @@ -70,7 +70,7 @@ public class PrintStream extends FilterOutputStream private OutputStreamWriter charOut; /** - * nonNull is explicitly delcared here so as not to create an extra + * nonNull is explicitly declared here so as not to create an extra * dependency on java.util.Objects.nonNull. PrintStream is loaded * early during system initialization. */ diff --git a/jdk/src/share/classes/java/net/SocksSocketImpl.java b/jdk/src/share/classes/java/net/SocksSocketImpl.java index 99161753cda..4fb61efe633 100644 --- a/jdk/src/share/classes/java/net/SocksSocketImpl.java +++ b/jdk/src/share/classes/java/net/SocksSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, 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 @@ -29,6 +29,7 @@ import java.io.OutputStream; import java.io.BufferedOutputStream; import java.security.AccessController; import java.security.PrivilegedExceptionAction; +import sun.net.SocksProxy; import sun.net.www.ParseUtil; /* import org.ietf.jgss.*; */ @@ -397,6 +398,11 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { // Use getHostString() to avoid reverse lookups server = ((InetSocketAddress) p.address()).getHostString(); serverPort = ((InetSocketAddress) p.address()).getPort(); + if (p instanceof SocksProxy) { + if (((SocksProxy)p).protocolVersion() == 4) { + useV4 = true; + } + } // Connects to the SOCKS server try { @@ -700,6 +706,11 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { // Use getHostString() to avoid reverse lookups server = ((InetSocketAddress) p.address()).getHostString(); serverPort = ((InetSocketAddress) p.address()).getPort(); + if (p instanceof SocksProxy) { + if (((SocksProxy)p).protocolVersion() == 4) { + useV4 = true; + } + } // Connects to the SOCKS server try { diff --git a/jdk/src/share/classes/java/net/doc-files/net-properties.html b/jdk/src/share/classes/java/net/doc-files/net-properties.html index fffdfebc431..ae39fec8e8b 100644 --- a/jdk/src/share/classes/java/net/doc-files/net-properties.html +++ b/jdk/src/share/classes/java/net/doc-files/net-properties.html @@ -127,10 +127,15 @@ of proxies.

are specified. If SOCKS is supported by a Java SE implementation, the following properties will be used: