mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
Merge
This commit is contained in:
commit
86f7ad735d
124 changed files with 5920 additions and 6593 deletions
|
@ -121,15 +121,13 @@ static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct use
|
||||||
#define ptrace_getregs(request, pid, addr, data) ptrace(request, pid, data, addr)
|
#define ptrace_getregs(request, pid, addr, data) ptrace(request, pid, data, addr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _LP64
|
#if defined(_LP64) && defined(PTRACE_GETREGS64)
|
||||||
#ifdef PTRACE_GETREGS64
|
|
||||||
#define PTRACE_GETREGS_REQ PTRACE_GETREGS64
|
#define PTRACE_GETREGS_REQ PTRACE_GETREGS64
|
||||||
#endif
|
#elif defined(PTRACE_GETREGS)
|
||||||
#else
|
|
||||||
#if defined(PTRACE_GETREGS) || defined(PT_GETREGS)
|
|
||||||
#define PTRACE_GETREGS_REQ PTRACE_GETREGS
|
#define PTRACE_GETREGS_REQ PTRACE_GETREGS
|
||||||
|
#elif defined(PT_GETREGS)
|
||||||
|
#define PTRACE_GETREGS_REQ PT_GETREGS
|
||||||
#endif
|
#endif
|
||||||
#endif /* _LP64 */
|
|
||||||
|
|
||||||
#ifdef PTRACE_GETREGS_REQ
|
#ifdef PTRACE_GETREGS_REQ
|
||||||
if (ptrace_getregs(PTRACE_GETREGS_REQ, pid, user, NULL) < 0) {
|
if (ptrace_getregs(PTRACE_GETREGS_REQ, pid, user, NULL) < 0) {
|
||||||
|
|
|
@ -101,15 +101,14 @@ ifndef HOTSPOT_RELEASE_VERSION
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef HOTSPOT_BUILD_VERSION
|
ifdef HOTSPOT_BUILD_VERSION
|
||||||
# specified in command line (PRT build)
|
# specified in command line
|
||||||
else
|
|
||||||
ifdef JPRT_BUILD_VERSION
|
|
||||||
# JPR build
|
|
||||||
HOTSPOT_BUILD_VERSION=$(JPRT_BUILD_VERSION)
|
|
||||||
else
|
else
|
||||||
ifdef COOKED_BUILD_NUMBER
|
ifdef COOKED_BUILD_NUMBER
|
||||||
# JRE build
|
# JRE build
|
||||||
HOTSPOT_BUILD_VERSION=
|
HOTSPOT_BUILD_VERSION=
|
||||||
|
else
|
||||||
|
ifdef USER_RELEASE_SUFFIX
|
||||||
|
HOTSPOT_BUILD_VERSION=internal-$(USER_RELEASE_SUFFIX)
|
||||||
else
|
else
|
||||||
HOTSPOT_BUILD_VERSION=internal
|
HOTSPOT_BUILD_VERSION=internal
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -25,9 +25,6 @@
|
||||||
# JPRT rule to build this workspace
|
# JPRT rule to build this workspace
|
||||||
|
|
||||||
JPRT_ARCHIVE_BUNDLE=$(ABS_OUTPUTDIR)/$(JPRT_BUILD_FLAVOR)-bundle.zip
|
JPRT_ARCHIVE_BUNDLE=$(ABS_OUTPUTDIR)/$(JPRT_BUILD_FLAVOR)-bundle.zip
|
||||||
ifdef JPRT_BUILD_VERSION
|
|
||||||
MILESTONE=$(JPRT_BUILD_VERSION)
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(OSNAME),windows)
|
ifeq ($(OSNAME),windows)
|
||||||
ZIPFLAGS=-q
|
ZIPFLAGS=-q
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
# If we're cross compiling use that path for nm
|
# If we're cross compiling use that path for nm
|
||||||
if [ "$ALT_COMPILER_PATH" != "" ]; then
|
if [ "$CROSS_COMPILE_ARCH" != "" ]; then
|
||||||
NM=$ALT_COMPILER_PATH/nm
|
NM=$ALT_COMPILER_PATH/nm
|
||||||
else
|
else
|
||||||
NM=nm
|
NM=nm
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
# OS_FAMILY - operating system
|
# OS_FAMILY - operating system
|
||||||
# VARIANT - core, compiler1, compiler2, or tiered
|
# VARIANT - core, compiler1, compiler2, or tiered
|
||||||
# HOTSPOT_RELEASE_VERSION - <major>.<minor>-b<nn> (11.0-b07)
|
# HOTSPOT_RELEASE_VERSION - <major>.<minor>-b<nn> (11.0-b07)
|
||||||
# HOTSPOT_BUILD_VERSION - internal, PRTjob ID, JPRTjob ID
|
# HOTSPOT_BUILD_VERSION - internal, internal-$(USER_RELEASE_SUFFIX) or empty
|
||||||
# JRE_RELEASE_VERSION - <major>.<minor>.<micro> (1.7.0)
|
# JRE_RELEASE_VERSION - <major>.<minor>.<micro> (1.7.0)
|
||||||
#
|
#
|
||||||
# Builds the directory trees with makefiles plus some convenience files in
|
# Builds the directory trees with makefiles plus some convenience files in
|
||||||
|
|
|
@ -25,7 +25,9 @@
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
# CC, CPP & AS
|
# CC, CPP & AS
|
||||||
|
|
||||||
ifdef ALT_COMPILER_PATH
|
# When cross-compiling the ALT_COMPILER_PATH points
|
||||||
|
# to the cross-compilation toolset
|
||||||
|
ifdef CROSS_COMPILE_ARCH
|
||||||
CPP = $(ALT_COMPILER_PATH)/g++
|
CPP = $(ALT_COMPILER_PATH)/g++
|
||||||
CC = $(ALT_COMPILER_PATH)/gcc
|
CC = $(ALT_COMPILER_PATH)/gcc
|
||||||
else
|
else
|
||||||
|
@ -42,11 +44,14 @@ CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
|
||||||
|
|
||||||
# check for precompiled headers support
|
# check for precompiled headers support
|
||||||
ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 4 \) \))" "0"
|
ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 4 \) \))" "0"
|
||||||
|
# Allow the user to turn off precompiled headers from the command line.
|
||||||
|
ifneq ($(USE_PRECOMPILED_HEADER),0)
|
||||||
USE_PRECOMPILED_HEADER=1
|
USE_PRECOMPILED_HEADER=1
|
||||||
PRECOMPILED_HEADER_DIR=.
|
PRECOMPILED_HEADER_DIR=.
|
||||||
PRECOMPILED_HEADER_SRC=$(GAMMADIR)/src/share/vm/precompiled.hpp
|
PRECOMPILED_HEADER_SRC=$(GAMMADIR)/src/share/vm/precompiled.hpp
|
||||||
PRECOMPILED_HEADER=$(PRECOMPILED_HEADER_DIR)/precompiled.hpp.gch
|
PRECOMPILED_HEADER=$(PRECOMPILED_HEADER_DIR)/precompiled.hpp.gch
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
|
@ -150,6 +155,11 @@ ifneq ("${CC_VER_MAJOR}", "2")
|
||||||
DEPFLAGS = -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
|
DEPFLAGS = -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp.
|
||||||
|
ifneq ($(USE_PRECOMPILED_HEADER),1)
|
||||||
|
CFLAGS += -DDONT_USE_PRECOMPILED_HEADER
|
||||||
|
endif
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
# Linker flags
|
# Linker flags
|
||||||
|
|
||||||
|
|
|
@ -24,19 +24,23 @@
|
||||||
|
|
||||||
# Rules to build gamma launcher, used by vm.make
|
# Rules to build gamma launcher, used by vm.make
|
||||||
|
|
||||||
# gamma[_g]: launcher
|
|
||||||
|
|
||||||
|
LAUNCHER_SCRIPT = hotspot
|
||||||
LAUNCHER = gamma
|
LAUNCHER = gamma
|
||||||
LAUNCHER_G = $(LAUNCHER)$(G_SUFFIX)
|
|
||||||
|
|
||||||
LAUNCHERDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/launcher
|
LAUNCHERDIR := $(GAMMADIR)/src/os/posix/launcher
|
||||||
LAUNCHERFLAGS = $(ARCHFLAG) \
|
LAUNCHERDIR_SHARE := $(GAMMADIR)/src/share/tools/launcher
|
||||||
|
LAUNCHERFLAGS := $(ARCHFLAG) \
|
||||||
-I$(LAUNCHERDIR) -I$(GAMMADIR)/src/share/vm/prims \
|
-I$(LAUNCHERDIR) -I$(GAMMADIR)/src/share/vm/prims \
|
||||||
|
-I$(LAUNCHERDIR_SHARE) \
|
||||||
-DFULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \
|
-DFULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \
|
||||||
|
-DJDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \
|
||||||
|
-DJDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \
|
||||||
-DARCH=\"$(LIBARCH)\" \
|
-DARCH=\"$(LIBARCH)\" \
|
||||||
-DGAMMA \
|
-DGAMMA \
|
||||||
-DLAUNCHER_TYPE=\"gamma\" \
|
-DLAUNCHER_TYPE=\"gamma\" \
|
||||||
-DLINK_INTO_$(LINK_INTO)
|
-DLINK_INTO_$(LINK_INTO) \
|
||||||
|
$(TARGET_DEFINES)
|
||||||
|
|
||||||
ifeq ($(LINK_INTO),AOUT)
|
ifeq ($(LINK_INTO),AOUT)
|
||||||
LAUNCHER.o = launcher.o $(JVM_OBJ_FILES)
|
LAUNCHER.o = launcher.o $(JVM_OBJ_FILES)
|
||||||
|
@ -55,22 +59,35 @@ LINK_LAUNCHER = $(LINK.c)
|
||||||
LINK_LAUNCHER/PRE_HOOK = $(LINK_LIB.CC/PRE_HOOK)
|
LINK_LAUNCHER/PRE_HOOK = $(LINK_LIB.CC/PRE_HOOK)
|
||||||
LINK_LAUNCHER/POST_HOOK = $(LINK_LIB.CC/POST_HOOK)
|
LINK_LAUNCHER/POST_HOOK = $(LINK_LIB.CC/POST_HOOK)
|
||||||
|
|
||||||
launcher.o: launcher.c $(LAUNCHERDIR)/java.c $(LAUNCHERDIR)/java_md.c
|
LAUNCHER_OUT = launcher
|
||||||
$(CC) -g -c -o $@ launcher.c $(LAUNCHERFLAGS) $(CPPFLAGS) $(TARGET_DEFINES)
|
|
||||||
|
|
||||||
launcher.c:
|
SUFFIXES += .d
|
||||||
@echo Generating $@
|
|
||||||
$(QUIETLY) { \
|
SOURCES := $(shell find $(LAUNCHERDIR) -name "*.c")
|
||||||
echo '#define debug launcher_debug'; \
|
SOURCES_SHARE := $(shell find $(LAUNCHERDIR_SHARE) -name "*.c")
|
||||||
echo '#include "java.c"'; \
|
|
||||||
echo '#include "java_md.c"'; \
|
OBJS := $(patsubst $(LAUNCHERDIR)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES)) $(patsubst $(LAUNCHERDIR_SHARE)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES_SHARE))
|
||||||
} > $@
|
|
||||||
|
DEPFILES := $(patsubst %.o,%.d,$(OBJS))
|
||||||
|
-include $(DEPFILES)
|
||||||
|
|
||||||
|
$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR_SHARE)/%.c
|
||||||
|
$(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); }
|
||||||
|
$(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS)
|
||||||
|
|
||||||
|
$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c
|
||||||
|
$(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); }
|
||||||
|
$(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS)
|
||||||
|
|
||||||
|
$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE)
|
||||||
|
$(QUIETLY) echo Linking launcher...
|
||||||
|
$(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK)
|
||||||
|
$(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(OBJS) $(LIBS_LAUNCHER)
|
||||||
|
$(QUIETLY) $(LINK_LAUNCHER/POST_HOOK)
|
||||||
|
|
||||||
|
$(LAUNCHER): $(LAUNCHER_SCRIPT)
|
||||||
|
|
||||||
|
$(LAUNCHER_SCRIPT): $(LAUNCHERDIR)/launcher.script
|
||||||
|
$(QUIETLY) sed -e 's/@@LIBARCH@@/$(LIBARCH)/g' $< > $@
|
||||||
|
$(QUIETLY) chmod +x $@
|
||||||
|
|
||||||
$(LAUNCHER): $(LAUNCHER.o) $(LIBJVM) $(LAUNCHER_MAPFILE)
|
|
||||||
$(QUIETLY) { \
|
|
||||||
echo Linking launcher...; \
|
|
||||||
$(LINK_LAUNCHER/PRE_HOOK) \
|
|
||||||
$(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(LAUNCHER.o) $(LIBS_LAUNCHER); \
|
|
||||||
$(LINK_LAUNCHER/POST_HOOK) \
|
|
||||||
[ -f $(LAUNCHER_G) ] || { ln -s $@ $(LAUNCHER_G); }; \
|
|
||||||
}
|
|
||||||
|
|
|
@ -79,6 +79,9 @@ ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1)
|
||||||
DEPFLAGS = -xMMD -xMF $(DEP_DIR)/$(@:%=%.d)
|
DEPFLAGS = -xMMD -xMF $(DEP_DIR)/$(@:%=%.d)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp.
|
||||||
|
CFLAGS += -DDONT_USE_PRECOMPILED_HEADER
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
# Linker flags
|
# Linker flags
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ endef
|
||||||
|
|
||||||
Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e)))
|
Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e)))
|
||||||
|
|
||||||
Obj_Files = $(addsuffix .o,$(basename $(Src_Files)))
|
Obj_Files = $(sort $(addsuffix .o,$(basename $(Src_Files))))
|
||||||
|
|
||||||
JVM_OBJ_FILES = $(Obj_Files)
|
JVM_OBJ_FILES = $(Obj_Files)
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
# OS_FAMILY - operating system
|
# OS_FAMILY - operating system
|
||||||
# VARIANT - core, compiler1, compiler2, or tiered
|
# VARIANT - core, compiler1, compiler2, or tiered
|
||||||
# HOTSPOT_RELEASE_VERSION - <major>.<minor>-b<nn> (11.0-b07)
|
# HOTSPOT_RELEASE_VERSION - <major>.<minor>-b<nn> (11.0-b07)
|
||||||
# HOTSPOT_BUILD_VERSION - internal, PRTjob ID, JPRTjob ID
|
# HOTSPOT_BUILD_VERSION - internal, internal-$(USER_RELEASE_SUFFIX) or empty
|
||||||
# JRE_RELEASE_VERSION - <major>.<minor>.<micro> (1.7.0)
|
# JRE_RELEASE_VERSION - <major>.<minor>.<micro> (1.7.0)
|
||||||
#
|
#
|
||||||
# Builds the directory trees with makefiles plus some convenience files in
|
# Builds the directory trees with makefiles plus some convenience files in
|
||||||
|
|
|
@ -47,11 +47,14 @@ $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
|
||||||
|
|
||||||
# check for precompiled headers support
|
# check for precompiled headers support
|
||||||
ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 4 \) \))" "0"
|
ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 4 \) \))" "0"
|
||||||
|
# Allow the user to turn off precompiled headers from the command line.
|
||||||
|
ifneq ($(USE_PRECOMPILED_HEADER),0)
|
||||||
USE_PRECOMPILED_HEADER=1
|
USE_PRECOMPILED_HEADER=1
|
||||||
PRECOMPILED_HEADER_DIR=.
|
PRECOMPILED_HEADER_DIR=.
|
||||||
PRECOMPILED_HEADER_SRC=$(GAMMADIR)/src/share/vm/precompiled.hpp
|
PRECOMPILED_HEADER_SRC=$(GAMMADIR)/src/share/vm/precompiled.hpp
|
||||||
PRECOMPILED_HEADER=$(PRECOMPILED_HEADER_DIR)/precompiled.hpp.gch
|
PRECOMPILED_HEADER=$(PRECOMPILED_HEADER_DIR)/precompiled.hpp.gch
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
|
@ -138,6 +141,11 @@ ifneq ("${CC_VER_MAJOR}", "2")
|
||||||
DEPFLAGS = -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
|
DEPFLAGS = -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp.
|
||||||
|
ifneq ($(USE_PRECOMPILED_HEADER),1)
|
||||||
|
CFLAGS += -DDONT_USE_PRECOMPILED_HEADER
|
||||||
|
endif
|
||||||
|
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
# Linker flags
|
# Linker flags
|
||||||
|
|
||||||
|
|
|
@ -24,18 +24,22 @@
|
||||||
|
|
||||||
# Rules to build gamma launcher, used by vm.make
|
# Rules to build gamma launcher, used by vm.make
|
||||||
|
|
||||||
# gamma[_g]: launcher
|
LAUNCHER_SCRIPT = hotspot
|
||||||
LAUNCHER = gamma
|
LAUNCHER = gamma
|
||||||
LAUNCHER_G = $(LAUNCHER)$(G_SUFFIX)
|
|
||||||
|
|
||||||
LAUNCHERDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/launcher
|
LAUNCHERDIR = $(GAMMADIR)/src/os/posix/launcher
|
||||||
|
LAUNCHERDIR_SHARE := $(GAMMADIR)/src/share/tools/launcher
|
||||||
LAUNCHERFLAGS = $(ARCHFLAG) \
|
LAUNCHERFLAGS = $(ARCHFLAG) \
|
||||||
-I$(LAUNCHERDIR) -I$(GAMMADIR)/src/share/vm/prims \
|
-I$(LAUNCHERDIR) -I$(GAMMADIR)/src/share/vm/prims \
|
||||||
|
-I$(LAUNCHERDIR_SHARE) \
|
||||||
-DFULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \
|
-DFULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \
|
||||||
|
-DJDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \
|
||||||
|
-DJDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \
|
||||||
-DARCH=\"$(LIBARCH)\" \
|
-DARCH=\"$(LIBARCH)\" \
|
||||||
-DGAMMA \
|
-DGAMMA \
|
||||||
-DLAUNCHER_TYPE=\"gamma\" \
|
-DLAUNCHER_TYPE=\"gamma\" \
|
||||||
-DLINK_INTO_$(LINK_INTO)
|
-DLINK_INTO_$(LINK_INTO) \
|
||||||
|
$(TARGET_DEFINES)
|
||||||
|
|
||||||
ifeq ($(LINK_INTO),AOUT)
|
ifeq ($(LINK_INTO),AOUT)
|
||||||
LAUNCHER.o = launcher.o $(JVM_OBJ_FILES)
|
LAUNCHER.o = launcher.o $(JVM_OBJ_FILES)
|
||||||
|
@ -68,24 +72,37 @@ ifeq ("${Platform_compiler}", "sparcWorks")
|
||||||
#LAUNCHERFLAGS += -W0,-noglobal
|
#LAUNCHERFLAGS += -W0,-noglobal
|
||||||
endif # Platform_compiler == sparcWorks
|
endif # Platform_compiler == sparcWorks
|
||||||
|
|
||||||
launcher.o: launcher.c $(LAUNCHERDIR)/java.c $(LAUNCHERDIR)/java_md.c
|
LAUNCHER_OUT = launcher
|
||||||
$(CC) -g -c -o $@ launcher.c $(LAUNCHERFLAGS) $(CPPFLAGS) ${TARGET_DEFINES}
|
|
||||||
|
|
||||||
launcher.c:
|
SUFFIXES += .d
|
||||||
@echo Generating $@
|
|
||||||
$(QUIETLY) { \
|
|
||||||
echo '#define debug launcher_debug'; \
|
|
||||||
echo '#include "java.c"'; \
|
|
||||||
echo '#include "java_md.c"'; \
|
|
||||||
} > $@
|
|
||||||
|
|
||||||
$(LAUNCHER): $(LAUNCHER.o) $(LIBJVM) $(LAUNCHER_MAPFILE)
|
SOURCES := $(shell find $(LAUNCHERDIR) -name "*.c")
|
||||||
|
SOURCES_SHARE := $(shell find $(LAUNCHERDIR_SHARE) -name "*.c")
|
||||||
|
|
||||||
|
OBJS := $(patsubst $(LAUNCHERDIR)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES)) $(patsubst $(LAUNCHERDIR_SHARE)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES_SHARE))
|
||||||
|
|
||||||
|
DEPFILES := $(patsubst %.o,%.d,$(OBJS))
|
||||||
|
-include $(DEPFILES)
|
||||||
|
|
||||||
|
$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR_SHARE)/%.c
|
||||||
|
$(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); }
|
||||||
|
$(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS)
|
||||||
|
|
||||||
|
$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c
|
||||||
|
$(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); }
|
||||||
|
$(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS)
|
||||||
|
|
||||||
|
$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE)
|
||||||
ifeq ($(filter -sbfast -xsbfast, $(CFLAGS_BROWSE)),)
|
ifeq ($(filter -sbfast -xsbfast, $(CFLAGS_BROWSE)),)
|
||||||
@echo Linking launcher...
|
$(QUIETLY) echo Linking launcher...
|
||||||
$(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK)
|
$(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK)
|
||||||
$(QUIETLY) \
|
$(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(OBJS) $(LIBS_LAUNCHER)
|
||||||
$(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(LAUNCHER.o) $(LIBS_LAUNCHER)
|
|
||||||
$(QUIETLY) $(LINK_LAUNCHER/POST_HOOK)
|
$(QUIETLY) $(LINK_LAUNCHER/POST_HOOK)
|
||||||
[ -f $(LAUNCHER_G) ] || ln -s $@ $(LAUNCHER_G)
|
|
||||||
endif # filter -sbfast -xsbfast
|
endif # filter -sbfast -xsbfast
|
||||||
|
|
||||||
|
$(LAUNCHER): $(LAUNCHER_SCRIPT)
|
||||||
|
|
||||||
|
$(LAUNCHER_SCRIPT): $(LAUNCHERDIR)/launcher.script
|
||||||
|
$(QUIETLY) sed -e 's/@@LIBARCH@@/$(LIBARCH)/g' $< > $@
|
||||||
|
$(QUIETLY) chmod +x $@
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,9 @@ ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1)
|
||||||
DEPFLAGS = -xMMD -xMF $(DEP_DIR)/$(@:%=%.d)
|
DEPFLAGS = -xMMD -xMF $(DEP_DIR)/$(@:%=%.d)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp.
|
||||||
|
CFLAGS += -DDONT_USE_PRECOMPILED_HEADER
|
||||||
|
|
||||||
################################################
|
################################################
|
||||||
# Begin current (>=5.9) Forte compiler options #
|
# Begin current (>=5.9) Forte compiler options #
|
||||||
#################################################
|
#################################################
|
||||||
|
|
|
@ -189,7 +189,7 @@ endef
|
||||||
|
|
||||||
Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e)))
|
Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e)))
|
||||||
|
|
||||||
Obj_Files = $(addsuffix .o,$(basename $(Src_Files)))
|
Obj_Files = $(sort $(addsuffix .o,$(basename $(Src_Files))))
|
||||||
|
|
||||||
JVM_OBJ_FILES = $(Obj_Files) $(DTRACE_OBJS)
|
JVM_OBJ_FILES = $(Obj_Files) $(DTRACE_OBJS)
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,14 @@ ADLCFLAGS=-q -T -D_LP64
|
||||||
ADLCFLAGS=-q -T -U_LP64
|
ADLCFLAGS=-q -T -U_LP64
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
|
CPP_FLAGS=$(CPP_FLAGS) \
|
||||||
|
/D TARGET_OS_FAMILY_windows \
|
||||||
|
/D TARGET_ARCH_$(Platform_arch) \
|
||||||
|
/D TARGET_ARCH_MODEL_$(Platform_arch_model) \
|
||||||
|
/D TARGET_OS_ARCH_windows_$(Platform_arch) \
|
||||||
|
/D TARGET_OS_ARCH_MODEL_windows_$(Platform_arch_model) \
|
||||||
|
/D TARGET_COMPILER_visCPP
|
||||||
|
|
||||||
CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE
|
CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE
|
||||||
|
|
||||||
CPP_INCLUDE_DIRS=\
|
CPP_INCLUDE_DIRS=\
|
||||||
|
|
|
@ -26,9 +26,15 @@ HS_INTERNAL_NAME=jvm
|
||||||
HS_FNAME=$(HS_INTERNAL_NAME).dll
|
HS_FNAME=$(HS_INTERNAL_NAME).dll
|
||||||
AOUT=$(HS_FNAME)
|
AOUT=$(HS_FNAME)
|
||||||
SAWINDBG=sawindbg.dll
|
SAWINDBG=sawindbg.dll
|
||||||
|
LAUNCHER_NAME=hotspot.exe
|
||||||
GENERATED=../generated
|
GENERATED=../generated
|
||||||
|
|
||||||
default:: _build_pch_file.obj $(AOUT) checkAndBuildSA
|
# Allow the user to turn off precompiled headers from the command line.
|
||||||
|
!if "$(USE_PRECOMPILED_HEADER)" != "0"
|
||||||
|
BUILD_PCH_FILE=_build_pch_file.obj
|
||||||
|
!endif
|
||||||
|
|
||||||
|
default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA
|
||||||
|
|
||||||
!include ../local.make
|
!include ../local.make
|
||||||
!include compile.make
|
!include compile.make
|
||||||
|
@ -57,3 +63,4 @@ $(AOUT): $(Res_Files) $(Obj_Files)
|
||||||
|
|
||||||
!include $(WorkSpace)/make/windows/makefiles/shared.make
|
!include $(WorkSpace)/make/windows/makefiles/shared.make
|
||||||
!include $(WorkSpace)/make/windows/makefiles/sa.make
|
!include $(WorkSpace)/make/windows/makefiles/sa.make
|
||||||
|
!include $(WorkSpace)/make/windows/makefiles/launcher.make
|
||||||
|
|
|
@ -26,9 +26,15 @@ HS_INTERNAL_NAME=jvm
|
||||||
HS_FNAME=$(HS_INTERNAL_NAME).dll
|
HS_FNAME=$(HS_INTERNAL_NAME).dll
|
||||||
AOUT=$(HS_FNAME)
|
AOUT=$(HS_FNAME)
|
||||||
SAWINDBG=sawindbg.dll
|
SAWINDBG=sawindbg.dll
|
||||||
|
LAUNCHER_NAME=hotspot.exe
|
||||||
GENERATED=../generated
|
GENERATED=../generated
|
||||||
|
|
||||||
default:: _build_pch_file.obj $(AOUT) checkAndBuildSA
|
# Allow the user to turn off precompiled headers from the command line.
|
||||||
|
!if "$(USE_PRECOMPILED_HEADER)" != "0"
|
||||||
|
BUILD_PCH_FILE=_build_pch_file.obj
|
||||||
|
!endif
|
||||||
|
|
||||||
|
default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA
|
||||||
|
|
||||||
!include ../local.make
|
!include ../local.make
|
||||||
!include compile.make
|
!include compile.make
|
||||||
|
@ -57,3 +63,4 @@ $(AOUT): $(Res_Files) $(Obj_Files)
|
||||||
|
|
||||||
!include $(WorkSpace)/make/windows/makefiles/shared.make
|
!include $(WorkSpace)/make/windows/makefiles/shared.make
|
||||||
!include $(WorkSpace)/make/windows/makefiles/sa.make
|
!include $(WorkSpace)/make/windows/makefiles/sa.make
|
||||||
|
!include $(WorkSpace)/make/windows/makefiles/launcher.make
|
||||||
|
|
67
hotspot/make/windows/makefiles/launcher.make
Normal file
67
hotspot/make/windows/makefiles/launcher.make
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
LAUNCHER_FLAGS=$(ARCHFLAG) \
|
||||||
|
/D FULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \
|
||||||
|
/D JDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \
|
||||||
|
/D JDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \
|
||||||
|
/D GAMMA \
|
||||||
|
/D LAUNCHER_TYPE=\"gamma\" \
|
||||||
|
/D _CRT_SECURE_NO_WARNINGS \
|
||||||
|
/D _CRT_SECURE_NO_DEPRECATE \
|
||||||
|
/D LINK_INTO_LIBJVM \
|
||||||
|
/I $(WorkSpace)\src\os\windows\launcher \
|
||||||
|
/I $(WorkSpace)\src\share\tools\launcher
|
||||||
|
|
||||||
|
CPP_FLAGS=$(CPP_FLAGS) $(LAUNCHER_FLAGS)
|
||||||
|
|
||||||
|
LINK_FLAGS=/manifest $(HS_INTERNAL_NAME).lib kernel32.lib user32.lib /nologo /machine:$(MACHINE) /map /debug /subsystem:console
|
||||||
|
|
||||||
|
!if "$(COMPILER_NAME)" == "VS2005"
|
||||||
|
# This VS2005 compiler has /GS as a default and requires bufferoverflowU.lib
|
||||||
|
# on the link command line, otherwise we get missing __security_check_cookie
|
||||||
|
# externals at link time. Even with /GS-, you need bufferoverflowU.lib.
|
||||||
|
BUFFEROVERFLOWLIB = bufferoverflowU.lib
|
||||||
|
LINK_FLAGS = $(LINK_FLAGS) $(BUFFEROVERFLOWLIB)
|
||||||
|
!endif
|
||||||
|
|
||||||
|
LAUNCHERDIR = $(GAMMADIR)/src/os/windows/launcher
|
||||||
|
LAUNCHERDIR_SHARE = $(GAMMADIR)/src/share/tools/launcher
|
||||||
|
|
||||||
|
OUTDIR = launcher
|
||||||
|
|
||||||
|
{$(LAUNCHERDIR)}.c{$(OUTDIR)}.obj:
|
||||||
|
-mkdir $(OUTDIR)
|
||||||
|
$(CPP) $(CPP_FLAGS) /c /Fo$@ $<
|
||||||
|
|
||||||
|
{$(LAUNCHERDIR_SHARE)}.c{$(OUTDIR)}.obj:
|
||||||
|
-mkdir $(OUTDIR)
|
||||||
|
$(CPP) $(CPP_FLAGS) /c /Fo$@ $<
|
||||||
|
|
||||||
|
$(OUTDIR)\*.obj: $(LAUNCHERDIR)\*.c $(LAUNCHERDIR)\*.h $(LAUNCHERDIR_SHARE)\*.c $(LAUNCHERDIR_SHARE)\*.h
|
||||||
|
|
||||||
|
$(LAUNCHER_NAME): $(OUTDIR)\java.obj $(OUTDIR)\java_md.obj $(OUTDIR)\jli_util.obj
|
||||||
|
$(LINK) $(LINK_FLAGS) /out:$@ $**
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,15 @@
|
||||||
HS_INTERNAL_NAME=jvm
|
HS_INTERNAL_NAME=jvm
|
||||||
HS_FNAME=$(HS_INTERNAL_NAME).dll
|
HS_FNAME=$(HS_INTERNAL_NAME).dll
|
||||||
AOUT=$(HS_FNAME)
|
AOUT=$(HS_FNAME)
|
||||||
|
LAUNCHER_NAME=hotspot.exe
|
||||||
GENERATED=../generated
|
GENERATED=../generated
|
||||||
|
|
||||||
default:: _build_pch_file.obj $(AOUT) checkAndBuildSA
|
# Allow the user to turn off precompiled headers from the command line.
|
||||||
|
!if "$(USE_PRECOMPILED_HEADER)" != "0"
|
||||||
|
BUILD_PCH_FILE=_build_pch_file.obj
|
||||||
|
!endif
|
||||||
|
|
||||||
|
default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA
|
||||||
|
|
||||||
!include ../local.make
|
!include ../local.make
|
||||||
!include compile.make
|
!include compile.make
|
||||||
|
@ -68,3 +74,4 @@ $(AOUT): $(Res_Files) $(Obj_Files)
|
||||||
|
|
||||||
!include $(WorkSpace)/make/windows/makefiles/shared.make
|
!include $(WorkSpace)/make/windows/makefiles/shared.make
|
||||||
!include $(WorkSpace)/make/windows/makefiles/sa.make
|
!include $(WorkSpace)/make/windows/makefiles/sa.make
|
||||||
|
!include $(WorkSpace)/make/windows/makefiles/launcher.make
|
||||||
|
|
|
@ -128,7 +128,13 @@ CPP_INCLUDE_DIRS=\
|
||||||
/I "$(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm" \
|
/I "$(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm" \
|
||||||
/I "$(WorkSpace)\src\cpu\$(Platform_arch)\vm"
|
/I "$(WorkSpace)\src\cpu\$(Platform_arch)\vm"
|
||||||
|
|
||||||
|
CPP_DONT_USE_PCH=/D DONT_USE_PRECOMPILED_HEADER
|
||||||
|
|
||||||
|
!if "$(USE_PRECOMPILED_HEADER)" != "0"
|
||||||
CPP_USE_PCH=/Fp"vm.pch" /Yu"precompiled.hpp"
|
CPP_USE_PCH=/Fp"vm.pch" /Yu"precompiled.hpp"
|
||||||
|
!else
|
||||||
|
CPP_USE_PCH=$(CPP_DONT_USE_PCH)
|
||||||
|
!endif
|
||||||
|
|
||||||
# Where to find the source code for the virtual machine
|
# Where to find the source code for the virtual machine
|
||||||
VM_PATH=../generated
|
VM_PATH=../generated
|
||||||
|
@ -164,31 +170,31 @@ VM_PATH={$(VM_PATH)}
|
||||||
# Special case files not using precompiled header files.
|
# Special case files not using precompiled header files.
|
||||||
|
|
||||||
c1_RInfo_$(Platform_arch).obj: $(WorkSpace)\src\cpu\$(Platform_arch)\vm\c1_RInfo_$(Platform_arch).cpp
|
c1_RInfo_$(Platform_arch).obj: $(WorkSpace)\src\cpu\$(Platform_arch)\vm\c1_RInfo_$(Platform_arch).cpp
|
||||||
$(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\cpu\$(Platform_arch)\vm\c1_RInfo_$(Platform_arch).cpp
|
$(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\cpu\$(Platform_arch)\vm\c1_RInfo_$(Platform_arch).cpp
|
||||||
|
|
||||||
os_windows.obj: $(WorkSpace)\src\os\windows\vm\os_windows.cpp
|
os_windows.obj: $(WorkSpace)\src\os\windows\vm\os_windows.cpp
|
||||||
$(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\os\windows\vm\os_windows.cpp
|
$(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\os\windows\vm\os_windows.cpp
|
||||||
|
|
||||||
os_windows_$(Platform_arch).obj: $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\os_windows_$(Platform_arch).cpp
|
os_windows_$(Platform_arch).obj: $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\os_windows_$(Platform_arch).cpp
|
||||||
$(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\os_windows_$(Platform_arch).cpp
|
$(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\os_windows_$(Platform_arch).cpp
|
||||||
|
|
||||||
osThread_windows.obj: $(WorkSpace)\src\os\windows\vm\osThread_windows.cpp
|
osThread_windows.obj: $(WorkSpace)\src\os\windows\vm\osThread_windows.cpp
|
||||||
$(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\os\windows\vm\osThread_windows.cpp
|
$(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\os\windows\vm\osThread_windows.cpp
|
||||||
|
|
||||||
conditionVar_windows.obj: $(WorkSpace)\src\os\windows\vm\conditionVar_windows.cpp
|
conditionVar_windows.obj: $(WorkSpace)\src\os\windows\vm\conditionVar_windows.cpp
|
||||||
$(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\os\windows\vm\conditionVar_windows.cpp
|
$(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\os\windows\vm\conditionVar_windows.cpp
|
||||||
|
|
||||||
getThread_windows_$(Platform_arch).obj: $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\getThread_windows_$(Platform_arch).cpp
|
getThread_windows_$(Platform_arch).obj: $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\getThread_windows_$(Platform_arch).cpp
|
||||||
$(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\getThread_windows_$(Platform_arch).cpp
|
$(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\getThread_windows_$(Platform_arch).cpp
|
||||||
|
|
||||||
opcodes.obj: $(WorkSpace)\src\share\vm\opto\opcodes.cpp
|
opcodes.obj: $(WorkSpace)\src\share\vm\opto\opcodes.cpp
|
||||||
$(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\share\vm\opto\opcodes.cpp
|
$(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\share\vm\opto\opcodes.cpp
|
||||||
|
|
||||||
bytecodeInterpreter.obj: $(WorkSpace)\src\share\vm\interpreter\bytecodeInterpreter.cpp
|
bytecodeInterpreter.obj: $(WorkSpace)\src\share\vm\interpreter\bytecodeInterpreter.cpp
|
||||||
$(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\share\vm\interpreter\bytecodeInterpreter.cpp
|
$(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\share\vm\interpreter\bytecodeInterpreter.cpp
|
||||||
|
|
||||||
bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWithChecks.cpp
|
bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWithChecks.cpp
|
||||||
$(CPP) $(CPP_FLAGS) /c ..\generated\jvmtifiles\bytecodeInterpreterWithChecks.cpp
|
$(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c ..\generated\jvmtifiles\bytecodeInterpreterWithChecks.cpp
|
||||||
|
|
||||||
# Default rules for the Virtual Machine
|
# Default rules for the Virtual Machine
|
||||||
{$(WorkSpace)\src\share\vm\c1}.cpp.obj::
|
{$(WorkSpace)\src\share\vm\c1}.cpp.obj::
|
||||||
|
|
|
@ -65,7 +65,11 @@ HOTSPOT_RELEASE_VERSION="$(HOTSPOT_RELEASE_VERSION)"
|
||||||
!else
|
!else
|
||||||
HOTSPOT_RELEASE_VERSION="$(HS_MAJOR_VER).$(HS_MINOR_VER)-b$(HS_BUILD_NUMBER)"
|
HOTSPOT_RELEASE_VERSION="$(HS_MAJOR_VER).$(HS_MINOR_VER)-b$(HS_BUILD_NUMBER)"
|
||||||
!endif
|
!endif
|
||||||
|
!if "$(USER_RELEASE_SUFFIX)" != ""
|
||||||
|
HOTSPOT_BUILD_VERSION$(HOTSPOT_BUILD_VERSION) = internal-$(USER_RELEASE_SUFFIX)
|
||||||
|
!else
|
||||||
HOTSPOT_BUILD_VERSION$(HOTSPOT_BUILD_VERSION) = internal
|
HOTSPOT_BUILD_VERSION$(HOTSPOT_BUILD_VERSION) = internal
|
||||||
|
!endif
|
||||||
!if "$(HOTSPOT_BUILD_VERSION)" != ""
|
!if "$(HOTSPOT_BUILD_VERSION)" != ""
|
||||||
HOTSPOT_RELEASE_VERSION="$(HOTSPOT_RELEASE_VERSION)-$(HOTSPOT_BUILD_VERSION)"
|
HOTSPOT_RELEASE_VERSION="$(HOTSPOT_RELEASE_VERSION)-$(HOTSPOT_BUILD_VERSION)"
|
||||||
!endif
|
!endif
|
||||||
|
|
|
@ -25,6 +25,5 @@
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "compiler/disassembler.hpp"
|
#include "compiler/disassembler.hpp"
|
||||||
#include "depChecker_sparc.hpp"
|
#include "depChecker_sparc.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
|
|
||||||
// Nothing to do on Sparc
|
// Nothing to do on Sparc
|
||||||
|
|
|
@ -5538,17 +5538,14 @@ void MacroAssembler::stop(const char* msg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroAssembler::warn(const char* msg) {
|
void MacroAssembler::warn(const char* msg) {
|
||||||
push(r12);
|
push(rsp);
|
||||||
movq(r12, rsp);
|
|
||||||
andq(rsp, -16); // align stack as required by push_CPU_state and call
|
andq(rsp, -16); // align stack as required by push_CPU_state and call
|
||||||
|
|
||||||
push_CPU_state(); // keeps alignment at 16 bytes
|
push_CPU_state(); // keeps alignment at 16 bytes
|
||||||
lea(c_rarg0, ExternalAddress((address) msg));
|
lea(c_rarg0, ExternalAddress((address) msg));
|
||||||
call_VM_leaf(CAST_FROM_FN_PTR(address, warning), c_rarg0);
|
call_VM_leaf(CAST_FROM_FN_PTR(address, warning), c_rarg0);
|
||||||
pop_CPU_state();
|
pop_CPU_state();
|
||||||
|
pop(rsp);
|
||||||
movq(rsp, r12);
|
|
||||||
pop(r12);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -5860,6 +5857,10 @@ void MacroAssembler::call_VM_base(Register oop_result,
|
||||||
// debugging support
|
// debugging support
|
||||||
assert(number_of_arguments >= 0 , "cannot have negative number of arguments");
|
assert(number_of_arguments >= 0 , "cannot have negative number of arguments");
|
||||||
LP64_ONLY(assert(java_thread == r15_thread, "unexpected register"));
|
LP64_ONLY(assert(java_thread == r15_thread, "unexpected register"));
|
||||||
|
#ifdef ASSERT
|
||||||
|
LP64_ONLY(if (UseCompressedOops) verify_heapbase("call_VM_base");)
|
||||||
|
#endif // ASSERT
|
||||||
|
|
||||||
assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result");
|
assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result");
|
||||||
assert(java_thread != last_java_sp, "cannot use the same register for java_thread & last_java_sp");
|
assert(java_thread != last_java_sp, "cannot use the same register for java_thread & last_java_sp");
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,5 @@
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "compiler/disassembler.hpp"
|
#include "compiler/disassembler.hpp"
|
||||||
#include "depChecker_x86.hpp"
|
#include "depChecker_x86.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
|
|
||||||
// Nothing to do on i486
|
// Nothing to do on i486
|
||||||
|
|
|
@ -449,10 +449,9 @@ void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register
|
||||||
// JVMTI events, such as single-stepping, are implemented partly by avoiding running
|
// JVMTI events, such as single-stepping, are implemented partly by avoiding running
|
||||||
// compiled code in threads for which the event is enabled. Check here for
|
// compiled code in threads for which the event is enabled. Check here for
|
||||||
// interp_only_mode if these events CAN be enabled.
|
// interp_only_mode if these events CAN be enabled.
|
||||||
get_thread(temp);
|
|
||||||
// interp_only is an int, on little endian it is sufficient to test the byte only
|
// interp_only is an int, on little endian it is sufficient to test the byte only
|
||||||
// Is a cmpl faster (ce
|
// Is a cmpl faster?
|
||||||
cmpb(Address(temp, JavaThread::interp_only_mode_offset()), 0);
|
cmpb(Address(r15_thread, JavaThread::interp_only_mode_offset()), 0);
|
||||||
jcc(Assembler::zero, run_compiled_code);
|
jcc(Assembler::zero, run_compiled_code);
|
||||||
jmp(Address(method, methodOopDesc::interpreter_entry_offset()));
|
jmp(Address(method, methodOopDesc::interpreter_entry_offset()));
|
||||||
bind(run_compiled_code);
|
bind(run_compiled_code);
|
||||||
|
|
|
@ -1069,7 +1069,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||||
// runtime call by hand.
|
// runtime call by hand.
|
||||||
//
|
//
|
||||||
__ mov(c_rarg0, r15_thread);
|
__ mov(c_rarg0, r15_thread);
|
||||||
__ mov(r12, rsp); // remember sp
|
__ mov(r12, rsp); // remember sp (can only use r12 if not using call_VM)
|
||||||
__ subptr(rsp, frame::arg_reg_save_area_bytes); // windows
|
__ subptr(rsp, frame::arg_reg_save_area_bytes); // windows
|
||||||
__ andptr(rsp, -16); // align stack as required by ABI
|
__ andptr(rsp, -16); // align stack as required by ABI
|
||||||
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)));
|
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)));
|
||||||
|
@ -1116,7 +1116,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||||
__ jcc(Assembler::notEqual, no_reguard);
|
__ jcc(Assembler::notEqual, no_reguard);
|
||||||
|
|
||||||
__ pusha(); // XXX only save smashed registers
|
__ pusha(); // XXX only save smashed registers
|
||||||
__ mov(r12, rsp); // remember sp
|
__ mov(r12, rsp); // remember sp (can only use r12 if not using call_VM)
|
||||||
__ subptr(rsp, frame::arg_reg_save_area_bytes); // windows
|
__ subptr(rsp, frame::arg_reg_save_area_bytes); // windows
|
||||||
__ andptr(rsp, -16); // align stack as required by ABI
|
__ andptr(rsp, -16); // align stack as required by ABI
|
||||||
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages)));
|
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages)));
|
||||||
|
@ -1907,7 +1907,7 @@ void TemplateInterpreterGenerator::trace_bytecode(Template* t) {
|
||||||
|
|
||||||
assert(Interpreter::trace_code(t->tos_in()) != NULL,
|
assert(Interpreter::trace_code(t->tos_in()) != NULL,
|
||||||
"entry must have been generated");
|
"entry must have been generated");
|
||||||
__ mov(r12, rsp); // remember sp
|
__ mov(r12, rsp); // remember sp (can only use r12 if not using call_VM)
|
||||||
__ andptr(rsp, -16); // align stack as required by ABI
|
__ andptr(rsp, -16); // align stack as required by ABI
|
||||||
__ call(RuntimeAddress(Interpreter::trace_code(t->tos_in())));
|
__ call(RuntimeAddress(Interpreter::trace_code(t->tos_in())));
|
||||||
__ mov(rsp, r12); // restore sp
|
__ mov(rsp, r12); // restore sp
|
||||||
|
|
|
@ -2762,7 +2762,7 @@ void TemplateTable::fast_accessfield(TosState state) {
|
||||||
// access constant pool cache entry
|
// access constant pool cache entry
|
||||||
__ get_cache_entry_pointer_at_bcp(c_rarg2, rcx, 1);
|
__ get_cache_entry_pointer_at_bcp(c_rarg2, rcx, 1);
|
||||||
__ verify_oop(rax);
|
__ verify_oop(rax);
|
||||||
__ mov(r12, rax); // save object pointer before call_VM() clobbers it
|
__ push_ptr(rax); // save object pointer before call_VM() clobbers it
|
||||||
__ mov(c_rarg1, rax);
|
__ mov(c_rarg1, rax);
|
||||||
// c_rarg1: object pointer copied above
|
// c_rarg1: object pointer copied above
|
||||||
// c_rarg2: cache entry pointer
|
// c_rarg2: cache entry pointer
|
||||||
|
@ -2770,8 +2770,7 @@ void TemplateTable::fast_accessfield(TosState state) {
|
||||||
CAST_FROM_FN_PTR(address,
|
CAST_FROM_FN_PTR(address,
|
||||||
InterpreterRuntime::post_field_access),
|
InterpreterRuntime::post_field_access),
|
||||||
c_rarg1, c_rarg2);
|
c_rarg1, c_rarg2);
|
||||||
__ mov(rax, r12); // restore object pointer
|
__ pop_ptr(rax); // restore object pointer
|
||||||
__ reinit_heapbase();
|
|
||||||
__ bind(L1);
|
__ bind(L1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3365,10 +3364,7 @@ void TemplateTable::checkcast() {
|
||||||
JVM_CONSTANT_Class);
|
JVM_CONSTANT_Class);
|
||||||
__ jcc(Assembler::equal, quicked);
|
__ jcc(Assembler::equal, quicked);
|
||||||
__ push(atos); // save receiver for result, and for GC
|
__ push(atos); // save receiver for result, and for GC
|
||||||
__ mov(r12, rcx); // save rcx XXX
|
|
||||||
call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc));
|
call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc));
|
||||||
__ movq(rcx, r12); // restore rcx XXX
|
|
||||||
__ reinit_heapbase();
|
|
||||||
__ pop_ptr(rdx); // restore receiver
|
__ pop_ptr(rdx); // restore receiver
|
||||||
__ jmpb(resolved);
|
__ jmpb(resolved);
|
||||||
|
|
||||||
|
@ -3422,11 +3418,9 @@ void TemplateTable::instanceof() {
|
||||||
__ jcc(Assembler::equal, quicked);
|
__ jcc(Assembler::equal, quicked);
|
||||||
|
|
||||||
__ push(atos); // save receiver for result, and for GC
|
__ push(atos); // save receiver for result, and for GC
|
||||||
__ mov(r12, rcx); // save rcx
|
|
||||||
call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc));
|
call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc));
|
||||||
__ movq(rcx, r12); // restore rcx
|
|
||||||
__ reinit_heapbase();
|
|
||||||
__ pop_ptr(rdx); // restore receiver
|
__ pop_ptr(rdx); // restore receiver
|
||||||
|
__ verify_oop(rdx);
|
||||||
__ load_klass(rdx, rdx);
|
__ load_klass(rdx, rdx);
|
||||||
__ jmpb(resolved);
|
__ jmpb(resolved);
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,5 @@
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "compiler/disassembler.hpp"
|
#include "compiler/disassembler.hpp"
|
||||||
#include "depChecker_zero.hpp"
|
#include "depChecker_zero.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
|
|
||||||
// This file is intentionally empty
|
// This file is intentionally empty
|
||||||
|
|
|
@ -1,88 +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.
|
|
||||||
*
|
|
||||||
* 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 "precompiled.hpp"
|
|
||||||
#include "oops/oop.inline.hpp"
|
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/os.hpp"
|
|
||||||
|
|
||||||
# include <sys/param.h>
|
|
||||||
# include <dlfcn.h>
|
|
||||||
|
|
||||||
typedef jint (JNICALL *init_t)(GetInterfaceFunc *, void *);
|
|
||||||
|
|
||||||
void hpi::initialize_get_interface(vm_calls_t *callbacks) {
|
|
||||||
char buf[JVM_MAXPATHLEN];
|
|
||||||
void *hpi_handle;
|
|
||||||
GetInterfaceFunc& getintf = _get_interface;
|
|
||||||
jint (JNICALL * DLL_Initialize)(GetInterfaceFunc *, void *);
|
|
||||||
|
|
||||||
if (HPILibPath && HPILibPath[0]) {
|
|
||||||
strncpy(buf, HPILibPath, JVM_MAXPATHLEN - 1);
|
|
||||||
buf[JVM_MAXPATHLEN - 1] = '\0';
|
|
||||||
} else {
|
|
||||||
const char *thread_type = "native_threads";
|
|
||||||
|
|
||||||
os::jvm_path(buf, JVM_MAXPATHLEN);
|
|
||||||
|
|
||||||
#ifdef PRODUCT
|
|
||||||
const char * hpi_lib = "/libhpi.so";
|
|
||||||
#else
|
|
||||||
char * ptr = strrchr(buf, '/');
|
|
||||||
assert(strstr(ptr, "/libjvm") == ptr, "invalid library name");
|
|
||||||
const char * hpi_lib = strstr(ptr, "_g") ? "/libhpi_g.so" : "/libhpi.so";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*(strrchr(buf, '/')) = '\0'; /* get rid of /libjvm.so */
|
|
||||||
char* p = strrchr(buf, '/');
|
|
||||||
if (p != NULL) p[1] = '\0'; /* get rid of hotspot */
|
|
||||||
strcat(buf, thread_type);
|
|
||||||
strcat(buf, hpi_lib);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TraceHPI) tty->print_cr("Loading HPI %s ", buf);
|
|
||||||
#ifdef SPARC
|
|
||||||
// On 64-bit Ubuntu Sparc RTLD_NOW leads to unresolved deps in libpthread.so
|
|
||||||
# define OPEN_MODE RTLD_LAZY
|
|
||||||
#else
|
|
||||||
// We use RTLD_NOW because of bug 4032715
|
|
||||||
# define OPEN_MODE RTLD_NOW
|
|
||||||
#endif
|
|
||||||
hpi_handle = dlopen(buf, OPEN_MODE);
|
|
||||||
#undef OPEN_MODE
|
|
||||||
|
|
||||||
if (hpi_handle == NULL) {
|
|
||||||
if (TraceHPI) tty->print_cr("HPI dlopen failed: %s", dlerror());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DLL_Initialize = CAST_TO_FN_PTR(jint (JNICALL *)(GetInterfaceFunc *, void *),
|
|
||||||
dlsym(hpi_handle, "DLL_Initialize"));
|
|
||||||
if (TraceHPI && DLL_Initialize == NULL) tty->print_cr("HPI dlsym of DLL_Initialize failed: %s", dlerror());
|
|
||||||
if (DLL_Initialize == NULL ||
|
|
||||||
(*DLL_Initialize)(&getintf, callbacks) < 0) {
|
|
||||||
if (TraceHPI) tty->print_cr("HPI DLL_Initialize failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (TraceHPI) tty->print_cr("HPI loaded successfully");
|
|
||||||
}
|
|
|
@ -1,229 +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.
|
|
||||||
*
|
|
||||||
* 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 OS_LINUX_VM_HPI_LINUX_HPP
|
|
||||||
#define OS_LINUX_VM_HPI_LINUX_HPP
|
|
||||||
|
|
||||||
//
|
|
||||||
// Because the interruptible IO has been dropped for HotSpot/Linux,
|
|
||||||
// the following HPI interface is very different from HotSparc.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/poll.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
|
|
||||||
// HPI_FileInterface
|
|
||||||
|
|
||||||
inline int hpi::close(int fd) {
|
|
||||||
return ::close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t hpi::read(int fd, void *buf, unsigned int nBytes) {
|
|
||||||
size_t res;
|
|
||||||
RESTARTABLE( (size_t) ::read(fd, buf, (size_t) nBytes), res);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t hpi::write(int fd, const void *buf, unsigned int nBytes) {
|
|
||||||
size_t res;
|
|
||||||
RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// HPI_SocketInterface
|
|
||||||
|
|
||||||
inline int hpi::socket_close(int fd) {
|
|
||||||
return ::close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::socket(int domain, int type, int protocol) {
|
|
||||||
return ::socket(domain, type, protocol);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::recv(int fd, char *buf, int nBytes, int flags) {
|
|
||||||
RESTARTABLE_RETURN_INT(::recv(fd, buf, nBytes, (unsigned int) flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::send(int fd, char *buf, int nBytes, int flags) {
|
|
||||||
RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, (unsigned int) flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::raw_send(int fd, char *buf, int nBytes, int flags) {
|
|
||||||
return send(fd, buf, nBytes, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::timeout(int fd, long timeout) {
|
|
||||||
julong prevtime,newtime;
|
|
||||||
struct timeval t;
|
|
||||||
|
|
||||||
gettimeofday(&t, NULL);
|
|
||||||
prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
struct pollfd pfd;
|
|
||||||
|
|
||||||
pfd.fd = fd;
|
|
||||||
pfd.events = POLLIN | POLLERR;
|
|
||||||
|
|
||||||
int res = ::poll(&pfd, 1, timeout);
|
|
||||||
|
|
||||||
if (res == OS_ERR && errno == EINTR) {
|
|
||||||
|
|
||||||
// On Linux any value < 0 means "forever"
|
|
||||||
|
|
||||||
if(timeout >= 0) {
|
|
||||||
gettimeofday(&t, NULL);
|
|
||||||
newtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
|
|
||||||
timeout -= newtime - prevtime;
|
|
||||||
if(timeout <= 0)
|
|
||||||
return OS_OK;
|
|
||||||
prevtime = newtime;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::listen(int fd, int count) {
|
|
||||||
return ::listen(fd, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::connect(int fd, struct sockaddr *him, int len) {
|
|
||||||
RESTARTABLE_RETURN_INT(::connect(fd, him, len));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::accept(int fd, struct sockaddr *him, int *len) {
|
|
||||||
// This cast is from int to unsigned int on linux. Since we
|
|
||||||
// only pass the parameter "len" around the vm and don't try to
|
|
||||||
// fetch it's value, this cast is safe for now. The java.net group
|
|
||||||
// may need and want to change this interface someday if socklen_t goes
|
|
||||||
// to 64 bits on some platform that we support.
|
|
||||||
// Linux doc says this can't return EINTR, unlike accept() on Solaris
|
|
||||||
|
|
||||||
return ::accept(fd, him, (socklen_t *)len);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::recvfrom(int fd, char *buf, int nBytes, int flags,
|
|
||||||
sockaddr *from, int *fromlen) {
|
|
||||||
RESTARTABLE_RETURN_INT(::recvfrom(fd, buf, nBytes, (unsigned int) flags, from, (socklen_t *)fromlen));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::sendto(int fd, char *buf, int len, int flags,
|
|
||||||
struct sockaddr *to, int tolen) {
|
|
||||||
RESTARTABLE_RETURN_INT(::sendto(fd, buf, len, (unsigned int) flags, to, tolen));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::socket_available(int fd, jint *pbytes) {
|
|
||||||
// Linux doc says EINTR not returned, unlike Solaris
|
|
||||||
int ret = ::ioctl(fd, FIONREAD, pbytes);
|
|
||||||
|
|
||||||
//%% note ioctl can return 0 when successful, JVM_SocketAvailable
|
|
||||||
// is expected to return 0 on failure and 1 on success to the jdk.
|
|
||||||
return (ret < 0) ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// following methods have been updated to avoid problems in
|
|
||||||
// hpi's sockets calls based on sys_api_td.c (JDK1.3)
|
|
||||||
|
|
||||||
/*
|
|
||||||
HPIDECL(socket_shutdown, "socket_shutdown", _socket, SocketShutdown,
|
|
||||||
int, "%d",
|
|
||||||
(int fd, int howto),
|
|
||||||
("fd = %d, howto = %d", fd, howto),
|
|
||||||
(fd, howto));
|
|
||||||
*/
|
|
||||||
inline int hpi::socket_shutdown(int fd, int howto){
|
|
||||||
return ::shutdown(fd, howto);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
HPIDECL(bind, "bind", _socket, Bind,
|
|
||||||
int, "%d",
|
|
||||||
(int fd, struct sockaddr *him, int len),
|
|
||||||
("fd = %d, him = %p, len = %d",
|
|
||||||
fd, him, len),
|
|
||||||
(fd, him, len));
|
|
||||||
*/
|
|
||||||
inline int hpi::bind(int fd, struct sockaddr *him, int len){
|
|
||||||
return ::bind(fd, him, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
HPIDECL(get_sock_name, "get_sock_name", _socket, GetSocketName,
|
|
||||||
int, "%d",
|
|
||||||
(int fd, struct sockaddr *him, int *len),
|
|
||||||
("fd = %d, him = %p, len = %p",
|
|
||||||
fd, him, len),
|
|
||||||
(fd, him, len));
|
|
||||||
*/
|
|
||||||
inline int hpi::get_sock_name(int fd, struct sockaddr *him, int *len){
|
|
||||||
return ::getsockname(fd, him, (socklen_t *)len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
HPIDECL(get_host_name, "get_host_name", _socket, GetHostName, int, "%d",
|
|
||||||
(char *hostname, int namelen),
|
|
||||||
("hostname = %p, namelen = %d",
|
|
||||||
hostname, namelen),
|
|
||||||
(hostname, namelen));
|
|
||||||
*/
|
|
||||||
inline int hpi::get_host_name(char* name, int namelen){
|
|
||||||
return ::gethostname(name, namelen);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
HPIDECL(get_sock_opt, "get_sock_opt", _socket, SocketGetOption, int, "%d",
|
|
||||||
(int fd, int level, int optname, char *optval, int* optlen),
|
|
||||||
("fd = %d, level = %d, optname = %d, optval = %p, optlen = %p",
|
|
||||||
fd, level, optname, optval, optlen),
|
|
||||||
(fd, level, optname, optval, optlen));
|
|
||||||
*/
|
|
||||||
inline int hpi::get_sock_opt(int fd, int level, int optname,
|
|
||||||
char *optval, int* optlen){
|
|
||||||
return ::getsockopt(fd, level, optname, optval, (socklen_t *)optlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
HPIDECL(set_sock_opt, "set_sock_opt", _socket, SocketSetOption, int, "%d",
|
|
||||||
(int fd, int level, int optname, const char *optval, int optlen),
|
|
||||||
("fd = %d, level = %d, optname = %d, optval = %p, optlen = %d",
|
|
||||||
fd, level, optname, optval, optlen),
|
|
||||||
(fd, level, optname, optval, optlen));
|
|
||||||
*/
|
|
||||||
inline int hpi::set_sock_opt(int fd, int level, int optname,
|
|
||||||
const char *optval, int optlen){
|
|
||||||
return ::setsockopt(fd, level, optname, optval, optlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Reconciliation History
|
|
||||||
// hpi_solaris.hpp 1.9 99/08/30 16:31:23
|
|
||||||
// End
|
|
||||||
|
|
||||||
#endif // OS_LINUX_VM_HPI_LINUX_HPP
|
|
|
@ -44,7 +44,6 @@
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/extendedPC.hpp"
|
#include "runtime/extendedPC.hpp"
|
||||||
#include "runtime/globals.hpp"
|
#include "runtime/globals.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
|
@ -1566,6 +1565,24 @@ void os::die() {
|
||||||
// unused on linux for now.
|
// unused on linux for now.
|
||||||
void os::set_error_file(const char *logfile) {}
|
void os::set_error_file(const char *logfile) {}
|
||||||
|
|
||||||
|
|
||||||
|
// This method is a copy of JDK's sysGetLastErrorString
|
||||||
|
// from src/solaris/hpi/src/system_md.c
|
||||||
|
|
||||||
|
size_t os::lasterror(char *buf, size_t len) {
|
||||||
|
|
||||||
|
if (errno == 0) return 0;
|
||||||
|
|
||||||
|
const char *s = ::strerror(errno);
|
||||||
|
size_t n = ::strlen(s);
|
||||||
|
if (n >= len) {
|
||||||
|
n = len - 1;
|
||||||
|
}
|
||||||
|
::strncpy(buf, s, n);
|
||||||
|
buf[n] = '\0';
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
intx os::current_thread_id() { return (intx)pthread_self(); }
|
intx os::current_thread_id() { return (intx)pthread_self(); }
|
||||||
int os::current_process_id() {
|
int os::current_process_id() {
|
||||||
|
|
||||||
|
@ -1939,19 +1956,19 @@ void* os::dll_lookup(void* handle, const char* name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool _print_ascii_file(const char* filename, outputStream* st) {
|
static bool _print_ascii_file(const char* filename, outputStream* st) {
|
||||||
int fd = open(filename, O_RDONLY);
|
int fd = ::open(filename, O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf[32];
|
char buf[32];
|
||||||
int bytes;
|
int bytes;
|
||||||
while ((bytes = read(fd, buf, sizeof(buf))) > 0) {
|
while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) {
|
||||||
st->print_raw(buf, bytes);
|
st->print_raw(buf, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
::close(fd);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2229,8 +2246,6 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||||
// Use current module name "libjvm[_g].so" instead of
|
// Use current module name "libjvm[_g].so" instead of
|
||||||
// "libjvm"debug_only("_g")".so" since for fastdebug version
|
// "libjvm"debug_only("_g")".so" since for fastdebug version
|
||||||
// we should have "libjvm.so" but debug_only("_g") adds "_g"!
|
// we should have "libjvm.so" but debug_only("_g") adds "_g"!
|
||||||
// It is used when we are choosing the HPI library's name
|
|
||||||
// "libhpi[_g].so" in hpi::initialize_get_interface().
|
|
||||||
len = strlen(buf);
|
len = strlen(buf);
|
||||||
snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p);
|
snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2414,18 +2429,18 @@ void linux_wrap_code(char* base, size_t size) {
|
||||||
os::get_temp_directory(), os::current_process_id(), num);
|
os::get_temp_directory(), os::current_process_id(), num);
|
||||||
unlink(buf);
|
unlink(buf);
|
||||||
|
|
||||||
int fd = open(buf, O_CREAT | O_RDWR, S_IRWXU);
|
int fd = ::open(buf, O_CREAT | O_RDWR, S_IRWXU);
|
||||||
|
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
off_t rv = lseek(fd, size-2, SEEK_SET);
|
off_t rv = ::lseek(fd, size-2, SEEK_SET);
|
||||||
if (rv != (off_t)-1) {
|
if (rv != (off_t)-1) {
|
||||||
if (write(fd, "", 1) == 1) {
|
if (::write(fd, "", 1) == 1) {
|
||||||
mmap(base, size,
|
mmap(base, size,
|
||||||
PROT_READ|PROT_WRITE|PROT_EXEC,
|
PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||||
MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE, fd, 0);
|
MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE, fd, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(fd);
|
::close(fd);
|
||||||
unlink(buf);
|
unlink(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4057,13 +4072,6 @@ jint os::init_2(void)
|
||||||
// Initialize lock used to serialize thread creation (see os::create_thread)
|
// Initialize lock used to serialize thread creation (see os::create_thread)
|
||||||
Linux::set_createThread_lock(new Mutex(Mutex::leaf, "createThread_lock", false));
|
Linux::set_createThread_lock(new Mutex(Mutex::leaf, "createThread_lock", false));
|
||||||
|
|
||||||
// Initialize HPI.
|
|
||||||
jint hpi_result = hpi::initialize();
|
|
||||||
if (hpi_result != JNI_OK) {
|
|
||||||
tty->print_cr("There was an error trying to initialize the HPI library.");
|
|
||||||
return hpi_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// at-exit methods are called in the reverse order of their registration.
|
// at-exit methods are called in the reverse order of their registration.
|
||||||
// atexit functions are called on return from main or as a result of a
|
// atexit functions are called on return from main or as a result of a
|
||||||
// call to exit(3C). There can be only 32 of these functions registered
|
// call to exit(3C). There can be only 32 of these functions registered
|
||||||
|
@ -4261,7 +4269,7 @@ int os::stat(const char *path, struct stat *sbuf) {
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
hpi::native_path(strcpy(pathbuf, path));
|
os::native_path(strcpy(pathbuf, path));
|
||||||
return ::stat(pathbuf, sbuf);
|
return ::stat(pathbuf, sbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4293,6 +4301,85 @@ bool os::dir_is_empty(const char* path) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This code originates from JDK's sysOpen and open64_w
|
||||||
|
// from src/solaris/hpi/src/system_md.c
|
||||||
|
|
||||||
|
#ifndef O_DELETE
|
||||||
|
#define O_DELETE 0x10000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Open a file. Unlink the file immediately after open returns
|
||||||
|
// if the specified oflag has the O_DELETE flag set.
|
||||||
|
// O_DELETE is used only in j2se/src/share/native/java/util/zip/ZipFile.c
|
||||||
|
|
||||||
|
int os::open(const char *path, int oflag, int mode) {
|
||||||
|
|
||||||
|
if (strlen(path) > MAX_PATH - 1) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int fd;
|
||||||
|
int o_delete = (oflag & O_DELETE);
|
||||||
|
oflag = oflag & ~O_DELETE;
|
||||||
|
|
||||||
|
fd = ::open64(path, oflag, mode);
|
||||||
|
if (fd == -1) return -1;
|
||||||
|
|
||||||
|
//If the open succeeded, the file might still be a directory
|
||||||
|
{
|
||||||
|
struct stat64 buf64;
|
||||||
|
int ret = ::fstat64(fd, &buf64);
|
||||||
|
int st_mode = buf64.st_mode;
|
||||||
|
|
||||||
|
if (ret != -1) {
|
||||||
|
if ((st_mode & S_IFMT) == S_IFDIR) {
|
||||||
|
errno = EISDIR;
|
||||||
|
::close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
::close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
if (o_delete != 0) {
|
||||||
|
::unlink(path);
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// create binary file, rewriting existing file if required
|
// create binary file, rewriting existing file if required
|
||||||
int os::create_binary_file(const char* path, bool rewrite_existing) {
|
int os::create_binary_file(const char* path, bool rewrite_existing) {
|
||||||
int oflags = O_WRONLY | O_CREAT;
|
int oflags = O_WRONLY | O_CREAT;
|
||||||
|
@ -4312,6 +4399,40 @@ jlong os::seek_to_file_offset(int fd, jlong offset) {
|
||||||
return (jlong)::lseek64(fd, (off64_t)offset, SEEK_SET);
|
return (jlong)::lseek64(fd, (off64_t)offset, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This code originates from JDK's sysAvailable
|
||||||
|
// from src/solaris/hpi/src/native_threads/src/sys_api_td.c
|
||||||
|
|
||||||
|
int os::available(int fd, jlong *bytes) {
|
||||||
|
jlong cur, end;
|
||||||
|
int mode;
|
||||||
|
struct stat64 buf64;
|
||||||
|
|
||||||
|
if (::fstat64(fd, &buf64) >= 0) {
|
||||||
|
mode = buf64.st_mode;
|
||||||
|
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) {
|
||||||
|
*bytes = n;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((cur = ::lseek64(fd, 0L, SEEK_CUR)) == -1) {
|
||||||
|
return 0;
|
||||||
|
} else if ((end = ::lseek64(fd, 0L, SEEK_END)) == -1) {
|
||||||
|
return 0;
|
||||||
|
} else if (::lseek64(fd, cur, SEEK_SET) == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*bytes = end - cur;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Map a block of memory.
|
// Map a block of memory.
|
||||||
char* os::map_memory(int fd, const char* file_name, size_t file_offset,
|
char* os::map_memory(int fd, const char* file_name, size_t file_offset,
|
||||||
char *addr, size_t bytes, bool read_only,
|
char *addr, size_t bytes, bool read_only,
|
||||||
|
@ -4538,7 +4659,7 @@ void os::pause() {
|
||||||
int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
close(fd);
|
::close(fd);
|
||||||
while (::stat(filename, &buf) == 0) {
|
while (::stat(filename, &buf) == 0) {
|
||||||
(void)::poll(NULL, 0, 100);
|
(void)::poll(NULL, 0, 100);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,14 @@
|
||||||
# include "orderAccess_linux_zero.inline.hpp"
|
# include "orderAccess_linux_zero.inline.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// System includes
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
inline void* os::thread_local_storage_at(int index) {
|
inline void* os::thread_local_storage_at(int index) {
|
||||||
return pthread_getspecific((pthread_key_t)index);
|
return pthread_getspecific((pthread_key_t)index);
|
||||||
}
|
}
|
||||||
|
@ -93,6 +101,12 @@ inline void os::split_reserved_memory(char *base, size_t size,
|
||||||
inline void os::bang_stack_shadow_pages() {
|
inline void os::bang_stack_shadow_pages() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void os::dll_unload(void *lib) {
|
||||||
|
::dlclose(lib);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const int os::default_file_open_flags() { return 0;}
|
||||||
|
|
||||||
inline DIR* os::opendir(const char* dirname)
|
inline DIR* os::opendir(const char* dirname)
|
||||||
{
|
{
|
||||||
assert(dirname != NULL, "just checking");
|
assert(dirname != NULL, "just checking");
|
||||||
|
@ -104,6 +118,22 @@ inline int os::readdir_buf_size(const char *path)
|
||||||
return NAME_MAX + sizeof(dirent) + 1;
|
return NAME_MAX + sizeof(dirent) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline jlong os::lseek(int fd, jlong offset, int whence) {
|
||||||
|
return (jlong) ::lseek64(fd, offset, whence);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::fsync(int fd) {
|
||||||
|
return ::fsync(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline char* os::native_path(char *path) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::ftruncate(int fd, jlong length) {
|
||||||
|
return ::ftruncate64(fd, length);
|
||||||
|
}
|
||||||
|
|
||||||
inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf)
|
inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf)
|
||||||
{
|
{
|
||||||
dirent* p;
|
dirent* p;
|
||||||
|
@ -121,9 +151,8 @@ inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int os::closedir(DIR *dirp)
|
inline int os::closedir(DIR *dirp) {
|
||||||
{
|
assert(dirp != NULL, "argument is NULL");
|
||||||
assert(dirp != NULL, "just checking");
|
|
||||||
return ::closedir(dirp);
|
return ::closedir(dirp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,4 +171,139 @@ inline int os::closedir(DIR *dirp)
|
||||||
inline bool os::numa_has_static_binding() { return true; }
|
inline bool os::numa_has_static_binding() { return true; }
|
||||||
inline bool os::numa_has_group_homing() { return false; }
|
inline bool os::numa_has_group_homing() { return false; }
|
||||||
|
|
||||||
|
inline size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) {
|
||||||
|
size_t res;
|
||||||
|
RESTARTABLE( (size_t) ::read(fd, buf, (size_t) nBytes), res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t os::write(int fd, const void *buf, unsigned int nBytes) {
|
||||||
|
size_t res;
|
||||||
|
RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::close(int fd) {
|
||||||
|
return ::close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::socket_close(int fd) {
|
||||||
|
return ::close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::socket(int domain, int type, int protocol) {
|
||||||
|
return ::socket(domain, type, protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::recv(int fd, char *buf, int nBytes, int flags) {
|
||||||
|
RESTARTABLE_RETURN_INT(::recv(fd, buf, nBytes, (unsigned int) flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::send(int fd, char *buf, int nBytes, int flags) {
|
||||||
|
RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, (unsigned int) flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::raw_send(int fd, char *buf, int nBytes, int flags) {
|
||||||
|
return os::send(fd, buf, nBytes, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::timeout(int fd, long timeout) {
|
||||||
|
julong prevtime,newtime;
|
||||||
|
struct timeval t;
|
||||||
|
|
||||||
|
gettimeofday(&t, NULL);
|
||||||
|
prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
struct pollfd pfd;
|
||||||
|
|
||||||
|
pfd.fd = fd;
|
||||||
|
pfd.events = POLLIN | POLLERR;
|
||||||
|
|
||||||
|
int res = ::poll(&pfd, 1, timeout);
|
||||||
|
|
||||||
|
if (res == OS_ERR && errno == EINTR) {
|
||||||
|
|
||||||
|
// On Linux any value < 0 means "forever"
|
||||||
|
|
||||||
|
if(timeout >= 0) {
|
||||||
|
gettimeofday(&t, NULL);
|
||||||
|
newtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
|
||||||
|
timeout -= newtime - prevtime;
|
||||||
|
if(timeout <= 0)
|
||||||
|
return OS_OK;
|
||||||
|
prevtime = newtime;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::listen(int fd, int count) {
|
||||||
|
return ::listen(fd, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::connect(int fd, struct sockaddr *him, int len) {
|
||||||
|
RESTARTABLE_RETURN_INT(::connect(fd, him, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::accept(int fd, struct sockaddr *him, int *len) {
|
||||||
|
// This cast is from int to unsigned int on linux. Since we
|
||||||
|
// only pass the parameter "len" around the vm and don't try to
|
||||||
|
// fetch it's value, this cast is safe for now. The java.net group
|
||||||
|
// may need and want to change this interface someday if socklen_t goes
|
||||||
|
// to 64 bits on some platform that we support.
|
||||||
|
// Linux doc says this can't return EINTR, unlike accept() on Solaris
|
||||||
|
|
||||||
|
return ::accept(fd, him, (socklen_t *)len);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::recvfrom(int fd, char *buf, int nBytes, int flags,
|
||||||
|
sockaddr *from, int *fromlen) {
|
||||||
|
RESTARTABLE_RETURN_INT(::recvfrom(fd, buf, nBytes, (unsigned int) flags, from, (socklen_t *)fromlen));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::sendto(int fd, char *buf, int len, int flags,
|
||||||
|
struct sockaddr *to, int tolen) {
|
||||||
|
RESTARTABLE_RETURN_INT(::sendto(fd, buf, len, (unsigned int) flags, to, tolen));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::socket_available(int fd, jint *pbytes) {
|
||||||
|
// Linux doc says EINTR not returned, unlike Solaris
|
||||||
|
int ret = ::ioctl(fd, FIONREAD, pbytes);
|
||||||
|
|
||||||
|
//%% note ioctl can return 0 when successful, JVM_SocketAvailable
|
||||||
|
// is expected to return 0 on failure and 1 on success to the jdk.
|
||||||
|
return (ret < 0) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline int os::socket_shutdown(int fd, int howto){
|
||||||
|
return ::shutdown(fd, howto);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::bind(int fd, struct sockaddr *him, int len){
|
||||||
|
return ::bind(fd, him, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::get_sock_name(int fd, struct sockaddr *him, int *len){
|
||||||
|
return ::getsockname(fd, him, (socklen_t *)len);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::get_host_name(char* name, int namelen){
|
||||||
|
return ::gethostname(name, namelen);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline struct hostent* os::get_host_by_name(char* name) {
|
||||||
|
return ::gethostbyname(name);
|
||||||
|
}
|
||||||
|
inline int os::get_sock_opt(int fd, int level, int optname,
|
||||||
|
char *optval, int* optlen){
|
||||||
|
return ::getsockopt(fd, level, optname, optval, (socklen_t *)optlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::set_sock_opt(int fd, int level, int optname,
|
||||||
|
const char *optval, int optlen){
|
||||||
|
return ::setsockopt(fd, level, optname, optval, optlen);
|
||||||
|
}
|
||||||
#endif // OS_LINUX_VM_OS_LINUX_INLINE_HPP
|
#endif // OS_LINUX_VM_OS_LINUX_INLINE_HPP
|
||||||
|
|
|
@ -22,10 +22,6 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK,
|
|
||||||
* search "GAMMA" for gamma specific changes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "java.h"
|
#include "java.h"
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
@ -45,64 +41,42 @@
|
||||||
#include "version_comp.h"
|
#include "version_comp.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <pthread.h>
|
||||||
|
#else
|
||||||
|
#include <thread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define JVM_DLL "libjvm.so"
|
#define JVM_DLL "libjvm.so"
|
||||||
#define JAVA_DLL "libjava.so"
|
#define JAVA_DLL "libjava.so"
|
||||||
|
|
||||||
#ifndef GAMMA /* launcher.make defines ARCH */
|
#ifndef GAMMA /* launcher.make defines ARCH */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If a processor / os combination has the ability to run binaries of
|
* If a processor / os combination has the ability to run binaries of
|
||||||
* two data models and cohabitation of jre/jdk bits with both data
|
* two data models and cohabitation of jre/jdk bits with both data
|
||||||
* models is supported, then DUAL_MODE is defined. When DUAL_MODE is
|
* models is supported, then DUAL_MODE is defined. When DUAL_MODE is
|
||||||
* defined, the architecture names for the narrow and wide version of
|
* defined, the architecture names for the narrow and wide version of
|
||||||
* the architecture are defined in BIG_ARCH and SMALL_ARCH. Currently
|
* the architecture are defined in LIBARCH64NAME and LIBARCH32NAME. Currently
|
||||||
* only Solaris on sparc/sparcv9 and i586/amd64 is DUAL_MODE; linux
|
* only Solaris on sparc/sparcv9 and i586/amd64 is DUAL_MODE; linux
|
||||||
* i586/amd64 could be defined as DUAL_MODE but that is not the
|
* i586/amd64 could be defined as DUAL_MODE but that is not the
|
||||||
* current policy.
|
* current policy.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef _LP64
|
#ifndef LIBARCHNAME
|
||||||
|
# error "The macro LIBARCHNAME was not defined on the compile line"
|
||||||
# ifdef ia64
|
|
||||||
# define ARCH "ia64"
|
|
||||||
# elif defined(amd64)
|
|
||||||
# define ARCH "amd64"
|
|
||||||
# elif defined(__sparc)
|
|
||||||
# define ARCH "sparcv9"
|
|
||||||
# else
|
|
||||||
# define ARCH "unknown" /* unknown 64-bit architecture */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else /* 32-bit data model */
|
|
||||||
|
|
||||||
# ifdef i586
|
|
||||||
# define ARCH "i386"
|
|
||||||
# elif defined(__sparc)
|
|
||||||
# define ARCH "sparc"
|
|
||||||
# elif defined(arm)
|
|
||||||
# define ARCH "arm"
|
|
||||||
# elif defined(PPC)
|
|
||||||
# define ARCH "ppc"
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#endif /* _LP64 */
|
|
||||||
|
|
||||||
#ifdef __sun
|
#ifdef __sun
|
||||||
# define DUAL_MODE
|
# define DUAL_MODE
|
||||||
# ifdef __sparc
|
# ifndef LIBARCH32NAME
|
||||||
# define BIG_ARCH "sparcv9"
|
# error "The macro LIBARCH32NAME was not defined on the compile line"
|
||||||
# define SMALL_ARCH "sparc"
|
# endif
|
||||||
# else
|
# ifndef LIBARCH64NAME
|
||||||
# define BIG_ARCH "amd64"
|
# error "The macro LIBARCH64NAME was not defined on the compile line"
|
||||||
# define SMALL_ARCH "i386"
|
|
||||||
# endif
|
# endif
|
||||||
# include <sys/systeminfo.h>
|
# include <sys/systeminfo.h>
|
||||||
# include <sys/elf.h>
|
# include <sys/elf.h>
|
||||||
# include <stdio.h>
|
# include <stdio.h>
|
||||||
#else
|
|
||||||
# ifndef ARCH
|
|
||||||
# include <sys/systeminfo.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* ifndef GAMMA */
|
#endif /* ifndef GAMMA */
|
||||||
|
@ -111,7 +85,6 @@
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
|
|
||||||
#ifndef GAMMA
|
#ifndef GAMMA
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A collection of useful strings. One should think of these as #define
|
* A collection of useful strings. One should think of these as #define
|
||||||
* entries, but actual strings can be more efficient (with many compilers).
|
* entries, but actual strings can be more efficient (with many compilers).
|
||||||
|
@ -196,23 +169,13 @@ static jboolean GetJVMPath(const char *jrepath, const char *jvmtype,
|
||||||
char *jvmpath, jint jvmpathsize, char * arch);
|
char *jvmpath, jint jvmpathsize, char * arch);
|
||||||
static jboolean GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative);
|
static jboolean GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative);
|
||||||
|
|
||||||
|
#ifndef GAMMA
|
||||||
const char *
|
const char *
|
||||||
GetArch()
|
GetArch()
|
||||||
{
|
{
|
||||||
static char *arch = NULL;
|
return LIBARCHNAME;
|
||||||
static char buf[12];
|
|
||||||
if (arch) {
|
|
||||||
return arch;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ARCH
|
|
||||||
strcpy(buf, ARCH);
|
|
||||||
#else
|
|
||||||
sysinfo(SI_ARCHITECTURE, buf, sizeof(buf));
|
|
||||||
#endif
|
|
||||||
arch = buf;
|
|
||||||
return arch;
|
|
||||||
}
|
}
|
||||||
|
#endif /* ifndef GAMMA */
|
||||||
|
|
||||||
void
|
void
|
||||||
CreateExecutionEnvironment(int *_argcp,
|
CreateExecutionEnvironment(int *_argcp,
|
||||||
|
@ -287,7 +250,7 @@ CreateExecutionEnvironment(int *_argcp,
|
||||||
{ /* open new scope to declare local variables */
|
{ /* open new scope to declare local variables */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
newargv = (char **)MemAlloc((argc+1) * sizeof(*newargv));
|
newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(*newargv));
|
||||||
newargv[newargc++] = argv[0];
|
newargv[newargc++] = argv[0];
|
||||||
|
|
||||||
/* scan for data model arguments and remove from argument list;
|
/* scan for data model arguments and remove from argument list;
|
||||||
|
@ -358,7 +321,7 @@ CreateExecutionEnvironment(int *_argcp,
|
||||||
#ifdef DUAL_MODE
|
#ifdef DUAL_MODE
|
||||||
if (running != wanted) {
|
if (running != wanted) {
|
||||||
/* Find out where the JRE is that we will be using. */
|
/* Find out where the JRE is that we will be using. */
|
||||||
if (!GetJREPath(jrepath, so_jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH), JNI_TRUE)) {
|
if (!GetJREPath(jrepath, so_jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE)) {
|
||||||
goto EndDataModelSpeculate;
|
goto EndDataModelSpeculate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,14 +329,14 @@ CreateExecutionEnvironment(int *_argcp,
|
||||||
* Read in jvm.cfg for target data model and process vm
|
* Read in jvm.cfg for target data model and process vm
|
||||||
* selection options.
|
* selection options.
|
||||||
*/
|
*/
|
||||||
if (ReadKnownVMs(jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH), JNI_TRUE) < 1) {
|
if (ReadKnownVMs(jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE) < 1) {
|
||||||
goto EndDataModelSpeculate;
|
goto EndDataModelSpeculate;
|
||||||
}
|
}
|
||||||
jvmpath[0] = '\0';
|
jvmpath[0] = '\0';
|
||||||
jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE);
|
jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE);
|
||||||
/* exec child can do error checking on the existence of the path */
|
/* exec child can do error checking on the existence of the path */
|
||||||
jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath,
|
jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath,
|
||||||
((wanted==64)?BIG_ARCH:SMALL_ARCH));
|
((wanted==64)?LIBARCH64NAME:LIBARCH32NAME));
|
||||||
|
|
||||||
}
|
}
|
||||||
EndDataModelSpeculate: /* give up and let other code report error message */
|
EndDataModelSpeculate: /* give up and let other code report error message */
|
||||||
|
@ -388,8 +351,8 @@ CreateExecutionEnvironment(int *_argcp,
|
||||||
* We will set the LD_LIBRARY_PATH as follows:
|
* We will set the LD_LIBRARY_PATH as follows:
|
||||||
*
|
*
|
||||||
* o $JVMPATH (directory portion only)
|
* o $JVMPATH (directory portion only)
|
||||||
* o $JRE/lib/$ARCH
|
* o $JRE/lib/$LIBARCHNAME
|
||||||
* o $JRE/../lib/$ARCH
|
* o $JRE/../lib/$LIBARCHNAME
|
||||||
*
|
*
|
||||||
* followed by the user's previous effective LD_LIBRARY_PATH, if
|
* followed by the user's previous effective LD_LIBRARY_PATH, if
|
||||||
* any.
|
* any.
|
||||||
|
@ -483,8 +446,8 @@ CreateExecutionEnvironment(int *_argcp,
|
||||||
|
|
||||||
/* runpath contains current effective LD_LIBRARY_PATH setting */
|
/* runpath contains current effective LD_LIBRARY_PATH setting */
|
||||||
|
|
||||||
jvmpath = strdup(jvmpath);
|
jvmpath = JLI_StringDup(jvmpath);
|
||||||
new_runpath = MemAlloc( ((runpath!=NULL)?strlen(runpath):0) +
|
new_runpath = JLI_MemAlloc( ((runpath!=NULL)?strlen(runpath):0) +
|
||||||
2*strlen(jrepath) + 2*strlen(arch) +
|
2*strlen(jrepath) + 2*strlen(arch) +
|
||||||
strlen(jvmpath) + 52);
|
strlen(jvmpath) + 52);
|
||||||
newpath = new_runpath + strlen("LD_LIBRARY_PATH=");
|
newpath = new_runpath + strlen("LD_LIBRARY_PATH=");
|
||||||
|
@ -500,7 +463,7 @@ CreateExecutionEnvironment(int *_argcp,
|
||||||
*lastslash = '\0';
|
*lastslash = '\0';
|
||||||
|
|
||||||
|
|
||||||
/* jvmpath, ((running != wanted)?((wanted==64)?"/"BIG_ARCH:"/.."):""), */
|
/* jvmpath, ((running != wanted)?((wanted==64)?"/"LIBARCH64NAME:"/.."):""), */
|
||||||
|
|
||||||
sprintf(new_runpath, "LD_LIBRARY_PATH="
|
sprintf(new_runpath, "LD_LIBRARY_PATH="
|
||||||
"%s:"
|
"%s:"
|
||||||
|
@ -508,8 +471,8 @@ CreateExecutionEnvironment(int *_argcp,
|
||||||
"%s/../lib/%s",
|
"%s/../lib/%s",
|
||||||
jvmpath,
|
jvmpath,
|
||||||
#ifdef DUAL_MODE
|
#ifdef DUAL_MODE
|
||||||
jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH),
|
jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME),
|
||||||
jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH)
|
jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME)
|
||||||
#else
|
#else
|
||||||
jrepath, arch,
|
jrepath, arch,
|
||||||
jrepath, arch
|
jrepath, arch
|
||||||
|
@ -576,7 +539,7 @@ CreateExecutionEnvironment(int *_argcp,
|
||||||
* executable must be updated accordingly; the executable name
|
* executable must be updated accordingly; the executable name
|
||||||
* and directory the executable resides in are separate. In the
|
* and directory the executable resides in are separate. In the
|
||||||
* case of 32 => 64, the new bits are assumed to reside in, e.g.
|
* case of 32 => 64, the new bits are assumed to reside in, e.g.
|
||||||
* "olddir/BIGARCH/execname"; in the case of 64 => 32,
|
* "olddir/LIBARCH64NAME/execname"; in the case of 64 => 32,
|
||||||
* the bits are assumed to be in "olddir/../execname". For example,
|
* the bits are assumed to be in "olddir/../execname". For example,
|
||||||
*
|
*
|
||||||
* olddir/sparcv9/execname
|
* olddir/sparcv9/execname
|
||||||
|
@ -586,19 +549,21 @@ CreateExecutionEnvironment(int *_argcp,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (running != wanted) {
|
if (running != wanted) {
|
||||||
char *oldexec = strcpy(MemAlloc(strlen(execname) + 1), execname);
|
char *oldexec = strcpy(JLI_MemAlloc(strlen(execname) + 1), execname);
|
||||||
char *olddir = oldexec;
|
char *olddir = oldexec;
|
||||||
char *oldbase = strrchr(oldexec, '/');
|
char *oldbase = strrchr(oldexec, '/');
|
||||||
|
|
||||||
|
|
||||||
newexec = MemAlloc(strlen(execname) + 20);
|
newexec = JLI_MemAlloc(strlen(execname) + 20);
|
||||||
*oldbase++ = 0;
|
*oldbase++ = 0;
|
||||||
sprintf(newexec, "%s/%s/%s", olddir,
|
sprintf(newexec, "%s/%s/%s", olddir,
|
||||||
((wanted==64) ? BIG_ARCH : ".."), oldbase);
|
((wanted==64) ? LIBARCH64NAME : ".."), oldbase);
|
||||||
argv[0] = newexec;
|
argv[0] = newexec;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
(void)fflush(stdout);
|
||||||
|
(void)fflush(stderr);
|
||||||
execve(newexec, argv, newenvp);
|
execve(newexec, argv, newenvp);
|
||||||
perror("execve()");
|
perror("execve()");
|
||||||
|
|
||||||
|
@ -630,12 +595,14 @@ CreateExecutionEnvironment(int *_argcp,
|
||||||
|
|
||||||
#else /* ifndef GAMMA */
|
#else /* ifndef GAMMA */
|
||||||
|
|
||||||
/* gamma launcher is simpler in that it doesn't handle VM flavors, data */
|
/*
|
||||||
/* model, LD_LIBRARY_PATH, etc. Assuming everything is set-up correctly */
|
* gamma launcher is simpler in that it doesn't handle VM flavors, data
|
||||||
/* all we need to do here is to return correct path names. See also */
|
* model, LD_LIBRARY_PATH, etc. Assuming everything is set-up correctly
|
||||||
/* GetJVMPath() and GetApplicationHome(). */
|
* all we need to do here is to return correct path names. See also
|
||||||
|
* GetJVMPath() and GetApplicationHome().
|
||||||
|
*/
|
||||||
|
|
||||||
{ char *arch = (char *)GetArch(); /* like sparc or sparcv9 */
|
{ char *arch = (char *) ARCH; /* like sparc or sparcv9 */
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) {
|
if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) {
|
||||||
|
@ -669,9 +636,11 @@ GetJVMPath(const char *jrepath, const char *jvmtype,
|
||||||
sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
|
sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* For gamma launcher, JVM is either built-in or in the same directory. */
|
/*
|
||||||
/* Either way we return "<exe_path>/libjvm.so" where <exe_path> is the */
|
* For gamma launcher, JVM is either built-in or in the same directory.
|
||||||
/* directory where gamma launcher is located. */
|
* Either way we return "<exe_path>/libjvm.so" where <exe_path> is the
|
||||||
|
* directory where gamma launcher is located.
|
||||||
|
*/
|
||||||
|
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
|
@ -684,7 +653,7 @@ GetJVMPath(const char *jrepath, const char *jvmtype,
|
||||||
/* this case shouldn't happen */
|
/* this case shouldn't happen */
|
||||||
snprintf(jvmpath, jvmpathsize, "%s", JVM_DLL);
|
snprintf(jvmpath, jvmpathsize, "%s", JVM_DLL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* ifndef GAMMA */
|
||||||
|
|
||||||
if (_launcher_debug)
|
if (_launcher_debug)
|
||||||
printf("Does `%s' exist ... ", jvmpath);
|
printf("Does `%s' exist ... ", jvmpath);
|
||||||
|
@ -813,24 +782,7 @@ LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
|
||||||
error:
|
error:
|
||||||
fprintf(stderr, "Error: failed %s, because %s\n", jvmpath, dlerror());
|
fprintf(stderr, "Error: failed %s, because %s\n", jvmpath, dlerror());
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
#endif /* GAMMA */
|
#endif /* ifndef GAMMA */
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the path to the file that has the usage message for -X options.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
GetXUsagePath(char *buf, jint bufsize)
|
|
||||||
{
|
|
||||||
static const char Xusage_txt[] = "/Xusage.txt";
|
|
||||||
Dl_info dlinfo;
|
|
||||||
|
|
||||||
/* we use RTLD_NOW because of problems with ld.so.1 and green threads */
|
|
||||||
dladdr(dlsym(dlopen(JVM_DLL, RTLD_NOW), "JNI_CreateJavaVM"), &dlinfo);
|
|
||||||
strncpy(buf, (char *)dlinfo.dli_fname, bufsize - sizeof(Xusage_txt));
|
|
||||||
|
|
||||||
buf[bufsize-1] = '\0';
|
|
||||||
strcpy(strrchr(buf, '/'), Xusage_txt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -860,10 +812,13 @@ GetApplicationHome(char *buf, jint bufsize)
|
||||||
|
|
||||||
#ifdef GAMMA
|
#ifdef GAMMA
|
||||||
{
|
{
|
||||||
/* gamma launcher uses JAVA_HOME environment variable to find JDK/JRE */
|
/* gamma launcher uses JAVA_HOME or ALT_JAVA_HOME environment variable to find JDK/JRE */
|
||||||
char* java_home_var = getenv("JAVA_HOME");
|
char* java_home_var = getenv("ALT_JAVA_HOME");
|
||||||
if (java_home_var == NULL) {
|
if (java_home_var == NULL) {
|
||||||
printf("JAVA_HOME must point to a valid JDK/JRE to run gamma\n");
|
java_home_var = getenv("JAVA_HOME");
|
||||||
|
}
|
||||||
|
if (java_home_var == NULL) {
|
||||||
|
printf("JAVA_HOME or ALT_JAVA_HOME must point to a valid JDK/JRE to run gamma\n");
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
snprintf(buf, bufsize, "%s", java_home_var);
|
snprintf(buf, bufsize, "%s", java_home_var);
|
||||||
|
@ -885,7 +840,7 @@ GetApplicationHome(char *buf, jint bufsize)
|
||||||
return JNI_FALSE;
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
*(strrchr(buf, '/')) = '\0'; /* bin */
|
*(strrchr(buf, '/')) = '\0'; /* bin */
|
||||||
#endif /* GAMMA */
|
#endif /* ifndef GAMMA */
|
||||||
|
|
||||||
return JNI_TRUE;
|
return JNI_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -915,7 +870,7 @@ Resolve(char *indir, char *cmd)
|
||||||
if ((strlen(indir) + strlen(cmd) + 1) > PATH_MAX) return 0;
|
if ((strlen(indir) + strlen(cmd) + 1) > PATH_MAX) return 0;
|
||||||
sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd);
|
sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd);
|
||||||
if (!ProgramExists(name)) return 0;
|
if (!ProgramExists(name)) return 0;
|
||||||
real = MemAlloc(PATH_MAX + 2);
|
real = JLI_MemAlloc(PATH_MAX + 2);
|
||||||
if (!realpath(name, real))
|
if (!realpath(name, real))
|
||||||
strcpy(real, name);
|
strcpy(real, name);
|
||||||
return real;
|
return real;
|
||||||
|
@ -948,7 +903,7 @@ FindExecName(char *program)
|
||||||
/* from search path? */
|
/* from search path? */
|
||||||
path = getenv("PATH");
|
path = getenv("PATH");
|
||||||
if (!path || !*path) path = ".";
|
if (!path || !*path) path = ".";
|
||||||
tmp_path = MemAlloc(strlen(path) + 2);
|
tmp_path = JLI_MemAlloc(strlen(path) + 2);
|
||||||
strcpy(tmp_path, path);
|
strcpy(tmp_path, path);
|
||||||
|
|
||||||
for (f=tmp_path; *f && result==0; ) {
|
for (f=tmp_path; *f && result==0; ) {
|
||||||
|
@ -967,7 +922,7 @@ FindExecName(char *program)
|
||||||
if (result != 0) break;
|
if (result != 0) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(tmp_path);
|
JLI_MemFree(tmp_path);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1000,11 +955,11 @@ SetExecname(char **argv)
|
||||||
{
|
{
|
||||||
Dl_info dlinfo;
|
Dl_info dlinfo;
|
||||||
if (dladdr((void*)&SetExecname, &dlinfo)) {
|
if (dladdr((void*)&SetExecname, &dlinfo)) {
|
||||||
char *resolved = (char*)MemAlloc(PATH_MAX+1);
|
char *resolved = (char*)JLI_MemAlloc(PATH_MAX+1);
|
||||||
if (resolved != NULL) {
|
if (resolved != NULL) {
|
||||||
exec_path = realpath(dlinfo.dli_fname, resolved);
|
exec_path = realpath(dlinfo.dli_fname, resolved);
|
||||||
if (exec_path == NULL) {
|
if (exec_path == NULL) {
|
||||||
free(resolved);
|
JLI_MemFree(resolved);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1016,7 +971,7 @@ SetExecname(char **argv)
|
||||||
int len = readlink(self, buf, PATH_MAX);
|
int len = readlink(self, buf, PATH_MAX);
|
||||||
if (len >= 0) {
|
if (len >= 0) {
|
||||||
buf[len] = '\0'; /* readlink doesn't nul terminate */
|
buf[len] = '\0'; /* readlink doesn't nul terminate */
|
||||||
exec_path = strdup(buf);
|
exec_path = JLI_StringDup(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else /* !__sun && !__linux */
|
#else /* !__sun && !__linux */
|
||||||
|
@ -1091,8 +1046,7 @@ void PrintMachineDependentOptions() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef GAMMA /* gamma launcher does not have ergonomics */
|
#ifndef GAMMA
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following methods (down to ServerClassMachine()) answer
|
* The following methods (down to ServerClassMachine()) answer
|
||||||
* the question about whether a machine is a "server-class"
|
* the question about whether a machine is a "server-class"
|
||||||
|
@ -1164,7 +1118,7 @@ solaris_sparc_ServerClassMachine(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_launcher_debug) {
|
if (_launcher_debug) {
|
||||||
printf("solaris_" ARCH "_ServerClassMachine: %s\n",
|
printf("solaris_" LIBARCHNAME "_ServerClassMachine: %s\n",
|
||||||
(result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE"));
|
(result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE"));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -1262,7 +1216,6 @@ get_cpuid(uint32_t arg,
|
||||||
uint32_t value_of_edx = 0;
|
uint32_t value_of_edx = 0;
|
||||||
__asm__ volatile (/* Instructions */
|
__asm__ volatile (/* Instructions */
|
||||||
/* ebx is callee-save, so push it */
|
/* ebx is callee-save, so push it */
|
||||||
/* even though it's in the clobbers section */
|
|
||||||
" pushl %%ebx \n"
|
" pushl %%ebx \n"
|
||||||
" movl %4, %%eax \n"
|
" movl %4, %%eax \n"
|
||||||
" cpuid \n"
|
" cpuid \n"
|
||||||
|
@ -1281,7 +1234,7 @@ get_cpuid(uint32_t arg,
|
||||||
: /* Inputs */
|
: /* Inputs */
|
||||||
"m" (arg)
|
"m" (arg)
|
||||||
: /* Clobbers */
|
: /* Clobbers */
|
||||||
"%eax", "%ebx", "%ecx", "%edx"
|
"%eax", "%ecx", "%edx"
|
||||||
);
|
);
|
||||||
*eaxp = value_of_eax;
|
*eaxp = value_of_eax;
|
||||||
*ebxp = value_of_ebx;
|
*ebxp = value_of_ebx;
|
||||||
|
@ -1461,7 +1414,7 @@ solaris_i586_ServerClassMachine(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_launcher_debug) {
|
if (_launcher_debug) {
|
||||||
printf("solaris_" ARCH "_ServerClassMachine: %s\n",
|
printf("solaris_" LIBARCHNAME "_ServerClassMachine: %s\n",
|
||||||
(result == JNI_TRUE ? "true" : "false"));
|
(result == JNI_TRUE ? "true" : "false"));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -1494,7 +1447,7 @@ linux_i586_ServerClassMachine(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_launcher_debug) {
|
if (_launcher_debug) {
|
||||||
printf("linux_" ARCH "_ServerClassMachine: %s\n",
|
printf("linux_" LIBARCHNAME "_ServerClassMachine: %s\n",
|
||||||
(result == JNI_TRUE ? "true" : "false"));
|
(result == JNI_TRUE ? "true" : "false"));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -1506,7 +1459,11 @@ linux_i586_ServerClassMachine(void) {
|
||||||
jboolean
|
jboolean
|
||||||
ServerClassMachine(void) {
|
ServerClassMachine(void) {
|
||||||
jboolean result = JNI_FALSE;
|
jboolean result = JNI_FALSE;
|
||||||
#if defined(__sun) && defined(__sparc)
|
#if defined(NEVER_ACT_AS_SERVER_CLASS_MACHINE)
|
||||||
|
result = JNI_FALSE;
|
||||||
|
#elif defined(ALWAYS_ACT_AS_SERVER_CLASS_MACHINE)
|
||||||
|
result = JNI_TRUE;
|
||||||
|
#elif defined(__sun) && defined(__sparc)
|
||||||
result = solaris_sparc_ServerClassMachine();
|
result = solaris_sparc_ServerClassMachine();
|
||||||
#elif defined(__sun) && defined(i586)
|
#elif defined(__sun) && defined(i586)
|
||||||
result = solaris_i586_ServerClassMachine();
|
result = solaris_i586_ServerClassMachine();
|
||||||
|
@ -1521,10 +1478,6 @@ ServerClassMachine(void) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* ifndef GAMMA */
|
|
||||||
|
|
||||||
#ifndef GAMMA /* gamma launcher does not choose JDK/JRE/JVM */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since using the file system as a registry is a bit risky, perform
|
* Since using the file system as a registry is a bit risky, perform
|
||||||
* additional sanity checks on the identified directory to validate
|
* additional sanity checks on the identified directory to validate
|
||||||
|
@ -1591,13 +1544,13 @@ static char
|
||||||
else if (strncmp(dp->d_name, "j2sdk", 5) == 0)
|
else if (strncmp(dp->d_name, "j2sdk", 5) == 0)
|
||||||
offset = 5;
|
offset = 5;
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
if ((acceptable_release(dp->d_name + offset,
|
if ((JLI_AcceptableRelease(dp->d_name + offset,
|
||||||
info->jre_version)) && CheckSanity(dirname, dp->d_name))
|
info->jre_version)) && CheckSanity(dirname, dp->d_name))
|
||||||
if ((best == NULL) || (exact_version_id(
|
if ((best == NULL) || (JLI_ExactVersionId(
|
||||||
dp->d_name + offset, best + best_offset) > 0)) {
|
dp->d_name + offset, best + best_offset) > 0)) {
|
||||||
if (best != NULL)
|
if (best != NULL)
|
||||||
free(best);
|
JLI_MemFree(best);
|
||||||
best = strdup(dp->d_name);
|
best = JLI_StringDup(dp->d_name);
|
||||||
best_offset = offset;
|
best_offset = offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1607,9 +1560,9 @@ static char
|
||||||
if (best == NULL)
|
if (best == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
else {
|
else {
|
||||||
ret_str = MemAlloc(strlen(dirname) + strlen(best) + 2);
|
ret_str = JLI_MemAlloc(strlen(dirname) + strlen(best) + 2);
|
||||||
ret_str = strcat(strcat(strcpy(ret_str, dirname), "/"), best);
|
ret_str = strcat(strcat(strcpy(ret_str, dirname), "/"), best);
|
||||||
free(best);
|
JLI_MemFree(best);
|
||||||
return (ret_str);
|
return (ret_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1636,16 +1589,17 @@ LocateJRE(manifest_info* info)
|
||||||
* Start by getting JAVA_VERSION_PATH
|
* Start by getting JAVA_VERSION_PATH
|
||||||
*/
|
*/
|
||||||
if (info->jre_restrict_search)
|
if (info->jre_restrict_search)
|
||||||
path = strdup(system_dir);
|
path = JLI_StringDup(system_dir);
|
||||||
else if ((path = getenv("JAVA_VERSION_PATH")) != NULL)
|
else if ((path = getenv("JAVA_VERSION_PATH")) != NULL)
|
||||||
path = strdup(path);
|
path = JLI_StringDup(path);
|
||||||
else
|
else
|
||||||
if ((home = getenv("HOME")) != NULL) {
|
if ((home = getenv("HOME")) != NULL) {
|
||||||
path = (char *)MemAlloc(strlen(home) + 13);
|
path = (char *)JLI_MemAlloc(strlen(home) + strlen(system_dir) +
|
||||||
|
strlen(user_dir) + 2);
|
||||||
path = strcat(strcat(strcat(strcpy(path, home),
|
path = strcat(strcat(strcat(strcpy(path, home),
|
||||||
user_dir), ":"), system_dir);
|
user_dir), ":"), system_dir);
|
||||||
} else
|
} else
|
||||||
path = strdup(system_dir);
|
path = JLI_StringDup(system_dir);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Step through each directory on the path. Terminate the scan with
|
* Step through each directory on the path. Terminate the scan with
|
||||||
|
@ -1662,7 +1616,7 @@ LocateJRE(manifest_info* info)
|
||||||
if (dp != NULL)
|
if (dp != NULL)
|
||||||
dp++;
|
dp++;
|
||||||
}
|
}
|
||||||
free(path);
|
JLI_MemFree(path);
|
||||||
return (target);
|
return (target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1740,16 +1694,19 @@ ExecJRE(char *jre, char **argv)
|
||||||
argv[0] = progname;
|
argv[0] = progname;
|
||||||
if (_launcher_debug) {
|
if (_launcher_debug) {
|
||||||
int i;
|
int i;
|
||||||
printf("execv(\"%s\"", wanted);
|
printf("ReExec Command: %s (%s)\n", wanted, argv[0]);
|
||||||
for (i = 0; argv[i] != NULL; i++)
|
printf("ReExec Args:");
|
||||||
printf(", \"%s\"", argv[i]);
|
for (i = 1; argv[i] != NULL; i++)
|
||||||
printf(")\n");
|
printf(" %s", argv[i]);
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
(void)fflush(stdout);
|
||||||
|
(void)fflush(stderr);
|
||||||
execv(wanted, argv);
|
execv(wanted, argv);
|
||||||
|
perror("execv()");
|
||||||
fprintf(stderr, "Exec of %s failed\n", wanted);
|
fprintf(stderr, "Exec of %s failed\n", wanted);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* ifndef GAMMA */
|
#endif /* ifndef GAMMA */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1830,23 +1787,92 @@ UnsetEnv(char *name)
|
||||||
{
|
{
|
||||||
return(borrowed_unsetenv(name));
|
return(borrowed_unsetenv(name));
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* The implementation for finding classes from the bootstrap
|
|
||||||
* class loader, refer to java.h
|
|
||||||
*/
|
|
||||||
static FindClassFromBootLoader_t *findBootClass = NULL;
|
|
||||||
|
|
||||||
jclass
|
/* --- Splash Screen shared library support --- */
|
||||||
FindBootStrapClass(JNIEnv *env, const char* classname)
|
|
||||||
{
|
static const char* SPLASHSCREEN_SO = "libsplashscreen.so";
|
||||||
if (findBootClass == NULL) {
|
|
||||||
findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT,
|
static void* hSplashLib = NULL;
|
||||||
"JVM_FindClassFromBootLoader");
|
|
||||||
if (findBootClass == NULL) {
|
void* SplashProcAddress(const char* name) {
|
||||||
fprintf(stderr, "Error: could load method JVM_FindClassFromBootLoader");
|
if (!hSplashLib) {
|
||||||
|
hSplashLib = dlopen(SPLASHSCREEN_SO, RTLD_LAZY | RTLD_GLOBAL);
|
||||||
|
}
|
||||||
|
if (hSplashLib) {
|
||||||
|
void* sym = dlsym(hSplashLib, name);
|
||||||
|
return sym;
|
||||||
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return findBootClass(env, classname, JNI_FALSE);
|
|
||||||
|
void SplashFreeLibrary() {
|
||||||
|
if (hSplashLib) {
|
||||||
|
dlclose(hSplashLib);
|
||||||
|
hSplashLib = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
jlong_format_specifier() {
|
||||||
|
return "%lld";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Block current thread and continue execution in a new thread
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void * args) {
|
||||||
|
int rslt;
|
||||||
|
#ifdef __linux__
|
||||||
|
pthread_t tid;
|
||||||
|
pthread_attr_t attr;
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||||
|
|
||||||
|
if (stack_size > 0) {
|
||||||
|
pthread_attr_setstacksize(&attr, stack_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) {
|
||||||
|
void * tmp;
|
||||||
|
pthread_join(tid, &tmp);
|
||||||
|
rslt = (int)tmp;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Continue execution in current thread if for some reason (e.g. out of
|
||||||
|
* memory/LWP) a new thread can't be created. This will likely fail
|
||||||
|
* later in continuation as JNI_CreateJavaVM needs to create quite a
|
||||||
|
* few new threads, anyway, just give it a try..
|
||||||
|
*/
|
||||||
|
rslt = continuation(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_attr_destroy(&attr);
|
||||||
|
#else
|
||||||
|
thread_t tid;
|
||||||
|
long flags = 0;
|
||||||
|
if (thr_create(NULL, stack_size, (void *(*)(void *))continuation, args, flags, &tid) == 0) {
|
||||||
|
void * tmp;
|
||||||
|
thr_join(tid, NULL, &tmp);
|
||||||
|
rslt = (int)tmp;
|
||||||
|
} else {
|
||||||
|
/* See above. Continue in current thread if thr_create() failed */
|
||||||
|
rslt = continuation(args);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return rslt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */
|
||||||
|
#define MAX_PID_STR_SZ 20
|
||||||
|
|
||||||
|
void SetJavaLauncherPlatformProps() {
|
||||||
|
/* Linux only */
|
||||||
|
#ifdef __linux__
|
||||||
|
const char *substr = "-Dsun.java.launcher.pid=";
|
||||||
|
char *pid_prop_str = (char *)JLI_MemAlloc(strlen(substr) + MAX_PID_STR_SZ + 1);
|
||||||
|
sprintf(pid_prop_str, "%s%d", substr, getpid());
|
||||||
|
AddOption(pid_prop_str, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -22,11 +22,6 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK,
|
|
||||||
* search "GAMMA" for gamma specific changes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef JAVA_MD_H
|
#ifndef JAVA_MD_H
|
||||||
#define JAVA_MD_H
|
#define JAVA_MD_H
|
||||||
|
|
||||||
|
@ -36,10 +31,12 @@
|
||||||
#ifndef GAMMA
|
#ifndef GAMMA
|
||||||
#include "manifest_info.h"
|
#include "manifest_info.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "jli_util.h"
|
||||||
|
|
||||||
#define PATH_SEPARATOR ':'
|
#define PATH_SEPARATOR ':'
|
||||||
#define FILESEP "/"
|
#define FILESEP "/"
|
||||||
#define FILE_SEPARATOR '/'
|
#define FILE_SEPARATOR '/'
|
||||||
|
#define IS_FILE_SEPARATOR(c) ((c) == '/')
|
||||||
#ifndef MAXNAMELEN
|
#ifndef MAXNAMELEN
|
||||||
#define MAXNAMELEN PATH_MAX
|
#define MAXNAMELEN PATH_MAX
|
||||||
#endif
|
#endif
|
208
hotspot/src/os/posix/launcher/launcher.script
Normal file
208
hotspot/src/os/posix/launcher/launcher.script
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
# This script launches HotSpot.
|
||||||
|
#
|
||||||
|
# If the first parameter is either "-gdb" or "-gud", HotSpot will be
|
||||||
|
# launched inside gdb. "-gud" means "open an Emacs window and run gdb
|
||||||
|
# inside Emacs".
|
||||||
|
#
|
||||||
|
# If the first parameter is "-dbx", HotSpot will be launched inside dbx.
|
||||||
|
#
|
||||||
|
# If the first parameter is "-valgrind", HotSpot will be launched
|
||||||
|
# inside Valgrind (http://valgrind.kde.org) using the Memcheck skin,
|
||||||
|
# and with memory leak detection enabled. This currently (2005jan19)
|
||||||
|
# requires at least Valgrind 2.3.0. -Xmx16m will also be passed as
|
||||||
|
# the first parameter to HotSpot, since lowering HotSpot's memory
|
||||||
|
# consumption makes execution inside of Valgrind *a lot* faster.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# User changeable parameters ------------------------------------------------
|
||||||
|
#
|
||||||
|
|
||||||
|
# This is the name of the gdb binary to use
|
||||||
|
if [ ! "$GDB" ]
|
||||||
|
then
|
||||||
|
GDB=gdb
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This is the name of the gdb binary to use
|
||||||
|
if [ ! "$DBX" ]
|
||||||
|
then
|
||||||
|
DBX=dbx
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This is the name of the Valgrind binary to use
|
||||||
|
if [ ! "$VALGRIND" ]
|
||||||
|
then
|
||||||
|
VALGRIND=valgrind
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This is the name of Emacs for running GUD
|
||||||
|
EMACS=emacs
|
||||||
|
|
||||||
|
#
|
||||||
|
# End of user changeable parameters -----------------------------------------
|
||||||
|
#
|
||||||
|
|
||||||
|
# Make sure the paths are fully specified, i.e. they must begin with /.
|
||||||
|
SCRIPT=$(cd $(dirname $0) && pwd)/$(basename $0)
|
||||||
|
RUNDIR=$(pwd)
|
||||||
|
|
||||||
|
# Look whether the user wants to run inside gdb
|
||||||
|
case "$1" in
|
||||||
|
-gdb)
|
||||||
|
MODE=gdb
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-gud)
|
||||||
|
MODE=gud
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-dbx)
|
||||||
|
MODE=dbx
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-valgrind)
|
||||||
|
MODE=valgrind
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
MODE=run
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "${ALT_JAVA_HOME}" = "" ]; then
|
||||||
|
if [ "${JAVA_HOME}" = "" ]; then
|
||||||
|
echo "Neither ALT_JAVA_HOME nor JAVA_HOME is set. Aborting.";
|
||||||
|
exit 1;
|
||||||
|
else
|
||||||
|
JDK=${JAVA_HOME%%/jre};
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JDK=${ALT_JAVA_HOME%%/jre};
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We will set the LD_LIBRARY_PATH as follows:
|
||||||
|
# o $JVMPATH (directory portion only)
|
||||||
|
# o $JRE/lib/$ARCH
|
||||||
|
# followed by the user's previous effective LD_LIBRARY_PATH, if
|
||||||
|
# any.
|
||||||
|
JRE=$JDK/jre
|
||||||
|
JAVA_HOME=$JDK
|
||||||
|
ARCH=@@LIBARCH@@
|
||||||
|
|
||||||
|
# Find out the absolute path to this script
|
||||||
|
MYDIR=$(cd $(dirname $SCRIPT) && pwd)
|
||||||
|
|
||||||
|
SBP=${MYDIR}:${JRE}/lib/${ARCH}
|
||||||
|
|
||||||
|
# Set up a suitable LD_LIBRARY_PATH
|
||||||
|
|
||||||
|
if [ -z "$LD_LIBRARY_PATH" ]
|
||||||
|
then
|
||||||
|
LD_LIBRARY_PATH="$SBP"
|
||||||
|
else
|
||||||
|
LD_LIBRARY_PATH="$SBP:$LD_LIBRARY_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
export LD_LIBRARY_PATH
|
||||||
|
export JAVA_HOME
|
||||||
|
|
||||||
|
JPARMS="$@ $JAVA_ARGS";
|
||||||
|
|
||||||
|
# Locate the gamma development launcher
|
||||||
|
LAUNCHER=${MYDIR}/gamma
|
||||||
|
if [ ! -x $LAUNCHER ] ; then
|
||||||
|
echo Error: Cannot find the gamma development launcher \"$LAUNCHER\"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
GDBSRCDIR=$MYDIR
|
||||||
|
BASEDIR=$(cd $MYDIR/../../.. && pwd)
|
||||||
|
|
||||||
|
init_gdb() {
|
||||||
|
# Create a gdb script in case we should run inside gdb
|
||||||
|
GDBSCR=/tmp/hsl.$$
|
||||||
|
rm -f $GDBSCR
|
||||||
|
cat >>$GDBSCR <<EOF
|
||||||
|
cd `pwd`
|
||||||
|
handle SIGUSR1 nostop noprint
|
||||||
|
handle SIGUSR2 nostop noprint
|
||||||
|
set args $JPARMS
|
||||||
|
file $LAUNCHER
|
||||||
|
directory $GDBSRCDIR
|
||||||
|
# Get us to a point where we can set breakpoints in libjvm.so
|
||||||
|
break InitializeJVM
|
||||||
|
run
|
||||||
|
# Stop in InitializeJVM
|
||||||
|
delete 1
|
||||||
|
# We can now set breakpoints wherever we like
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case "$MODE" in
|
||||||
|
gdb)
|
||||||
|
init_gdb
|
||||||
|
$GDB -x $GDBSCR
|
||||||
|
rm -f $GDBSCR
|
||||||
|
;;
|
||||||
|
gud)
|
||||||
|
init_gdb
|
||||||
|
# First find out what emacs version we're using, so that we can
|
||||||
|
# use the new pretty GDB mode if emacs -version >= 22.1
|
||||||
|
case $($EMACS -version 2> /dev/null) in
|
||||||
|
*GNU\ Emacs\ 2[23]*)
|
||||||
|
emacs_gud_cmd="gdba"
|
||||||
|
emacs_gud_args="--annotate=3"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
emacs_gud_cmd="gdb"
|
||||||
|
emacs_gud_args=
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
$EMACS --eval "($emacs_gud_cmd \"$GDB $emacs_gud_args -x $GDBSCR\")";
|
||||||
|
rm -f $GDBSCR
|
||||||
|
;;
|
||||||
|
dbx)
|
||||||
|
$DBX -s $MYDIR/.dbxrc $LAUNCHER $JPARAMS
|
||||||
|
;;
|
||||||
|
valgrind)
|
||||||
|
echo Warning: Defaulting to 16Mb heap to make Valgrind run faster, use -Xmx for larger heap
|
||||||
|
echo
|
||||||
|
$VALGRIND --tool=memcheck --leak-check=yes --num-callers=50 $LAUNCHER -Xmx16m $JPARMS
|
||||||
|
;;
|
||||||
|
run)
|
||||||
|
LD_PRELOAD=$PRELOADING exec $LAUNCHER $JPARMS
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo Error: Internal error, unknown launch mode \"$MODE\"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
RETVAL=$?
|
||||||
|
exit $RETVAL
|
File diff suppressed because it is too large
Load diff
|
@ -1,115 +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.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK,
|
|
||||||
* search "GAMMA" for gamma specific changes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _JAVA_H_
|
|
||||||
#define _JAVA_H_
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get system specific defines.
|
|
||||||
*/
|
|
||||||
#include "jni.h"
|
|
||||||
#include "java_md.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pointers to the needed JNI invocation API, initialized by LoadJavaVM.
|
|
||||||
*/
|
|
||||||
typedef jint (JNICALL *CreateJavaVM_t)(JavaVM **pvm, void **env, void *args);
|
|
||||||
typedef jint (JNICALL *GetDefaultJavaVMInitArgs_t)(void *args);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CreateJavaVM_t CreateJavaVM;
|
|
||||||
GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs;
|
|
||||||
} InvocationFunctions;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Prototypes for launcher functions in the system specific java_md.c.
|
|
||||||
*/
|
|
||||||
|
|
||||||
jboolean
|
|
||||||
LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn);
|
|
||||||
|
|
||||||
void
|
|
||||||
GetXUsagePath(char *buf, jint bufsize);
|
|
||||||
|
|
||||||
jboolean
|
|
||||||
GetApplicationHome(char *buf, jint bufsize);
|
|
||||||
|
|
||||||
const char *
|
|
||||||
GetArch();
|
|
||||||
|
|
||||||
void CreateExecutionEnvironment(int *_argc,
|
|
||||||
char ***_argv,
|
|
||||||
char jrepath[],
|
|
||||||
jint so_jrepath,
|
|
||||||
char jvmpath[],
|
|
||||||
jint so_jvmpath,
|
|
||||||
char **original_argv);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Report an error message to stderr or a window as appropriate. The
|
|
||||||
* flag always is set to JNI_TRUE if message is to be reported to both
|
|
||||||
* strerr and windows and set to JNI_FALSE if the message should only
|
|
||||||
* be sent to a window.
|
|
||||||
*/
|
|
||||||
void ReportErrorMessage(char * message, jboolean always);
|
|
||||||
void ReportErrorMessage2(char * format, char * string, jboolean always);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Report an exception which terminates the vm to stderr or a window
|
|
||||||
* as appropriate.
|
|
||||||
*/
|
|
||||||
void ReportExceptionDescription(JNIEnv * env);
|
|
||||||
|
|
||||||
jboolean RemovableMachineDependentOption(char * option);
|
|
||||||
void PrintMachineDependentOptions();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Functions defined in java.c and used in java_md.c.
|
|
||||||
*/
|
|
||||||
jint ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative);
|
|
||||||
char *CheckJvmType(int *argc, char ***argv, jboolean speculative);
|
|
||||||
void* MemAlloc(size_t size);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make launcher spit debug output.
|
|
||||||
*/
|
|
||||||
extern jboolean _launcher_debug;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This allows for finding classes from the VM's bootstrap class loader
|
|
||||||
* directly, FindClass uses the application class loader internally, this will
|
|
||||||
* cause unnecessary searching of the classpath for the required classes.
|
|
||||||
*/
|
|
||||||
typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env,
|
|
||||||
const char *name,
|
|
||||||
jboolean throwError));
|
|
||||||
|
|
||||||
jclass FindBootStrapClass(JNIEnv *env, const char *classname);
|
|
||||||
|
|
||||||
#endif /* _JAVA_H_ */
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,80 +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.
|
|
||||||
*
|
|
||||||
* 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 "precompiled.hpp"
|
|
||||||
#include "oops/oop.inline.hpp"
|
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/os.hpp"
|
|
||||||
|
|
||||||
# include <sys/param.h>
|
|
||||||
# include <dlfcn.h>
|
|
||||||
|
|
||||||
typedef jint (JNICALL *init_t)(GetInterfaceFunc *, void *);
|
|
||||||
|
|
||||||
void hpi::initialize_get_interface(vm_calls_t *callbacks)
|
|
||||||
{
|
|
||||||
char buf[JVM_MAXPATHLEN];
|
|
||||||
void *hpi_handle;
|
|
||||||
GetInterfaceFunc& getintf = _get_interface;
|
|
||||||
jint (JNICALL * DLL_Initialize)(GetInterfaceFunc *, void *);
|
|
||||||
|
|
||||||
if (HPILibPath && HPILibPath[0]) {
|
|
||||||
strncpy(buf, HPILibPath, JVM_MAXPATHLEN - 1);
|
|
||||||
buf[JVM_MAXPATHLEN - 1] = '\0';
|
|
||||||
} else {
|
|
||||||
const char *thread_type = "native_threads";
|
|
||||||
|
|
||||||
os::jvm_path(buf, JVM_MAXPATHLEN);
|
|
||||||
|
|
||||||
#ifdef PRODUCT
|
|
||||||
const char * hpi_lib = "/libhpi.so";
|
|
||||||
#else
|
|
||||||
char * ptr = strrchr(buf, '/');
|
|
||||||
assert(strstr(ptr, "/libjvm") == ptr, "invalid library name");
|
|
||||||
const char * hpi_lib = strstr(ptr, "_g") ? "/libhpi_g.so" : "/libhpi.so";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*(strrchr(buf, '/')) = '\0'; /* get rid of /libjvm.so */
|
|
||||||
char* p = strrchr(buf, '/');
|
|
||||||
if (p != NULL) p[1] = '\0'; /* get rid of hotspot */
|
|
||||||
strcat(buf, thread_type);
|
|
||||||
strcat(buf, hpi_lib);
|
|
||||||
}
|
|
||||||
/* we use RTLD_NOW because of bug 4032715 */
|
|
||||||
if (TraceHPI) tty->print_cr("Loading HPI %s ", buf);
|
|
||||||
hpi_handle = dlopen(buf, RTLD_NOW);
|
|
||||||
if (hpi_handle == NULL) {
|
|
||||||
if (TraceHPI) tty->print_cr("HPI dlopen failed: %s", dlerror());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DLL_Initialize = CAST_TO_FN_PTR(jint (JNICALL *)(GetInterfaceFunc *, void *),
|
|
||||||
dlsym(hpi_handle, "DLL_Initialize"));
|
|
||||||
if (TraceHPI && DLL_Initialize == NULL) tty->print_cr("HPI dlsym of DLL_Initialize failed: %s", dlerror());
|
|
||||||
if (DLL_Initialize == NULL ||
|
|
||||||
(*DLL_Initialize)(&getintf, callbacks) < 0) {
|
|
||||||
if (TraceHPI) tty->print_cr("HPI DLL_Initialize failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (TraceHPI) tty->print_cr("HPI loaded successfully");
|
|
||||||
}
|
|
|
@ -1,254 +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.
|
|
||||||
*
|
|
||||||
* 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 OS_SOLARIS_VM_HPI_SOLARIS_HPP
|
|
||||||
#define OS_SOLARIS_VM_HPI_SOLARIS_HPP
|
|
||||||
|
|
||||||
//
|
|
||||||
// Parts of the HPI interface for which the HotSparc does not use the
|
|
||||||
// HPI (because the interruptible IO mechanims used are different).
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/poll.h>
|
|
||||||
#include <sys/filio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <setjmp.h>
|
|
||||||
|
|
||||||
// HPI_FileInterface
|
|
||||||
|
|
||||||
// Many system calls can be interrupted by signals and must be restarted.
|
|
||||||
// Restart support was added without disturbing the extent of thread
|
|
||||||
// interruption support.
|
|
||||||
|
|
||||||
inline int hpi::close(int fd) {
|
|
||||||
RESTARTABLE_RETURN_INT(::close(fd));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t hpi::read(int fd, void *buf, unsigned int nBytes) {
|
|
||||||
INTERRUPTIBLE_RETURN_INT(::read(fd, buf, nBytes), os::Solaris::clear_interrupted);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t hpi::write(int fd, const void *buf, unsigned int nBytes) {
|
|
||||||
INTERRUPTIBLE_RETURN_INT(::write(fd, buf, nBytes), os::Solaris::clear_interrupted);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// HPI_SocketInterface
|
|
||||||
|
|
||||||
inline int hpi::socket_close(int fd) {
|
|
||||||
RESTARTABLE_RETURN_INT(::close(fd));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::socket(int domain, int type, int protocol) {
|
|
||||||
return ::socket(domain, type, protocol);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::recv(int fd, char *buf, int nBytes, int flags) {
|
|
||||||
INTERRUPTIBLE_RETURN_INT(::recv(fd, buf, nBytes, flags), os::Solaris::clear_interrupted);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::send(int fd, char *buf, int nBytes, int flags) {
|
|
||||||
INTERRUPTIBLE_RETURN_INT(::send(fd, buf, nBytes, flags), os::Solaris::clear_interrupted);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::raw_send(int fd, char *buf, int nBytes, int flags) {
|
|
||||||
RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
// As both poll and select can be interrupted by signals, we have to be
|
|
||||||
// prepared to restart the system call after updating the timeout, unless
|
|
||||||
// a poll() is done with timeout == -1, in which case we repeat with this
|
|
||||||
// "wait forever" value.
|
|
||||||
|
|
||||||
inline int hpi::timeout(int fd, long timeout) {
|
|
||||||
int res;
|
|
||||||
struct timeval t;
|
|
||||||
julong prevtime, newtime;
|
|
||||||
static const char* aNull = 0;
|
|
||||||
|
|
||||||
struct pollfd pfd;
|
|
||||||
pfd.fd = fd;
|
|
||||||
pfd.events = POLLIN;
|
|
||||||
|
|
||||||
gettimeofday(&t, &aNull);
|
|
||||||
prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
INTERRUPTIBLE_NORESTART(::poll(&pfd, 1, timeout), res, os::Solaris::clear_interrupted);
|
|
||||||
if(res == OS_ERR && errno == EINTR) {
|
|
||||||
if(timeout != -1) {
|
|
||||||
gettimeofday(&t, &aNull);
|
|
||||||
newtime = ((julong)t.tv_sec * 1000) + t.tv_usec /1000;
|
|
||||||
timeout -= newtime - prevtime;
|
|
||||||
if(timeout <= 0)
|
|
||||||
return OS_OK;
|
|
||||||
prevtime = newtime;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::listen(int fd, int count) {
|
|
||||||
if (fd < 0)
|
|
||||||
return OS_ERR;
|
|
||||||
|
|
||||||
return ::listen(fd, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int
|
|
||||||
hpi::connect(int fd, struct sockaddr *him, int len) {
|
|
||||||
do {
|
|
||||||
int _result;
|
|
||||||
INTERRUPTIBLE_NORESTART(::connect(fd, him, len), _result,
|
|
||||||
os::Solaris::clear_interrupted);
|
|
||||||
|
|
||||||
// Depending on when thread interruption is reset, _result could be
|
|
||||||
// one of two values when errno == EINTR
|
|
||||||
|
|
||||||
if (((_result == OS_INTRPT) || (_result == OS_ERR)) && (errno == EINTR)) {
|
|
||||||
/* restarting a connect() changes its errno semantics */
|
|
||||||
INTERRUPTIBLE(::connect(fd, him, len), _result,
|
|
||||||
os::Solaris::clear_interrupted);
|
|
||||||
/* undo these changes */
|
|
||||||
if (_result == OS_ERR) {
|
|
||||||
if (errno == EALREADY) errno = EINPROGRESS; /* fall through */
|
|
||||||
else if (errno == EISCONN) { errno = 0; return OS_OK; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _result;
|
|
||||||
} while(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::accept(int fd, struct sockaddr *him, int *len) {
|
|
||||||
if (fd < 0)
|
|
||||||
return OS_ERR;
|
|
||||||
INTERRUPTIBLE_RETURN_INT((int)::accept(fd, him, (socklen_t*) len), os::Solaris::clear_interrupted);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::recvfrom(int fd, char *buf, int nBytes, int flags,
|
|
||||||
sockaddr *from, int *fromlen) {
|
|
||||||
//%%note jvm_r11
|
|
||||||
INTERRUPTIBLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes, (unsigned int) flags, from, (socklen_t *)fromlen), os::Solaris::clear_interrupted);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::sendto(int fd, char *buf, int len, int flags,
|
|
||||||
struct sockaddr *to, int tolen) {
|
|
||||||
//%%note jvm_r11
|
|
||||||
INTERRUPTIBLE_RETURN_INT((int)::sendto(fd, buf, len, (unsigned int) flags, to, tolen),os::Solaris::clear_interrupted);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int hpi::socket_available(int fd, jint *pbytes) {
|
|
||||||
if (fd < 0)
|
|
||||||
return OS_OK;
|
|
||||||
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
RESTARTABLE(::ioctl(fd, FIONREAD, pbytes), ret);
|
|
||||||
|
|
||||||
//%% note ioctl can return 0 when successful, JVM_SocketAvailable
|
|
||||||
// is expected to return 0 on failure and 1 on success to the jdk.
|
|
||||||
|
|
||||||
return (ret == OS_ERR) ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
HPIDECL(socket_shutdown, "socket_shutdown", _socket, SocketShutdown,
|
|
||||||
int, "%d",
|
|
||||||
(int fd, int howto),
|
|
||||||
("fd = %d, howto = %d", fd, howto),
|
|
||||||
(fd, howto));
|
|
||||||
*/
|
|
||||||
inline int hpi::socket_shutdown(int fd, int howto){
|
|
||||||
return ::shutdown(fd, howto);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
HPIDECL(bind, "bind", _socket, Bind,
|
|
||||||
int, "%d",
|
|
||||||
(int fd, struct sockaddr *him, int len),
|
|
||||||
("fd = %d, him = %p, len = %d",
|
|
||||||
fd, him, len),
|
|
||||||
(fd, him, len));
|
|
||||||
*/
|
|
||||||
inline int hpi::bind(int fd, struct sockaddr *him, int len){
|
|
||||||
INTERRUPTIBLE_RETURN_INT_NORESTART(::bind(fd, him, len),os::Solaris::clear_interrupted);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
HPIDECL(get_sock_name, "get_sock_name", _socket, GetSocketName,
|
|
||||||
int, "%d",
|
|
||||||
(int fd, struct sockaddr *him, int *len),
|
|
||||||
("fd = %d, him = %p, len = %p",
|
|
||||||
fd, him, len),
|
|
||||||
(fd, him, len));
|
|
||||||
*/
|
|
||||||
inline int hpi::get_sock_name(int fd, struct sockaddr *him, int *len){
|
|
||||||
return ::getsockname(fd, him, (socklen_t*) len);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
HPIDECL(get_host_name, "get_host_name", _socket, GetHostName, int, "%d",
|
|
||||||
(char *hostname, int namelen),
|
|
||||||
("hostname = %p, namelen = %d",
|
|
||||||
hostname, namelen),
|
|
||||||
(hostname, namelen));
|
|
||||||
*/
|
|
||||||
inline int hpi::get_host_name(char* name, int namelen){
|
|
||||||
return ::gethostname(name, namelen);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
HPIDECL(get_sock_opt, "get_sock_opt", _socket, SocketGetOption, int, "%d",
|
|
||||||
(int fd, int level, int optname, char *optval, int* optlen),
|
|
||||||
("fd = %d, level = %d, optname = %d, optval = %p, optlen = %p",
|
|
||||||
fd, level, optname, optval, optlen),
|
|
||||||
(fd, level, optname, optval, optlen));
|
|
||||||
*/
|
|
||||||
inline int hpi::get_sock_opt(int fd, int level, int optname,
|
|
||||||
char *optval, int* optlen){
|
|
||||||
return ::getsockopt(fd, level, optname, optval, (socklen_t*) optlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
HPIDECL(set_sock_opt, "set_sock_opt", _socket, SocketSetOption, int, "%d",
|
|
||||||
(int fd, int level, int optname, const char *optval, int optlen),
|
|
||||||
("fd = %d, level = %d, optname = %d, optval = %p, optlen = %d",
|
|
||||||
fd, level, optname, optval, optlen),
|
|
||||||
(fd, level, optname, optval, optlen));
|
|
||||||
*/
|
|
||||||
inline int hpi::set_sock_opt(int fd, int level, int optname,
|
|
||||||
const char *optval, int optlen){
|
|
||||||
return ::setsockopt(fd, level, optname, optval, optlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Reconciliation History
|
|
||||||
// 1.3 98/10/21 18:17:14 hpi_win32.hpp
|
|
||||||
// 1.6 99/06/28 11:01:36 hpi_win32.hpp
|
|
||||||
//End
|
|
||||||
|
|
||||||
#endif // OS_SOLARIS_VM_HPI_SOLARIS_HPP
|
|
|
@ -42,7 +42,6 @@
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/extendedPC.hpp"
|
#include "runtime/extendedPC.hpp"
|
||||||
#include "runtime/globals.hpp"
|
#include "runtime/globals.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
|
@ -116,6 +115,7 @@
|
||||||
# include <sys/iapriocntl.h>
|
# include <sys/iapriocntl.h>
|
||||||
# include <sys/loadavg.h>
|
# include <sys/loadavg.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
|
||||||
# define _STRUCTURED_PROC 1 // this gets us the new structured proc interfaces of 5.6 & later
|
# define _STRUCTURED_PROC 1 // this gets us the new structured proc interfaces of 5.6 & later
|
||||||
# include <sys/procfs.h> // see comment in <sys/procfs.h>
|
# include <sys/procfs.h> // see comment in <sys/procfs.h>
|
||||||
|
@ -220,6 +220,9 @@ int prio_policy1[MaxPriority+1] = { -99999, 0, 16, 32, 48, 64,
|
||||||
// System parameters used internally
|
// System parameters used internally
|
||||||
static clock_t clock_tics_per_sec = 100;
|
static clock_t clock_tics_per_sec = 100;
|
||||||
|
|
||||||
|
// Track if we have called enable_extended_FILE_stdio (on Solaris 10u4+)
|
||||||
|
static bool enabled_extended_FILE_stdio = false;
|
||||||
|
|
||||||
// For diagnostics to print a message once. see run_periodic_checks
|
// For diagnostics to print a message once. see run_periodic_checks
|
||||||
static bool check_addr0_done = false;
|
static bool check_addr0_done = false;
|
||||||
static sigset_t check_signal_done;
|
static sigset_t check_signal_done;
|
||||||
|
@ -387,7 +390,7 @@ struct tm* os::localtime_pd(const time_t* clock, struct tm* res) {
|
||||||
// The saved state is used to restore the thread to
|
// The saved state is used to restore the thread to
|
||||||
// its former state whether or not an interrupt is received.
|
// its former state whether or not an interrupt is received.
|
||||||
// Used by classloader os::read
|
// Used by classloader os::read
|
||||||
// hpi calls skip this layer and stay in _thread_in_native
|
// os::restartable_read calls skip this layer and stay in _thread_in_native
|
||||||
|
|
||||||
void os::Solaris::setup_interruptible(JavaThread* thread) {
|
void os::Solaris::setup_interruptible(JavaThread* thread) {
|
||||||
|
|
||||||
|
@ -1751,13 +1754,13 @@ bool os::getTimesSecs(double* process_real_time,
|
||||||
bool os::supports_vtime() { return true; }
|
bool os::supports_vtime() { return true; }
|
||||||
|
|
||||||
bool os::enable_vtime() {
|
bool os::enable_vtime() {
|
||||||
int fd = open("/proc/self/ctl", O_WRONLY);
|
int fd = ::open("/proc/self/ctl", O_WRONLY);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
long cmd[] = { PCSET, PR_MSACCT };
|
long cmd[] = { PCSET, PR_MSACCT };
|
||||||
int res = write(fd, cmd, sizeof(long) * 2);
|
int res = ::write(fd, cmd, sizeof(long) * 2);
|
||||||
close(fd);
|
::close(fd);
|
||||||
if (res != sizeof(long) * 2)
|
if (res != sizeof(long) * 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1765,13 +1768,13 @@ bool os::enable_vtime() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool os::vtime_enabled() {
|
bool os::vtime_enabled() {
|
||||||
int fd = open("/proc/self/status", O_RDONLY);
|
int fd = ::open("/proc/self/status", O_RDONLY);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pstatus_t status;
|
pstatus_t status;
|
||||||
int res = read(fd, (void*) &status, sizeof(pstatus_t));
|
int res = os::read(fd, (void*) &status, sizeof(pstatus_t));
|
||||||
close(fd);
|
::close(fd);
|
||||||
if (res != sizeof(pstatus_t))
|
if (res != sizeof(pstatus_t))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1887,7 +1890,6 @@ static bool file_exists(const char* filename) {
|
||||||
|
|
||||||
void os::dll_build_name(char* buffer, size_t buflen,
|
void os::dll_build_name(char* buffer, size_t buflen,
|
||||||
const char* pname, const char* fname) {
|
const char* pname, const char* fname) {
|
||||||
// Copied from libhpi
|
|
||||||
const size_t pnamelen = pname ? strlen(pname) : 0;
|
const size_t pnamelen = pname ? strlen(pname) : 0;
|
||||||
|
|
||||||
// Quietly truncate on buffer overflow. Should be an error.
|
// Quietly truncate on buffer overflow. Should be an error.
|
||||||
|
@ -2198,20 +2200,29 @@ void* os::dll_lookup(void* handle, const char* name) {
|
||||||
return dlsym(handle, name);
|
return dlsym(handle, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int os::stat(const char *path, struct stat *sbuf) {
|
||||||
|
char pathbuf[MAX_PATH];
|
||||||
|
if (strlen(path) > MAX_PATH - 1) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
os::native_path(strcpy(pathbuf, path));
|
||||||
|
return ::stat(pathbuf, sbuf);
|
||||||
|
}
|
||||||
|
|
||||||
bool _print_ascii_file(const char* filename, outputStream* st) {
|
static bool _print_ascii_file(const char* filename, outputStream* st) {
|
||||||
int fd = open(filename, O_RDONLY);
|
int fd = ::open(filename, O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf[32];
|
char buf[32];
|
||||||
int bytes;
|
int bytes;
|
||||||
while ((bytes = read(fd, buf, sizeof(buf))) > 0) {
|
while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) {
|
||||||
st->print_raw(buf, bytes);
|
st->print_raw(buf, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
::close(fd);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2274,10 +2285,10 @@ void os::print_os_info(outputStream* st) {
|
||||||
|
|
||||||
static bool check_addr0(outputStream* st) {
|
static bool check_addr0(outputStream* st) {
|
||||||
jboolean status = false;
|
jboolean status = false;
|
||||||
int fd = open("/proc/self/map",O_RDONLY);
|
int fd = ::open("/proc/self/map",O_RDONLY);
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
prmap_t p;
|
prmap_t p;
|
||||||
while(read(fd, &p, sizeof(p)) > 0) {
|
while(::read(fd, &p, sizeof(p)) > 0) {
|
||||||
if (p.pr_vaddr == 0x0) {
|
if (p.pr_vaddr == 0x0) {
|
||||||
st->print("Warning: Address: 0x%x, Size: %dK, ",p.pr_vaddr, p.pr_size/1024, p.pr_mapname);
|
st->print("Warning: Address: 0x%x, Size: %dK, ",p.pr_vaddr, p.pr_size/1024, p.pr_mapname);
|
||||||
st->print("Mapped file: %s, ", p.pr_mapname[0] == '\0' ? "None" : p.pr_mapname);
|
st->print("Mapped file: %s, ", p.pr_mapname[0] == '\0' ? "None" : p.pr_mapname);
|
||||||
|
@ -2288,7 +2299,7 @@ static bool check_addr0(outputStream* st) {
|
||||||
st->cr();
|
st->cr();
|
||||||
status = true;
|
status = true;
|
||||||
}
|
}
|
||||||
close(fd);
|
::close(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
|
@ -2536,8 +2547,6 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||||
// Use current module name "libjvm[_g].so" instead of
|
// Use current module name "libjvm[_g].so" instead of
|
||||||
// "libjvm"debug_only("_g")".so" since for fastdebug version
|
// "libjvm"debug_only("_g")".so" since for fastdebug version
|
||||||
// we should have "libjvm.so" but debug_only("_g") adds "_g"!
|
// we should have "libjvm.so" but debug_only("_g") adds "_g"!
|
||||||
// It is used when we are choosing the HPI library's name
|
|
||||||
// "libhpi[_g].so" in hpi::initialize_get_interface().
|
|
||||||
len = strlen(buf);
|
len = strlen(buf);
|
||||||
snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p);
|
snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2561,6 +2570,23 @@ void os::print_jni_name_suffix_on(outputStream* st, int args_size) {
|
||||||
// no suffix required
|
// no suffix required
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method is a copy of JDK's sysGetLastErrorString
|
||||||
|
// from src/solaris/hpi/src/system_md.c
|
||||||
|
|
||||||
|
size_t os::lasterror(char *buf, size_t len) {
|
||||||
|
|
||||||
|
if (errno == 0) return 0;
|
||||||
|
|
||||||
|
const char *s = ::strerror(errno);
|
||||||
|
size_t n = ::strlen(s);
|
||||||
|
if (n >= len) {
|
||||||
|
n = len - 1;
|
||||||
|
}
|
||||||
|
::strncpy(buf, s, n);
|
||||||
|
buf[n] = '\0';
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// sun.misc.Signal
|
// sun.misc.Signal
|
||||||
|
|
||||||
|
@ -3470,6 +3496,10 @@ size_t os::read(int fd, void *buf, unsigned int nBytes) {
|
||||||
INTERRUPTIBLE_RETURN_INT_VM(::read(fd, buf, nBytes), os::Solaris::clear_interrupted);
|
INTERRUPTIBLE_RETURN_INT_VM(::read(fd, buf, nBytes), os::Solaris::clear_interrupted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) {
|
||||||
|
INTERRUPTIBLE_RETURN_INT(::read(fd, buf, nBytes), os::Solaris::clear_interrupted);
|
||||||
|
}
|
||||||
|
|
||||||
int os::sleep(Thread* thread, jlong millis, bool interruptible) {
|
int os::sleep(Thread* thread, jlong millis, bool interruptible) {
|
||||||
assert(thread == Thread::current(), "thread consistency check");
|
assert(thread == Thread::current(), "thread consistency check");
|
||||||
|
|
||||||
|
@ -4639,16 +4669,16 @@ bool isT2_libthread() {
|
||||||
#define ADR(x) ((uintptr_t)(x))
|
#define ADR(x) ((uintptr_t)(x))
|
||||||
#define LWPINDEX(ary,ix) ((lwpstatus_t *)(((ary)->pr_entsize * (ix)) + (ADR((ary) + 1))))
|
#define LWPINDEX(ary,ix) ((lwpstatus_t *)(((ary)->pr_entsize * (ix)) + (ADR((ary) + 1))))
|
||||||
|
|
||||||
lwpFile = open("/proc/self/lstatus", O_RDONLY, 0);
|
lwpFile = ::open("/proc/self/lstatus", O_RDONLY, 0);
|
||||||
if (lwpFile < 0) {
|
if (lwpFile < 0) {
|
||||||
if (ThreadPriorityVerbose) warning ("Couldn't open /proc/self/lstatus\n");
|
if (ThreadPriorityVerbose) warning ("Couldn't open /proc/self/lstatus\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
lwpSize = 16*1024;
|
lwpSize = 16*1024;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
lseek (lwpFile, 0, SEEK_SET);
|
::lseek64 (lwpFile, 0, SEEK_SET);
|
||||||
lwpArray = (prheader_t *)NEW_C_HEAP_ARRAY(char, lwpSize);
|
lwpArray = (prheader_t *)NEW_C_HEAP_ARRAY(char, lwpSize);
|
||||||
if (read(lwpFile, lwpArray, lwpSize) < 0) {
|
if (::read(lwpFile, lwpArray, lwpSize) < 0) {
|
||||||
if (ThreadPriorityVerbose) warning("Error reading /proc/self/lstatus\n");
|
if (ThreadPriorityVerbose) warning("Error reading /proc/self/lstatus\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4669,7 +4699,7 @@ bool isT2_libthread() {
|
||||||
}
|
}
|
||||||
|
|
||||||
FREE_C_HEAP_ARRAY(char, lwpArray);
|
FREE_C_HEAP_ARRAY(char, lwpArray);
|
||||||
close (lwpFile);
|
::close (lwpFile);
|
||||||
if (ThreadPriorityVerbose) {
|
if (ThreadPriorityVerbose) {
|
||||||
if (isT2) tty->print_cr("We are running with a T2 libthread\n");
|
if (isT2) tty->print_cr("We are running with a T2 libthread\n");
|
||||||
else tty->print_cr("We are not running with a T2 libthread\n");
|
else tty->print_cr("We are not running with a T2 libthread\n");
|
||||||
|
@ -4865,7 +4895,7 @@ void os::init(void) {
|
||||||
// if we need them.
|
// if we need them.
|
||||||
Solaris::misc_sym_init();
|
Solaris::misc_sym_init();
|
||||||
|
|
||||||
int fd = open("/dev/zero", O_RDWR);
|
int fd = ::open("/dev/zero", O_RDWR);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fatal(err_msg("os::init: cannot open /dev/zero (%s)", strerror(errno)));
|
fatal(err_msg("os::init: cannot open /dev/zero (%s)", strerror(errno)));
|
||||||
} else {
|
} else {
|
||||||
|
@ -5035,13 +5065,6 @@ jint os::init_2(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize HPI.
|
|
||||||
jint hpi_result = hpi::initialize();
|
|
||||||
if (hpi_result != JNI_OK) {
|
|
||||||
tty->print_cr("There was an error trying to initialize the HPI library.");
|
|
||||||
return hpi_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate theoretical max. size of Threads to guard gainst
|
// Calculate theoretical max. size of Threads to guard gainst
|
||||||
// artifical out-of-memory situations, where all available address-
|
// artifical out-of-memory situations, where all available address-
|
||||||
// space has been reserved by thread stacks. Default stack size is 1Mb.
|
// space has been reserved by thread stacks. Default stack size is 1Mb.
|
||||||
|
@ -5101,17 +5124,6 @@ void os::make_polling_page_readable(void) {
|
||||||
|
|
||||||
// OS interface.
|
// OS interface.
|
||||||
|
|
||||||
int os::stat(const char *path, struct stat *sbuf) {
|
|
||||||
char pathbuf[MAX_PATH];
|
|
||||||
if (strlen(path) > MAX_PATH - 1) {
|
|
||||||
errno = ENAMETOOLONG;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
hpi::native_path(strcpy(pathbuf, path));
|
|
||||||
return ::stat(pathbuf, sbuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool os::check_heap(bool force) { return true; }
|
bool os::check_heap(bool force) { return true; }
|
||||||
|
|
||||||
typedef int (*vsnprintf_t)(char* buf, size_t count, const char* fmt, va_list argptr);
|
typedef int (*vsnprintf_t)(char* buf, size_t count, const char* fmt, va_list argptr);
|
||||||
|
@ -5156,6 +5168,125 @@ bool os::dir_is_empty(const char* path) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This code originates from JDK's sysOpen and open64_w
|
||||||
|
// from src/solaris/hpi/src/system_md.c
|
||||||
|
|
||||||
|
#ifndef O_DELETE
|
||||||
|
#define O_DELETE 0x10000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Open a file. Unlink the file immediately after open returns
|
||||||
|
// if the specified oflag has the O_DELETE flag set.
|
||||||
|
// O_DELETE is used only in j2se/src/share/native/java/util/zip/ZipFile.c
|
||||||
|
|
||||||
|
int os::open(const char *path, int oflag, int mode) {
|
||||||
|
if (strlen(path) > MAX_PATH - 1) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int fd;
|
||||||
|
int o_delete = (oflag & O_DELETE);
|
||||||
|
oflag = oflag & ~O_DELETE;
|
||||||
|
|
||||||
|
fd = ::open(path, oflag, mode);
|
||||||
|
if (fd == -1) return -1;
|
||||||
|
|
||||||
|
//If the open succeeded, the file might still be a directory
|
||||||
|
{
|
||||||
|
struct stat64 buf64;
|
||||||
|
int ret = ::fstat64(fd, &buf64);
|
||||||
|
int st_mode = buf64.st_mode;
|
||||||
|
|
||||||
|
if (ret != -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
|
||||||
|
*
|
||||||
|
* - As of Solaris 10u4, we can request that Solaris raise the 256
|
||||||
|
* stdio fopen limit by calling function enable_extended_FILE_stdio.
|
||||||
|
* This is done in init_2 and recorded in enabled_extended_FILE_stdio
|
||||||
|
*
|
||||||
|
* - 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
|
||||||
|
*/
|
||||||
|
#ifndef _LP64
|
||||||
|
if ((!enabled_extended_FILE_stdio) && 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
|
||||||
|
|
||||||
|
if (o_delete != 0) {
|
||||||
|
::unlink(path);
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
// create binary file, rewriting existing file if required
|
// create binary file, rewriting existing file if required
|
||||||
int os::create_binary_file(const char* path, bool rewrite_existing) {
|
int os::create_binary_file(const char* path, bool rewrite_existing) {
|
||||||
int oflags = O_WRONLY | O_CREAT;
|
int oflags = O_WRONLY | O_CREAT;
|
||||||
|
@ -5175,6 +5306,55 @@ jlong os::seek_to_file_offset(int fd, jlong offset) {
|
||||||
return (jlong)::lseek64(fd, (off64_t)offset, SEEK_SET);
|
return (jlong)::lseek64(fd, (off64_t)offset, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jlong os::lseek(int fd, jlong offset, int whence) {
|
||||||
|
return (jlong) ::lseek64(fd, offset, whence);
|
||||||
|
}
|
||||||
|
|
||||||
|
char * os::native_path(char *path) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::ftruncate(int fd, jlong length) {
|
||||||
|
return ::ftruncate64(fd, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::fsync(int fd) {
|
||||||
|
RESTARTABLE_RETURN_INT(::fsync(fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::available(int fd, jlong *bytes) {
|
||||||
|
jlong cur, end;
|
||||||
|
int mode;
|
||||||
|
struct stat64 buf64;
|
||||||
|
|
||||||
|
if (::fstat64(fd, &buf64) >= 0) {
|
||||||
|
mode = buf64.st_mode;
|
||||||
|
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,ioctl_return;
|
||||||
|
|
||||||
|
INTERRUPTIBLE(::ioctl(fd, FIONREAD, &n),ioctl_return,os::Solaris::clear_interrupted);
|
||||||
|
if (ioctl_return>= 0) {
|
||||||
|
*bytes = n;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((cur = ::lseek64(fd, 0L, SEEK_CUR)) == -1) {
|
||||||
|
return 0;
|
||||||
|
} else if ((end = ::lseek64(fd, 0L, SEEK_END)) == -1) {
|
||||||
|
return 0;
|
||||||
|
} else if (::lseek64(fd, cur, SEEK_SET) == -1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*bytes = end - cur;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Map a block of memory.
|
// Map a block of memory.
|
||||||
char* os::map_memory(int fd, const char* file_name, size_t file_offset,
|
char* os::map_memory(int fd, const char* file_name, size_t file_offset,
|
||||||
char *addr, size_t bytes, bool read_only,
|
char *addr, size_t bytes, bool read_only,
|
||||||
|
@ -5233,7 +5413,7 @@ void os::pause() {
|
||||||
int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
close(fd);
|
::close(fd);
|
||||||
while (::stat(filename, &buf) == 0) {
|
while (::stat(filename, &buf) == 0) {
|
||||||
(void)::poll(NULL, 0, 100);
|
(void)::poll(NULL, 0, 100);
|
||||||
}
|
}
|
||||||
|
@ -5430,16 +5610,16 @@ jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
|
||||||
sprintf(proc_name, "/proc/%d/lwp/%d/lwpusage",
|
sprintf(proc_name, "/proc/%d/lwp/%d/lwpusage",
|
||||||
getpid(),
|
getpid(),
|
||||||
thread->osthread()->lwp_id());
|
thread->osthread()->lwp_id());
|
||||||
fd = open(proc_name, O_RDONLY);
|
fd = ::open(proc_name, O_RDONLY);
|
||||||
if ( fd == -1 ) return -1;
|
if ( fd == -1 ) return -1;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
count = pread(fd,
|
count = ::pread(fd,
|
||||||
(void *)&prusage.pr_utime,
|
(void *)&prusage.pr_utime,
|
||||||
thr_time_size,
|
thr_time_size,
|
||||||
thr_time_off);
|
thr_time_off);
|
||||||
} while (count < 0 && errno == EINTR);
|
} while (count < 0 && errno == EINTR);
|
||||||
close(fd);
|
::close(fd);
|
||||||
if ( count < 0 ) return -1;
|
if ( count < 0 ) return -1;
|
||||||
|
|
||||||
if (user_sys_cpu_time) {
|
if (user_sys_cpu_time) {
|
||||||
|
@ -6111,4 +6291,127 @@ bool os::is_headless_jre() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t os::write(int fd, const void *buf, unsigned int nBytes) {
|
||||||
|
INTERRUPTIBLE_RETURN_INT(::write(fd, buf, nBytes), os::Solaris::clear_interrupted);
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::close(int fd) {
|
||||||
|
RESTARTABLE_RETURN_INT(::close(fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::socket_close(int fd) {
|
||||||
|
RESTARTABLE_RETURN_INT(::close(fd));
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::recv(int fd, char *buf, int nBytes, int flags) {
|
||||||
|
INTERRUPTIBLE_RETURN_INT(::recv(fd, buf, nBytes, flags), os::Solaris::clear_interrupted);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int os::send(int fd, char *buf, int nBytes, int flags) {
|
||||||
|
INTERRUPTIBLE_RETURN_INT(::send(fd, buf, nBytes, flags), os::Solaris::clear_interrupted);
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::raw_send(int fd, char *buf, int nBytes, int flags) {
|
||||||
|
RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
// As both poll and select can be interrupted by signals, we have to be
|
||||||
|
// prepared to restart the system call after updating the timeout, unless
|
||||||
|
// a poll() is done with timeout == -1, in which case we repeat with this
|
||||||
|
// "wait forever" value.
|
||||||
|
|
||||||
|
int os::timeout(int fd, long timeout) {
|
||||||
|
int res;
|
||||||
|
struct timeval t;
|
||||||
|
julong prevtime, newtime;
|
||||||
|
static const char* aNull = 0;
|
||||||
|
struct pollfd pfd;
|
||||||
|
pfd.fd = fd;
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
|
||||||
|
gettimeofday(&t, &aNull);
|
||||||
|
prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000;
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
INTERRUPTIBLE_NORESTART(::poll(&pfd, 1, timeout), res, os::Solaris::clear_interrupted);
|
||||||
|
if(res == OS_ERR && errno == EINTR) {
|
||||||
|
if(timeout != -1) {
|
||||||
|
gettimeofday(&t, &aNull);
|
||||||
|
newtime = ((julong)t.tv_sec * 1000) + t.tv_usec /1000;
|
||||||
|
timeout -= newtime - prevtime;
|
||||||
|
if(timeout <= 0)
|
||||||
|
return OS_OK;
|
||||||
|
prevtime = newtime;
|
||||||
|
}
|
||||||
|
} else return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::connect(int fd, struct sockaddr *him, int len) {
|
||||||
|
int _result;
|
||||||
|
INTERRUPTIBLE_NORESTART(::connect(fd, him, len), _result,
|
||||||
|
os::Solaris::clear_interrupted);
|
||||||
|
|
||||||
|
// Depending on when thread interruption is reset, _result could be
|
||||||
|
// one of two values when errno == EINTR
|
||||||
|
|
||||||
|
if (((_result == OS_INTRPT) || (_result == OS_ERR))
|
||||||
|
&& (errno == EINTR)) {
|
||||||
|
/* restarting a connect() changes its errno semantics */
|
||||||
|
INTERRUPTIBLE(::connect(fd, him, len), _result,
|
||||||
|
os::Solaris::clear_interrupted);
|
||||||
|
/* undo these changes */
|
||||||
|
if (_result == OS_ERR) {
|
||||||
|
if (errno == EALREADY) {
|
||||||
|
errno = EINPROGRESS; /* fall through */
|
||||||
|
} else if (errno == EISCONN) {
|
||||||
|
errno = 0;
|
||||||
|
return OS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::accept(int fd, struct sockaddr *him, int *len) {
|
||||||
|
if (fd < 0)
|
||||||
|
return OS_ERR;
|
||||||
|
INTERRUPTIBLE_RETURN_INT((int)::accept(fd, him,\
|
||||||
|
(socklen_t*) len), os::Solaris::clear_interrupted);
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::recvfrom(int fd, char *buf, int nBytes, int flags,
|
||||||
|
sockaddr *from, int *fromlen) {
|
||||||
|
//%%note jvm_r11
|
||||||
|
INTERRUPTIBLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes,\
|
||||||
|
flags, from, fromlen), os::Solaris::clear_interrupted);
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::sendto(int fd, char *buf, int len, int flags,
|
||||||
|
struct sockaddr *to, int tolen) {
|
||||||
|
//%%note jvm_r11
|
||||||
|
INTERRUPTIBLE_RETURN_INT((int)::sendto(fd, buf, len, flags,\
|
||||||
|
to, tolen), os::Solaris::clear_interrupted);
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::socket_available(int fd, jint *pbytes) {
|
||||||
|
if (fd < 0)
|
||||||
|
return OS_OK;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
RESTARTABLE(::ioctl(fd, FIONREAD, pbytes), ret);
|
||||||
|
|
||||||
|
//%% note ioctl can return 0 when successful, JVM_SocketAvailable
|
||||||
|
// is expected to return 0 on failure and 1 on success to the jdk.
|
||||||
|
|
||||||
|
return (ret == OS_ERR) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int os::bind(int fd, struct sockaddr *him, int len) {
|
||||||
|
INTERRUPTIBLE_RETURN_INT_NORESTART(::bind(fd, him, len),\
|
||||||
|
os::Solaris::clear_interrupted);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,16 @@
|
||||||
# include "orderAccess_solaris_sparc.inline.hpp"
|
# include "orderAccess_solaris_sparc.inline.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// System includes
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
#include <sys/filio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
inline const char* os::file_separator() { return "/"; }
|
inline const char* os::file_separator() { return "/"; }
|
||||||
inline const char* os::line_separator() { return "\n"; }
|
inline const char* os::line_separator() { return "\n"; }
|
||||||
inline const char* os::path_separator() { return ":"; }
|
inline const char* os::path_separator() { return ":"; }
|
||||||
|
@ -69,21 +79,19 @@ inline void os::split_reserved_memory(char *base, size_t size,
|
||||||
// Bang the shadow pages if they need to be touched to be mapped.
|
// Bang the shadow pages if they need to be touched to be mapped.
|
||||||
inline void os::bang_stack_shadow_pages() {
|
inline void os::bang_stack_shadow_pages() {
|
||||||
}
|
}
|
||||||
|
inline void os::dll_unload(void *lib) { ::dlclose(lib); }
|
||||||
|
|
||||||
inline DIR* os::opendir(const char* dirname)
|
inline DIR* os::opendir(const char* dirname) {
|
||||||
{
|
|
||||||
assert(dirname != NULL, "just checking");
|
assert(dirname != NULL, "just checking");
|
||||||
return ::opendir(dirname);
|
return ::opendir(dirname);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int os::readdir_buf_size(const char *path)
|
inline int os::readdir_buf_size(const char *path) {
|
||||||
{
|
|
||||||
int size = pathconf(path, _PC_NAME_MAX);
|
int size = pathconf(path, _PC_NAME_MAX);
|
||||||
return (size < 0 ? MAXPATHLEN : size) + sizeof(dirent) + 1;
|
return (size < 0 ? MAXPATHLEN : size) + sizeof(dirent) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline struct dirent* os::readdir(DIR* dirp, dirent* dbuf)
|
inline struct dirent* os::readdir(DIR* dirp, dirent* dbuf) {
|
||||||
{
|
|
||||||
assert(dirp != NULL, "just checking");
|
assert(dirp != NULL, "just checking");
|
||||||
#if defined(_LP64) || defined(_GNU_SOURCE)
|
#if defined(_LP64) || defined(_GNU_SOURCE)
|
||||||
dirent* p;
|
dirent* p;
|
||||||
|
@ -99,9 +107,8 @@ inline struct dirent* os::readdir(DIR* dirp, dirent* dbuf)
|
||||||
#endif // defined(_LP64) || defined(_GNU_SOURCE)
|
#endif // defined(_LP64) || defined(_GNU_SOURCE)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int os::closedir(DIR *dirp)
|
inline int os::closedir(DIR *dirp) {
|
||||||
{
|
assert(dirp != NULL, "argument is NULL");
|
||||||
assert(dirp != NULL, "just checking");
|
|
||||||
return ::closedir(dirp);
|
return ::closedir(dirp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,4 +229,38 @@ do { \
|
||||||
inline bool os::numa_has_static_binding() { return false; }
|
inline bool os::numa_has_static_binding() { return false; }
|
||||||
inline bool os::numa_has_group_homing() { return true; }
|
inline bool os::numa_has_group_homing() { return true; }
|
||||||
|
|
||||||
|
inline int os::socket(int domain, int type, int protocol) {
|
||||||
|
return ::socket(domain, type, protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::listen(int fd, int count) {
|
||||||
|
if (fd < 0) return OS_ERR;
|
||||||
|
|
||||||
|
return ::listen(fd, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::socket_shutdown(int fd, int howto){
|
||||||
|
return ::shutdown(fd, howto);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::get_sock_name(int fd, struct sockaddr *him, int *len){
|
||||||
|
return ::getsockname(fd, him, (socklen_t*) len);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::get_host_name(char* name, int namelen){
|
||||||
|
return ::gethostname(name, namelen);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline struct hostent* os::get_host_by_name(char* name) {
|
||||||
|
return ::gethostbyname(name);
|
||||||
|
}
|
||||||
|
inline int os::get_sock_opt(int fd, int level, int optname,
|
||||||
|
char *optval, int* optlen){
|
||||||
|
return ::getsockopt(fd, level, optname, optval, (socklen_t*) optlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::set_sock_opt(int fd, int level, int optname,
|
||||||
|
const char *optval, int optlen){
|
||||||
|
return ::setsockopt(fd, level, optname, optval, optlen);
|
||||||
|
}
|
||||||
#endif // OS_SOLARIS_VM_OS_SOLARIS_INLINE_HPP
|
#endif // OS_SOLARIS_VM_OS_SOLARIS_INLINE_HPP
|
||||||
|
|
1465
hotspot/src/os/windows/launcher/java_md.c
Normal file
1465
hotspot/src/os/windows/launcher/java_md.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,28 +22,31 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK,
|
|
||||||
* search "GAMMA" for gamma specific changes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef JAVA_MD_H
|
#ifndef JAVA_MD_H
|
||||||
#define JAVA_MD_H
|
#define JAVA_MD_H
|
||||||
|
|
||||||
#include <limits.h>
|
#include <jni.h>
|
||||||
#include <unistd.h>
|
#include <windows.h>
|
||||||
#include <sys/param.h>
|
#include <io.h>
|
||||||
#ifndef GAMMA
|
#ifndef GAMMA
|
||||||
#include "manifest_info.h"
|
#include "manifest_info.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "jli_util.h"
|
||||||
|
|
||||||
#define PATH_SEPARATOR ':'
|
#ifdef GAMMA
|
||||||
#define FILESEP "/"
|
#define stricmp _stricmp
|
||||||
#define FILE_SEPARATOR '/'
|
#define strnicmp _strnicmp
|
||||||
#ifndef MAXNAMELEN
|
#define snprintf _snprintf
|
||||||
#define MAXNAMELEN PATH_MAX
|
#define strdup _strdup
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define PATH_SEPARATOR ';'
|
||||||
|
#define FILESEP "\\"
|
||||||
|
#define FILE_SEPARATOR '\\'
|
||||||
|
#define IS_FILE_SEPARATOR(c) ((c) == '\\' || (c) == '/')
|
||||||
|
#define MAXPATHLEN MAX_PATH
|
||||||
|
#define MAXNAMELEN MAX_PATH
|
||||||
|
|
||||||
#ifdef JAVA_ARGS
|
#ifdef JAVA_ARGS
|
||||||
/*
|
/*
|
||||||
* ApplicationHome is prepended to each of these entries; the resulting
|
* ApplicationHome is prepended to each of these entries; the resulting
|
||||||
|
@ -51,21 +54,20 @@
|
||||||
* value of -cp option to the launcher.
|
* value of -cp option to the launcher.
|
||||||
*/
|
*/
|
||||||
#ifndef APP_CLASSPATH
|
#ifndef APP_CLASSPATH
|
||||||
#define APP_CLASSPATH { "/lib/tools.jar", "/classes" }
|
#define APP_CLASSPATH { "\\lib\\tools.jar", "\\classes" }
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_GETHRTIME
|
|
||||||
/*
|
/*
|
||||||
* Support for doing cheap, accurate interval timing.
|
* Support for doing cheap, accurate interval timing.
|
||||||
*/
|
*/
|
||||||
#include <sys/time.h>
|
extern jlong CounterGet(void);
|
||||||
#define CounterGet() (gethrtime()/1000)
|
extern jlong Counter2Micros(jlong counts);
|
||||||
#define Counter2Micros(counts) (counts)
|
|
||||||
#else
|
#ifdef JAVAW
|
||||||
#define CounterGet() (0)
|
#define main _main
|
||||||
#define Counter2Micros(counts) (1)
|
extern int _main(int argc, char **argv);
|
||||||
#endif /* HAVE_GETHRTIME */
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function prototypes.
|
* Function prototypes.
|
|
@ -1,82 +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.
|
|
||||||
*
|
|
||||||
* 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 "precompiled.hpp"
|
|
||||||
#include "oops/oop.inline.hpp"
|
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/os.hpp"
|
|
||||||
|
|
||||||
typedef jint (JNICALL *init_t)(GetInterfaceFunc *, void *);
|
|
||||||
|
|
||||||
void hpi::initialize_get_interface(vm_calls_t *callbacks)
|
|
||||||
{
|
|
||||||
// Build name of HPI.
|
|
||||||
char lib_name[JVM_MAXPATHLEN];
|
|
||||||
|
|
||||||
if (HPILibPath && HPILibPath[0]) {
|
|
||||||
strncpy(lib_name, HPILibPath, JVM_MAXPATHLEN - 1);
|
|
||||||
lib_name[JVM_MAXPATHLEN - 1] = '\0';
|
|
||||||
} else {
|
|
||||||
os::jvm_path(lib_name, sizeof lib_name);
|
|
||||||
|
|
||||||
#ifdef PRODUCT
|
|
||||||
const char *hpi_lib = "\\hpi.dll";
|
|
||||||
#else
|
|
||||||
char *ptr = strrchr(lib_name, '\\');
|
|
||||||
// On Win98 GetModuleFileName() returns the path in the upper case.
|
|
||||||
assert(_strnicmp(ptr, "\\jvm",4) == 0, "invalid library name");
|
|
||||||
const char *hpi_lib = (_strnicmp(ptr, "\\jvm_g",6) == 0) ? "\\hpi_g.dll" : "\\hpi.dll";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*(::strrchr(lib_name, '\\')) = '\0'; /* get rid of "\\jvm.dll" */
|
|
||||||
char *p = ::strrchr(lib_name, '\\');
|
|
||||||
if (p != NULL) *p = '\0'; /* get rid of "\\hotspot" */
|
|
||||||
strcat(lib_name, hpi_lib);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load it.
|
|
||||||
if (TraceHPI) tty->print_cr("Loading HPI %s ", lib_name);
|
|
||||||
HINSTANCE lib_handle = LoadLibrary(lib_name);
|
|
||||||
if (lib_handle == NULL) {
|
|
||||||
if (TraceHPI) tty->print_cr("LoadLibrary failed, code = %d", GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find hpi initializer.
|
|
||||||
init_t initer = (init_t)GetProcAddress(lib_handle, "DLL_Initialize");
|
|
||||||
if (initer == NULL) {
|
|
||||||
if (TraceHPI) tty->print_cr("GetProcAddress failed, errcode = %d", GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call initializer.
|
|
||||||
jint init_result = (*initer)(&_get_interface, callbacks);
|
|
||||||
if (init_result < 0) {
|
|
||||||
if (TraceHPI) tty->print_cr("DLL_Initialize failed, returned %ld", init_result);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TraceHPI) tty->print_cr("success");
|
|
||||||
return;
|
|
||||||
}
|
|
|
@ -1,175 +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.
|
|
||||||
*
|
|
||||||
* 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 OS_WINDOWS_VM_HPI_WINDOWS_HPP
|
|
||||||
#define OS_WINDOWS_VM_HPI_WINDOWS_HPP
|
|
||||||
|
|
||||||
// Win32 delegates these to the HPI. Solaris provides its own
|
|
||||||
// implementation without using the HPI (for Interrupitble I/O).
|
|
||||||
|
|
||||||
// HPI_FileInterface
|
|
||||||
|
|
||||||
HPIDECL(close, "close", _file, Close, int, "%d",
|
|
||||||
(int fd),
|
|
||||||
("fd = %d", fd),
|
|
||||||
(fd));
|
|
||||||
|
|
||||||
HPIDECL(read, "read", _file, Read, size_t, "%ld",
|
|
||||||
(int fd, void *buf, unsigned int nBytes),
|
|
||||||
("fd = %d, buf = %p, nBytes = %u", fd, buf, nBytes),
|
|
||||||
(fd, buf, nBytes));
|
|
||||||
|
|
||||||
HPIDECL(write, "write", _file, Write, size_t, "%ld",
|
|
||||||
(int fd, const void *buf, unsigned int nBytes),
|
|
||||||
("fd = %d, buf = %p, nBytes = %u", fd, buf, nBytes),
|
|
||||||
(fd, buf, nBytes));
|
|
||||||
|
|
||||||
|
|
||||||
// HPI_SocketInterface
|
|
||||||
|
|
||||||
HPIDECL(socket_close, "socket_close", _socket, Close, int, "%d",
|
|
||||||
(int fd),
|
|
||||||
("fd = %d", fd),
|
|
||||||
(fd));
|
|
||||||
|
|
||||||
HPIDECL(socket_available, "socket_available", _socket, Available,
|
|
||||||
int, "%d",
|
|
||||||
(int fd, jint *pbytes),
|
|
||||||
("fd = %d, pbytes = %p", fd, pbytes),
|
|
||||||
(fd, pbytes));
|
|
||||||
|
|
||||||
HPIDECL(socket, "socket", _socket, Socket, int, "%d",
|
|
||||||
(int domain, int type, int protocol),
|
|
||||||
("domain = %d, type = %d, protocol = %d", domain, type, protocol),
|
|
||||||
(domain, type, protocol));
|
|
||||||
|
|
||||||
HPIDECL(listen, "listen", _socket, Listen, int, "%d",
|
|
||||||
(int fd, int count),
|
|
||||||
("fd = %d, count = %d", fd, count),
|
|
||||||
(fd, count));
|
|
||||||
|
|
||||||
HPIDECL(connect, "connect", _socket, Connect, int, "%d",
|
|
||||||
(int fd, struct sockaddr *him, int len),
|
|
||||||
("fd = %d, him = %p, len = %d", fd, him, len),
|
|
||||||
(fd, him, len));
|
|
||||||
|
|
||||||
HPIDECL(accept, "accept", _socket, Accept, int, "%d",
|
|
||||||
(int fd, struct sockaddr *him, int *len),
|
|
||||||
("fd = %d, him = %p, len = %p", fd, him, len),
|
|
||||||
(fd, him, len));
|
|
||||||
|
|
||||||
HPIDECL(sendto, "sendto", _socket, SendTo, int, "%d",
|
|
||||||
(int fd, char *buf, int len, int flags,
|
|
||||||
struct sockaddr *to, int tolen),
|
|
||||||
("fd = %d, buf = %p, len = %d, flags = %d, to = %p, tolen = %d",
|
|
||||||
fd, buf, len, flags, to, tolen),
|
|
||||||
(fd, buf, len, flags, to, tolen));
|
|
||||||
|
|
||||||
HPIDECL(recvfrom, "recvfrom", _socket, RecvFrom, int, "%d",
|
|
||||||
(int fd, char *buf, int nbytes, int flags,
|
|
||||||
struct sockaddr *from, int *fromlen),
|
|
||||||
("fd = %d, buf = %p, len = %d, flags = %d, frm = %p, frmlen = %d",
|
|
||||||
fd, buf, nbytes, flags, from, fromlen),
|
|
||||||
(fd, buf, nbytes, flags, from, fromlen));
|
|
||||||
|
|
||||||
HPIDECL(recv, "recv", _socket, Recv, int, "%d",
|
|
||||||
(int fd, char *buf, int nBytes, int flags),
|
|
||||||
("fd = %d, buf = %p, nBytes = %d, flags = %d",
|
|
||||||
fd, buf, nBytes, flags),
|
|
||||||
(fd, buf, nBytes, flags));
|
|
||||||
|
|
||||||
HPIDECL(send, "send", _socket, Send, int, "%d",
|
|
||||||
(int fd, char *buf, int nBytes, int flags),
|
|
||||||
("fd = %d, buf = %p, nBytes = %d, flags = %d",
|
|
||||||
fd, buf, nBytes, flags),
|
|
||||||
(fd, buf, nBytes, flags));
|
|
||||||
|
|
||||||
inline int hpi::raw_send(int fd, char *buf, int nBytes, int flags) {
|
|
||||||
return send(fd, buf, nBytes, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
HPIDECL(timeout, "timeout", _socket, Timeout, int, "%d",
|
|
||||||
(int fd, long timeout),
|
|
||||||
("fd = %d, timeout = %ld", fd, timeout),
|
|
||||||
(fd, timeout));
|
|
||||||
|
|
||||||
HPIDECL(get_host_by_name, "get_host_by_name", _socket, GetHostByName,
|
|
||||||
struct hostent *, "(struct hostent *)%p",
|
|
||||||
(char *name),
|
|
||||||
("%s", name),
|
|
||||||
(name));
|
|
||||||
|
|
||||||
HPIDECL(socket_shutdown, "socket_shutdown", _socket, SocketShutdown,
|
|
||||||
int, "%d",
|
|
||||||
(int fd, int howto),
|
|
||||||
("fd = %d, howto = %d", fd, howto),
|
|
||||||
(fd, howto));
|
|
||||||
|
|
||||||
HPIDECL(bind, "bind", _socket, Bind,
|
|
||||||
int, "%d",
|
|
||||||
(int fd, struct sockaddr *him, int len),
|
|
||||||
("fd = %d, him = %p, len = %d",
|
|
||||||
fd, him, len),
|
|
||||||
(fd, him, len));
|
|
||||||
|
|
||||||
HPIDECL(get_sock_name, "get_sock_name", _socket, GetSocketName,
|
|
||||||
int, "%d",
|
|
||||||
(int fd, struct sockaddr *him, int *len),
|
|
||||||
("fd = %d, him = %p, len = %p",
|
|
||||||
fd, him, len),
|
|
||||||
(fd, him, len));
|
|
||||||
|
|
||||||
HPIDECL(get_host_name, "get_host_name", _socket, GetHostName, int, "%d",
|
|
||||||
(char *hostname, int namelen),
|
|
||||||
("hostname = %p, namelen = %d",
|
|
||||||
hostname, namelen),
|
|
||||||
(hostname, namelen));
|
|
||||||
|
|
||||||
HPIDECL(get_host_by_addr, "get_host_by_addr", _socket, GetHostByAddr,
|
|
||||||
struct hostent *, "(struct hostent *)%p",
|
|
||||||
(const char* name, int len, int type),
|
|
||||||
("name = %p, len = %d, type = %d",
|
|
||||||
name, len, type),
|
|
||||||
(name, len, type));
|
|
||||||
|
|
||||||
HPIDECL(get_sock_opt, "get_sock_opt", _socket, SocketGetOption, int, "%d",
|
|
||||||
(int fd, int level, int optname, char *optval, int* optlen),
|
|
||||||
("fd = %d, level = %d, optname = %d, optval = %p, optlen = %p",
|
|
||||||
fd, level, optname, optval, optlen),
|
|
||||||
(fd, level, optname, optval, optlen));
|
|
||||||
|
|
||||||
HPIDECL(set_sock_opt, "set_sock_opt", _socket, SocketSetOption, int, "%d",
|
|
||||||
(int fd, int level, int optname, const char *optval, int optlen),
|
|
||||||
("fd = %d, level = %d, optname = %d, optval = %p, optlen = %d",
|
|
||||||
fd, level, optname, optval, optlen),
|
|
||||||
(fd, level, optname, optval, optlen));
|
|
||||||
|
|
||||||
HPIDECL(get_proto_by_name, "get_proto_by_name", _socket, GetProtoByName,
|
|
||||||
struct protoent *, "(struct protoent *)%p",
|
|
||||||
(char* name),
|
|
||||||
("name = %p",
|
|
||||||
name),
|
|
||||||
(name));
|
|
||||||
|
|
||||||
#endif // OS_WINDOWS_VM_HPI_WINDOWS_HPP
|
|
|
@ -47,7 +47,6 @@
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/extendedPC.hpp"
|
#include "runtime/extendedPC.hpp"
|
||||||
#include "runtime/globals.hpp"
|
#include "runtime/globals.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
|
@ -1045,8 +1044,6 @@ os::closedir(DIR *dirp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* os::dll_file_extension() { return ".dll"; }
|
|
||||||
|
|
||||||
const char* os::get_temp_directory() {
|
const char* os::get_temp_directory() {
|
||||||
const char *prop = Arguments::get_property("java.io.tmpdir");
|
const char *prop = Arguments::get_property("java.io.tmpdir");
|
||||||
if (prop != 0) return prop;
|
if (prop != 0) return prop;
|
||||||
|
@ -1068,7 +1065,6 @@ static bool file_exists(const char* filename) {
|
||||||
|
|
||||||
void os::dll_build_name(char *buffer, size_t buflen,
|
void os::dll_build_name(char *buffer, size_t buflen,
|
||||||
const char* pname, const char* fname) {
|
const char* pname, const char* fname) {
|
||||||
// Copied from libhpi
|
|
||||||
const size_t pnamelen = pname ? strlen(pname) : 0;
|
const size_t pnamelen = pname ? strlen(pname) : 0;
|
||||||
const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0;
|
const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0;
|
||||||
|
|
||||||
|
@ -1378,10 +1374,6 @@ bool os::dll_address_to_function_name(address addr, char *buf,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* os::dll_lookup(void* handle, const char* name) {
|
|
||||||
return GetProcAddress((HMODULE)handle, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the start and end address of jvm.dll into param[0] and param[1]
|
// save the start and end address of jvm.dll into param[0] and param[1]
|
||||||
static int _locate_jvm_dll(int pid, char* mod_fname, address base_addr,
|
static int _locate_jvm_dll(int pid, char* mod_fname, address base_addr,
|
||||||
unsigned size, void * param) {
|
unsigned size, void * param) {
|
||||||
|
@ -1716,7 +1708,37 @@ void os::jvm_path(char *buf, jint buflen) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf[0] = '\0';
|
||||||
|
if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) {
|
||||||
|
// Support for the gamma launcher. Check for an
|
||||||
|
// ALT_JAVA_HOME or JAVA_HOME environment variable
|
||||||
|
// and fix up the path so it looks like
|
||||||
|
// libjvm.so is installed there (append a fake suffix
|
||||||
|
// hotspot/libjvm.so).
|
||||||
|
char* java_home_var = ::getenv("ALT_JAVA_HOME");
|
||||||
|
if (java_home_var == NULL) {
|
||||||
|
java_home_var = ::getenv("JAVA_HOME");
|
||||||
|
}
|
||||||
|
if (java_home_var != NULL && java_home_var[0] != 0) {
|
||||||
|
|
||||||
|
strncpy(buf, java_home_var, buflen);
|
||||||
|
|
||||||
|
// determine if this is a legacy image or modules image
|
||||||
|
// modules image doesn't have "jre" subdirectory
|
||||||
|
size_t len = strlen(buf);
|
||||||
|
char* jrebin_p = buf + len;
|
||||||
|
jio_snprintf(jrebin_p, buflen-len, "\\jre\\bin\\");
|
||||||
|
if (0 != _access(buf, 0)) {
|
||||||
|
jio_snprintf(jrebin_p, buflen-len, "\\bin\\");
|
||||||
|
}
|
||||||
|
len = strlen(buf);
|
||||||
|
jio_snprintf(buf + len, buflen-len, "hotspot\\jvm.dll");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(buf[0] == '\0') {
|
||||||
GetModuleFileName(vm_lib_handle, buf, buflen);
|
GetModuleFileName(vm_lib_handle, buf, buflen);
|
||||||
|
}
|
||||||
strcpy(saved_jvm_path, buf);
|
strcpy(saved_jvm_path, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1734,6 +1756,44 @@ void os::print_jni_name_suffix_on(outputStream* st, int args_size) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method is a copy of JDK's sysGetLastErrorString
|
||||||
|
// from src/windows/hpi/src/system_md.c
|
||||||
|
|
||||||
|
size_t os::lasterror(char *buf, size_t len) {
|
||||||
|
long errval;
|
||||||
|
|
||||||
|
if ((errval = GetLastError()) != 0) {
|
||||||
|
/* DOS error */
|
||||||
|
int n = (int)FormatMessage(
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL,
|
||||||
|
errval,
|
||||||
|
0,
|
||||||
|
buf,
|
||||||
|
(DWORD)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);
|
||||||
|
size_t n = strlen(s);
|
||||||
|
if (n >= len) n = len - 1;
|
||||||
|
strncpy(buf, s, n);
|
||||||
|
buf[n] = '\0';
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// sun.misc.Signal
|
// sun.misc.Signal
|
||||||
// NOTE that this is a workaround for an apparent kernel bug where if
|
// NOTE that this is a workaround for an apparent kernel bug where if
|
||||||
// a signal handler for SIGBREAK is installed then that signal handler
|
// a signal handler for SIGBREAK is installed then that signal handler
|
||||||
|
@ -2941,10 +3001,6 @@ void os::pd_start_thread(Thread* thread) {
|
||||||
assert(ret != SYS_THREAD_ERROR, "StartThread failed"); // should propagate back
|
assert(ret != SYS_THREAD_ERROR, "StartThread failed"); // should propagate back
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t os::read(int fd, void *buf, unsigned int nBytes) {
|
|
||||||
return ::read(fd, buf, nBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
class HighResolutionInterval {
|
class HighResolutionInterval {
|
||||||
// The default timer resolution seems to be 10 milliseconds.
|
// The default timer resolution seems to be 10 milliseconds.
|
||||||
// (Where is this written down?)
|
// (Where is this written down?)
|
||||||
|
@ -3423,10 +3479,6 @@ jint os::init_2(void) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize HPI.
|
|
||||||
jint hpi_result = hpi::initialize();
|
|
||||||
if (hpi_result != JNI_OK) { return hpi_result; }
|
|
||||||
|
|
||||||
// If stack_commit_size is 0, windows will reserve the default size,
|
// If stack_commit_size is 0, windows will reserve the default size,
|
||||||
// but only commit a small portion of it.
|
// but only commit a small portion of it.
|
||||||
size_t stack_commit_size = round_to(ThreadStackSize*K, os::vm_page_size());
|
size_t stack_commit_size = round_to(ThreadStackSize*K, os::vm_page_size());
|
||||||
|
@ -3531,7 +3583,7 @@ int os::stat(const char *path, struct stat *sbuf) {
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
hpi::native_path(strcpy(pathbuf, path));
|
os::native_path(strcpy(pathbuf, path));
|
||||||
int ret = ::stat(pathbuf, sbuf);
|
int ret = ::stat(pathbuf, sbuf);
|
||||||
if (sbuf != NULL && UseUTCFileTimestamp) {
|
if (sbuf != NULL && UseUTCFileTimestamp) {
|
||||||
// Fix for 6539723. st_mtime returned from stat() is dependent on
|
// Fix for 6539723. st_mtime returned from stat() is dependent on
|
||||||
|
@ -3675,6 +3727,20 @@ bool os::dont_yield() {
|
||||||
return DontYieldALot;
|
return DontYieldALot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method is a slightly reworked copy of JDK's sysOpen
|
||||||
|
// from src/windows/hpi/src/sys_api_md.c
|
||||||
|
|
||||||
|
int os::open(const char *path, int oflag, int mode) {
|
||||||
|
char pathbuf[MAX_PATH];
|
||||||
|
|
||||||
|
if (strlen(path) > MAX_PATH - 1) {
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
os::native_path(strcpy(pathbuf, path));
|
||||||
|
return ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode);
|
||||||
|
}
|
||||||
|
|
||||||
// Is a (classpath) directory empty?
|
// Is a (classpath) directory empty?
|
||||||
bool os::dir_is_empty(const char* path) {
|
bool os::dir_is_empty(const char* path) {
|
||||||
WIN32_FIND_DATA fd;
|
WIN32_FIND_DATA fd;
|
||||||
|
@ -3706,6 +3772,297 @@ jlong os::seek_to_file_offset(int fd, jlong offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
jlong os::lseek(int fd, jlong offset, int whence) {
|
||||||
|
return (jlong) ::_lseeki64(fd, offset, whence);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method is a slightly reworked copy of JDK's sysNativePath
|
||||||
|
// from src/windows/hpi/src/path_md.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 * os::native_path(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 */
|
||||||
|
assert(((!::IsDBCSLeadByte('/'))
|
||||||
|
&& (!::IsDBCSLeadByte('\\'))
|
||||||
|
&& (!::IsDBCSLeadByte(':'))),
|
||||||
|
"Illegal lead byte");
|
||||||
|
|
||||||
|
/* Check for leading separators */
|
||||||
|
#define isfilesep(c) ((c) == '/' || (c) == '\\')
|
||||||
|
while (isfilesep(*src)) {
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (::isalpha(*src) && !::IsDBCSLeadByte(*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 (::IsDBCSLeadByte(*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
|
||||||
|
jio_fprintf(stderr, "sysNativePath: %s\n", path);
|
||||||
|
#endif DEBUG
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This code is a copy of JDK's sysSetLength
|
||||||
|
// from src/windows/hpi/src/sys_api_md.c
|
||||||
|
|
||||||
|
int os::ftruncate(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This code is a copy of JDK's sysSync
|
||||||
|
// from src/windows/hpi/src/sys_api_md.c
|
||||||
|
// except for the legacy workaround for a bug in Win 98
|
||||||
|
|
||||||
|
int os::fsync(int fd) {
|
||||||
|
HANDLE handle = (HANDLE)::_get_osfhandle(fd);
|
||||||
|
|
||||||
|
if ( (!::FlushFileBuffers(handle)) &&
|
||||||
|
(GetLastError() != ERROR_ACCESS_DENIED) ) {
|
||||||
|
/* from winerror.h */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nonSeekAvailable(int, long *);
|
||||||
|
static int stdinAvailable(int, long *);
|
||||||
|
|
||||||
|
#define S_ISCHR(mode) (((mode) & _S_IFCHR) == _S_IFCHR)
|
||||||
|
#define S_ISFIFO(mode) (((mode) & _S_IFIFO) == _S_IFIFO)
|
||||||
|
|
||||||
|
// This code is a copy of JDK's sysAvailable
|
||||||
|
// from src/windows/hpi/src/sys_api_md.c
|
||||||
|
|
||||||
|
int os::available(int fd, jlong *bytes) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
(*bytes) = (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;
|
||||||
|
}
|
||||||
|
*bytes = end - cur;
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This code is a copy of JDK's nonSeekAvailable
|
||||||
|
// from src/windows/hpi/src/sys_api_md.c
|
||||||
|
|
||||||
|
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, (LPDWORD)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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_INPUT_EVENTS 2000
|
||||||
|
|
||||||
|
// This code is a copy of JDK's stdinAvailable
|
||||||
|
// from src/windows/hpi/src/sys_api_md.c
|
||||||
|
|
||||||
|
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 = (INPUT_RECORD *)os::malloc(numEvents * sizeof(INPUT_RECORD));
|
||||||
|
if (lpBuffer == NULL) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = ::PeekConsoleInput(han, lpBuffer, numEvents, &numEventsRead);
|
||||||
|
if (error == 0) {
|
||||||
|
os::free(lpBuffer);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Examine input records for the number of bytes available */
|
||||||
|
for(i=0; i<numEvents; i++) {
|
||||||
|
if (lpBuffer[i].EventType == KEY_EVENT) {
|
||||||
|
|
||||||
|
KEY_EVENT_RECORD *keyRecord = (KEY_EVENT_RECORD *)
|
||||||
|
&(lpBuffer[i].Event);
|
||||||
|
if (keyRecord->bKeyDown == TRUE) {
|
||||||
|
CHAR *keyPressed = (CHAR *) &(keyRecord->uChar);
|
||||||
|
curLength++;
|
||||||
|
if (*keyPressed == '\r') {
|
||||||
|
actualLength = curLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lpBuffer != NULL) {
|
||||||
|
os::free(lpBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
*pbytes = (long) actualLength;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// Map a block of memory.
|
// Map a block of memory.
|
||||||
char* os::map_memory(int fd, const char* file_name, size_t file_offset,
|
char* os::map_memory(int fd, const char* file_name, size_t file_offset,
|
||||||
char *addr, size_t bytes, bool read_only,
|
char *addr, size_t bytes, bool read_only,
|
||||||
|
@ -3871,7 +4228,7 @@ void os::pause() {
|
||||||
int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
close(fd);
|
::close(fd);
|
||||||
while (::stat(filename, &buf) == 0) {
|
while (::stat(filename, &buf) == 0) {
|
||||||
Sleep(100);
|
Sleep(100);
|
||||||
}
|
}
|
||||||
|
@ -4232,3 +4589,164 @@ static int getLastErrorString(char *buf, size_t len)
|
||||||
// We don't build a headless jre for Windows
|
// We don't build a headless jre for Windows
|
||||||
bool os::is_headless_jre() { return false; }
|
bool os::is_headless_jre() { return false; }
|
||||||
|
|
||||||
|
// OS_SocketInterface
|
||||||
|
// Not used on Windows
|
||||||
|
|
||||||
|
// OS_SocketInterface
|
||||||
|
typedef struct hostent * (PASCAL FAR *ws2_ifn_ptr_t)(...);
|
||||||
|
ws2_ifn_ptr_t *get_host_by_name_fn = NULL;
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
static bool sockfnptrs_initialized = FALSE;
|
||||||
|
static mutex_t sockFnTableMutex;
|
||||||
|
|
||||||
|
/* is Winsock2 loaded? better to be explicit than to rely on sockfnptrs */
|
||||||
|
static bool winsock2Available = FALSE;
|
||||||
|
|
||||||
|
|
||||||
|
static void initSockFnTable() {
|
||||||
|
int (PASCAL FAR* WSAStartupPtr)(WORD, LPWSADATA);
|
||||||
|
WSADATA wsadata;
|
||||||
|
|
||||||
|
::mutexInit(&sockFnTableMutex);
|
||||||
|
::mutexLock(&sockFnTableMutex);
|
||||||
|
|
||||||
|
if (sockfnptrs_initialized == FALSE) {
|
||||||
|
HMODULE hWinsock;
|
||||||
|
|
||||||
|
/* try to load Winsock2, and if that fails, load Winsock */
|
||||||
|
hWinsock = ::LoadLibrary("ws2_32.dll");
|
||||||
|
|
||||||
|
if (hWinsock == NULL) {
|
||||||
|
jio_fprintf(stderr, "Could not load Winsock 2 (error: %d)\n",
|
||||||
|
::GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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) {
|
||||||
|
jio_fprintf(stderr, "Could not initialize Winsock\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
get_host_by_name_fn
|
||||||
|
= (ws2_ifn_ptr_t*) GetProcAddress(hWinsock, "gethostbyname");
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(get_host_by_name_fn != NULL,
|
||||||
|
"gethostbyname function not found");
|
||||||
|
sockfnptrs_initialized = TRUE;
|
||||||
|
::mutexUnlock(&sockFnTableMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hostent* os::get_host_by_name(char* name) {
|
||||||
|
if (!sockfnptrs_initialized) {
|
||||||
|
initSockFnTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(sockfnptrs_initialized == TRUE && get_host_by_name_fn != NULL,
|
||||||
|
"sockfnptrs is not initialized or pointer to gethostbyname function is NULL");
|
||||||
|
return (*get_host_by_name_fn)(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int os::socket_close(int fd) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::socket_available(int fd, jint *pbytes) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::socket(int domain, int type, int protocol) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::listen(int fd, int count) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::connect(int fd, struct sockaddr *him, int len) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::accept(int fd, struct sockaddr *him, int *len) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::sendto(int fd, char *buf, int len, int flags,
|
||||||
|
struct sockaddr *to, int tolen) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::recvfrom(int fd, char *buf, int nBytes, int flags,
|
||||||
|
sockaddr *from, int *fromlen) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::recv(int fd, char *buf, int nBytes, int flags) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::send(int fd, char *buf, int nBytes, int flags) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::raw_send(int fd, char *buf, int nBytes, int flags) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::timeout(int fd, long timeout) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::get_host_name(char* name, int namelen) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::socket_shutdown(int fd, int howto) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::bind(int fd, struct sockaddr *him, int len) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::get_sock_name(int fd, struct sockaddr *him, int *len) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::get_sock_opt(int fd, int level, int optname,
|
||||||
|
char *optval, int* optlen) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int os::set_sock_opt(int fd, int level, int optname,
|
||||||
|
const char *optval, int optlen) {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -35,15 +35,26 @@
|
||||||
inline const char* os::file_separator() { return "\\"; }
|
inline const char* os::file_separator() { return "\\"; }
|
||||||
inline const char* os::line_separator() { return "\r\n"; }
|
inline const char* os::line_separator() { return "\r\n"; }
|
||||||
inline const char* os::path_separator() { return ";"; }
|
inline const char* os::path_separator() { return ";"; }
|
||||||
|
inline const char* os::dll_file_extension() { return ".dll"; }
|
||||||
|
|
||||||
inline const char* os::jlong_format_specifier() { return "%I64d"; }
|
inline const char* os::jlong_format_specifier() { return "%I64d"; }
|
||||||
inline const char* os::julong_format_specifier() { return "%I64u"; }
|
inline const char* os::julong_format_specifier() { return "%I64u"; }
|
||||||
|
|
||||||
|
inline const int os::default_file_open_flags() { return O_BINARY | O_NOINHERIT;}
|
||||||
|
|
||||||
// File names are case-insensitive on windows only
|
// File names are case-insensitive on windows only
|
||||||
inline int os::file_name_strcmp(const char* s, const char* t) {
|
inline int os::file_name_strcmp(const char* s, const char* t) {
|
||||||
return _stricmp(s, t);
|
return _stricmp(s, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void os::dll_unload(void *lib) {
|
||||||
|
::FreeLibrary((HMODULE)lib);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* os::dll_lookup(void *lib, const char *name) {
|
||||||
|
return (void*)::GetProcAddress((HMODULE)lib, name);
|
||||||
|
}
|
||||||
|
|
||||||
// Used to improve time-sharing on some systems
|
// Used to improve time-sharing on some systems
|
||||||
inline void os::loop_breaker(int attempts) {}
|
inline void os::loop_breaker(int attempts) {}
|
||||||
|
|
||||||
|
@ -83,4 +94,19 @@ inline void os::bang_stack_shadow_pages() {
|
||||||
inline bool os::numa_has_static_binding() { return true; }
|
inline bool os::numa_has_static_binding() { return true; }
|
||||||
inline bool os::numa_has_group_homing() { return false; }
|
inline bool os::numa_has_group_homing() { return false; }
|
||||||
|
|
||||||
|
inline size_t os::read(int fd, void *buf, unsigned int nBytes) {
|
||||||
|
return ::read(fd, buf, nBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) {
|
||||||
|
return ::read(fd, buf, nBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t os::write(int fd, const void *buf, unsigned int nBytes) {
|
||||||
|
return ::write(fd, buf, nBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int os::close(int fd) {
|
||||||
|
return ::close(fd);
|
||||||
|
}
|
||||||
#endif // OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP
|
#endif // OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/extendedPC.hpp"
|
#include "runtime/extendedPC.hpp"
|
||||||
#include "runtime/frame.inline.hpp"
|
#include "runtime/frame.inline.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/extendedPC.hpp"
|
#include "runtime/extendedPC.hpp"
|
||||||
#include "runtime/frame.inline.hpp"
|
#include "runtime/frame.inline.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
|
|
|
@ -42,7 +42,6 @@
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/extendedPC.hpp"
|
#include "runtime/extendedPC.hpp"
|
||||||
#include "runtime/frame.inline.hpp"
|
#include "runtime/frame.inline.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/extendedPC.hpp"
|
#include "runtime/extendedPC.hpp"
|
||||||
#include "runtime/frame.inline.hpp"
|
#include "runtime/frame.inline.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
|
@ -289,17 +288,17 @@ static int threadgetstate(thread_t tid, int *flags, lwpid_t *lwp, stack_t *ss, g
|
||||||
if (*flags == TRS_LWPID) {
|
if (*flags == TRS_LWPID) {
|
||||||
sprintf(lwpstatusfile, "/proc/%d/lwp/%d/lwpstatus", getpid(),
|
sprintf(lwpstatusfile, "/proc/%d/lwp/%d/lwpstatus", getpid(),
|
||||||
*lwp);
|
*lwp);
|
||||||
if ((lwpfd = open(lwpstatusfile, O_RDONLY)) < 0) {
|
if ((lwpfd = ::open(lwpstatusfile, O_RDONLY)) < 0) {
|
||||||
perror("thr_mutator_status: open lwpstatus");
|
perror("thr_mutator_status: open lwpstatus");
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
if (pread(lwpfd, lwpstatus, sizeof (lwpstatus_t), (off_t)0) !=
|
if (pread(lwpfd, lwpstatus, sizeof (lwpstatus_t), (off_t)0) !=
|
||||||
sizeof (lwpstatus_t)) {
|
sizeof (lwpstatus_t)) {
|
||||||
perror("thr_mutator_status: read lwpstatus");
|
perror("thr_mutator_status: read lwpstatus");
|
||||||
(void) close(lwpfd);
|
(void) ::close(lwpfd);
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
(void) close(lwpfd);
|
(void) ::close(lwpfd);
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/extendedPC.hpp"
|
#include "runtime/extendedPC.hpp"
|
||||||
#include "runtime/frame.inline.hpp"
|
#include "runtime/frame.inline.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
|
|
|
@ -41,7 +41,6 @@
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/extendedPC.hpp"
|
#include "runtime/extendedPC.hpp"
|
||||||
#include "runtime/frame.inline.hpp"
|
#include "runtime/frame.inline.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -22,10 +22,6 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK,
|
|
||||||
* search "GAMMA" for gamma specific changes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _JAVA_H_
|
#ifndef _JAVA_H_
|
||||||
#define _JAVA_H_
|
#define _JAVA_H_
|
||||||
|
@ -35,6 +31,7 @@
|
||||||
*/
|
*/
|
||||||
#include "jni.h"
|
#include "jni.h"
|
||||||
#include "java_md.h"
|
#include "java_md.h"
|
||||||
|
#include "jli_util.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pointers to the needed JNI invocation API, initialized by LoadJavaVM.
|
* Pointers to the needed JNI invocation API, initialized by LoadJavaVM.
|
||||||
|
@ -89,26 +86,26 @@ void ReportExceptionDescription(JNIEnv * env);
|
||||||
jboolean RemovableMachineDependentOption(char * option);
|
jboolean RemovableMachineDependentOption(char * option);
|
||||||
void PrintMachineDependentOptions();
|
void PrintMachineDependentOptions();
|
||||||
|
|
||||||
|
const char *jlong_format_specifier();
|
||||||
|
/*
|
||||||
|
* Block current thread and continue execution in new thread
|
||||||
|
*/
|
||||||
|
int ContinueInNewThread(int (JNICALL *continuation)(void *),
|
||||||
|
jlong stack_size, void * args);
|
||||||
|
|
||||||
|
/* sun.java.launcher.* platform properties. */
|
||||||
|
void SetJavaLauncherPlatformProps(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Functions defined in java.c and used in java_md.c.
|
* Functions defined in java.c and used in java_md.c.
|
||||||
*/
|
*/
|
||||||
jint ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative);
|
jint ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative);
|
||||||
char *CheckJvmType(int *argc, char ***argv, jboolean speculative);
|
char *CheckJvmType(int *argc, char ***argv, jboolean speculative);
|
||||||
void* MemAlloc(size_t size);
|
void AddOption(char *str, void *info);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make launcher spit debug output.
|
* Make launcher spit debug output.
|
||||||
*/
|
*/
|
||||||
extern jboolean _launcher_debug;
|
extern jboolean _launcher_debug;
|
||||||
/*
|
|
||||||
* This allows for finding classes from the VM's bootstrap class loader
|
|
||||||
* directly, FindClass uses the application class loader internally, this will
|
|
||||||
* cause unnecessary searching of the classpath for the required classes.
|
|
||||||
*/
|
|
||||||
typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env,
|
|
||||||
const char *name,
|
|
||||||
jboolean throwError));
|
|
||||||
|
|
||||||
jclass FindBootStrapClass(JNIEnv *env, const char *classname);
|
|
||||||
|
|
||||||
#endif /* _JAVA_H_ */
|
#endif /* _JAVA_H_ */
|
88
hotspot/src/share/tools/launcher/jli_util.c
Normal file
88
hotspot/src/share/tools/launcher/jli_util.c
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "jli_util.h"
|
||||||
|
|
||||||
|
#ifdef GAMMA
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
#define strdup _strdup
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a pointer to a block of at least 'size' bytes of memory.
|
||||||
|
* Prints error message and exits if the memory could not be allocated.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
JLI_MemAlloc(size_t size)
|
||||||
|
{
|
||||||
|
void *p = malloc(size);
|
||||||
|
if (p == 0) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Equivalent to realloc(size).
|
||||||
|
* Prints error message and exits if the memory could not be reallocated.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
JLI_MemRealloc(void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
void *p = realloc(ptr, size);
|
||||||
|
if (p == 0) {
|
||||||
|
perror("realloc");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper over strdup(3C) which prints an error message and exits if memory
|
||||||
|
* could not be allocated.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
JLI_StringDup(const char *s1)
|
||||||
|
{
|
||||||
|
char *s = strdup(s1);
|
||||||
|
if (s == NULL) {
|
||||||
|
perror("strdup");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Very equivalent to free(ptr).
|
||||||
|
* Here to maintain pairing with the above routines.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
JLI_MemFree(void *ptr)
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
35
hotspot/src/share/tools/launcher/jli_util.h
Normal file
35
hotspot/src/share/tools/launcher/jli_util.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 _JLI_UTIL_H
|
||||||
|
#define _JLI_UTIL_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void *JLI_MemAlloc(size_t size);
|
||||||
|
void *JLI_MemRealloc(void *ptr, size_t size);
|
||||||
|
char *JLI_StringDup(const char *s1);
|
||||||
|
void JLI_MemFree(void *ptr);
|
||||||
|
|
||||||
|
#endif /* _JLI_UTIL_H */
|
494
hotspot/src/share/tools/launcher/wildcard.c
Normal file
494
hotspot/src/share/tools/launcher/wildcard.c
Normal file
|
@ -0,0 +1,494 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class-Path Wildcards
|
||||||
|
*
|
||||||
|
* The syntax for wildcards is a single asterisk. The class path
|
||||||
|
* foo/"*", e.g., loads all jar files in the directory named foo.
|
||||||
|
* (This requires careful quotation when used in shell scripts.)
|
||||||
|
*
|
||||||
|
* Only files whose names end in .jar or .JAR are matched.
|
||||||
|
* Files whose names end in .zip, or which have a particular
|
||||||
|
* magic number, regardless of filename extension, are not
|
||||||
|
* matched.
|
||||||
|
*
|
||||||
|
* Files are considered regardless of whether or not they are
|
||||||
|
* "hidden" in the UNIX sense, i.e., have names beginning with '.'.
|
||||||
|
*
|
||||||
|
* A wildcard only matches jar files, not class files in the same
|
||||||
|
* directory. If you want to load both class files and jar files from
|
||||||
|
* a single directory foo then you can say foo:foo/"*", or foo/"*":foo
|
||||||
|
* if you want the jar files to take precedence.
|
||||||
|
*
|
||||||
|
* Subdirectories are not searched recursively, i.e., foo/"*" only
|
||||||
|
* looks for jar files in foo, not in foo/bar, foo/baz, etc.
|
||||||
|
*
|
||||||
|
* Expansion of wildcards is done early, prior to the invocation of a
|
||||||
|
* program's main method, rather than late, during the class-loading
|
||||||
|
* process itself. Each element of the input class path containing a
|
||||||
|
* wildcard is replaced by the (possibly empty) sequence of elements
|
||||||
|
* generated by enumerating the jar files in the named directory. If
|
||||||
|
* the directory foo contains a.jar, b.jar, and c.jar,
|
||||||
|
* e.g., then the class path foo/"*" is expanded into
|
||||||
|
* foo/a.jar:foo/b.jar:foo/c.jar, and that string would be the value
|
||||||
|
* of the system property java.class.path.
|
||||||
|
*
|
||||||
|
* The order in which the jar files in a directory are enumerated in
|
||||||
|
* the expanded class path is not specified and may vary from platform
|
||||||
|
* to platform and even from moment to moment on the same machine. A
|
||||||
|
* well-constructed application should not depend upon any particular
|
||||||
|
* order. If a specific order is required then the jar files can be
|
||||||
|
* enumerated explicitly in the class path.
|
||||||
|
*
|
||||||
|
* The CLASSPATH environment variable is not treated any differently
|
||||||
|
* from the -classpath (equiv. -cp) command-line option,
|
||||||
|
* i.e. wildcards are honored in all these cases.
|
||||||
|
*
|
||||||
|
* Class-path wildcards are not honored in the Class-Path jar-manifest
|
||||||
|
* header.
|
||||||
|
*
|
||||||
|
* Class-path wildcards are honored not only by the Java launcher but
|
||||||
|
* also by most other command-line tools that accept class paths, and
|
||||||
|
* in particular by javac and javadoc.
|
||||||
|
*
|
||||||
|
* Class-path wildcards are not honored in any other kind of path, and
|
||||||
|
* especially not in the bootstrap class path, which is a mere
|
||||||
|
* artifact of our implementation and not something that developers
|
||||||
|
* should use.
|
||||||
|
*
|
||||||
|
* Classpath wildcards are only expanded in the Java launcher code,
|
||||||
|
* supporting the use of wildcards on the command line and in the
|
||||||
|
* CLASSPATH environment variable. We do not support the use of
|
||||||
|
* wildcards by applications that embed the JVM.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include "java.h" /* Strictly for PATH_SEPARATOR/FILE_SEPARATOR */
|
||||||
|
#include "jli_util.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else /* Unix */
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#endif /* Unix */
|
||||||
|
|
||||||
|
static int
|
||||||
|
exists(const char* filename)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return _access(filename, 0) == 0;
|
||||||
|
#else
|
||||||
|
return access(filename, F_OK) == 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NEW_(TYPE) ((TYPE) JLI_MemAlloc(sizeof(struct TYPE##_)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wildcard directory iteration.
|
||||||
|
* WildcardIterator_for(wildcard) returns an iterator.
|
||||||
|
* Each call to that iterator's next() method returns the basename
|
||||||
|
* of an entry in the wildcard's directory. The basename's memory
|
||||||
|
* belongs to the iterator. The caller is responsible for prepending
|
||||||
|
* the directory name and file separator, if necessary.
|
||||||
|
* When done with the iterator, call the close method to clean up.
|
||||||
|
*/
|
||||||
|
typedef struct WildcardIterator_* WildcardIterator;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct WildcardIterator_
|
||||||
|
{
|
||||||
|
HANDLE handle;
|
||||||
|
char *firstFile; /* Stupid FindFirstFile...FindNextFile */
|
||||||
|
};
|
||||||
|
|
||||||
|
static WildcardIterator
|
||||||
|
WildcardIterator_for(const char *wildcard)
|
||||||
|
{
|
||||||
|
WIN32_FIND_DATA find_data;
|
||||||
|
WildcardIterator it = NEW_(WildcardIterator);
|
||||||
|
HANDLE handle = FindFirstFile(wildcard, &find_data);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
return NULL;
|
||||||
|
it->handle = handle;
|
||||||
|
it->firstFile = find_data.cFileName;
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
WildcardIterator_next(WildcardIterator it)
|
||||||
|
{
|
||||||
|
WIN32_FIND_DATA find_data;
|
||||||
|
if (it->firstFile != NULL) {
|
||||||
|
char *firstFile = it->firstFile;
|
||||||
|
it->firstFile = NULL;
|
||||||
|
return firstFile;
|
||||||
|
}
|
||||||
|
return FindNextFile(it->handle, &find_data)
|
||||||
|
? find_data.cFileName : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
WildcardIterator_close(WildcardIterator it)
|
||||||
|
{
|
||||||
|
if (it) {
|
||||||
|
FindClose(it->handle);
|
||||||
|
JLI_MemFree(it->firstFile);
|
||||||
|
JLI_MemFree(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* Unix */
|
||||||
|
struct WildcardIterator_
|
||||||
|
{
|
||||||
|
DIR *dir;
|
||||||
|
};
|
||||||
|
|
||||||
|
static WildcardIterator
|
||||||
|
WildcardIterator_for(const char *wildcard)
|
||||||
|
{
|
||||||
|
DIR *dir;
|
||||||
|
int wildlen = strlen(wildcard);
|
||||||
|
if (wildlen < 2) {
|
||||||
|
dir = opendir(".");
|
||||||
|
} else {
|
||||||
|
char *dirname = JLI_StringDup(wildcard);
|
||||||
|
dirname[wildlen - 1] = '\0';
|
||||||
|
dir = opendir(dirname);
|
||||||
|
JLI_MemFree(dirname);
|
||||||
|
}
|
||||||
|
if (dir == NULL)
|
||||||
|
return NULL;
|
||||||
|
else {
|
||||||
|
WildcardIterator it = NEW_(WildcardIterator);
|
||||||
|
it->dir = dir;
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
WildcardIterator_next(WildcardIterator it)
|
||||||
|
{
|
||||||
|
struct dirent* dirp = readdir(it->dir);
|
||||||
|
return dirp ? dirp->d_name : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
WildcardIterator_close(WildcardIterator it)
|
||||||
|
{
|
||||||
|
if (it) {
|
||||||
|
closedir(it->dir);
|
||||||
|
JLI_MemFree(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* Unix */
|
||||||
|
|
||||||
|
static int
|
||||||
|
equal(const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
return strcmp(s1, s2) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FileList ADT - a dynamic list of C filenames
|
||||||
|
*/
|
||||||
|
struct FileList_
|
||||||
|
{
|
||||||
|
char **files;
|
||||||
|
int size;
|
||||||
|
int capacity;
|
||||||
|
};
|
||||||
|
typedef struct FileList_ *FileList;
|
||||||
|
|
||||||
|
static FileList
|
||||||
|
FileList_new(int capacity)
|
||||||
|
{
|
||||||
|
FileList fl = NEW_(FileList);
|
||||||
|
fl->capacity = capacity;
|
||||||
|
fl->files = (char **) JLI_MemAlloc(capacity * sizeof(fl->files[0]));
|
||||||
|
fl->size = 0;
|
||||||
|
return fl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_WILDCARD
|
||||||
|
static void
|
||||||
|
FileList_print(FileList fl)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
putchar('[');
|
||||||
|
for (i = 0; i < fl->size; i++) {
|
||||||
|
if (i > 0) printf(", ");
|
||||||
|
printf("\"%s\"",fl->files[i]);
|
||||||
|
}
|
||||||
|
putchar(']');
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
FileList_free(FileList fl)
|
||||||
|
{
|
||||||
|
if (fl) {
|
||||||
|
if (fl->files) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < fl->size; i++)
|
||||||
|
JLI_MemFree(fl->files[i]);
|
||||||
|
JLI_MemFree(fl->files);
|
||||||
|
}
|
||||||
|
JLI_MemFree(fl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
FileList_ensureCapacity(FileList fl, int capacity)
|
||||||
|
{
|
||||||
|
if (fl->capacity < capacity) {
|
||||||
|
while (fl->capacity < capacity)
|
||||||
|
fl->capacity *= 2;
|
||||||
|
fl->files = JLI_MemRealloc(fl->files,
|
||||||
|
fl->capacity * sizeof(fl->files[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
FileList_add(FileList fl, char *file)
|
||||||
|
{
|
||||||
|
FileList_ensureCapacity(fl, fl->size+1);
|
||||||
|
fl->files[fl->size++] = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
FileList_addSubstring(FileList fl, const char *beg, int len)
|
||||||
|
{
|
||||||
|
char *filename = (char *) JLI_MemAlloc(len+1);
|
||||||
|
memcpy(filename, beg, len);
|
||||||
|
filename[len] = '\0';
|
||||||
|
FileList_ensureCapacity(fl, fl->size+1);
|
||||||
|
fl->files[fl->size++] = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
FileList_join(FileList fl, char sep)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int size;
|
||||||
|
char *path;
|
||||||
|
char *p;
|
||||||
|
for (i = 0, size = 1; i < fl->size; i++)
|
||||||
|
size += strlen(fl->files[i]) + 1;
|
||||||
|
|
||||||
|
path = JLI_MemAlloc(size);
|
||||||
|
|
||||||
|
for (i = 0, p = path; i < fl->size; i++) {
|
||||||
|
int len = strlen(fl->files[i]);
|
||||||
|
if (i > 0) *p++ = sep;
|
||||||
|
memcpy(p, fl->files[i], len);
|
||||||
|
p += len;
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FileList
|
||||||
|
FileList_split(const char *path, char sep)
|
||||||
|
{
|
||||||
|
const char *p, *q;
|
||||||
|
int len = strlen(path);
|
||||||
|
int count;
|
||||||
|
FileList fl;
|
||||||
|
for (count = 1, p = path; p < path + len; p++)
|
||||||
|
count += (*p == sep);
|
||||||
|
fl = FileList_new(count);
|
||||||
|
for (p = path;;) {
|
||||||
|
for (q = p; q <= path + len; q++) {
|
||||||
|
if (*q == sep || *q == '\0') {
|
||||||
|
FileList_addSubstring(fl, p, q - p);
|
||||||
|
if (*q == '\0')
|
||||||
|
return fl;
|
||||||
|
p = q + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
isJarFileName(const char *filename)
|
||||||
|
{
|
||||||
|
int len = strlen(filename);
|
||||||
|
return (len >= 4) &&
|
||||||
|
(filename[len - 4] == '.') &&
|
||||||
|
(equal(filename + len - 3, "jar") ||
|
||||||
|
equal(filename + len - 3, "JAR")) &&
|
||||||
|
/* Paranoia: Maybe filename is "DIR:foo.jar" */
|
||||||
|
(strchr(filename, PATH_SEPARATOR) == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
wildcardConcat(const char *wildcard, const char *basename)
|
||||||
|
{
|
||||||
|
int wildlen = strlen(wildcard);
|
||||||
|
int baselen = strlen(basename);
|
||||||
|
char *filename = (char *) JLI_MemAlloc(wildlen + baselen);
|
||||||
|
/* Replace the trailing '*' with basename */
|
||||||
|
memcpy(filename, wildcard, wildlen-1);
|
||||||
|
memcpy(filename+wildlen-1, basename, baselen+1);
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FileList
|
||||||
|
wildcardFileList(const char *wildcard)
|
||||||
|
{
|
||||||
|
const char *basename;
|
||||||
|
FileList fl = FileList_new(16);
|
||||||
|
WildcardIterator it = WildcardIterator_for(wildcard);
|
||||||
|
if (it == NULL)
|
||||||
|
return NULL;
|
||||||
|
while ((basename = WildcardIterator_next(it)) != NULL)
|
||||||
|
if (isJarFileName(basename))
|
||||||
|
FileList_add(fl, wildcardConcat(wildcard, basename));
|
||||||
|
WildcardIterator_close(it);
|
||||||
|
return fl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
isWildcard(const char *filename)
|
||||||
|
{
|
||||||
|
int len = strlen(filename);
|
||||||
|
return (len > 0) &&
|
||||||
|
(filename[len - 1] == '*') &&
|
||||||
|
(len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) &&
|
||||||
|
(! exists(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
FileList_expandWildcards(FileList fl)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; i < fl->size; i++) {
|
||||||
|
if (isWildcard(fl->files[i])) {
|
||||||
|
FileList expanded = wildcardFileList(fl->files[i]);
|
||||||
|
if (expanded != NULL && expanded->size > 0) {
|
||||||
|
JLI_MemFree(fl->files[i]);
|
||||||
|
FileList_ensureCapacity(fl, fl->size + expanded->size);
|
||||||
|
for (j = fl->size - 1; j >= i+1; j--)
|
||||||
|
fl->files[j+expanded->size-1] = fl->files[j];
|
||||||
|
for (j = 0; j < expanded->size; j++)
|
||||||
|
fl->files[i+j] = expanded->files[j];
|
||||||
|
i += expanded->size - 1;
|
||||||
|
fl->size += expanded->size - 1;
|
||||||
|
/* fl expropriates expanded's elements. */
|
||||||
|
expanded->size = 0;
|
||||||
|
}
|
||||||
|
FileList_free(expanded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
JLI_WildcardExpandClasspath(const char *classpath)
|
||||||
|
{
|
||||||
|
char *expanded;
|
||||||
|
FileList fl;
|
||||||
|
|
||||||
|
if (strchr(classpath, '*') == NULL)
|
||||||
|
return classpath;
|
||||||
|
fl = FileList_split(classpath, PATH_SEPARATOR);
|
||||||
|
FileList_expandWildcards(fl);
|
||||||
|
expanded = FileList_join(fl, PATH_SEPARATOR);
|
||||||
|
FileList_free(fl);
|
||||||
|
if (getenv("_JAVA_LAUNCHER_DEBUG") != 0)
|
||||||
|
printf("Expanded wildcards:\n"
|
||||||
|
" before: \"%s\"\n"
|
||||||
|
" after : \"%s\"\n",
|
||||||
|
classpath, expanded);
|
||||||
|
return expanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_WILDCARD
|
||||||
|
static void
|
||||||
|
wildcardExpandArgv(const char ***argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; (*argv)[i]; i++) {
|
||||||
|
if (equal((*argv)[i], "-cp") ||
|
||||||
|
equal((*argv)[i], "-classpath")) {
|
||||||
|
i++;
|
||||||
|
(*argv)[i] = wildcardExpandClasspath((*argv)[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
debugPrintArgv(char *argv[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
putchar('[');
|
||||||
|
for (i = 0; argv[i]; i++) {
|
||||||
|
if (i > 0) printf(", ");
|
||||||
|
printf("\"%s\"", argv[i]);
|
||||||
|
}
|
||||||
|
printf("]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
argv[0] = "java";
|
||||||
|
wildcardExpandArgv((const char***)&argv);
|
||||||
|
debugPrintArgv(argv);
|
||||||
|
/* execvp("java", argv); */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* DEBUG_WILDCARD */
|
||||||
|
|
||||||
|
/* Cute little perl prototype implementation....
|
||||||
|
|
||||||
|
my $sep = ($^O =~ /^(Windows|cygwin)/) ? ";" : ":";
|
||||||
|
|
||||||
|
sub expand($) {
|
||||||
|
opendir DIR, $_[0] or return $_[0];
|
||||||
|
join $sep, map {"$_[0]/$_"} grep {/\.(jar|JAR)$/} readdir DIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub munge($) {
|
||||||
|
join $sep,
|
||||||
|
map {(! -r $_ and s/[\/\\]+\*$//) ? expand $_ : $_} split $sep, $_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (my $i = 0; $i < @ARGV - 1; $i++) {
|
||||||
|
$ARGV[$i+1] = munge $ARGV[$i+1] if $ARGV[$i] =~ /^-c(p|lasspath)$/;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ENV{CLASSPATH} = munge $ENV{CLASSPATH} if exists $ENV{CLASSPATH};
|
||||||
|
@ARGV = ("java", @ARGV);
|
||||||
|
print "@ARGV\n";
|
||||||
|
exec @ARGV;
|
||||||
|
|
||||||
|
*/
|
34
hotspot/src/share/tools/launcher/wildcard.h
Normal file
34
hotspot/src/share/tools/launcher/wildcard.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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 WILDCARD_H_
|
||||||
|
#define WILDCARD_H_
|
||||||
|
|
||||||
|
#ifdef EXPAND_CLASSPATH_WILDCARDS
|
||||||
|
const char *JLI_WildcardExpandClasspath(const char *classpath);
|
||||||
|
#else
|
||||||
|
#define JLI_WildcardExpandClasspath(s) (s)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* include guard */
|
|
@ -26,6 +26,7 @@
|
||||||
#define SHARE_VM_CI_CICALLPROFILE_HPP
|
#define SHARE_VM_CI_CICALLPROFILE_HPP
|
||||||
|
|
||||||
#include "ci/ciClassList.hpp"
|
#include "ci/ciClassList.hpp"
|
||||||
|
#include "memory/allocation.hpp"
|
||||||
|
|
||||||
// ciCallProfile
|
// ciCallProfile
|
||||||
//
|
//
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#ifndef SHARE_VM_CI_CIMETHODHANDLE_HPP
|
#ifndef SHARE_VM_CI_CIMETHODHANDLE_HPP
|
||||||
#define SHARE_VM_CI_CIMETHODHANDLE_HPP
|
#define SHARE_VM_CI_CIMETHODHANDLE_HPP
|
||||||
|
|
||||||
|
#include "ci/ciInstance.hpp"
|
||||||
#include "prims/methodHandles.hpp"
|
#include "prims/methodHandles.hpp"
|
||||||
|
|
||||||
// ciMethodHandle
|
// ciMethodHandle
|
||||||
|
|
|
@ -48,7 +48,6 @@
|
||||||
#include "runtime/fprofiler.hpp"
|
#include "runtime/fprofiler.hpp"
|
||||||
#include "runtime/handles.hpp"
|
#include "runtime/handles.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/init.hpp"
|
#include "runtime/init.hpp"
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
|
@ -61,15 +60,12 @@
|
||||||
#include "utilities/hashtable.hpp"
|
#include "utilities/hashtable.hpp"
|
||||||
#include "utilities/hashtable.inline.hpp"
|
#include "utilities/hashtable.inline.hpp"
|
||||||
#ifdef TARGET_OS_FAMILY_linux
|
#ifdef TARGET_OS_FAMILY_linux
|
||||||
# include "hpi_linux.hpp"
|
|
||||||
# include "os_linux.inline.hpp"
|
# include "os_linux.inline.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_OS_FAMILY_solaris
|
#ifdef TARGET_OS_FAMILY_solaris
|
||||||
# include "hpi_solaris.hpp"
|
|
||||||
# include "os_solaris.inline.hpp"
|
# include "os_solaris.inline.hpp"
|
||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_OS_FAMILY_windows
|
#ifdef TARGET_OS_FAMILY_windows
|
||||||
# include "hpi_windows.hpp"
|
|
||||||
# include "os_windows.inline.hpp"
|
# include "os_windows.inline.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -208,13 +204,13 @@ ClassFileStream* ClassPathDirEntry::open_stream(const char* name) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (os::stat(path, &st) == 0) {
|
if (os::stat(path, &st) == 0) {
|
||||||
// found file, open it
|
// found file, open it
|
||||||
int file_handle = hpi::open(path, 0, 0);
|
int file_handle = os::open(path, 0, 0);
|
||||||
if (file_handle != -1) {
|
if (file_handle != -1) {
|
||||||
// read contents into resource array
|
// read contents into resource array
|
||||||
u1* buffer = NEW_RESOURCE_ARRAY(u1, st.st_size);
|
u1* buffer = NEW_RESOURCE_ARRAY(u1, st.st_size);
|
||||||
size_t num_read = os::read(file_handle, (char*) buffer, st.st_size);
|
size_t num_read = os::read(file_handle, (char*) buffer, st.st_size);
|
||||||
// close file
|
// close file
|
||||||
hpi::close(file_handle);
|
os::close(file_handle);
|
||||||
// construct ClassFileStream
|
// construct ClassFileStream
|
||||||
if (num_read == (size_t)st.st_size) {
|
if (num_read == (size_t)st.st_size) {
|
||||||
if (UsePerfData) {
|
if (UsePerfData) {
|
||||||
|
@ -607,18 +603,18 @@ void ClassLoader::load_zip_library() {
|
||||||
// Load zip library
|
// Load zip library
|
||||||
char path[JVM_MAXPATHLEN];
|
char path[JVM_MAXPATHLEN];
|
||||||
char ebuf[1024];
|
char ebuf[1024];
|
||||||
hpi::dll_build_name(path, sizeof(path), Arguments::get_dll_dir(), "zip");
|
os::dll_build_name(path, sizeof(path), Arguments::get_dll_dir(), "zip");
|
||||||
void* handle = hpi::dll_load(path, ebuf, sizeof ebuf);
|
void* handle = os::dll_load(path, ebuf, sizeof ebuf);
|
||||||
if (handle == NULL) {
|
if (handle == NULL) {
|
||||||
vm_exit_during_initialization("Unable to load ZIP library", path);
|
vm_exit_during_initialization("Unable to load ZIP library", path);
|
||||||
}
|
}
|
||||||
// Lookup zip entry points
|
// Lookup zip entry points
|
||||||
ZipOpen = CAST_TO_FN_PTR(ZipOpen_t, hpi::dll_lookup(handle, "ZIP_Open"));
|
ZipOpen = CAST_TO_FN_PTR(ZipOpen_t, os::dll_lookup(handle, "ZIP_Open"));
|
||||||
ZipClose = CAST_TO_FN_PTR(ZipClose_t, hpi::dll_lookup(handle, "ZIP_Close"));
|
ZipClose = CAST_TO_FN_PTR(ZipClose_t, os::dll_lookup(handle, "ZIP_Close"));
|
||||||
FindEntry = CAST_TO_FN_PTR(FindEntry_t, hpi::dll_lookup(handle, "ZIP_FindEntry"));
|
FindEntry = CAST_TO_FN_PTR(FindEntry_t, os::dll_lookup(handle, "ZIP_FindEntry"));
|
||||||
ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, hpi::dll_lookup(handle, "ZIP_ReadEntry"));
|
ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, os::dll_lookup(handle, "ZIP_ReadEntry"));
|
||||||
ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, hpi::dll_lookup(handle, "ZIP_ReadMappedEntry"));
|
ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, os::dll_lookup(handle, "ZIP_ReadMappedEntry"));
|
||||||
GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, hpi::dll_lookup(handle, "ZIP_GetNextEntry"));
|
GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry"));
|
||||||
|
|
||||||
// ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL
|
// ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL
|
||||||
if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || GetNextEntry == NULL) {
|
if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || GetNextEntry == NULL) {
|
||||||
|
@ -627,7 +623,7 @@ void ClassLoader::load_zip_library() {
|
||||||
|
|
||||||
// Lookup canonicalize entry in libjava.dll
|
// Lookup canonicalize entry in libjava.dll
|
||||||
void *javalib_handle = os::native_java_library();
|
void *javalib_handle = os::native_java_library();
|
||||||
CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, hpi::dll_lookup(javalib_handle, "Canonicalize"));
|
CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, os::dll_lookup(javalib_handle, "Canonicalize"));
|
||||||
// This lookup only works on 1.3. Do not check for non-null here
|
// This lookup only works on 1.3. Do not check for non-null here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1076,7 +1072,7 @@ bool ClassLoader::get_canonical_path(char* orig, char* out, int len) {
|
||||||
assert(orig != NULL && out != NULL && len > 0, "bad arguments");
|
assert(orig != NULL && out != NULL && len > 0, "bad arguments");
|
||||||
if (CanonicalizeEntry != NULL) {
|
if (CanonicalizeEntry != NULL) {
|
||||||
JNIEnv* env = JavaThread::current()->jni_environment();
|
JNIEnv* env = JavaThread::current()->jni_environment();
|
||||||
if ((CanonicalizeEntry)(env, hpi::native_path(orig), out, len) < 0) {
|
if ((CanonicalizeEntry)(env, os::native_path(orig), out, len) < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -182,7 +182,7 @@ Handle java_lang_String::create_from_platform_dependent_str(const char* str, TRA
|
||||||
|
|
||||||
if (_to_java_string_fn == NULL) {
|
if (_to_java_string_fn == NULL) {
|
||||||
void *lib_handle = os::native_java_library();
|
void *lib_handle = os::native_java_library();
|
||||||
_to_java_string_fn = CAST_TO_FN_PTR(to_java_string_fn_t, hpi::dll_lookup(lib_handle, "NewStringPlatform"));
|
_to_java_string_fn = CAST_TO_FN_PTR(to_java_string_fn_t, os::dll_lookup(lib_handle, "NewStringPlatform"));
|
||||||
if (_to_java_string_fn == NULL) {
|
if (_to_java_string_fn == NULL) {
|
||||||
fatal("NewStringPlatform missing");
|
fatal("NewStringPlatform missing");
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ char* java_lang_String::as_platform_dependent_str(Handle java_string, TRAPS) {
|
||||||
|
|
||||||
if (_to_platform_string_fn == NULL) {
|
if (_to_platform_string_fn == NULL) {
|
||||||
void *lib_handle = os::native_java_library();
|
void *lib_handle = os::native_java_library();
|
||||||
_to_platform_string_fn = CAST_TO_FN_PTR(to_platform_string_fn_t, hpi::dll_lookup(lib_handle, "GetStringPlatformChars"));
|
_to_platform_string_fn = CAST_TO_FN_PTR(to_platform_string_fn_t, os::dll_lookup(lib_handle, "GetStringPlatformChars"));
|
||||||
if (_to_platform_string_fn == NULL) {
|
if (_to_platform_string_fn == NULL) {
|
||||||
fatal("GetStringPlatformChars missing");
|
fatal("GetStringPlatformChars missing");
|
||||||
}
|
}
|
||||||
|
@ -313,6 +313,14 @@ char* java_lang_String::as_utf8_string(oop java_string) {
|
||||||
return UNICODE::as_utf8(position, length);
|
return UNICODE::as_utf8(position, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* java_lang_String::as_utf8_string(oop java_string, char* buf, int buflen) {
|
||||||
|
typeArrayOop value = java_lang_String::value(java_string);
|
||||||
|
int offset = java_lang_String::offset(java_string);
|
||||||
|
int length = java_lang_String::length(java_string);
|
||||||
|
jchar* position = (length == 0) ? NULL : value->char_at_addr(offset);
|
||||||
|
return UNICODE::as_utf8(position, length, buf, buflen);
|
||||||
|
}
|
||||||
|
|
||||||
char* java_lang_String::as_utf8_string(oop java_string, int start, int len) {
|
char* java_lang_String::as_utf8_string(oop java_string, int start, int len) {
|
||||||
typeArrayOop value = java_lang_String::value(java_string);
|
typeArrayOop value = java_lang_String::value(java_string);
|
||||||
int offset = java_lang_String::offset(java_string);
|
int offset = java_lang_String::offset(java_string);
|
||||||
|
|
|
@ -104,6 +104,7 @@ class java_lang_String : AllStatic {
|
||||||
|
|
||||||
// String converters
|
// String converters
|
||||||
static char* as_utf8_string(oop java_string);
|
static char* as_utf8_string(oop java_string);
|
||||||
|
static char* as_utf8_string(oop java_string, char* buf, int buflen);
|
||||||
static char* as_utf8_string(oop java_string, int start, int len);
|
static char* as_utf8_string(oop java_string, int start, int len);
|
||||||
static char* as_platform_dependent_str(Handle java_string, TRAPS);
|
static char* as_platform_dependent_str(Handle java_string, TRAPS);
|
||||||
static jchar* as_unicode_string(oop java_string, int& length);
|
static jchar* as_unicode_string(oop java_string, int& length);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#ifndef SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP
|
#ifndef SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP
|
||||||
#define SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP
|
#define SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP
|
||||||
|
|
||||||
|
#include "runtime/thread.hpp"
|
||||||
#include "utilities/hashtable.hpp"
|
#include "utilities/hashtable.hpp"
|
||||||
|
|
||||||
class PlaceholderEntry;
|
class PlaceholderEntry;
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include "prims/jvm.h"
|
#include "prims/jvm.h"
|
||||||
#include "runtime/fieldDescriptor.hpp"
|
#include "runtime/fieldDescriptor.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/javaCalls.hpp"
|
#include "runtime/javaCalls.hpp"
|
||||||
#include "runtime/orderAccess.hpp"
|
#include "runtime/orderAccess.hpp"
|
||||||
|
@ -69,11 +68,11 @@ static volatile jint _is_new_verify_byte_codes_fn = (jint) true;
|
||||||
static void* verify_byte_codes_fn() {
|
static void* verify_byte_codes_fn() {
|
||||||
if (_verify_byte_codes_fn == NULL) {
|
if (_verify_byte_codes_fn == NULL) {
|
||||||
void *lib_handle = os::native_java_library();
|
void *lib_handle = os::native_java_library();
|
||||||
void *func = hpi::dll_lookup(lib_handle, "VerifyClassCodesForMajorVersion");
|
void *func = os::dll_lookup(lib_handle, "VerifyClassCodesForMajorVersion");
|
||||||
OrderAccess::release_store_ptr(&_verify_byte_codes_fn, func);
|
OrderAccess::release_store_ptr(&_verify_byte_codes_fn, func);
|
||||||
if (func == NULL) {
|
if (func == NULL) {
|
||||||
OrderAccess::release_store(&_is_new_verify_byte_codes_fn, false);
|
OrderAccess::release_store(&_is_new_verify_byte_codes_fn, false);
|
||||||
func = hpi::dll_lookup(lib_handle, "VerifyClassCodes");
|
func = os::dll_lookup(lib_handle, "VerifyClassCodes");
|
||||||
OrderAccess::release_store_ptr(&_verify_byte_codes_fn, func);
|
OrderAccess::release_store_ptr(&_verify_byte_codes_fn, func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -619,8 +619,8 @@ nmethod::nmethod(
|
||||||
OopMapSet* oop_maps )
|
OopMapSet* oop_maps )
|
||||||
: CodeBlob("native nmethod", code_buffer, sizeof(nmethod),
|
: CodeBlob("native nmethod", code_buffer, sizeof(nmethod),
|
||||||
nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps),
|
nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps),
|
||||||
_compiled_synchronized_native_basic_lock_owner_sp_offset(basic_lock_owner_sp_offset),
|
_native_receiver_sp_offset(basic_lock_owner_sp_offset),
|
||||||
_compiled_synchronized_native_basic_lock_sp_offset(basic_lock_sp_offset)
|
_native_basic_lock_sp_offset(basic_lock_sp_offset)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
debug_only(No_Safepoint_Verifier nsv;)
|
debug_only(No_Safepoint_Verifier nsv;)
|
||||||
|
@ -696,8 +696,8 @@ nmethod::nmethod(
|
||||||
int frame_size)
|
int frame_size)
|
||||||
: CodeBlob("dtrace nmethod", code_buffer, sizeof(nmethod),
|
: CodeBlob("dtrace nmethod", code_buffer, sizeof(nmethod),
|
||||||
nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, NULL),
|
nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, NULL),
|
||||||
_compiled_synchronized_native_basic_lock_owner_sp_offset(in_ByteSize(-1)),
|
_native_receiver_sp_offset(in_ByteSize(-1)),
|
||||||
_compiled_synchronized_native_basic_lock_sp_offset(in_ByteSize(-1))
|
_native_basic_lock_sp_offset(in_ByteSize(-1))
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
debug_only(No_Safepoint_Verifier nsv;)
|
debug_only(No_Safepoint_Verifier nsv;)
|
||||||
|
@ -790,8 +790,8 @@ nmethod::nmethod(
|
||||||
)
|
)
|
||||||
: CodeBlob("nmethod", code_buffer, sizeof(nmethod),
|
: CodeBlob("nmethod", code_buffer, sizeof(nmethod),
|
||||||
nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps),
|
nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, oop_maps),
|
||||||
_compiled_synchronized_native_basic_lock_owner_sp_offset(in_ByteSize(-1)),
|
_native_receiver_sp_offset(in_ByteSize(-1)),
|
||||||
_compiled_synchronized_native_basic_lock_sp_offset(in_ByteSize(-1))
|
_native_basic_lock_sp_offset(in_ByteSize(-1))
|
||||||
{
|
{
|
||||||
assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR");
|
assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR");
|
||||||
{
|
{
|
||||||
|
|
|
@ -210,7 +210,7 @@ class nmethod : public CodeBlob {
|
||||||
ExceptionCache *_exception_cache;
|
ExceptionCache *_exception_cache;
|
||||||
PcDescCache _pc_desc_cache;
|
PcDescCache _pc_desc_cache;
|
||||||
|
|
||||||
// These are only used for compiled synchronized native methods to
|
// These are used for compiled synchronized native methods to
|
||||||
// locate the owner and stack slot for the BasicLock so that we can
|
// locate the owner and stack slot for the BasicLock so that we can
|
||||||
// properly revoke the bias of the owner if necessary. They are
|
// properly revoke the bias of the owner if necessary. They are
|
||||||
// needed because there is no debug information for compiled native
|
// needed because there is no debug information for compiled native
|
||||||
|
@ -220,8 +220,10 @@ class nmethod : public CodeBlob {
|
||||||
// sharing between platforms. Note that currently biased locking
|
// sharing between platforms. Note that currently biased locking
|
||||||
// will never cause Class instances to be biased but this code
|
// will never cause Class instances to be biased but this code
|
||||||
// handles the static synchronized case as well.
|
// handles the static synchronized case as well.
|
||||||
ByteSize _compiled_synchronized_native_basic_lock_owner_sp_offset;
|
// JVMTI's GetLocalInstance() also uses these offsets to find the receiver
|
||||||
ByteSize _compiled_synchronized_native_basic_lock_sp_offset;
|
// for non-static native wrapper frames.
|
||||||
|
ByteSize _native_receiver_sp_offset;
|
||||||
|
ByteSize _native_basic_lock_sp_offset;
|
||||||
|
|
||||||
friend class nmethodLocker;
|
friend class nmethodLocker;
|
||||||
|
|
||||||
|
@ -676,11 +678,11 @@ public:
|
||||||
bool is_patchable_at(address instr_address);
|
bool is_patchable_at(address instr_address);
|
||||||
|
|
||||||
// UseBiasedLocking support
|
// UseBiasedLocking support
|
||||||
ByteSize compiled_synchronized_native_basic_lock_owner_sp_offset() {
|
ByteSize native_receiver_sp_offset() {
|
||||||
return _compiled_synchronized_native_basic_lock_owner_sp_offset;
|
return _native_receiver_sp_offset;
|
||||||
}
|
}
|
||||||
ByteSize compiled_synchronized_native_basic_lock_sp_offset() {
|
ByteSize native_basic_lock_sp_offset() {
|
||||||
return _compiled_synchronized_native_basic_lock_sp_offset;
|
return _native_basic_lock_sp_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// support for code generation
|
// support for code generation
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#ifndef SHARE_VM_CODE_VTABLESTUBS_HPP
|
#ifndef SHARE_VM_CODE_VTABLESTUBS_HPP
|
||||||
#define SHARE_VM_CODE_VTABLESTUBS_HPP
|
#define SHARE_VM_CODE_VTABLESTUBS_HPP
|
||||||
|
|
||||||
|
#include "code/vmreg.hpp"
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
|
|
||||||
// A VtableStub holds an individual code stub for a pair (vtable index, #args) for either itables or vtables
|
// A VtableStub holds an individual code stub for a pair (vtable index, #args) for either itables or vtables
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include "memory/cardTableModRefBS.hpp"
|
#include "memory/cardTableModRefBS.hpp"
|
||||||
#include "runtime/fprofiler.hpp"
|
#include "runtime/fprofiler.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/stubCodeGenerator.hpp"
|
#include "runtime/stubCodeGenerator.hpp"
|
||||||
#include "runtime/stubRoutines.hpp"
|
#include "runtime/stubRoutines.hpp"
|
||||||
#ifdef TARGET_ARCH_x86
|
#ifdef TARGET_ARCH_x86
|
||||||
|
@ -84,17 +83,17 @@ bool Disassembler::load_library() {
|
||||||
// Find the disassembler next to libjvm.so.
|
// Find the disassembler next to libjvm.so.
|
||||||
strcpy(&buf[jvm_offset], hsdis_library_name);
|
strcpy(&buf[jvm_offset], hsdis_library_name);
|
||||||
strcat(&buf[jvm_offset], os::dll_file_extension());
|
strcat(&buf[jvm_offset], os::dll_file_extension());
|
||||||
_library = hpi::dll_load(buf, ebuf, sizeof ebuf);
|
_library = os::dll_load(buf, ebuf, sizeof ebuf);
|
||||||
}
|
}
|
||||||
if (_library == NULL) {
|
if (_library == NULL) {
|
||||||
// Try a free-floating lookup.
|
// Try a free-floating lookup.
|
||||||
strcpy(&buf[0], hsdis_library_name);
|
strcpy(&buf[0], hsdis_library_name);
|
||||||
strcat(&buf[0], os::dll_file_extension());
|
strcat(&buf[0], os::dll_file_extension());
|
||||||
_library = hpi::dll_load(buf, ebuf, sizeof ebuf);
|
_library = os::dll_load(buf, ebuf, sizeof ebuf);
|
||||||
}
|
}
|
||||||
if (_library != NULL) {
|
if (_library != NULL) {
|
||||||
_decode_instructions = CAST_TO_FN_PTR(Disassembler::decode_func,
|
_decode_instructions = CAST_TO_FN_PTR(Disassembler::decode_func,
|
||||||
hpi::dll_lookup(_library, decode_instructions_name));
|
os::dll_lookup(_library, decode_instructions_name));
|
||||||
}
|
}
|
||||||
_tried_to_load_library = true;
|
_tried_to_load_library = true;
|
||||||
if (_decode_instructions == NULL) {
|
if (_decode_instructions == NULL) {
|
||||||
|
|
|
@ -1051,6 +1051,7 @@ public:
|
||||||
void work(int worker_i) {
|
void work(int worker_i) {
|
||||||
assert(Thread::current()->is_ConcurrentGC_thread(),
|
assert(Thread::current()->is_ConcurrentGC_thread(),
|
||||||
"this should only be done by a conc GC thread");
|
"this should only be done by a conc GC thread");
|
||||||
|
ResourceMark rm;
|
||||||
|
|
||||||
double start_vtime = os::elapsedVTime();
|
double start_vtime = os::elapsedVTime();
|
||||||
|
|
||||||
|
@ -1888,6 +1889,9 @@ void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
|
||||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||||
ReferenceProcessor* rp = g1h->ref_processor();
|
ReferenceProcessor* rp = g1h->ref_processor();
|
||||||
|
|
||||||
|
// See the comment in G1CollectedHeap::ref_processing_init()
|
||||||
|
// about how reference processing currently works in G1.
|
||||||
|
|
||||||
// Process weak references.
|
// Process weak references.
|
||||||
rp->setup_policy(clear_all_soft_refs);
|
rp->setup_policy(clear_all_soft_refs);
|
||||||
assert(_markStack.isEmpty(), "mark stack should be empty");
|
assert(_markStack.isEmpty(), "mark stack should be empty");
|
||||||
|
@ -2918,7 +2922,11 @@ public:
|
||||||
CMOopClosure(G1CollectedHeap* g1h,
|
CMOopClosure(G1CollectedHeap* g1h,
|
||||||
ConcurrentMark* cm,
|
ConcurrentMark* cm,
|
||||||
CMTask* task)
|
CMTask* task)
|
||||||
: _g1h(g1h), _cm(cm), _task(task) { }
|
: _g1h(g1h), _cm(cm), _task(task)
|
||||||
|
{
|
||||||
|
_ref_processor = g1h->ref_processor();
|
||||||
|
assert(_ref_processor != NULL, "should not be NULL");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void CMTask::setup_for_region(HeapRegion* hr) {
|
void CMTask::setup_for_region(HeapRegion* hr) {
|
||||||
|
|
|
@ -58,10 +58,11 @@ size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0;
|
||||||
// INVARIANTS/NOTES
|
// INVARIANTS/NOTES
|
||||||
//
|
//
|
||||||
// All allocation activity covered by the G1CollectedHeap interface is
|
// All allocation activity covered by the G1CollectedHeap interface is
|
||||||
// serialized by acquiring the HeapLock. This happens in
|
// serialized by acquiring the HeapLock. This happens in mem_allocate
|
||||||
// mem_allocate_work, which all such allocation functions call.
|
// and allocate_new_tlab, which are the "entry" points to the
|
||||||
// (Note that this does not apply to TLAB allocation, which is not part
|
// allocation code from the rest of the JVM. (Note that this does not
|
||||||
// of this interface: it is done by clients of this interface.)
|
// apply to TLAB allocation, which is not part of this interface: it
|
||||||
|
// is done by clients of this interface.)
|
||||||
|
|
||||||
// Local to this file.
|
// Local to this file.
|
||||||
|
|
||||||
|
@ -536,15 +537,17 @@ HeapRegion* G1CollectedHeap::newAllocRegionWithExpansion(int purpose,
|
||||||
// If could fit into free regions w/o expansion, try.
|
// If could fit into free regions w/o expansion, try.
|
||||||
// Otherwise, if can expand, do so.
|
// Otherwise, if can expand, do so.
|
||||||
// Otherwise, if using ex regions might help, try with ex given back.
|
// Otherwise, if using ex regions might help, try with ex given back.
|
||||||
HeapWord* G1CollectedHeap::humongousObjAllocate(size_t word_size) {
|
HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size) {
|
||||||
|
assert_heap_locked_or_at_safepoint();
|
||||||
assert(regions_accounted_for(), "Region leakage!");
|
assert(regions_accounted_for(), "Region leakage!");
|
||||||
|
|
||||||
// We can't allocate H regions while cleanupComplete is running, since
|
// We can't allocate humongous regions while cleanupComplete is
|
||||||
// some of the regions we find to be empty might not yet be added to the
|
// running, since some of the regions we find to be empty might not
|
||||||
// unclean list. (If we're already at a safepoint, this call is
|
// yet be added to the unclean list. If we're already at a
|
||||||
// unnecessary, not to mention wrong.)
|
// safepoint, this call is unnecessary, not to mention wrong.
|
||||||
if (!SafepointSynchronize::is_at_safepoint())
|
if (!SafepointSynchronize::is_at_safepoint()) {
|
||||||
wait_for_cleanup_complete();
|
wait_for_cleanup_complete();
|
||||||
|
}
|
||||||
|
|
||||||
size_t num_regions =
|
size_t num_regions =
|
||||||
round_to(word_size, HeapRegion::GrainWords) / HeapRegion::GrainWords;
|
round_to(word_size, HeapRegion::GrainWords) / HeapRegion::GrainWords;
|
||||||
|
@ -598,106 +601,391 @@ HeapWord* G1CollectedHeap::humongousObjAllocate(size_t word_size) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
G1CollectedHeap::retire_cur_alloc_region(HeapRegion* cur_alloc_region) {
|
||||||
|
// The cleanup operation might update _summary_bytes_used
|
||||||
|
// concurrently with this method. So, right now, if we don't wait
|
||||||
|
// for it to complete, updates to _summary_bytes_used might get
|
||||||
|
// lost. This will be resolved in the near future when the operation
|
||||||
|
// of the free region list is revamped as part of CR 6977804.
|
||||||
|
wait_for_cleanup_complete();
|
||||||
|
|
||||||
|
retire_cur_alloc_region_common(cur_alloc_region);
|
||||||
|
assert(_cur_alloc_region == NULL, "post-condition");
|
||||||
|
}
|
||||||
|
|
||||||
|
// See the comment in the .hpp file about the locking protocol and
|
||||||
|
// assumptions of this method (and other related ones).
|
||||||
HeapWord*
|
HeapWord*
|
||||||
G1CollectedHeap::attempt_allocation_slow(size_t word_size,
|
G1CollectedHeap::replace_cur_alloc_region_and_allocate(size_t word_size,
|
||||||
bool permit_collection_pause) {
|
bool at_safepoint,
|
||||||
HeapWord* res = NULL;
|
bool do_dirtying) {
|
||||||
HeapRegion* allocated_young_region = NULL;
|
assert_heap_locked_or_at_safepoint();
|
||||||
|
assert(_cur_alloc_region == NULL,
|
||||||
|
"replace_cur_alloc_region_and_allocate() should only be called "
|
||||||
|
"after retiring the previous current alloc region");
|
||||||
|
assert(SafepointSynchronize::is_at_safepoint() == at_safepoint,
|
||||||
|
"at_safepoint and is_at_safepoint() should be a tautology");
|
||||||
|
|
||||||
assert( SafepointSynchronize::is_at_safepoint() ||
|
if (!g1_policy()->is_young_list_full()) {
|
||||||
Heap_lock->owned_by_self(), "pre condition of the call" );
|
if (!at_safepoint) {
|
||||||
|
// The cleanup operation might update _summary_bytes_used
|
||||||
if (isHumongous(word_size)) {
|
// concurrently with this method. So, right now, if we don't
|
||||||
// Allocation of a humongous object can, in a sense, complete a
|
// wait for it to complete, updates to _summary_bytes_used might
|
||||||
// partial region, if the previous alloc was also humongous, and
|
// get lost. This will be resolved in the near future when the
|
||||||
// caused the test below to succeed.
|
// operation of the free region list is revamped as part of
|
||||||
if (permit_collection_pause)
|
// CR 6977804. If we're already at a safepoint, this call is
|
||||||
do_collection_pause_if_appropriate(word_size);
|
// unnecessary, not to mention wrong.
|
||||||
res = humongousObjAllocate(word_size);
|
|
||||||
assert(_cur_alloc_region == NULL
|
|
||||||
|| !_cur_alloc_region->isHumongous(),
|
|
||||||
"Prevent a regression of this bug.");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// We may have concurrent cleanup working at the time. Wait for it
|
|
||||||
// to complete. In the future we would probably want to make the
|
|
||||||
// concurrent cleanup truly concurrent by decoupling it from the
|
|
||||||
// allocation.
|
|
||||||
if (!SafepointSynchronize::is_at_safepoint())
|
|
||||||
wait_for_cleanup_complete();
|
wait_for_cleanup_complete();
|
||||||
// If we do a collection pause, this will be reset to a non-NULL
|
|
||||||
// value. If we don't, nulling here ensures that we allocate a new
|
|
||||||
// region below.
|
|
||||||
if (_cur_alloc_region != NULL) {
|
|
||||||
// We're finished with the _cur_alloc_region.
|
|
||||||
// As we're builing (at least the young portion) of the collection
|
|
||||||
// set incrementally we'll add the current allocation region to
|
|
||||||
// the collection set here.
|
|
||||||
if (_cur_alloc_region->is_young()) {
|
|
||||||
g1_policy()->add_region_to_incremental_cset_lhs(_cur_alloc_region);
|
|
||||||
}
|
}
|
||||||
_summary_bytes_used += _cur_alloc_region->used();
|
|
||||||
_cur_alloc_region = NULL;
|
|
||||||
}
|
|
||||||
assert(_cur_alloc_region == NULL, "Invariant.");
|
|
||||||
// Completion of a heap region is perhaps a good point at which to do
|
|
||||||
// a collection pause.
|
|
||||||
if (permit_collection_pause)
|
|
||||||
do_collection_pause_if_appropriate(word_size);
|
|
||||||
// Make sure we have an allocation region available.
|
|
||||||
if (_cur_alloc_region == NULL) {
|
|
||||||
if (!SafepointSynchronize::is_at_safepoint())
|
|
||||||
wait_for_cleanup_complete();
|
|
||||||
bool next_is_young = should_set_young_locked();
|
|
||||||
// If the next region is not young, make sure it's zero-filled.
|
|
||||||
_cur_alloc_region = newAllocRegion(word_size, !next_is_young);
|
|
||||||
if (_cur_alloc_region != NULL) {
|
|
||||||
_summary_bytes_used -= _cur_alloc_region->used();
|
|
||||||
if (next_is_young) {
|
|
||||||
set_region_short_lived_locked(_cur_alloc_region);
|
|
||||||
allocated_young_region = _cur_alloc_region;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(_cur_alloc_region == NULL || !_cur_alloc_region->isHumongous(),
|
|
||||||
"Prevent a regression of this bug.");
|
|
||||||
|
|
||||||
// Now retry the allocation.
|
HeapRegion* new_cur_alloc_region = newAllocRegion(word_size,
|
||||||
if (_cur_alloc_region != NULL) {
|
false /* zero_filled */);
|
||||||
if (allocated_young_region != NULL) {
|
if (new_cur_alloc_region != NULL) {
|
||||||
// We need to ensure that the store to top does not
|
assert(new_cur_alloc_region->is_empty(),
|
||||||
// float above the setting of the young type.
|
"the newly-allocated region should be empty, "
|
||||||
|
"as right now we only allocate new regions out of the free list");
|
||||||
|
g1_policy()->update_region_num(true /* next_is_young */);
|
||||||
|
_summary_bytes_used -= new_cur_alloc_region->used();
|
||||||
|
set_region_short_lived_locked(new_cur_alloc_region);
|
||||||
|
|
||||||
|
assert(!new_cur_alloc_region->isHumongous(),
|
||||||
|
"Catch a regression of this bug.");
|
||||||
|
|
||||||
|
// We need to ensure that the stores to _cur_alloc_region and,
|
||||||
|
// subsequently, to top do not float above the setting of the
|
||||||
|
// young type.
|
||||||
OrderAccess::storestore();
|
OrderAccess::storestore();
|
||||||
}
|
|
||||||
res = _cur_alloc_region->allocate(word_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: fails frequently in PRT
|
// Now allocate out of the new current alloc region. We could
|
||||||
assert(regions_accounted_for(), "Region leakage!");
|
// 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);
|
||||||
|
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");
|
||||||
|
|
||||||
if (res != NULL) {
|
_cur_alloc_region = new_cur_alloc_region;
|
||||||
if (!SafepointSynchronize::is_at_safepoint()) {
|
|
||||||
assert( permit_collection_pause, "invariant" );
|
if (!at_safepoint) {
|
||||||
assert( Heap_lock->owned_by_self(), "invariant" );
|
|
||||||
Heap_lock->unlock();
|
Heap_lock->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allocated_young_region != NULL) {
|
// do the dirtying, if necessary, after we release the Heap_lock
|
||||||
HeapRegion* hr = allocated_young_region;
|
if (do_dirtying) {
|
||||||
HeapWord* bottom = hr->bottom();
|
dirty_young_block(result, word_size);
|
||||||
HeapWord* end = hr->end();
|
}
|
||||||
MemRegion mr(bottom, end);
|
return result;
|
||||||
((CardTableModRefBS*)_g1h->barrier_set())->dirty(mr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( SafepointSynchronize::is_at_safepoint() ||
|
assert(_cur_alloc_region == NULL, "we failed to allocate a new current "
|
||||||
(res == NULL && Heap_lock->owned_by_self()) ||
|
"alloc region, it should still be NULL");
|
||||||
(res != NULL && !Heap_lock->owned_by_self()),
|
assert_heap_locked_or_at_safepoint();
|
||||||
"post condition of the call" );
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
// See the comment in the .hpp file about the locking protocol and
|
||||||
|
// assumptions of this method (and other related ones).
|
||||||
|
HeapWord*
|
||||||
|
G1CollectedHeap::attempt_allocation_slow(size_t word_size) {
|
||||||
|
assert_heap_locked_and_not_at_safepoint();
|
||||||
|
assert(!isHumongous(word_size), "attempt_allocation_slow() should not be "
|
||||||
|
"used for humongous allocations");
|
||||||
|
|
||||||
|
// We will loop while succeeded is false, which means that we tried
|
||||||
|
// to do a collection, but the VM op did not succeed. So, when we
|
||||||
|
// exit the loop, either one of the allocation attempts was
|
||||||
|
// successful, or we succeeded in doing the VM op but which was
|
||||||
|
// unable to allocate after the collection.
|
||||||
|
for (int try_count = 1; /* we'll return or break */; try_count += 1) {
|
||||||
|
bool succeeded = true;
|
||||||
|
|
||||||
|
{
|
||||||
|
// We may have concurrent cleanup working at the time. Wait for
|
||||||
|
// it to complete. In the future we would probably want to make
|
||||||
|
// the concurrent cleanup truly concurrent by decoupling it from
|
||||||
|
// the allocation. This will happen in the near future as part
|
||||||
|
// of CR 6977804 which will revamp the operation of the free
|
||||||
|
// region list. The fact that wait_for_cleanup_complete() will
|
||||||
|
// do a wait() means that we'll give up the Heap_lock. So, it's
|
||||||
|
// possible that when we exit wait_for_cleanup_complete() we
|
||||||
|
// might be able to allocate successfully (since somebody else
|
||||||
|
// might have done a collection meanwhile). So, we'll attempt to
|
||||||
|
// allocate again, just in case. When we make cleanup truly
|
||||||
|
// concurrent with allocation, we should remove this allocation
|
||||||
|
// 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);
|
||||||
|
if (result != NULL) {
|
||||||
|
assert_heap_not_locked();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GC_locker::is_active_and_needs_gc()) {
|
||||||
|
// We are locked out of GC because of the GC locker. Right now,
|
||||||
|
// we'll just stall until the GC locker-induced GC
|
||||||
|
// completes. This will be fixed in the near future by extending
|
||||||
|
// the eden while waiting for the GC locker to schedule the GC
|
||||||
|
// (see CR 6994056).
|
||||||
|
|
||||||
|
// If this thread is not in a jni critical section, we stall
|
||||||
|
// the requestor until the critical section has cleared and
|
||||||
|
// GC allowed. When the critical section clears, a GC is
|
||||||
|
// initiated by the last thread exiting the critical section; so
|
||||||
|
// we retry the allocation sequence from the beginning of the loop,
|
||||||
|
// 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 (CheckJNICalls) {
|
||||||
|
fatal("Possible deadlock due to allocating while"
|
||||||
|
" in jni critical section");
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We are not locked out. So, let's try to do a GC. The VM op
|
||||||
|
// will retry the allocation before it completes.
|
||||||
|
|
||||||
|
// Read the GC count while holding the Heap_lock
|
||||||
|
unsigned int gc_count_before = SharedHeap::heap()->total_collections();
|
||||||
|
|
||||||
|
Heap_lock->unlock();
|
||||||
|
|
||||||
|
HeapWord* result =
|
||||||
|
do_collection_pause(word_size, gc_count_before, &succeeded);
|
||||||
|
assert_heap_not_locked();
|
||||||
|
if (result != NULL) {
|
||||||
|
assert(succeeded, "the VM op should have succeeded");
|
||||||
|
|
||||||
|
// Allocations that take place on VM operations do not do any
|
||||||
|
// card dirtying and we have to do it here.
|
||||||
|
dirty_young_block(result, word_size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Heap_lock->lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_heap_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
|
||||||
|
// out of GC due to the GC locker. In either case a new alloc
|
||||||
|
// region might be available so we will retry the allocation.
|
||||||
|
HeapWord* result = attempt_allocation(word_size);
|
||||||
|
if (result != NULL) {
|
||||||
|
assert_heap_not_locked();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// So far our attempts to allocate failed. The only time we'll go
|
||||||
|
// around the loop and try again is if we tried to do a GC and the
|
||||||
|
// VM op that we tried to schedule was not successful because
|
||||||
|
// another thread beat us to it. If that happened it's possible
|
||||||
|
// that by the time we grabbed the Heap_lock again and tried to
|
||||||
|
// allocate other threads filled up the young generation, which
|
||||||
|
// means that the allocation attempt after the GC also failed. So,
|
||||||
|
// it's worth trying to schedule another GC pause.
|
||||||
|
if (succeeded) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give a warning if we seem to be looping forever.
|
||||||
|
if ((QueuedAllocationWarningCount > 0) &&
|
||||||
|
(try_count % QueuedAllocationWarningCount == 0)) {
|
||||||
|
warning("G1CollectedHeap::attempt_allocation_slow() "
|
||||||
|
"retries %d times", try_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_heap_locked();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See the comment in the .hpp file about the locking protocol and
|
||||||
|
// assumptions of this method (and other related ones).
|
||||||
|
HeapWord*
|
||||||
|
G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
|
||||||
|
bool at_safepoint) {
|
||||||
|
// This is the method that will allocate a humongous object. All
|
||||||
|
// allocation paths that attempt to allocate a humongous object
|
||||||
|
// should eventually reach here. Currently, the only paths are from
|
||||||
|
// mem_allocate() and attempt_allocation_at_safepoint().
|
||||||
|
assert_heap_locked_or_at_safepoint();
|
||||||
|
assert(isHumongous(word_size), "attempt_allocation_humongous() "
|
||||||
|
"should only be used for humongous allocations");
|
||||||
|
assert(SafepointSynchronize::is_at_safepoint() == at_safepoint,
|
||||||
|
"at_safepoint and is_at_safepoint() should be a tautology");
|
||||||
|
|
||||||
|
HeapWord* result = NULL;
|
||||||
|
|
||||||
|
// We will loop while succeeded is false, which means that we tried
|
||||||
|
// to do a collection, but the VM op did not succeed. So, when we
|
||||||
|
// exit the loop, either one of the allocation attempts was
|
||||||
|
// successful, or we succeeded in doing the VM op but which was
|
||||||
|
// unable to allocate after the collection.
|
||||||
|
for (int try_count = 1; /* we'll return or break */; try_count += 1) {
|
||||||
|
bool succeeded = true;
|
||||||
|
|
||||||
|
// Given that humongous objects are not allocated in young
|
||||||
|
// regions, we'll first try to do the allocation without doing a
|
||||||
|
// collection hoping that there's enough space in the heap.
|
||||||
|
result = humongous_obj_allocate(word_size);
|
||||||
|
assert(_cur_alloc_region == NULL || !_cur_alloc_region->isHumongous(),
|
||||||
|
"catch a regression of this bug.");
|
||||||
|
if (result != NULL) {
|
||||||
|
if (!at_safepoint) {
|
||||||
|
// If we're not at a safepoint, unlock the Heap_lock.
|
||||||
|
Heap_lock->unlock();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we failed to allocate the humongous object, we should try to
|
||||||
|
// do a collection pause (if we're allowed) in case it reclaims
|
||||||
|
// enough space for the allocation to succeed after the pause.
|
||||||
|
if (!at_safepoint) {
|
||||||
|
// Read the GC count while holding the Heap_lock
|
||||||
|
unsigned int gc_count_before = SharedHeap::heap()->total_collections();
|
||||||
|
|
||||||
|
// If we're allowed to do a collection we're not at a
|
||||||
|
// safepoint, so it is safe to unlock the Heap_lock.
|
||||||
|
Heap_lock->unlock();
|
||||||
|
|
||||||
|
result = do_collection_pause(word_size, gc_count_before, &succeeded);
|
||||||
|
assert_heap_not_locked();
|
||||||
|
if (result != NULL) {
|
||||||
|
assert(succeeded, "the VM op should have succeeded");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, the VM operation either did not succeed
|
||||||
|
// (i.e., another thread beat us to it) or it succeeded but
|
||||||
|
// failed to allocate the object.
|
||||||
|
|
||||||
|
// If we're allowed to do a collection we're not at a
|
||||||
|
// safepoint, so it is safe to lock the Heap_lock.
|
||||||
|
Heap_lock->lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(result == NULL, "otherwise we should have exited the loop earlier");
|
||||||
|
|
||||||
|
// So far our attempts to allocate failed. The only time we'll go
|
||||||
|
// around the loop and try again is if we tried to do a GC and the
|
||||||
|
// VM op that we tried to schedule was not successful because
|
||||||
|
// another thread beat us to it. That way it's possible that some
|
||||||
|
// space was freed up by the thread that successfully scheduled a
|
||||||
|
// GC. So it's worth trying to allocate again.
|
||||||
|
if (succeeded) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give a warning if we seem to be looping forever.
|
||||||
|
if ((QueuedAllocationWarningCount > 0) &&
|
||||||
|
(try_count % QueuedAllocationWarningCount == 0)) {
|
||||||
|
warning("G1CollectedHeap::attempt_allocation_humongous "
|
||||||
|
"retries %d times", try_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_heap_locked_or_at_safepoint();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapWord* G1CollectedHeap::attempt_allocation_at_safepoint(size_t word_size,
|
||||||
|
bool expect_null_cur_alloc_region) {
|
||||||
|
assert_at_safepoint();
|
||||||
|
assert(_cur_alloc_region == NULL || !expect_null_cur_alloc_region,
|
||||||
|
err_msg("the current alloc region was unexpectedly found "
|
||||||
|
"to be non-NULL, cur alloc region: "PTR_FORMAT" "
|
||||||
|
"expect_null_cur_alloc_region: %d word_size: "SIZE_FORMAT,
|
||||||
|
_cur_alloc_region, expect_null_cur_alloc_region, word_size));
|
||||||
|
|
||||||
|
if (!isHumongous(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);
|
||||||
|
if (result != NULL) {
|
||||||
|
assert(is_in(result), "result should be in the heap");
|
||||||
|
|
||||||
|
// We will not do any dirtying here. This is guaranteed to be
|
||||||
|
// called during a safepoint and the thread that scheduled the
|
||||||
|
// pause will do the dirtying if we return a non-NULL result.
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
retire_cur_alloc_region_common(cur_alloc_region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(_cur_alloc_region == NULL,
|
||||||
|
"at this point we should have no cur alloc region");
|
||||||
|
return replace_cur_alloc_region_and_allocate(word_size,
|
||||||
|
true, /* at_safepoint */
|
||||||
|
false /* do_dirtying */);
|
||||||
|
} else {
|
||||||
|
return attempt_allocation_humongous(word_size,
|
||||||
|
true /* at_safepoint */);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
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.
|
||||||
|
result = attempt_allocation_slow(word_size);
|
||||||
|
if (result != NULL) {
|
||||||
|
assert_heap_not_locked();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_heap_locked();
|
||||||
|
Heap_lock->unlock();
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapWord*
|
HeapWord*
|
||||||
|
@ -705,46 +993,82 @@ G1CollectedHeap::mem_allocate(size_t word_size,
|
||||||
bool is_noref,
|
bool is_noref,
|
||||||
bool is_tlab,
|
bool is_tlab,
|
||||||
bool* gc_overhead_limit_was_exceeded) {
|
bool* gc_overhead_limit_was_exceeded) {
|
||||||
debug_only(check_for_valid_allocation_state());
|
assert_heap_not_locked_and_not_at_safepoint();
|
||||||
assert(no_gc_in_progress(), "Allocation during gc not allowed");
|
assert(!is_tlab, "mem_allocate() this should not be called directly "
|
||||||
HeapWord* result = NULL;
|
"to allocate TLABs");
|
||||||
|
|
||||||
// Loop until the allocation is satisified,
|
// Loop until the allocation is satisified,
|
||||||
// or unsatisfied after GC.
|
// or unsatisfied after GC.
|
||||||
for (int try_count = 1; /* return or throw */; try_count += 1) {
|
for (int try_count = 1; /* we'll return */; try_count += 1) {
|
||||||
int gc_count_before;
|
unsigned int gc_count_before;
|
||||||
{
|
{
|
||||||
Heap_lock->lock();
|
Heap_lock->lock();
|
||||||
result = attempt_allocation(word_size);
|
|
||||||
|
if (!isHumongous(word_size)) {
|
||||||
|
// First attempt: try allocating out of the current alloc
|
||||||
|
// region or after replacing the current alloc region.
|
||||||
|
HeapWord* result = attempt_allocation(word_size);
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
// attempt_allocation should have unlocked the heap lock
|
assert_heap_not_locked();
|
||||||
assert(is_in(result), "result not in heap");
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert_heap_locked();
|
||||||
|
|
||||||
|
// Second attempt: go into the even 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 {
|
||||||
|
HeapWord* result = attempt_allocation_humongous(word_size,
|
||||||
|
false /* at_safepoint */);
|
||||||
|
if (result != NULL) {
|
||||||
|
assert_heap_not_locked();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_heap_locked();
|
||||||
// Read the gc count while the heap lock is held.
|
// Read the gc count while the heap lock is held.
|
||||||
gc_count_before = SharedHeap::heap()->total_collections();
|
gc_count_before = SharedHeap::heap()->total_collections();
|
||||||
|
// We cannot be at a safepoint, so it is safe to unlock the Heap_lock
|
||||||
Heap_lock->unlock();
|
Heap_lock->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the garbage collection operation...
|
// Create the garbage collection operation...
|
||||||
VM_G1CollectForAllocation op(word_size,
|
VM_G1CollectForAllocation op(gc_count_before, word_size);
|
||||||
gc_count_before);
|
|
||||||
|
|
||||||
// ...and get the VM thread to execute it.
|
// ...and get the VM thread to execute it.
|
||||||
VMThread::execute(&op);
|
VMThread::execute(&op);
|
||||||
if (op.prologue_succeeded()) {
|
|
||||||
result = op.result();
|
assert_heap_not_locked();
|
||||||
assert(result == NULL || is_in(result), "result not in heap");
|
if (op.prologue_succeeded() && op.pause_succeeded()) {
|
||||||
|
// If the operation was successful we'll return the result even
|
||||||
|
// if it is NULL. If the allocation attempt failed immediately
|
||||||
|
// after a Full GC, it's unlikely we'll be able to allocate now.
|
||||||
|
HeapWord* result = op.result();
|
||||||
|
if (result != NULL && !isHumongous(word_size)) {
|
||||||
|
// Allocations that take place on VM operations do not do any
|
||||||
|
// card dirtying and we have to do it here. We only have to do
|
||||||
|
// this for non-humongous allocations, though.
|
||||||
|
dirty_young_block(result, word_size);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
|
} else {
|
||||||
|
assert(op.result() == NULL,
|
||||||
|
"the result should be NULL if the VM op did not succeed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give a warning if we seem to be looping forever.
|
// Give a warning if we seem to be looping forever.
|
||||||
if ((QueuedAllocationWarningCount > 0) &&
|
if ((QueuedAllocationWarningCount > 0) &&
|
||||||
(try_count % QueuedAllocationWarningCount == 0)) {
|
(try_count % QueuedAllocationWarningCount == 0)) {
|
||||||
warning("G1CollectedHeap::mem_allocate_work retries %d times",
|
warning("G1CollectedHeap::mem_allocate retries %d times", try_count);
|
||||||
try_count);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectedHeap::abandon_cur_alloc_region() {
|
void G1CollectedHeap::abandon_cur_alloc_region() {
|
||||||
|
@ -841,11 +1165,11 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void G1CollectedHeap::do_collection(bool explicit_gc,
|
bool G1CollectedHeap::do_collection(bool explicit_gc,
|
||||||
bool clear_all_soft_refs,
|
bool clear_all_soft_refs,
|
||||||
size_t word_size) {
|
size_t word_size) {
|
||||||
if (GC_locker::check_active_before_gc()) {
|
if (GC_locker::check_active_before_gc()) {
|
||||||
return; // GC is disabled (e.g. JNI GetXXXCritical operation)
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
|
@ -929,6 +1253,9 @@ void G1CollectedHeap::do_collection(bool explicit_gc,
|
||||||
g1_policy()->set_full_young_gcs(true);
|
g1_policy()->set_full_young_gcs(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See the comment in G1CollectedHeap::ref_processing_init() about
|
||||||
|
// how reference processing currently works in G1.
|
||||||
|
|
||||||
// Temporarily make reference _discovery_ single threaded (non-MT).
|
// Temporarily make reference _discovery_ single threaded (non-MT).
|
||||||
ReferenceProcessorMTMutator rp_disc_ser(ref_processor(), false);
|
ReferenceProcessorMTMutator rp_disc_ser(ref_processor(), false);
|
||||||
|
|
||||||
|
@ -1047,10 +1374,17 @@ void G1CollectedHeap::do_collection(bool explicit_gc,
|
||||||
if (PrintHeapAtGC) {
|
if (PrintHeapAtGC) {
|
||||||
Universe::print_heap_after_gc();
|
Universe::print_heap_after_gc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) {
|
void G1CollectedHeap::do_full_collection(bool clear_all_soft_refs) {
|
||||||
do_collection(true, /* explicit_gc */
|
// do_collection() will return whether it succeeded in performing
|
||||||
|
// the GC. Currently, there is no facility on the
|
||||||
|
// do_full_collection() API to notify the caller than the collection
|
||||||
|
// did not succeed (e.g., because it was locked out by the GC
|
||||||
|
// locker). So, right now, we'll ignore the return value.
|
||||||
|
bool dummy = do_collection(true, /* explicit_gc */
|
||||||
clear_all_soft_refs,
|
clear_all_soft_refs,
|
||||||
0 /* word_size */);
|
0 /* word_size */);
|
||||||
}
|
}
|
||||||
|
@ -1175,36 +1509,63 @@ resize_if_necessary_after_full_collection(size_t word_size) {
|
||||||
|
|
||||||
|
|
||||||
HeapWord*
|
HeapWord*
|
||||||
G1CollectedHeap::satisfy_failed_allocation(size_t word_size) {
|
G1CollectedHeap::satisfy_failed_allocation(size_t word_size,
|
||||||
HeapWord* result = NULL;
|
bool* succeeded) {
|
||||||
|
assert(SafepointSynchronize::is_at_safepoint(),
|
||||||
|
"satisfy_failed_allocation() should only be called at a safepoint");
|
||||||
|
assert(Thread::current()->is_VM_thread(),
|
||||||
|
"satisfy_failed_allocation() should only be called by the VM thread");
|
||||||
|
|
||||||
|
*succeeded = true;
|
||||||
|
// Let's attempt the allocation first.
|
||||||
|
HeapWord* result = attempt_allocation_at_safepoint(word_size,
|
||||||
|
false /* expect_null_cur_alloc_region */);
|
||||||
|
if (result != NULL) {
|
||||||
|
assert(*succeeded, "sanity");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// In a G1 heap, we're supposed to keep allocation from failing by
|
// In a G1 heap, we're supposed to keep allocation from failing by
|
||||||
// incremental pauses. Therefore, at least for now, we'll favor
|
// incremental pauses. Therefore, at least for now, we'll favor
|
||||||
// expansion over collection. (This might change in the future if we can
|
// expansion over collection. (This might change in the future if we can
|
||||||
// do something smarter than full collection to satisfy a failed alloc.)
|
// do something smarter than full collection to satisfy a failed alloc.)
|
||||||
|
|
||||||
result = expand_and_allocate(word_size);
|
result = expand_and_allocate(word_size);
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
assert(is_in(result), "result not in heap");
|
assert(*succeeded, "sanity");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// OK, I guess we have to try collection.
|
// Expansion didn't work, we'll try to do a Full GC.
|
||||||
|
bool gc_succeeded = do_collection(false, /* explicit_gc */
|
||||||
do_collection(false, false, word_size);
|
false, /* clear_all_soft_refs */
|
||||||
|
word_size);
|
||||||
result = attempt_allocation(word_size, /*permit_collection_pause*/false);
|
if (!gc_succeeded) {
|
||||||
|
*succeeded = false;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retry the allocation
|
||||||
|
result = attempt_allocation_at_safepoint(word_size,
|
||||||
|
true /* expect_null_cur_alloc_region */);
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
assert(is_in(result), "result not in heap");
|
assert(*succeeded, "sanity");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try collecting soft references.
|
// Then, try a Full GC that will collect all soft references.
|
||||||
do_collection(false, true, word_size);
|
gc_succeeded = do_collection(false, /* explicit_gc */
|
||||||
result = attempt_allocation(word_size, /*permit_collection_pause*/false);
|
true, /* clear_all_soft_refs */
|
||||||
|
word_size);
|
||||||
|
if (!gc_succeeded) {
|
||||||
|
*succeeded = false;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retry the allocation once more
|
||||||
|
result = attempt_allocation_at_safepoint(word_size,
|
||||||
|
true /* expect_null_cur_alloc_region */);
|
||||||
if (result != NULL) {
|
if (result != NULL) {
|
||||||
assert(is_in(result), "result not in heap");
|
assert(*succeeded, "sanity");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1215,6 +1576,7 @@ G1CollectedHeap::satisfy_failed_allocation(size_t word_size) {
|
||||||
// space available is large enough for the allocation, then a more
|
// space available is large enough for the allocation, then a more
|
||||||
// complete compaction phase than we've tried so far might be
|
// complete compaction phase than we've tried so far might be
|
||||||
// appropriate.
|
// appropriate.
|
||||||
|
assert(*succeeded, "sanity");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1224,14 +1586,20 @@ G1CollectedHeap::satisfy_failed_allocation(size_t word_size) {
|
||||||
// allocated block, or else "NULL".
|
// allocated block, or else "NULL".
|
||||||
|
|
||||||
HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) {
|
HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) {
|
||||||
|
assert(SafepointSynchronize::is_at_safepoint(),
|
||||||
|
"expand_and_allocate() should only be called at a safepoint");
|
||||||
|
assert(Thread::current()->is_VM_thread(),
|
||||||
|
"expand_and_allocate() should only be called by the VM thread");
|
||||||
|
|
||||||
size_t expand_bytes = word_size * HeapWordSize;
|
size_t expand_bytes = word_size * HeapWordSize;
|
||||||
if (expand_bytes < MinHeapDeltaBytes) {
|
if (expand_bytes < MinHeapDeltaBytes) {
|
||||||
expand_bytes = MinHeapDeltaBytes;
|
expand_bytes = MinHeapDeltaBytes;
|
||||||
}
|
}
|
||||||
expand(expand_bytes);
|
expand(expand_bytes);
|
||||||
assert(regions_accounted_for(), "Region leakage!");
|
assert(regions_accounted_for(), "Region leakage!");
|
||||||
HeapWord* result = attempt_allocation(word_size, false /* permit_collection_pause */);
|
|
||||||
return result;
|
return attempt_allocation_at_safepoint(word_size,
|
||||||
|
false /* expect_null_cur_alloc_region */);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t G1CollectedHeap::free_region_if_totally_empty(HeapRegion* hr) {
|
size_t G1CollectedHeap::free_region_if_totally_empty(HeapRegion* hr) {
|
||||||
|
@ -1649,6 +2017,24 @@ jint G1CollectedHeap::initialize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectedHeap::ref_processing_init() {
|
void G1CollectedHeap::ref_processing_init() {
|
||||||
|
// Reference processing in G1 currently works as follows:
|
||||||
|
//
|
||||||
|
// * There is only one reference processor instance that
|
||||||
|
// 'spans' the entire heap. It is created by the code
|
||||||
|
// below.
|
||||||
|
// * Reference discovery is not enabled during an incremental
|
||||||
|
// pause (see 6484982).
|
||||||
|
// * Discoverered refs are not enqueued nor are they processed
|
||||||
|
// during an incremental pause (see 6484982).
|
||||||
|
// * Reference discovery is enabled at initial marking.
|
||||||
|
// * Reference discovery is disabled and the discovered
|
||||||
|
// references processed etc during remarking.
|
||||||
|
// * Reference discovery is MT (see below).
|
||||||
|
// * Reference discovery requires a barrier (see below).
|
||||||
|
// * Reference processing is currently not MT (see 6608385).
|
||||||
|
// * A full GC enables (non-MT) reference discovery and
|
||||||
|
// processes any discovered references.
|
||||||
|
|
||||||
SharedHeap::ref_processing_init();
|
SharedHeap::ref_processing_init();
|
||||||
MemRegion mr = reserved_region();
|
MemRegion mr = reserved_region();
|
||||||
_ref_processor = ReferenceProcessor::create_ref_processor(
|
_ref_processor = ReferenceProcessor::create_ref_processor(
|
||||||
|
@ -1842,20 +2228,24 @@ void G1CollectedHeap::collect(GCCause::Cause cause) {
|
||||||
unsigned int full_gc_count_before;
|
unsigned int full_gc_count_before;
|
||||||
{
|
{
|
||||||
MutexLocker ml(Heap_lock);
|
MutexLocker ml(Heap_lock);
|
||||||
|
|
||||||
|
// Don't want to do a GC until cleanup is completed. This
|
||||||
|
// limitation will be removed in the near future when the
|
||||||
|
// operation of the free region list is revamped as part of
|
||||||
|
// CR 6977804.
|
||||||
|
wait_for_cleanup_complete();
|
||||||
|
|
||||||
// Read the GC count while holding the Heap_lock
|
// Read the GC count while holding the Heap_lock
|
||||||
gc_count_before = SharedHeap::heap()->total_collections();
|
gc_count_before = SharedHeap::heap()->total_collections();
|
||||||
full_gc_count_before = SharedHeap::heap()->total_full_collections();
|
full_gc_count_before = SharedHeap::heap()->total_full_collections();
|
||||||
|
|
||||||
// Don't want to do a GC until cleanup is completed.
|
|
||||||
wait_for_cleanup_complete();
|
|
||||||
|
|
||||||
// We give up heap lock; VMThread::execute gets it back below
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (should_do_concurrent_full_gc(cause)) {
|
if (should_do_concurrent_full_gc(cause)) {
|
||||||
// Schedule an initial-mark evacuation pause that will start a
|
// Schedule an initial-mark evacuation pause that will start a
|
||||||
// concurrent cycle.
|
// concurrent cycle. We're setting word_size to 0 which means that
|
||||||
|
// we are not requesting a post-GC allocation.
|
||||||
VM_G1IncCollectionPause op(gc_count_before,
|
VM_G1IncCollectionPause op(gc_count_before,
|
||||||
|
0, /* word_size */
|
||||||
true, /* should_initiate_conc_mark */
|
true, /* should_initiate_conc_mark */
|
||||||
g1_policy()->max_pause_time_ms(),
|
g1_policy()->max_pause_time_ms(),
|
||||||
cause);
|
cause);
|
||||||
|
@ -1864,8 +2254,10 @@ void G1CollectedHeap::collect(GCCause::Cause cause) {
|
||||||
if (cause == GCCause::_gc_locker
|
if (cause == GCCause::_gc_locker
|
||||||
DEBUG_ONLY(|| cause == GCCause::_scavenge_alot)) {
|
DEBUG_ONLY(|| cause == GCCause::_scavenge_alot)) {
|
||||||
|
|
||||||
// Schedule a standard evacuation pause.
|
// Schedule a standard evacuation pause. We're setting word_size
|
||||||
|
// to 0 which means that we are not requesting a post-GC allocation.
|
||||||
VM_G1IncCollectionPause op(gc_count_before,
|
VM_G1IncCollectionPause op(gc_count_before,
|
||||||
|
0, /* word_size */
|
||||||
false, /* should_initiate_conc_mark */
|
false, /* should_initiate_conc_mark */
|
||||||
g1_policy()->max_pause_time_ms(),
|
g1_policy()->max_pause_time_ms(),
|
||||||
cause);
|
cause);
|
||||||
|
@ -2221,14 +2613,6 @@ size_t G1CollectedHeap::unsafe_max_tlab_alloc(Thread* ignored) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapWord* G1CollectedHeap::allocate_new_tlab(size_t word_size) {
|
|
||||||
assert(!isHumongous(word_size),
|
|
||||||
err_msg("a TLAB should not be of humongous size, "
|
|
||||||
"word_size = "SIZE_FORMAT, word_size));
|
|
||||||
bool dummy;
|
|
||||||
return G1CollectedHeap::mem_allocate(word_size, false, true, &dummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool G1CollectedHeap::allocs_are_zero_filled() {
|
bool G1CollectedHeap::allocs_are_zero_filled() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2633,27 +3017,26 @@ void G1CollectedHeap::gc_epilogue(bool full /* Ignored */) {
|
||||||
// always_do_update_barrier = true;
|
// always_do_update_barrier = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectedHeap::do_collection_pause() {
|
HeapWord* G1CollectedHeap::do_collection_pause(size_t word_size,
|
||||||
assert(Heap_lock->owned_by_self(), "we assume we'reholding the Heap_lock");
|
unsigned int gc_count_before,
|
||||||
|
bool* succeeded) {
|
||||||
// Read the GC count while holding the Heap_lock
|
assert_heap_not_locked_and_not_at_safepoint();
|
||||||
// we need to do this _before_ wait_for_cleanup_complete(), to
|
|
||||||
// ensure that we do not give up the heap lock and potentially
|
|
||||||
// pick up the wrong count
|
|
||||||
unsigned int gc_count_before = SharedHeap::heap()->total_collections();
|
|
||||||
|
|
||||||
// Don't want to do a GC pause while cleanup is being completed!
|
|
||||||
wait_for_cleanup_complete();
|
|
||||||
|
|
||||||
g1_policy()->record_stop_world_start();
|
g1_policy()->record_stop_world_start();
|
||||||
{
|
|
||||||
MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back
|
|
||||||
VM_G1IncCollectionPause op(gc_count_before,
|
VM_G1IncCollectionPause op(gc_count_before,
|
||||||
|
word_size,
|
||||||
false, /* should_initiate_conc_mark */
|
false, /* should_initiate_conc_mark */
|
||||||
g1_policy()->max_pause_time_ms(),
|
g1_policy()->max_pause_time_ms(),
|
||||||
GCCause::_g1_inc_collection_pause);
|
GCCause::_g1_inc_collection_pause);
|
||||||
VMThread::execute(&op);
|
VMThread::execute(&op);
|
||||||
}
|
|
||||||
|
HeapWord* result = op.result();
|
||||||
|
bool ret_succeeded = op.prologue_succeeded() && op.pause_succeeded();
|
||||||
|
assert(result == NULL || ret_succeeded,
|
||||||
|
"the result should be NULL if the VM did not succeed");
|
||||||
|
*succeeded = ret_succeeded;
|
||||||
|
|
||||||
|
assert_heap_not_locked();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2797,10 +3180,10 @@ void G1CollectedHeap::reset_taskqueue_stats() {
|
||||||
}
|
}
|
||||||
#endif // TASKQUEUE_STATS
|
#endif // TASKQUEUE_STATS
|
||||||
|
|
||||||
void
|
bool
|
||||||
G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||||
if (GC_locker::check_active_before_gc()) {
|
if (GC_locker::check_active_before_gc()) {
|
||||||
return; // GC is disabled (e.g. JNI GetXXXCritical operation)
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PrintHeapAtGC) {
|
if (PrintHeapAtGC) {
|
||||||
|
@ -2871,6 +3254,9 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||||
|
|
||||||
COMPILER2_PRESENT(DerivedPointerTable::clear());
|
COMPILER2_PRESENT(DerivedPointerTable::clear());
|
||||||
|
|
||||||
|
// Please see comment in G1CollectedHeap::ref_processing_init()
|
||||||
|
// to see how reference processing currently works in G1.
|
||||||
|
//
|
||||||
// We want to turn off ref discovery, if necessary, and turn it back on
|
// We want to turn off ref discovery, if necessary, and turn it back on
|
||||||
// on again later if we do. XXX Dubious: why is discovery disabled?
|
// on again later if we do. XXX Dubious: why is discovery disabled?
|
||||||
bool was_enabled = ref_processor()->discovery_enabled();
|
bool was_enabled = ref_processor()->discovery_enabled();
|
||||||
|
@ -3068,6 +3454,8 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
|
||||||
(total_collections() % G1SummarizeRSetStatsPeriod == 0)) {
|
(total_collections() % G1SummarizeRSetStatsPeriod == 0)) {
|
||||||
g1_rem_set()->print_summary_info();
|
g1_rem_set()->print_summary_info();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t G1CollectedHeap::desired_plab_sz(GCAllocPurpose purpose)
|
size_t G1CollectedHeap::desired_plab_sz(GCAllocPurpose purpose)
|
||||||
|
@ -3298,6 +3686,7 @@ void G1CollectedHeap::release_gc_alloc_regions(bool totally) {
|
||||||
// untag the GC alloc regions and tear down the GC alloc region
|
// untag the GC alloc regions and tear down the GC alloc region
|
||||||
// list. It's desirable that no regions are tagged as GC alloc
|
// list. It's desirable that no regions are tagged as GC alloc
|
||||||
// outside GCs.
|
// outside GCs.
|
||||||
|
|
||||||
forget_alloc_region_list();
|
forget_alloc_region_list();
|
||||||
|
|
||||||
// The current alloc regions contain objs that have survived
|
// The current alloc regions contain objs that have survived
|
||||||
|
@ -3361,19 +3750,6 @@ void G1CollectedHeap::finalize_for_evac_failure() {
|
||||||
|
|
||||||
// *** Sequential G1 Evacuation
|
// *** Sequential G1 Evacuation
|
||||||
|
|
||||||
HeapWord* G1CollectedHeap::allocate_during_gc(GCAllocPurpose purpose, size_t word_size) {
|
|
||||||
HeapRegion* alloc_region = _gc_alloc_regions[purpose];
|
|
||||||
// let the caller handle alloc failure
|
|
||||||
if (alloc_region == NULL) return NULL;
|
|
||||||
assert(isHumongous(word_size) || !alloc_region->isHumongous(),
|
|
||||||
"Either the object is humongous or the region isn't");
|
|
||||||
HeapWord* block = alloc_region->allocate(word_size);
|
|
||||||
if (block == NULL) {
|
|
||||||
block = allocate_during_gc_slow(purpose, alloc_region, false, word_size);
|
|
||||||
}
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
class G1IsAliveClosure: public BoolObjectClosure {
|
class G1IsAliveClosure: public BoolObjectClosure {
|
||||||
G1CollectedHeap* _g1;
|
G1CollectedHeap* _g1;
|
||||||
public:
|
public:
|
||||||
|
@ -4316,6 +4692,10 @@ g1_process_strong_roots(bool collecting_perm_gen,
|
||||||
}
|
}
|
||||||
// Finish with the ref_processor roots.
|
// Finish with the ref_processor roots.
|
||||||
if (!_process_strong_tasks->is_task_claimed(G1H_PS_refProcessor_oops_do)) {
|
if (!_process_strong_tasks->is_task_claimed(G1H_PS_refProcessor_oops_do)) {
|
||||||
|
// We need to treat the discovered reference lists as roots and
|
||||||
|
// keep entries (which are added by the marking threads) on them
|
||||||
|
// live until they can be processed at the end of marking.
|
||||||
|
ref_processor()->weak_oops_do(scan_non_heap_roots);
|
||||||
ref_processor()->oops_do(scan_non_heap_roots);
|
ref_processor()->oops_do(scan_non_heap_roots);
|
||||||
}
|
}
|
||||||
g1_policy()->record_collection_pause_end_G1_strong_roots();
|
g1_policy()->record_collection_pause_end_G1_strong_roots();
|
||||||
|
@ -4381,6 +4761,11 @@ void G1CollectedHeap::evacuate_collection_set() {
|
||||||
// on individual heap regions when we allocate from
|
// on individual heap regions when we allocate from
|
||||||
// them in parallel, so this seems like the correct place for this.
|
// them in parallel, so this seems like the correct place for this.
|
||||||
retire_all_alloc_regions();
|
retire_all_alloc_regions();
|
||||||
|
|
||||||
|
// Weak root processing.
|
||||||
|
// Note: when JSR 292 is enabled and code blobs can contain
|
||||||
|
// non-perm oops then we will need to process the code blobs
|
||||||
|
// here too.
|
||||||
{
|
{
|
||||||
G1IsAliveClosure is_alive(this);
|
G1IsAliveClosure is_alive(this);
|
||||||
G1KeepAliveClosure keep_alive(this);
|
G1KeepAliveClosure keep_alive(this);
|
||||||
|
@ -4625,12 +5010,6 @@ void G1CollectedHeap::cleanUpCardTable() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectedHeap::do_collection_pause_if_appropriate(size_t word_size) {
|
|
||||||
if (g1_policy()->should_do_collection_pause(word_size)) {
|
|
||||||
do_collection_pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) {
|
void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) {
|
||||||
double young_time_ms = 0.0;
|
double young_time_ms = 0.0;
|
||||||
double non_young_time_ms = 0.0;
|
double non_young_time_ms = 0.0;
|
||||||
|
@ -4789,6 +5168,7 @@ void G1CollectedHeap::set_unclean_regions_coming_locked(bool b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectedHeap::wait_for_cleanup_complete() {
|
void G1CollectedHeap::wait_for_cleanup_complete() {
|
||||||
|
assert_not_at_safepoint();
|
||||||
MutexLockerEx x(Cleanup_mon);
|
MutexLockerEx x(Cleanup_mon);
|
||||||
wait_for_cleanup_complete_locked();
|
wait_for_cleanup_complete_locked();
|
||||||
}
|
}
|
||||||
|
@ -5093,13 +5473,6 @@ size_t G1CollectedHeap::count_free_regions_list() {
|
||||||
return n + m;
|
return n + m;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool G1CollectedHeap::should_set_young_locked() {
|
|
||||||
assert(heap_lock_held_for_gc(),
|
|
||||||
"the heap lock should already be held by or for this thread");
|
|
||||||
return (g1_policy()->in_young_gc_mode() &&
|
|
||||||
g1_policy()->should_add_next_region_to_young_list());
|
|
||||||
}
|
|
||||||
|
|
||||||
void G1CollectedHeap::set_region_short_lived_locked(HeapRegion* hr) {
|
void G1CollectedHeap::set_region_short_lived_locked(HeapRegion* hr) {
|
||||||
assert(heap_lock_held_for_gc(),
|
assert(heap_lock_held_for_gc(),
|
||||||
"the heap lock should already be held by or for this thread");
|
"the heap lock should already be held by or for this thread");
|
||||||
|
|
|
@ -290,6 +290,63 @@ private:
|
||||||
// started is maintained in _total_full_collections in CollectedHeap.
|
// started is maintained in _total_full_collections in CollectedHeap.
|
||||||
volatile unsigned int _full_collections_completed;
|
volatile unsigned int _full_collections_completed;
|
||||||
|
|
||||||
|
// These are macros so that, if the assert fires, we get the correct
|
||||||
|
// line number, file, etc.
|
||||||
|
|
||||||
|
#define heap_locking_asserts_err_msg(__extra_message) \
|
||||||
|
err_msg("%s : Heap_lock %slocked, %sat a safepoint", \
|
||||||
|
(__extra_message), \
|
||||||
|
(!Heap_lock->owned_by_self()) ? "NOT " : "", \
|
||||||
|
(!SafepointSynchronize::is_at_safepoint()) ? "NOT " : "")
|
||||||
|
|
||||||
|
#define assert_heap_locked() \
|
||||||
|
do { \
|
||||||
|
assert(Heap_lock->owned_by_self(), \
|
||||||
|
heap_locking_asserts_err_msg("should be holding the Heap_lock")); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define assert_heap_locked_or_at_safepoint() \
|
||||||
|
do { \
|
||||||
|
assert(Heap_lock->owned_by_self() || \
|
||||||
|
SafepointSynchronize::is_at_safepoint(), \
|
||||||
|
heap_locking_asserts_err_msg("should be holding the Heap_lock or " \
|
||||||
|
"should be at a safepoint")); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define assert_heap_locked_and_not_at_safepoint() \
|
||||||
|
do { \
|
||||||
|
assert(Heap_lock->owned_by_self() && \
|
||||||
|
!SafepointSynchronize::is_at_safepoint(), \
|
||||||
|
heap_locking_asserts_err_msg("should be holding the Heap_lock and " \
|
||||||
|
"should not be at a safepoint")); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define assert_heap_not_locked() \
|
||||||
|
do { \
|
||||||
|
assert(!Heap_lock->owned_by_self(), \
|
||||||
|
heap_locking_asserts_err_msg("should not be holding the Heap_lock")); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define assert_heap_not_locked_and_not_at_safepoint() \
|
||||||
|
do { \
|
||||||
|
assert(!Heap_lock->owned_by_self() && \
|
||||||
|
!SafepointSynchronize::is_at_safepoint(), \
|
||||||
|
heap_locking_asserts_err_msg("should not be holding the Heap_lock and " \
|
||||||
|
"should not be at a safepoint")); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define assert_at_safepoint() \
|
||||||
|
do { \
|
||||||
|
assert(SafepointSynchronize::is_at_safepoint(), \
|
||||||
|
heap_locking_asserts_err_msg("should be at a safepoint")); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define assert_not_at_safepoint() \
|
||||||
|
do { \
|
||||||
|
assert(!SafepointSynchronize::is_at_safepoint(), \
|
||||||
|
heap_locking_asserts_err_msg("should not be at a safepoint")); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Returns "true" iff none of the gc alloc regions have any allocations
|
// Returns "true" iff none of the gc alloc regions have any allocations
|
||||||
|
@ -329,31 +386,162 @@ protected:
|
||||||
|
|
||||||
// Attempt to allocate an object of the given (very large) "word_size".
|
// Attempt to allocate an object of the given (very large) "word_size".
|
||||||
// Returns "NULL" on failure.
|
// Returns "NULL" on failure.
|
||||||
virtual HeapWord* humongousObjAllocate(size_t word_size);
|
virtual HeapWord* humongous_obj_allocate(size_t word_size);
|
||||||
|
|
||||||
// If possible, allocate a block of the given word_size, else return "NULL".
|
// The following two methods, allocate_new_tlab() and
|
||||||
// Returning NULL will trigger GC or heap expansion.
|
// mem_allocate(), are the two main entry points from the runtime
|
||||||
// These two methods have rather awkward pre- and
|
// into the G1's allocation routines. They have the following
|
||||||
// post-conditions. If they are called outside a safepoint, then
|
// assumptions:
|
||||||
// they assume that the caller is holding the heap lock. Upon return
|
//
|
||||||
// they release the heap lock, if they are returning a non-NULL
|
// * They should both be called outside safepoints.
|
||||||
// value. attempt_allocation_slow() also dirties the cards of a
|
//
|
||||||
// newly-allocated young region after it releases the heap
|
// * They should both be called without holding the Heap_lock.
|
||||||
// lock. This change in interface was the neatest way to achieve
|
//
|
||||||
// this card dirtying without affecting mem_allocate(), which is a
|
// * All allocation requests for new TLABs should go to
|
||||||
// more frequently called method. We tried two or three different
|
// allocate_new_tlab().
|
||||||
// approaches, but they were even more hacky.
|
//
|
||||||
HeapWord* attempt_allocation(size_t word_size,
|
// * All non-TLAB allocation requests should go to mem_allocate()
|
||||||
bool permit_collection_pause = true);
|
// and mem_allocate() should never be called with is_tlab == true.
|
||||||
|
//
|
||||||
|
// * If the GC locker is active we currently stall until we can
|
||||||
|
// allocate a new young region. This will be changed in the
|
||||||
|
// near future (see CR 6994056).
|
||||||
|
//
|
||||||
|
// * If either call cannot satisfy the allocation request using the
|
||||||
|
// current allocating region, they will try to get a new one. If
|
||||||
|
// this fails, they will attempt to do an evacuation pause and
|
||||||
|
// retry the allocation.
|
||||||
|
//
|
||||||
|
// * If all allocation attempts fail, even after trying to schedule
|
||||||
|
// an evacuation pause, allocate_new_tlab() will return NULL,
|
||||||
|
// whereas mem_allocate() will attempt a heap expansion and/or
|
||||||
|
// schedule a Full GC.
|
||||||
|
//
|
||||||
|
// * We do not allow humongous-sized TLABs. So, allocate_new_tlab
|
||||||
|
// should never be called with word_size being humongous. All
|
||||||
|
// humongous allocation requests should go to mem_allocate() which
|
||||||
|
// will satisfy them with a special path.
|
||||||
|
|
||||||
HeapWord* attempt_allocation_slow(size_t word_size,
|
virtual HeapWord* allocate_new_tlab(size_t word_size);
|
||||||
bool permit_collection_pause = true);
|
|
||||||
|
virtual HeapWord* mem_allocate(size_t word_size,
|
||||||
|
bool is_noref,
|
||||||
|
bool is_tlab, /* expected to be false */
|
||||||
|
bool* gc_overhead_limit_was_exceeded);
|
||||||
|
|
||||||
|
// The following methods, allocate_from_cur_allocation_region(),
|
||||||
|
// attempt_allocation(), replace_cur_alloc_region_and_allocate(),
|
||||||
|
// attempt_allocation_slow(), and attempt_allocation_humongous()
|
||||||
|
// have very awkward pre- and post-conditions with respect to
|
||||||
|
// locking:
|
||||||
|
//
|
||||||
|
// If they are called outside a safepoint they assume the caller
|
||||||
|
// holds the Heap_lock when it calls them. However, on exit they
|
||||||
|
// will release the Heap_lock if they return a non-NULL result, but
|
||||||
|
// keep holding the Heap_lock if they return a NULL result. The
|
||||||
|
// reason for this is that we need to dirty the cards that span
|
||||||
|
// allocated blocks on young regions to avoid having to take the
|
||||||
|
// slow path of the write barrier (for performance reasons we don't
|
||||||
|
// update RSets for references whose source is a young region, so we
|
||||||
|
// don't need to look at dirty cards on young regions). But, doing
|
||||||
|
// this card dirtying while holding the Heap_lock can be a
|
||||||
|
// scalability bottleneck, especially given that some allocation
|
||||||
|
// requests might be of non-trivial size (and the larger the region
|
||||||
|
// size is, the fewer allocations requests will be considered
|
||||||
|
// humongous, as the humongous size limit is a fraction of the
|
||||||
|
// region size). So, when one of these calls succeeds in allocating
|
||||||
|
// a block it does the card dirtying after it releases the Heap_lock
|
||||||
|
// which is why it will return without holding it.
|
||||||
|
//
|
||||||
|
// The above assymetry is the reason why locking / unlocking is done
|
||||||
|
// explicitly (i.e., with Heap_lock->lock() and
|
||||||
|
// Heap_lock->unlocked()) instead of using MutexLocker and
|
||||||
|
// MutexUnlocker objects. The latter would ensure that the lock is
|
||||||
|
// unlocked / re-locked at every possible exit out of the basic
|
||||||
|
// block. However, we only want that action to happen in selected
|
||||||
|
// places.
|
||||||
|
//
|
||||||
|
// Further, if the above methods are called during a safepoint, then
|
||||||
|
// naturally there's no assumption about the Heap_lock being held or
|
||||||
|
// there's no attempt to unlock it. The parameter at_safepoint
|
||||||
|
// indicates whether the call is made during a safepoint or not (as
|
||||||
|
// an optimization, to avoid reading the global flag with
|
||||||
|
// SafepointSynchronize::is_at_safepoint()).
|
||||||
|
//
|
||||||
|
// The methods share these parameters:
|
||||||
|
//
|
||||||
|
// * word_size : the size of the allocation request in words
|
||||||
|
// * at_safepoint : whether the call is done at a safepoint; this
|
||||||
|
// also determines whether a GC is permitted
|
||||||
|
// (at_safepoint == false) or not (at_safepoint == true)
|
||||||
|
// * do_dirtying : whether the method should dirty the allocated
|
||||||
|
// block before returning
|
||||||
|
//
|
||||||
|
// They all return either the address of the block, if they
|
||||||
|
// 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.
|
||||||
|
inline HeapWord* allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region,
|
||||||
|
size_t word_size);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
inline HeapWord* attempt_allocation(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
|
||||||
|
// _cur_alloc_region.
|
||||||
|
HeapWord* replace_cur_alloc_region_and_allocate(size_t word_size,
|
||||||
|
bool at_safepoint,
|
||||||
|
bool do_dirtying);
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
HeapWord* attempt_allocation_slow(size_t word_size);
|
||||||
|
|
||||||
|
// The method that tries to satisfy a humongous allocation
|
||||||
|
// request. If it cannot satisfy it it will try to do an evacuation
|
||||||
|
// pause to perhaps reclaim enough space to be able to satisfy the
|
||||||
|
// allocation request afterwards.
|
||||||
|
HeapWord* attempt_allocation_humongous(size_t word_size,
|
||||||
|
bool at_safepoint);
|
||||||
|
|
||||||
|
// It does the common work when we are retiring the current alloc region.
|
||||||
|
inline void retire_cur_alloc_region_common(HeapRegion* cur_alloc_region);
|
||||||
|
|
||||||
|
// It retires the current alloc region, which is passed as a
|
||||||
|
// parameter (since, typically, the caller is already holding on to
|
||||||
|
// it). It sets _cur_alloc_region to NULL.
|
||||||
|
void retire_cur_alloc_region(HeapRegion* cur_alloc_region);
|
||||||
|
|
||||||
|
// It attempts to do an allocation immediately before or after an
|
||||||
|
// evacuation pause and can only be called by the VM thread. It has
|
||||||
|
// slightly different assumptions that the ones before (i.e.,
|
||||||
|
// assumes that the current alloc region has been retired).
|
||||||
|
HeapWord* attempt_allocation_at_safepoint(size_t word_size,
|
||||||
|
bool expect_null_cur_alloc_region);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// belongs to a young region.
|
||||||
|
inline void dirty_young_block(HeapWord* start, size_t word_size);
|
||||||
|
|
||||||
// Allocate blocks during garbage collection. Will ensure an
|
// Allocate blocks during garbage collection. Will ensure an
|
||||||
// allocation region, either by picking one or expanding the
|
// allocation region, either by picking one or expanding the
|
||||||
// heap, and then allocate a block of the given size. The block
|
// heap, and then allocate a block of the given size. The block
|
||||||
// may not be a humongous - it must fit into a single heap region.
|
// may not be a humongous - it must fit into a single heap region.
|
||||||
HeapWord* allocate_during_gc(GCAllocPurpose purpose, size_t word_size);
|
|
||||||
HeapWord* par_allocate_during_gc(GCAllocPurpose purpose, size_t word_size);
|
HeapWord* par_allocate_during_gc(GCAllocPurpose purpose, size_t word_size);
|
||||||
|
|
||||||
HeapWord* allocate_during_gc_slow(GCAllocPurpose purpose,
|
HeapWord* allocate_during_gc_slow(GCAllocPurpose purpose,
|
||||||
|
@ -371,11 +559,13 @@ protected:
|
||||||
|
|
||||||
// - if explicit_gc is true, the GC is for a System.gc() or a heap
|
// - if explicit_gc is true, the GC is for a System.gc() or a heap
|
||||||
// inspection request and should collect the entire heap
|
// inspection request and should collect the entire heap
|
||||||
// - if clear_all_soft_refs is true, all soft references are cleared
|
// - if clear_all_soft_refs is true, all soft references should be
|
||||||
// during the GC
|
// cleared during the GC
|
||||||
// - if explicit_gc is false, word_size describes the allocation that
|
// - if explicit_gc is false, word_size describes the allocation that
|
||||||
// the GC should attempt (at least) to satisfy
|
// the GC should attempt (at least) to satisfy
|
||||||
void do_collection(bool explicit_gc,
|
// - it returns false if it is unable to do the collection due to the
|
||||||
|
// GC locker being active, true otherwise
|
||||||
|
bool do_collection(bool explicit_gc,
|
||||||
bool clear_all_soft_refs,
|
bool clear_all_soft_refs,
|
||||||
size_t word_size);
|
size_t word_size);
|
||||||
|
|
||||||
|
@ -391,13 +581,13 @@ protected:
|
||||||
// Callback from VM_G1CollectForAllocation operation.
|
// Callback from VM_G1CollectForAllocation operation.
|
||||||
// This function does everything necessary/possible to satisfy a
|
// This function does everything necessary/possible to satisfy a
|
||||||
// failed allocation request (including collection, expansion, etc.)
|
// failed allocation request (including collection, expansion, etc.)
|
||||||
HeapWord* satisfy_failed_allocation(size_t word_size);
|
HeapWord* satisfy_failed_allocation(size_t word_size, bool* succeeded);
|
||||||
|
|
||||||
// Attempting to expand the heap sufficiently
|
// Attempting to expand the heap sufficiently
|
||||||
// to support an allocation of the given "word_size". If
|
// to support an allocation of the given "word_size". If
|
||||||
// successful, perform the allocation and return the address of the
|
// successful, perform the allocation and return the address of the
|
||||||
// allocated block, or else "NULL".
|
// allocated block, or else "NULL".
|
||||||
virtual HeapWord* expand_and_allocate(size_t word_size);
|
HeapWord* expand_and_allocate(size_t word_size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Expand the garbage-first heap by at least the given size (in bytes!).
|
// Expand the garbage-first heap by at least the given size (in bytes!).
|
||||||
|
@ -478,21 +668,27 @@ protected:
|
||||||
void reset_taskqueue_stats();
|
void reset_taskqueue_stats();
|
||||||
#endif // TASKQUEUE_STATS
|
#endif // TASKQUEUE_STATS
|
||||||
|
|
||||||
// Do an incremental collection: identify a collection set, and evacuate
|
// Schedule the VM operation that will do an evacuation pause to
|
||||||
// its live objects elsewhere.
|
// satisfy an allocation request of word_size. *succeeded will
|
||||||
virtual void do_collection_pause();
|
// return whether the VM operation was successful (it did do an
|
||||||
|
// evacuation pause) or not (another thread beat us to it or the GC
|
||||||
|
// locker was active). Given that we should not be holding the
|
||||||
|
// Heap_lock when we enter this method, we will pass the
|
||||||
|
// gc_count_before (i.e., total_collections()) as a parameter since
|
||||||
|
// it has to be read while holding the Heap_lock. Currently, both
|
||||||
|
// methods that call do_collection_pause() release the Heap_lock
|
||||||
|
// before the call, so it's easy to read gc_count_before just before.
|
||||||
|
HeapWord* do_collection_pause(size_t word_size,
|
||||||
|
unsigned int gc_count_before,
|
||||||
|
bool* succeeded);
|
||||||
|
|
||||||
// The guts of the incremental collection pause, executed by the vm
|
// The guts of the incremental collection pause, executed by the vm
|
||||||
// thread.
|
// thread. It returns false if it is unable to do the collection due
|
||||||
virtual void do_collection_pause_at_safepoint(double target_pause_time_ms);
|
// to the GC locker being active, true otherwise
|
||||||
|
bool do_collection_pause_at_safepoint(double target_pause_time_ms);
|
||||||
|
|
||||||
// Actually do the work of evacuating the collection set.
|
// Actually do the work of evacuating the collection set.
|
||||||
virtual void evacuate_collection_set();
|
void evacuate_collection_set();
|
||||||
|
|
||||||
// If this is an appropriate right time, do a collection pause.
|
|
||||||
// The "word_size" argument, if non-zero, indicates the size of an
|
|
||||||
// allocation request that is prompting this query.
|
|
||||||
void do_collection_pause_if_appropriate(size_t word_size);
|
|
||||||
|
|
||||||
// The g1 remembered set of the heap.
|
// The g1 remembered set of the heap.
|
||||||
G1RemSet* _g1_rem_set;
|
G1RemSet* _g1_rem_set;
|
||||||
|
@ -762,11 +958,6 @@ public:
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
||||||
// These virtual functions do the actual allocation.
|
// These virtual functions do the actual allocation.
|
||||||
virtual HeapWord* mem_allocate(size_t word_size,
|
|
||||||
bool is_noref,
|
|
||||||
bool is_tlab,
|
|
||||||
bool* gc_overhead_limit_was_exceeded);
|
|
||||||
|
|
||||||
// Some heaps may offer a contiguous region for shared non-blocking
|
// Some heaps may offer a contiguous region for shared non-blocking
|
||||||
// allocation, via inlined code (by exporting the address of the top and
|
// allocation, via inlined code (by exporting the address of the top and
|
||||||
// end fields defining the extent of the contiguous allocation region.)
|
// end fields defining the extent of the contiguous allocation region.)
|
||||||
|
@ -1046,7 +1237,6 @@ public:
|
||||||
virtual bool supports_tlab_allocation() const;
|
virtual bool supports_tlab_allocation() const;
|
||||||
virtual size_t tlab_capacity(Thread* thr) const;
|
virtual size_t tlab_capacity(Thread* thr) const;
|
||||||
virtual size_t unsafe_max_tlab_alloc(Thread* thr) const;
|
virtual size_t unsafe_max_tlab_alloc(Thread* thr) const;
|
||||||
virtual HeapWord* allocate_new_tlab(size_t word_size);
|
|
||||||
|
|
||||||
// Can a compiler initialize a new object without store barriers?
|
// Can a compiler initialize a new object without store barriers?
|
||||||
// This permission only extends from the creation of a new object
|
// This permission only extends from the creation of a new object
|
||||||
|
@ -1186,7 +1376,6 @@ public:
|
||||||
static G1CollectedHeap* heap();
|
static G1CollectedHeap* heap();
|
||||||
|
|
||||||
void empty_young_list();
|
void empty_young_list();
|
||||||
bool should_set_young_locked();
|
|
||||||
|
|
||||||
void set_region_short_lived_locked(HeapRegion* hr);
|
void set_region_short_lived_locked(HeapRegion* hr);
|
||||||
// add appropriate methods for any other surv rate groups
|
// add appropriate methods for any other surv rate groups
|
||||||
|
@ -1339,8 +1528,6 @@ public:
|
||||||
protected:
|
protected:
|
||||||
size_t _max_heap_capacity;
|
size_t _max_heap_capacity;
|
||||||
|
|
||||||
// debug_only(static void check_for_valid_allocation_state();)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Temporary: call to mark things unimplemented for the G1 heap (e.g.,
|
// Temporary: call to mark things unimplemented for the G1 heap (e.g.,
|
||||||
// MemoryService). In productization, we can make this assert false
|
// MemoryService). In productization, we can make this assert false
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "gc_implementation/g1/concurrentMark.hpp"
|
#include "gc_implementation/g1/concurrentMark.hpp"
|
||||||
#include "gc_implementation/g1/g1CollectedHeap.hpp"
|
#include "gc_implementation/g1/g1CollectedHeap.hpp"
|
||||||
|
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
|
||||||
#include "gc_implementation/g1/heapRegionSeq.hpp"
|
#include "gc_implementation/g1/heapRegionSeq.hpp"
|
||||||
#include "utilities/taskqueue.hpp"
|
#include "utilities/taskqueue.hpp"
|
||||||
|
|
||||||
|
@ -58,37 +59,114 @@ inline bool G1CollectedHeap::obj_in_cs(oop obj) {
|
||||||
return r != NULL && r->in_collection_set();
|
return r != NULL && r->in_collection_set();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size,
|
// See the comment in the .hpp file about the locking protocol and
|
||||||
bool permit_collection_pause) {
|
// assumptions of this method (and other related ones).
|
||||||
HeapWord* res = NULL;
|
inline HeapWord*
|
||||||
|
G1CollectedHeap::allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region,
|
||||||
|
size_t word_size) {
|
||||||
|
assert_heap_locked_and_not_at_safepoint();
|
||||||
|
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() "
|
||||||
|
"should not be used for humongous allocations");
|
||||||
|
assert(!cur_alloc_region->isHumongous(), "Catch a regression of this bug.");
|
||||||
|
|
||||||
assert( SafepointSynchronize::is_at_safepoint() ||
|
assert(!cur_alloc_region->is_empty(),
|
||||||
Heap_lock->owned_by_self(), "pre-condition of the call" );
|
err_msg("region ["PTR_FORMAT","PTR_FORMAT"] should not be empty",
|
||||||
|
cur_alloc_region->bottom(), cur_alloc_region->end()));
|
||||||
// All humongous allocation requests should go through the slow path in
|
// This allocate method does BOT updates and we don't need them in
|
||||||
// attempt_allocation_slow().
|
// the young generation. This will be fixed in the near future by
|
||||||
if (!isHumongous(word_size) && _cur_alloc_region != NULL) {
|
// CR 6994297.
|
||||||
// If this allocation causes a region to become non empty,
|
HeapWord* result = cur_alloc_region->allocate(word_size);
|
||||||
// then we need to update our free_regions count.
|
if (result != NULL) {
|
||||||
|
assert(is_in(result), "result should be in the heap");
|
||||||
if (_cur_alloc_region->is_empty()) {
|
|
||||||
res = _cur_alloc_region->allocate(word_size);
|
|
||||||
if (res != NULL)
|
|
||||||
_free_regions--;
|
|
||||||
} else {
|
|
||||||
res = _cur_alloc_region->allocate(word_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res != NULL) {
|
|
||||||
if (!SafepointSynchronize::is_at_safepoint()) {
|
|
||||||
assert( Heap_lock->owned_by_self(), "invariant" );
|
|
||||||
Heap_lock->unlock();
|
Heap_lock->unlock();
|
||||||
|
|
||||||
|
// Do the dirtying after we release the Heap_lock.
|
||||||
|
dirty_young_block(result, word_size);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
|
assert_heap_locked();
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See the comment in the .hpp file about the locking protocol and
|
||||||
|
// 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(!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);
|
||||||
|
if (result != NULL) {
|
||||||
|
assert_heap_not_locked();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
// attempt_allocation_slow will also unlock the heap lock when appropriate.
|
|
||||||
return attempt_allocation_slow(word_size, permit_collection_pause);
|
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 */);
|
||||||
|
if (result != NULL) {
|
||||||
|
assert_heap_not_locked();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_heap_locked();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
G1CollectedHeap::retire_cur_alloc_region_common(HeapRegion* cur_alloc_region) {
|
||||||
|
assert_heap_locked_or_at_safepoint();
|
||||||
|
assert(cur_alloc_region != NULL && cur_alloc_region == _cur_alloc_region,
|
||||||
|
"pre-condition of the call");
|
||||||
|
assert(cur_alloc_region->is_young(),
|
||||||
|
"we only support young current alloc regions");
|
||||||
|
|
||||||
|
// The region is guaranteed to be young
|
||||||
|
g1_policy()->add_region_to_incremental_cset_lhs(cur_alloc_region);
|
||||||
|
_summary_bytes_used += cur_alloc_region->used();
|
||||||
|
_cur_alloc_region = 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
|
||||||
|
// belongs to a young region.
|
||||||
|
inline void
|
||||||
|
G1CollectedHeap::dirty_young_block(HeapWord* start, size_t word_size) {
|
||||||
|
assert_heap_not_locked();
|
||||||
|
|
||||||
|
// Assign the containing region to containing_hr so that we don't
|
||||||
|
// have to keep calling heap_region_containing_raw() in the
|
||||||
|
// asserts below.
|
||||||
|
DEBUG_ONLY(HeapRegion* containing_hr = heap_region_containing_raw(start);)
|
||||||
|
assert(containing_hr != NULL && start != NULL && word_size > 0,
|
||||||
|
"pre-condition");
|
||||||
|
assert(containing_hr->is_in(start), "it should contain start");
|
||||||
|
assert(containing_hr->is_young(), "it should be young");
|
||||||
|
assert(!containing_hr->isHumongous(), "it should not be humongous");
|
||||||
|
|
||||||
|
HeapWord* end = start + word_size;
|
||||||
|
assert(containing_hr->is_in(end - 1), "it should also contain end - 1");
|
||||||
|
|
||||||
|
MemRegion mr(start, end);
|
||||||
|
((CardTableModRefBS*)_g1h->barrier_set())->dirty(mr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline RefToScanQueue* G1CollectedHeap::task_queue(int i) const {
|
inline RefToScanQueue* G1CollectedHeap::task_queue(int i) const {
|
||||||
|
|
|
@ -458,8 +458,8 @@ void G1CollectorPolicy::calculate_young_list_min_length() {
|
||||||
double now_sec = os::elapsedTime();
|
double now_sec = os::elapsedTime();
|
||||||
double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0;
|
double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0;
|
||||||
double alloc_rate_ms = predict_alloc_rate_ms();
|
double alloc_rate_ms = predict_alloc_rate_ms();
|
||||||
int min_regions = (int) ceil(alloc_rate_ms * when_ms);
|
size_t min_regions = (size_t) ceil(alloc_rate_ms * when_ms);
|
||||||
int current_region_num = (int) _g1->young_list()->length();
|
size_t current_region_num = _g1->young_list()->length();
|
||||||
_young_list_min_length = min_regions + current_region_num;
|
_young_list_min_length = min_regions + current_region_num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -473,9 +473,12 @@ void G1CollectorPolicy::calculate_young_list_target_length() {
|
||||||
_young_list_target_length = _young_list_fixed_length;
|
_young_list_target_length = _young_list_fixed_length;
|
||||||
else
|
else
|
||||||
_young_list_target_length = _young_list_fixed_length / 2;
|
_young_list_target_length = _young_list_fixed_length / 2;
|
||||||
|
|
||||||
_young_list_target_length = MAX2(_young_list_target_length, (size_t)1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure we allow the application to allocate at least one
|
||||||
|
// region before we need to do a collection again.
|
||||||
|
size_t min_length = _g1->young_list()->length() + 1;
|
||||||
|
_young_list_target_length = MAX2(_young_list_target_length, min_length);
|
||||||
calculate_survivors_policy();
|
calculate_survivors_policy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,7 +571,7 @@ void G1CollectorPolicy::calculate_young_list_target_length(size_t rs_lengths) {
|
||||||
|
|
||||||
// we should have at least one region in the target young length
|
// we should have at least one region in the target young length
|
||||||
_young_list_target_length =
|
_young_list_target_length =
|
||||||
MAX2((size_t) 1, final_young_length + _recorded_survivor_regions);
|
final_young_length + _recorded_survivor_regions;
|
||||||
|
|
||||||
// let's keep an eye of how long we spend on this calculation
|
// let's keep an eye of how long we spend on this calculation
|
||||||
// right now, I assume that we'll print it when we need it; we
|
// right now, I assume that we'll print it when we need it; we
|
||||||
|
@ -617,8 +620,7 @@ void G1CollectorPolicy::calculate_young_list_target_length(size_t rs_lengths) {
|
||||||
_young_list_min_length);
|
_young_list_min_length);
|
||||||
#endif // TRACE_CALC_YOUNG_LENGTH
|
#endif // TRACE_CALC_YOUNG_LENGTH
|
||||||
// we'll do the pause as soon as possible by choosing the minimum
|
// we'll do the pause as soon as possible by choosing the minimum
|
||||||
_young_list_target_length =
|
_young_list_target_length = _young_list_min_length;
|
||||||
MAX2(_young_list_min_length, (size_t) 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_rs_lengths_prediction = rs_lengths;
|
_rs_lengths_prediction = rs_lengths;
|
||||||
|
@ -824,9 +826,9 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec,
|
||||||
gclog_or_tty->print(" (%s)", full_young_gcs() ? "young" : "partial");
|
gclog_or_tty->print(" (%s)", full_young_gcs() ? "young" : "partial");
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(_g1->used_regions() == _g1->recalculate_used_regions(),
|
assert(_g1->used() == _g1->recalculate_used(),
|
||||||
"sanity");
|
err_msg("sanity, used: "SIZE_FORMAT" recalculate_used: "SIZE_FORMAT,
|
||||||
assert(_g1->used() == _g1->recalculate_used(), "sanity");
|
_g1->used(), _g1->recalculate_used()));
|
||||||
|
|
||||||
double s_w_t_ms = (start_time_sec - _stop_world_start) * 1000.0;
|
double s_w_t_ms = (start_time_sec - _stop_world_start) * 1000.0;
|
||||||
_all_stop_world_times_ms->add(s_w_t_ms);
|
_all_stop_world_times_ms->add(s_w_t_ms);
|
||||||
|
@ -2266,24 +2268,13 @@ void G1CollectorPolicy::print_yg_surv_rate_info() const {
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
G1CollectorPolicy::should_add_next_region_to_young_list() {
|
G1CollectorPolicy::update_region_num(bool young) {
|
||||||
assert(in_young_gc_mode(), "should be in young GC mode");
|
if (young) {
|
||||||
bool ret;
|
|
||||||
size_t young_list_length = _g1->young_list()->length();
|
|
||||||
size_t young_list_max_length = _young_list_target_length;
|
|
||||||
if (G1FixedEdenSize) {
|
|
||||||
young_list_max_length -= _max_survivor_regions;
|
|
||||||
}
|
|
||||||
if (young_list_length < young_list_max_length) {
|
|
||||||
ret = true;
|
|
||||||
++_region_num_young;
|
++_region_num_young;
|
||||||
} else {
|
} else {
|
||||||
ret = false;
|
|
||||||
++_region_num_tenured;
|
++_region_num_tenured;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
|
@ -2327,32 +2318,6 @@ void G1CollectorPolicy::calculate_survivors_policy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
G1CollectorPolicy_BestRegionsFirst::should_do_collection_pause(size_t
|
|
||||||
word_size) {
|
|
||||||
assert(_g1->regions_accounted_for(), "Region leakage!");
|
|
||||||
double max_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0;
|
|
||||||
|
|
||||||
size_t young_list_length = _g1->young_list()->length();
|
|
||||||
size_t young_list_max_length = _young_list_target_length;
|
|
||||||
if (G1FixedEdenSize) {
|
|
||||||
young_list_max_length -= _max_survivor_regions;
|
|
||||||
}
|
|
||||||
bool reached_target_length = young_list_length >= young_list_max_length;
|
|
||||||
|
|
||||||
if (in_young_gc_mode()) {
|
|
||||||
if (reached_target_length) {
|
|
||||||
assert( young_list_length > 0 && _g1->young_list()->length() > 0,
|
|
||||||
"invariant" );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
guarantee( false, "should not reach here" );
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
class HRSortIndexIsOKClosure: public HeapRegionClosure {
|
class HRSortIndexIsOKClosure: public HeapRegionClosure {
|
||||||
CollectionSetChooser* _chooser;
|
CollectionSetChooser* _chooser;
|
||||||
|
|
|
@ -993,11 +993,6 @@ public:
|
||||||
void record_before_bytes(size_t bytes);
|
void record_before_bytes(size_t bytes);
|
||||||
void record_after_bytes(size_t bytes);
|
void record_after_bytes(size_t bytes);
|
||||||
|
|
||||||
// Returns "true" if this is a good time to do a collection pause.
|
|
||||||
// The "word_size" argument, if non-zero, indicates the size of an
|
|
||||||
// allocation request that is prompting this query.
|
|
||||||
virtual bool should_do_collection_pause(size_t word_size) = 0;
|
|
||||||
|
|
||||||
// Choose a new collection set. Marks the chosen regions as being
|
// Choose a new collection set. Marks the chosen regions as being
|
||||||
// "in_collection_set", and links them together. The head and number of
|
// "in_collection_set", and links them together. The head and number of
|
||||||
// the collection set are available via access methods.
|
// the collection set are available via access methods.
|
||||||
|
@ -1116,7 +1111,16 @@ public:
|
||||||
// do that for any other surv rate groups
|
// do that for any other surv rate groups
|
||||||
}
|
}
|
||||||
|
|
||||||
bool should_add_next_region_to_young_list();
|
bool is_young_list_full() {
|
||||||
|
size_t young_list_length = _g1->young_list()->length();
|
||||||
|
size_t young_list_max_length = _young_list_target_length;
|
||||||
|
if (G1FixedEdenSize) {
|
||||||
|
young_list_max_length -= _max_survivor_regions;
|
||||||
|
}
|
||||||
|
|
||||||
|
return young_list_length >= young_list_max_length;
|
||||||
|
}
|
||||||
|
void update_region_num(bool young);
|
||||||
|
|
||||||
bool in_young_gc_mode() {
|
bool in_young_gc_mode() {
|
||||||
return _in_young_gc_mode;
|
return _in_young_gc_mode;
|
||||||
|
@ -1270,7 +1274,6 @@ public:
|
||||||
_collectionSetChooser = new CollectionSetChooser();
|
_collectionSetChooser = new CollectionSetChooser();
|
||||||
}
|
}
|
||||||
void record_collection_pause_end();
|
void record_collection_pause_end();
|
||||||
bool should_do_collection_pause(size_t word_size);
|
|
||||||
// This is not needed any more, after the CSet choosing code was
|
// This is not needed any more, after the CSet choosing code was
|
||||||
// changed to use the pause prediction work. But let's leave the
|
// changed to use the pause prediction work. But let's leave the
|
||||||
// hook in just in case.
|
// hook in just in case.
|
||||||
|
|
|
@ -27,13 +27,22 @@
|
||||||
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
|
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
|
||||||
#include "gc_implementation/g1/vm_operations_g1.hpp"
|
#include "gc_implementation/g1/vm_operations_g1.hpp"
|
||||||
#include "gc_implementation/shared/isGCActiveMark.hpp"
|
#include "gc_implementation/shared/isGCActiveMark.hpp"
|
||||||
|
#include "gc_implementation/g1/vm_operations_g1.hpp"
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
|
|
||||||
|
VM_G1CollectForAllocation::VM_G1CollectForAllocation(
|
||||||
|
unsigned int gc_count_before,
|
||||||
|
size_t word_size)
|
||||||
|
: VM_G1OperationWithAllocRequest(gc_count_before, word_size) {
|
||||||
|
guarantee(word_size > 0, "an allocation should always be requested");
|
||||||
|
}
|
||||||
|
|
||||||
void VM_G1CollectForAllocation::doit() {
|
void VM_G1CollectForAllocation::doit() {
|
||||||
JvmtiGCForAllocationMarker jgcm;
|
JvmtiGCForAllocationMarker jgcm;
|
||||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||||
_res = g1h->satisfy_failed_allocation(_size);
|
_result = g1h->satisfy_failed_allocation(_word_size, &_pause_succeeded);
|
||||||
assert(g1h->is_in_or_null(_res), "result not in heap");
|
assert(_result == NULL || _pause_succeeded,
|
||||||
|
"if we get back a result, the pause should have succeeded");
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM_G1CollectFull::doit() {
|
void VM_G1CollectFull::doit() {
|
||||||
|
@ -43,6 +52,25 @@ void VM_G1CollectFull::doit() {
|
||||||
g1h->do_full_collection(false /* clear_all_soft_refs */);
|
g1h->do_full_collection(false /* clear_all_soft_refs */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VM_G1IncCollectionPause::VM_G1IncCollectionPause(
|
||||||
|
unsigned int gc_count_before,
|
||||||
|
size_t word_size,
|
||||||
|
bool should_initiate_conc_mark,
|
||||||
|
double target_pause_time_ms,
|
||||||
|
GCCause::Cause gc_cause)
|
||||||
|
: VM_G1OperationWithAllocRequest(gc_count_before, word_size),
|
||||||
|
_should_initiate_conc_mark(should_initiate_conc_mark),
|
||||||
|
_target_pause_time_ms(target_pause_time_ms),
|
||||||
|
_full_collections_completed_before(0) {
|
||||||
|
guarantee(target_pause_time_ms > 0.0,
|
||||||
|
err_msg("target_pause_time_ms = %1.6lf should be positive",
|
||||||
|
target_pause_time_ms));
|
||||||
|
guarantee(word_size == 0 || gc_cause == GCCause::_g1_inc_collection_pause,
|
||||||
|
"we can only request an allocation if the GC cause is for "
|
||||||
|
"an incremental GC pause");
|
||||||
|
_gc_cause = gc_cause;
|
||||||
|
}
|
||||||
|
|
||||||
void VM_G1IncCollectionPause::doit() {
|
void VM_G1IncCollectionPause::doit() {
|
||||||
JvmtiGCForAllocationMarker jgcm;
|
JvmtiGCForAllocationMarker jgcm;
|
||||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||||
|
@ -51,6 +79,18 @@ void VM_G1IncCollectionPause::doit() {
|
||||||
(_gc_cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)),
|
(_gc_cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)),
|
||||||
"only a GC locker or a System.gc() induced GC should start a cycle");
|
"only a GC locker or a System.gc() induced GC should start a cycle");
|
||||||
|
|
||||||
|
if (_word_size > 0) {
|
||||||
|
// An allocation has been requested. So, try to do that first.
|
||||||
|
_result = g1h->attempt_allocation_at_safepoint(_word_size,
|
||||||
|
false /* expect_null_cur_alloc_region */);
|
||||||
|
if (_result != NULL) {
|
||||||
|
// If we can successfully allocate before we actually do the
|
||||||
|
// pause then we will consider this pause successful.
|
||||||
|
_pause_succeeded = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GCCauseSetter x(g1h, _gc_cause);
|
GCCauseSetter x(g1h, _gc_cause);
|
||||||
if (_should_initiate_conc_mark) {
|
if (_should_initiate_conc_mark) {
|
||||||
// It's safer to read full_collections_completed() here, given
|
// It's safer to read full_collections_completed() here, given
|
||||||
|
@ -63,7 +103,16 @@ void VM_G1IncCollectionPause::doit() {
|
||||||
// will do so if one is not already in progress.
|
// will do so if one is not already in progress.
|
||||||
bool res = g1h->g1_policy()->force_initial_mark_if_outside_cycle();
|
bool res = g1h->g1_policy()->force_initial_mark_if_outside_cycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_pause_succeeded =
|
||||||
g1h->do_collection_pause_at_safepoint(_target_pause_time_ms);
|
g1h->do_collection_pause_at_safepoint(_target_pause_time_ms);
|
||||||
|
if (_pause_succeeded && _word_size > 0) {
|
||||||
|
// An allocation had been requested.
|
||||||
|
_result = g1h->attempt_allocation_at_safepoint(_word_size,
|
||||||
|
true /* expect_null_cur_alloc_region */);
|
||||||
|
} else {
|
||||||
|
assert(_result == NULL, "invariant");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM_G1IncCollectionPause::doit_epilogue() {
|
void VM_G1IncCollectionPause::doit_epilogue() {
|
||||||
|
|
|
@ -31,9 +31,24 @@
|
||||||
// VM_GC_Operation:
|
// VM_GC_Operation:
|
||||||
// - VM_CGC_Operation
|
// - VM_CGC_Operation
|
||||||
// - VM_G1CollectFull
|
// - VM_G1CollectFull
|
||||||
|
// - VM_G1OperationWithAllocRequest
|
||||||
// - VM_G1CollectForAllocation
|
// - VM_G1CollectForAllocation
|
||||||
// - VM_G1IncCollectionPause
|
// - VM_G1IncCollectionPause
|
||||||
// - VM_G1PopRegionCollectionPause
|
|
||||||
|
class VM_G1OperationWithAllocRequest: public VM_GC_Operation {
|
||||||
|
protected:
|
||||||
|
size_t _word_size;
|
||||||
|
HeapWord* _result;
|
||||||
|
bool _pause_succeeded;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VM_G1OperationWithAllocRequest(unsigned int gc_count_before,
|
||||||
|
size_t word_size)
|
||||||
|
: VM_GC_Operation(gc_count_before),
|
||||||
|
_word_size(word_size), _result(NULL), _pause_succeeded(false) { }
|
||||||
|
HeapWord* result() { return _result; }
|
||||||
|
bool pause_succeeded() { return _pause_succeeded; }
|
||||||
|
};
|
||||||
|
|
||||||
class VM_G1CollectFull: public VM_GC_Operation {
|
class VM_G1CollectFull: public VM_GC_Operation {
|
||||||
public:
|
public:
|
||||||
|
@ -43,7 +58,6 @@ class VM_G1CollectFull: public VM_GC_Operation {
|
||||||
: VM_GC_Operation(gc_count_before, full_gc_count_before) {
|
: VM_GC_Operation(gc_count_before, full_gc_count_before) {
|
||||||
_gc_cause = cause;
|
_gc_cause = cause;
|
||||||
}
|
}
|
||||||
~VM_G1CollectFull() {}
|
|
||||||
virtual VMOp_Type type() const { return VMOp_G1CollectFull; }
|
virtual VMOp_Type type() const { return VMOp_G1CollectFull; }
|
||||||
virtual void doit();
|
virtual void doit();
|
||||||
virtual const char* name() const {
|
virtual const char* name() const {
|
||||||
|
@ -51,45 +65,28 @@ class VM_G1CollectFull: public VM_GC_Operation {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class VM_G1CollectForAllocation: public VM_GC_Operation {
|
class VM_G1CollectForAllocation: public VM_G1OperationWithAllocRequest {
|
||||||
private:
|
|
||||||
HeapWord* _res;
|
|
||||||
size_t _size; // size of object to be allocated
|
|
||||||
public:
|
public:
|
||||||
VM_G1CollectForAllocation(size_t size, int gc_count_before)
|
VM_G1CollectForAllocation(unsigned int gc_count_before,
|
||||||
: VM_GC_Operation(gc_count_before) {
|
size_t word_size);
|
||||||
_size = size;
|
|
||||||
_res = NULL;
|
|
||||||
}
|
|
||||||
~VM_G1CollectForAllocation() {}
|
|
||||||
virtual VMOp_Type type() const { return VMOp_G1CollectForAllocation; }
|
virtual VMOp_Type type() const { return VMOp_G1CollectForAllocation; }
|
||||||
virtual void doit();
|
virtual void doit();
|
||||||
virtual const char* name() const {
|
virtual const char* name() const {
|
||||||
return "garbage-first collection to satisfy allocation";
|
return "garbage-first collection to satisfy allocation";
|
||||||
}
|
}
|
||||||
HeapWord* result() { return _res; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class VM_G1IncCollectionPause: public VM_GC_Operation {
|
class VM_G1IncCollectionPause: public VM_G1OperationWithAllocRequest {
|
||||||
private:
|
private:
|
||||||
bool _should_initiate_conc_mark;
|
bool _should_initiate_conc_mark;
|
||||||
double _target_pause_time_ms;
|
double _target_pause_time_ms;
|
||||||
unsigned int _full_collections_completed_before;
|
unsigned int _full_collections_completed_before;
|
||||||
public:
|
public:
|
||||||
VM_G1IncCollectionPause(unsigned int gc_count_before,
|
VM_G1IncCollectionPause(unsigned int gc_count_before,
|
||||||
|
size_t word_size,
|
||||||
bool should_initiate_conc_mark,
|
bool should_initiate_conc_mark,
|
||||||
double target_pause_time_ms,
|
double target_pause_time_ms,
|
||||||
GCCause::Cause cause)
|
GCCause::Cause gc_cause);
|
||||||
: VM_GC_Operation(gc_count_before),
|
|
||||||
_full_collections_completed_before(0),
|
|
||||||
_should_initiate_conc_mark(should_initiate_conc_mark),
|
|
||||||
_target_pause_time_ms(target_pause_time_ms) {
|
|
||||||
guarantee(target_pause_time_ms > 0.0,
|
|
||||||
err_msg("target_pause_time_ms = %1.6lf should be positive",
|
|
||||||
target_pause_time_ms));
|
|
||||||
|
|
||||||
_gc_cause = cause;
|
|
||||||
}
|
|
||||||
virtual VMOp_Type type() const { return VMOp_G1IncCollectionPause; }
|
virtual VMOp_Type type() const { return VMOp_G1IncCollectionPause; }
|
||||||
virtual void doit();
|
virtual void doit();
|
||||||
virtual void doit_epilogue();
|
virtual void doit_epilogue();
|
||||||
|
@ -104,13 +101,8 @@ class VM_CGC_Operation: public VM_Operation {
|
||||||
VoidClosure* _cl;
|
VoidClosure* _cl;
|
||||||
const char* _printGCMessage;
|
const char* _printGCMessage;
|
||||||
public:
|
public:
|
||||||
VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg) :
|
VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg)
|
||||||
_cl(cl),
|
: _cl(cl), _printGCMessage(printGCMsg) { }
|
||||||
_printGCMessage(printGCMsg)
|
|
||||||
{}
|
|
||||||
|
|
||||||
~VM_CGC_Operation() {}
|
|
||||||
|
|
||||||
virtual VMOp_Type type() const { return VMOp_CGC_Operation; }
|
virtual VMOp_Type type() const { return VMOp_CGC_Operation; }
|
||||||
virtual void doit();
|
virtual void doit();
|
||||||
virtual bool doit_prologue();
|
virtual bool doit_prologue();
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP
|
#define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP
|
||||||
|
|
||||||
#include "memory/allocation.hpp"
|
#include "memory/allocation.hpp"
|
||||||
|
#include "memory/blockOffsetTable.hpp"
|
||||||
#include "memory/threadLocalAllocBuffer.hpp"
|
#include "memory/threadLocalAllocBuffer.hpp"
|
||||||
#include "utilities/globalDefinitions.hpp"
|
#include "utilities/globalDefinitions.hpp"
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_HPP
|
#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_HPP
|
||||||
#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_HPP
|
#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_HPP
|
||||||
|
|
||||||
|
#include "memory/memRegion.hpp"
|
||||||
#include "gc_implementation/parallelScavenge/psVirtualspace.hpp"
|
#include "gc_implementation/parallelScavenge/psVirtualspace.hpp"
|
||||||
#include "utilities/bitMap.inline.hpp"
|
#include "utilities/bitMap.inline.hpp"
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_INLINE_HPP
|
#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_INLINE_HPP
|
||||||
#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_INLINE_HPP
|
#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_INLINE_HPP
|
||||||
|
|
||||||
|
#include "oops/oop.hpp"
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
ParMarkBitMap::mark_obj(oop obj)
|
ParMarkBitMap::mark_obj(oop obj)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1323,12 +1323,7 @@ run:
|
||||||
jfloat f;
|
jfloat f;
|
||||||
jdouble r;
|
jdouble r;
|
||||||
f = STACK_FLOAT(-1);
|
f = STACK_FLOAT(-1);
|
||||||
#ifdef IA64
|
|
||||||
// IA64 gcc bug
|
|
||||||
r = ( f == 0.0f ) ? (jdouble) f : (jdouble) f + ia64_double_zero;
|
|
||||||
#else
|
|
||||||
r = (jdouble) f;
|
r = (jdouble) f;
|
||||||
#endif
|
|
||||||
MORE_STACK(-1); // POP
|
MORE_STACK(-1); // POP
|
||||||
SET_STACK_DOUBLE(r, 1);
|
SET_STACK_DOUBLE(r, 1);
|
||||||
UPDATE_PC_AND_TOS_AND_CONTINUE(1, 2);
|
UPDATE_PC_AND_TOS_AND_CONTINUE(1, 2);
|
||||||
|
|
|
@ -1193,9 +1193,20 @@ void SignatureHandlerLibrary::add(methodHandle method) {
|
||||||
method->set_signature_handler(_handlers->at(handler_index));
|
method->set_signature_handler(_handlers->at(handler_index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef ASSERT
|
||||||
|
int handler_index, fingerprint_index;
|
||||||
|
{
|
||||||
|
// '_handlers' and '_fingerprints' are 'GrowableArray's and are NOT synchronized
|
||||||
|
// in any way if accessed from multiple threads. To avoid races with another
|
||||||
|
// thread which may change the arrays in the above, mutex protected block, we
|
||||||
|
// have to protect this read access here with the same mutex as well!
|
||||||
|
MutexLocker mu(SignatureHandlerLibrary_lock);
|
||||||
|
handler_index = _handlers->find(method->signature_handler());
|
||||||
|
fingerprint_index = _fingerprints->find(Fingerprinter(method).fingerprint());
|
||||||
|
}
|
||||||
assert(method->signature_handler() == Interpreter::slow_signature_handler() ||
|
assert(method->signature_handler() == Interpreter::slow_signature_handler() ||
|
||||||
_handlers->find(method->signature_handler()) == _fingerprints->find(Fingerprinter(method).fingerprint()),
|
handler_index == fingerprint_index, "sanity check");
|
||||||
"sanity check");
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#define SHARE_VM_INTERPRETER_OOPMAPCACHE_HPP
|
#define SHARE_VM_INTERPRETER_OOPMAPCACHE_HPP
|
||||||
|
|
||||||
#include "oops/generateOopMap.hpp"
|
#include "oops/generateOopMap.hpp"
|
||||||
|
#include "runtime/mutex.hpp"
|
||||||
|
|
||||||
// A Cache for storing (method, bci) -> oopMap.
|
// A Cache for storing (method, bci) -> oopMap.
|
||||||
// The memory management system uses the cache when locating object
|
// The memory management system uses the cache when locating object
|
||||||
|
|
|
@ -249,10 +249,10 @@ int VectorSet::disjoint(const Set &set) const
|
||||||
const VectorSet &s = *(set.asVectorSet());
|
const VectorSet &s = *(set.asVectorSet());
|
||||||
|
|
||||||
// NOTE: The intersection is never any larger than the smallest set.
|
// NOTE: The intersection is never any larger than the smallest set.
|
||||||
register uint small = ((size<s.size)?size:s.size);
|
register uint small_size = ((size<s.size)?size:s.size);
|
||||||
register uint32 *u1 = data; // Pointer to the destination data
|
register uint32 *u1 = data; // Pointer to the destination data
|
||||||
register uint32 *u2 = s.data; // Pointer to the source data
|
register uint32 *u2 = s.data; // Pointer to the source data
|
||||||
for( uint i=0; i<small; i++) // For data in set
|
for( uint i=0; i<small_size; i++) // For data in set
|
||||||
if( *u1++ & *u2++ ) // If any elements in common
|
if( *u1++ & *u2++ ) // If any elements in common
|
||||||
return 0; // Then not disjoint
|
return 0; // Then not disjoint
|
||||||
return 1; // Else disjoint
|
return 1; // Else disjoint
|
||||||
|
|
|
@ -1365,7 +1365,7 @@ void GenCollectedHeap::preload_and_dump(TRAPS) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
|
|
||||||
// Preload classes to be shared.
|
// Preload classes to be shared.
|
||||||
// Should use some hpi:: method rather than fopen() here. aB.
|
// Should use some os:: method rather than fopen() here. aB.
|
||||||
// Construct the path to the class list (in jre/lib)
|
// Construct the path to the class list (in jre/lib)
|
||||||
// Walk up two directories from the location of the VM and
|
// Walk up two directories from the location of the VM and
|
||||||
// optionally tack on "lib" (depending on platform)
|
// optionally tack on "lib" (depending on platform)
|
||||||
|
@ -1504,7 +1504,7 @@ void GenCollectedHeap::preload_and_dump(TRAPS) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
char errmsg[JVM_MAXPATHLEN];
|
char errmsg[JVM_MAXPATHLEN];
|
||||||
hpi::lasterror(errmsg, JVM_MAXPATHLEN);
|
os::lasterror(errmsg, JVM_MAXPATHLEN);
|
||||||
tty->print_cr("Loading classlist failed: %s", errmsg);
|
tty->print_cr("Loading classlist failed: %s", errmsg);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,15 +30,6 @@
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
#include "runtime/os.hpp"
|
#include "runtime/os.hpp"
|
||||||
#include "utilities/defaultStream.hpp"
|
#include "utilities/defaultStream.hpp"
|
||||||
#ifdef TARGET_OS_FAMILY_linux
|
|
||||||
# include "hpi_linux.hpp"
|
|
||||||
#endif
|
|
||||||
#ifdef TARGET_OS_FAMILY_solaris
|
|
||||||
# include "hpi_solaris.hpp"
|
|
||||||
#endif
|
|
||||||
#ifdef TARGET_OS_FAMILY_windows
|
|
||||||
# include "hpi_windows.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
# include <errno.h>
|
# include <errno.h>
|
||||||
|
|
|
@ -770,8 +770,7 @@ void ReferenceProcessor::abandon_partial_discovery() {
|
||||||
// loop over the lists
|
// loop over the lists
|
||||||
for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) {
|
for (int i = 0; i < _max_num_q * subclasses_of_ref; i++) {
|
||||||
if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) {
|
if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) {
|
||||||
gclog_or_tty->print_cr(
|
gclog_or_tty->print_cr("\nAbandoning %s discovered list",
|
||||||
"\nAbandoning %s discovered list",
|
|
||||||
list_name(i));
|
list_name(i));
|
||||||
}
|
}
|
||||||
abandon_partial_discovered_list(_discoveredSoftRefs[i]);
|
abandon_partial_discovered_list(_discoveredSoftRefs[i]);
|
||||||
|
@ -1059,9 +1058,7 @@ inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt)
|
||||||
// During a multi-threaded discovery phase,
|
// During a multi-threaded discovery phase,
|
||||||
// each thread saves to its "own" list.
|
// each thread saves to its "own" list.
|
||||||
Thread* thr = Thread::current();
|
Thread* thr = Thread::current();
|
||||||
assert(thr->is_GC_task_thread(),
|
id = thr->as_Worker_thread()->id();
|
||||||
"Dubious cast from Thread* to WorkerThread*?");
|
|
||||||
id = ((WorkerThread*)thr)->id();
|
|
||||||
} else {
|
} else {
|
||||||
// single-threaded discovery, we save in round-robin
|
// single-threaded discovery, we save in round-robin
|
||||||
// fashion to each of the lists.
|
// fashion to each of the lists.
|
||||||
|
@ -1095,8 +1092,7 @@ inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt)
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
if (TraceReferenceGC && PrintGCDetails) {
|
if (TraceReferenceGC && PrintGCDetails) {
|
||||||
gclog_or_tty->print_cr("Thread %d gets list " INTPTR_FORMAT,
|
gclog_or_tty->print_cr("Thread %d gets list " INTPTR_FORMAT, id, list);
|
||||||
id, list);
|
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
@ -1135,6 +1131,11 @@ ReferenceProcessor::add_to_discovered_list_mt(DiscoveredList& refs_list,
|
||||||
if (_discovered_list_needs_barrier) {
|
if (_discovered_list_needs_barrier) {
|
||||||
_bs->write_ref_field((void*)discovered_addr, current_head);
|
_bs->write_ref_field((void*)discovered_addr, current_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TraceReferenceGC) {
|
||||||
|
gclog_or_tty->print_cr("Enqueued reference (mt) (" INTPTR_FORMAT ": %s)",
|
||||||
|
obj, obj->blueprint()->internal_name());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// If retest was non NULL, another thread beat us to it:
|
// If retest was non NULL, another thread beat us to it:
|
||||||
// The reference has already been discovered...
|
// The reference has already been discovered...
|
||||||
|
@ -1239,8 +1240,8 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) {
|
||||||
// Check assumption that an object is not potentially
|
// Check assumption that an object is not potentially
|
||||||
// discovered twice except by concurrent collectors that potentially
|
// discovered twice except by concurrent collectors that potentially
|
||||||
// trace the same Reference object twice.
|
// trace the same Reference object twice.
|
||||||
assert(UseConcMarkSweepGC,
|
assert(UseConcMarkSweepGC || UseG1GC,
|
||||||
"Only possible with an incremental-update concurrent collector");
|
"Only possible with a concurrent marking collector");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1293,26 +1294,14 @@ bool ReferenceProcessor::discover_reference(oop obj, ReferenceType rt) {
|
||||||
}
|
}
|
||||||
list->set_head(obj);
|
list->set_head(obj);
|
||||||
list->inc_length(1);
|
list->inc_length(1);
|
||||||
}
|
|
||||||
|
|
||||||
// In the MT discovery case, it is currently possible to see
|
|
||||||
// the following message multiple times if several threads
|
|
||||||
// discover a reference about the same time. Only one will
|
|
||||||
// however have actually added it to the disocvered queue.
|
|
||||||
// One could let add_to_discovered_list_mt() return an
|
|
||||||
// indication for success in queueing (by 1 thread) or
|
|
||||||
// failure (by all other threads), but I decided the extra
|
|
||||||
// code was not worth the effort for something that is
|
|
||||||
// only used for debugging support.
|
|
||||||
if (TraceReferenceGC) {
|
if (TraceReferenceGC) {
|
||||||
oop referent = java_lang_ref_Reference::referent(obj);
|
|
||||||
if (PrintGCDetails) {
|
|
||||||
gclog_or_tty->print_cr("Enqueued reference (" INTPTR_FORMAT ": %s)",
|
gclog_or_tty->print_cr("Enqueued reference (" INTPTR_FORMAT ": %s)",
|
||||||
obj, obj->blueprint()->internal_name());
|
obj, obj->blueprint()->internal_name());
|
||||||
}
|
}
|
||||||
assert(referent->is_oop(), "Enqueued a bad referent");
|
|
||||||
}
|
}
|
||||||
assert(obj->is_oop(), "Enqueued a bad reference");
|
assert(obj->is_oop(), "Enqueued a bad reference");
|
||||||
|
assert(java_lang_ref_Reference::referent(obj)->is_oop(), "Enqueued a bad referent");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "gc_interface/collectedHeap.hpp"
|
#include "gc_interface/collectedHeap.hpp"
|
||||||
#include "memory/threadLocalAllocBuffer.hpp"
|
#include "memory/threadLocalAllocBuffer.hpp"
|
||||||
#include "runtime/atomic.hpp"
|
#include "runtime/atomic.hpp"
|
||||||
|
#include "runtime/thread.hpp"
|
||||||
#include "utilities/copy.hpp"
|
#include "utilities/copy.hpp"
|
||||||
|
|
||||||
inline HeapWord* ThreadLocalAllocBuffer::allocate(size_t size) {
|
inline HeapWord* ThreadLocalAllocBuffer::allocate(size_t size) {
|
||||||
|
|
|
@ -457,6 +457,11 @@ void instanceRefKlass::oop_verify_on(oop obj, outputStream* st) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool instanceRefKlass::owns_pending_list_lock(JavaThread* thread) {
|
||||||
|
Handle h_lock(thread, java_lang_ref_Reference::pending_list_lock());
|
||||||
|
return ObjectSynchronizer::current_thread_holds_lock(thread, h_lock);
|
||||||
|
}
|
||||||
|
|
||||||
void instanceRefKlass::acquire_pending_list_lock(BasicLock *pending_list_basic_lock) {
|
void instanceRefKlass::acquire_pending_list_lock(BasicLock *pending_list_basic_lock) {
|
||||||
// we may enter this with pending exception set
|
// we may enter this with pending exception set
|
||||||
PRESERVE_EXCEPTION_MARK; // exceptions are never thrown, needed for TRAPS argument
|
PRESERVE_EXCEPTION_MARK; // exceptions are never thrown, needed for TRAPS argument
|
||||||
|
|
|
@ -89,6 +89,7 @@ class instanceRefKlass: public instanceKlass {
|
||||||
|
|
||||||
static void release_and_notify_pending_list_lock(BasicLock *pending_list_basic_lock);
|
static void release_and_notify_pending_list_lock(BasicLock *pending_list_basic_lock);
|
||||||
static void acquire_pending_list_lock(BasicLock *pending_list_basic_lock);
|
static void acquire_pending_list_lock(BasicLock *pending_list_basic_lock);
|
||||||
|
static bool owns_pending_list_lock(JavaThread* thread);
|
||||||
|
|
||||||
// Update non-static oop maps so 'referent', 'nextPending' and
|
// Update non-static oop maps so 'referent', 'nextPending' and
|
||||||
// 'discovered' will look like non-oops
|
// 'discovered' will look like non-oops
|
||||||
|
|
|
@ -518,18 +518,21 @@ bool klassVtable::is_miranda_entry_at(int i) {
|
||||||
bool klassVtable::is_miranda(methodOop m, objArrayOop class_methods, klassOop super) {
|
bool klassVtable::is_miranda(methodOop m, objArrayOop class_methods, klassOop super) {
|
||||||
symbolOop name = m->name();
|
symbolOop name = m->name();
|
||||||
symbolOop signature = m->signature();
|
symbolOop signature = m->signature();
|
||||||
|
|
||||||
if (instanceKlass::find_method(class_methods, name, signature) == NULL) {
|
if (instanceKlass::find_method(class_methods, name, signature) == NULL) {
|
||||||
// did not find it in the method table of the current class
|
// did not find it in the method table of the current class
|
||||||
if (super == NULL) {
|
if (super == NULL) {
|
||||||
// super doesn't exist
|
// super doesn't exist
|
||||||
return true;
|
return true;
|
||||||
} else {
|
}
|
||||||
if (instanceKlass::cast(super)->lookup_method(name, signature) == NULL) {
|
|
||||||
// super class hierarchy does not implement it
|
methodOop mo = instanceKlass::cast(super)->lookup_method(name, signature);
|
||||||
|
if (mo == NULL || mo->access_flags().is_private() ) {
|
||||||
|
// super class hierarchy does not implement it or protection is different
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -309,6 +309,12 @@ void methodOopDesc::print_invocation_count() {
|
||||||
// Build a methodDataOop object to hold information about this method
|
// Build a methodDataOop object to hold information about this method
|
||||||
// collected in the interpreter.
|
// collected in the interpreter.
|
||||||
void methodOopDesc::build_interpreter_method_data(methodHandle method, TRAPS) {
|
void methodOopDesc::build_interpreter_method_data(methodHandle method, TRAPS) {
|
||||||
|
// Do not profile method if current thread holds the pending list lock,
|
||||||
|
// which avoids deadlock for acquiring the MethodData_lock.
|
||||||
|
if (instanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Grab a lock here to prevent multiple
|
// Grab a lock here to prevent multiple
|
||||||
// methodDataOops from being created.
|
// methodDataOops from being created.
|
||||||
MutexLocker ml(MethodData_lock, THREAD);
|
MutexLocker ml(MethodData_lock, THREAD);
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
#include "opto/runtime.hpp"
|
#include "opto/runtime.hpp"
|
||||||
#include "opto/type.hpp"
|
#include "opto/type.hpp"
|
||||||
#include "runtime/atomic.hpp"
|
#include "runtime/atomic.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/os.hpp"
|
#include "runtime/os.hpp"
|
||||||
#ifdef TARGET_ARCH_MODEL_x86_32
|
#ifdef TARGET_ARCH_MODEL_x86_32
|
||||||
# include "adfiles/ad_x86_32.hpp"
|
# include "adfiles/ad_x86_32.hpp"
|
||||||
|
|
|
@ -22,6 +22,10 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Precompiled headers are turned off for Sun Studion,
|
||||||
|
// or if the user passes USE_PRECOMPILED_HEADER=0 to the makefiles.
|
||||||
|
#ifndef DONT_USE_PRECOMPILED_HEADER
|
||||||
|
|
||||||
# include "asm/assembler.hpp"
|
# include "asm/assembler.hpp"
|
||||||
# include "asm/assembler.inline.hpp"
|
# include "asm/assembler.inline.hpp"
|
||||||
# include "asm/codeBuffer.hpp"
|
# include "asm/codeBuffer.hpp"
|
||||||
|
@ -168,7 +172,6 @@
|
||||||
# include "oops/symbolOop.hpp"
|
# include "oops/symbolOop.hpp"
|
||||||
# include "oops/typeArrayKlass.hpp"
|
# include "oops/typeArrayKlass.hpp"
|
||||||
# include "oops/typeArrayOop.hpp"
|
# include "oops/typeArrayOop.hpp"
|
||||||
# include "prims/hpi_imported.h"
|
|
||||||
# include "prims/jni.h"
|
# include "prims/jni.h"
|
||||||
# include "prims/jvm.h"
|
# include "prims/jvm.h"
|
||||||
# include "prims/jvmtiExport.hpp"
|
# include "prims/jvmtiExport.hpp"
|
||||||
|
@ -185,7 +188,6 @@
|
||||||
# include "runtime/globals_extension.hpp"
|
# include "runtime/globals_extension.hpp"
|
||||||
# include "runtime/handles.hpp"
|
# include "runtime/handles.hpp"
|
||||||
# include "runtime/handles.inline.hpp"
|
# include "runtime/handles.inline.hpp"
|
||||||
# include "runtime/hpi.hpp"
|
|
||||||
# include "runtime/icache.hpp"
|
# include "runtime/icache.hpp"
|
||||||
# include "runtime/init.hpp"
|
# include "runtime/init.hpp"
|
||||||
# include "runtime/interfaceSupport.hpp"
|
# include "runtime/interfaceSupport.hpp"
|
||||||
|
@ -325,3 +327,5 @@
|
||||||
# include "gc_implementation/shared/gcAdaptivePolicyCounters.hpp"
|
# include "gc_implementation/shared/gcAdaptivePolicyCounters.hpp"
|
||||||
# include "gc_implementation/shared/gcPolicyCounters.hpp"
|
# include "gc_implementation/shared/gcPolicyCounters.hpp"
|
||||||
#endif // SERIALGC
|
#endif // SERIALGC
|
||||||
|
|
||||||
|
#endif // !DONT_USE_PRECOMPILED_HEADER
|
||||||
|
|
|
@ -1,319 +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.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HotSpot integration note:
|
|
||||||
*
|
|
||||||
* This is a consolidation of these two files:
|
|
||||||
* src/share/hpi/export/hpi.h 1.15 99/06/18 JDK1.3 beta build I
|
|
||||||
* src/share/hpi/export/dll.h 1.3 98/09/15 JDK1.3 beta build I
|
|
||||||
* from the classic VM.
|
|
||||||
*
|
|
||||||
* bool_t is a type in the classic VM, and we define it here,
|
|
||||||
* but in the future this should be a jboolean.
|
|
||||||
*
|
|
||||||
* The files are included verbatim expect for local includes removed from hpi.h.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SHARE_VM_PRIMS_HPI_IMPORTED_H
|
|
||||||
#define SHARE_VM_PRIMS_HPI_IMPORTED_H
|
|
||||||
|
|
||||||
#include "jni.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* A classic VMism that should become a jboolean. Fix in 1.2.1? */
|
|
||||||
typedef enum { HPI_FALSE = 0, HPI_TRUE = 1 } bool_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
typedef jint (JNICALL * GetInterfaceFunc)
|
|
||||||
(void **intfP, const char *name, jint ver);
|
|
||||||
|
|
||||||
jint JNICALL DLL_Initialize(GetInterfaceFunc *, void *args);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Host Porting Interface. This defines the "porting layer" for
|
|
||||||
* POSIX.1 compliant operating systems.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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, const 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;
|
|
||||||
int 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);
|
|
||||||
int (*SendTo)(int fd, char *buf, int len, int flags,
|
|
||||||
struct sockaddr *to, int tolen);
|
|
||||||
int (*RecvFrom)(int fd, char *buf, int nbytes, int flags,
|
|
||||||
struct sockaddr *from, int *fromlen);
|
|
||||||
int (*Listen)(int fd, long count);
|
|
||||||
int (*Recv)(int fd, char *buf, int nBytes, int flags);
|
|
||||||
int (*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 // SHARE_VM_PRIMS_HPI_IMPORTED_H
|
|
|
@ -2113,11 +2113,10 @@ JNI_END
|
||||||
JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy))
|
JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy))
|
||||||
JNIWrapper("GetStringUTFChars");
|
JNIWrapper("GetStringUTFChars");
|
||||||
DTRACE_PROBE3(hotspot_jni, GetStringUTFChars__entry, env, string, isCopy);
|
DTRACE_PROBE3(hotspot_jni, GetStringUTFChars__entry, env, string, isCopy);
|
||||||
ResourceMark rm;
|
oop java_string = JNIHandles::resolve_non_null(string);
|
||||||
char* str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(string));
|
size_t length = java_lang_String::utf8_length(java_string);
|
||||||
int length = (int)strlen(str);
|
|
||||||
char* result = AllocateHeap(length + 1, "GetStringUTFChars");
|
char* result = AllocateHeap(length + 1, "GetStringUTFChars");
|
||||||
strcpy(result, str);
|
java_lang_String::as_utf8_string(java_string, result, (int) length + 1);
|
||||||
if (isCopy != NULL) *isCopy = JNI_TRUE;
|
if (isCopy != NULL) *isCopy = JNI_TRUE;
|
||||||
DTRACE_PROBE1(hotspot_jni, GetStringUTFChars__return, result);
|
DTRACE_PROBE1(hotspot_jni, GetStringUTFChars__return, result);
|
||||||
return result;
|
return result;
|
||||||
|
@ -3258,7 +3257,6 @@ struct JavaVM_ main_vm = {&jni_InvokeInterface};
|
||||||
|
|
||||||
|
|
||||||
#define JAVASTACKSIZE (400 * 1024) /* Default size of a thread java stack */
|
#define JAVASTACKSIZE (400 * 1024) /* Default size of a thread java stack */
|
||||||
#define PROCSTACKSIZE 0 /* 0 means default size in HPI */
|
|
||||||
enum { VERIFY_NONE, VERIFY_REMOTE, VERIFY_ALL };
|
enum { VERIFY_NONE, VERIFY_REMOTE, VERIFY_ALL };
|
||||||
|
|
||||||
HS_DTRACE_PROBE_DECL1(hotspot_jni, GetDefaultJavaVMInitArgs__entry, void*);
|
HS_DTRACE_PROBE_DECL1(hotspot_jni, GetDefaultJavaVMInitArgs__entry, void*);
|
||||||
|
|
|
@ -1288,6 +1288,9 @@ JNI_ENTRY_CHECKED(jsize,
|
||||||
return result;
|
return result;
|
||||||
JNI_END
|
JNI_END
|
||||||
|
|
||||||
|
// Arbitrary (but well-known) tag
|
||||||
|
const jint STRING_TAG = 0x47114711;
|
||||||
|
|
||||||
JNI_ENTRY_CHECKED(const jchar *,
|
JNI_ENTRY_CHECKED(const jchar *,
|
||||||
checked_jni_GetStringChars(JNIEnv *env,
|
checked_jni_GetStringChars(JNIEnv *env,
|
||||||
jstring str,
|
jstring str,
|
||||||
|
@ -1297,8 +1300,19 @@ JNI_ENTRY_CHECKED(const jchar *,
|
||||||
checkString(thr, str);
|
checkString(thr, str);
|
||||||
)
|
)
|
||||||
const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy);
|
const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy);
|
||||||
|
assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringChars didn't return a copy as expected");
|
||||||
|
|
||||||
|
size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination
|
||||||
|
jint* tagLocation = (jint*) AllocateHeap(len * sizeof(jchar) + sizeof(jint), "checked_jni_GetStringChars");
|
||||||
|
*tagLocation = STRING_TAG;
|
||||||
|
jchar* newResult = (jchar*) (tagLocation + 1);
|
||||||
|
memcpy(newResult, result, len * sizeof(jchar));
|
||||||
|
// Avoiding call to UNCHECKED()->ReleaseStringChars() since that will fire unexpected dtrace probes
|
||||||
|
// Note that the dtrace arguments for the allocated memory will not match up with this solution.
|
||||||
|
FreeHeap((char*)result);
|
||||||
|
|
||||||
functionExit(env);
|
functionExit(env);
|
||||||
return result;
|
return newResult;
|
||||||
JNI_END
|
JNI_END
|
||||||
|
|
||||||
JNI_ENTRY_CHECKED(void,
|
JNI_ENTRY_CHECKED(void,
|
||||||
|
@ -1309,11 +1323,17 @@ JNI_ENTRY_CHECKED(void,
|
||||||
IN_VM(
|
IN_VM(
|
||||||
checkString(thr, str);
|
checkString(thr, str);
|
||||||
)
|
)
|
||||||
/* cannot check validity of copy, unless every request is logged by
|
if (chars == NULL) {
|
||||||
* checking code. Implementation of this check is deferred until a
|
// still do the unchecked call to allow dtrace probes
|
||||||
* subsequent release.
|
|
||||||
*/
|
|
||||||
UNCHECKED()->ReleaseStringChars(env,str,chars);
|
UNCHECKED()->ReleaseStringChars(env,str,chars);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jint* tagLocation = ((jint*) chars) - 1;
|
||||||
|
if (*tagLocation != STRING_TAG) {
|
||||||
|
NativeReportJNIFatalError(thr, "ReleaseStringChars called on something not allocated by GetStringChars");
|
||||||
|
}
|
||||||
|
UNCHECKED()->ReleaseStringChars(env,str,(const jchar*)tagLocation);
|
||||||
|
}
|
||||||
functionExit(env);
|
functionExit(env);
|
||||||
JNI_END
|
JNI_END
|
||||||
|
|
||||||
|
@ -1338,6 +1358,9 @@ JNI_ENTRY_CHECKED(jsize,
|
||||||
return result;
|
return result;
|
||||||
JNI_END
|
JNI_END
|
||||||
|
|
||||||
|
// Arbitrary (but well-known) tag - different than GetStringChars
|
||||||
|
const jint STRING_UTF_TAG = 0x48124812;
|
||||||
|
|
||||||
JNI_ENTRY_CHECKED(const char *,
|
JNI_ENTRY_CHECKED(const char *,
|
||||||
checked_jni_GetStringUTFChars(JNIEnv *env,
|
checked_jni_GetStringUTFChars(JNIEnv *env,
|
||||||
jstring str,
|
jstring str,
|
||||||
|
@ -1347,8 +1370,19 @@ JNI_ENTRY_CHECKED(const char *,
|
||||||
checkString(thr, str);
|
checkString(thr, str);
|
||||||
)
|
)
|
||||||
const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy);
|
const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy);
|
||||||
|
assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringUTFChars didn't return a copy as expected");
|
||||||
|
|
||||||
|
size_t len = strlen(result) + 1; // + 1 for NULL termination
|
||||||
|
jint* tagLocation = (jint*) AllocateHeap(len + sizeof(jint), "checked_jni_GetStringUTFChars");
|
||||||
|
*tagLocation = STRING_UTF_TAG;
|
||||||
|
char* newResult = (char*) (tagLocation + 1);
|
||||||
|
strcpy(newResult, result);
|
||||||
|
// Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes
|
||||||
|
// Note that the dtrace arguments for the allocated memory will not match up with this solution.
|
||||||
|
FreeHeap((char*)result);
|
||||||
|
|
||||||
functionExit(env);
|
functionExit(env);
|
||||||
return result;
|
return newResult;
|
||||||
JNI_END
|
JNI_END
|
||||||
|
|
||||||
JNI_ENTRY_CHECKED(void,
|
JNI_ENTRY_CHECKED(void,
|
||||||
|
@ -1359,11 +1393,17 @@ JNI_ENTRY_CHECKED(void,
|
||||||
IN_VM(
|
IN_VM(
|
||||||
checkString(thr, str);
|
checkString(thr, str);
|
||||||
)
|
)
|
||||||
/* cannot check validity of copy, unless every request is logged by
|
if (chars == NULL) {
|
||||||
* checking code. Implementation of this check is deferred until a
|
// still do the unchecked call to allow dtrace probes
|
||||||
* subsequent release.
|
|
||||||
*/
|
|
||||||
UNCHECKED()->ReleaseStringUTFChars(env,str,chars);
|
UNCHECKED()->ReleaseStringUTFChars(env,str,chars);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jint* tagLocation = ((jint*) chars) - 1;
|
||||||
|
if (*tagLocation != STRING_UTF_TAG) {
|
||||||
|
NativeReportJNIFatalError(thr, "ReleaseStringUTFChars called on something not allocated by GetStringUTFChars");
|
||||||
|
}
|
||||||
|
UNCHECKED()->ReleaseStringUTFChars(env,str,(const char*)tagLocation);
|
||||||
|
}
|
||||||
functionExit(env);
|
functionExit(env);
|
||||||
JNI_END
|
JNI_END
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,6 @@
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/dtraceJSDT.hpp"
|
#include "runtime/dtraceJSDT.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "runtime/hpi.hpp"
|
|
||||||
#include "runtime/init.hpp"
|
#include "runtime/init.hpp"
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
|
@ -65,15 +64,12 @@
|
||||||
#include "utilities/top.hpp"
|
#include "utilities/top.hpp"
|
||||||
#include "utilities/utf8.hpp"
|
#include "utilities/utf8.hpp"
|
||||||
#ifdef TARGET_OS_FAMILY_linux
|
#ifdef TARGET_OS_FAMILY_linux
|
||||||
# include "hpi_linux.hpp"
|
|
||||||
# include "jvm_linux.h"
|
# include "jvm_linux.h"
|
||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_OS_FAMILY_solaris
|
#ifdef TARGET_OS_FAMILY_solaris
|
||||||
# include "hpi_solaris.hpp"
|
|
||||||
# include "jvm_solaris.h"
|
# include "jvm_solaris.h"
|
||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_OS_FAMILY_windows
|
#ifdef TARGET_OS_FAMILY_windows
|
||||||
# include "hpi_windows.hpp"
|
|
||||||
# include "jvm_windows.h"
|
# include "jvm_windows.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -653,7 +649,7 @@ JVM_END
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_GetLastErrorString(char *buf, int len))
|
JVM_LEAF(jint, JVM_GetLastErrorString(char *buf, int len))
|
||||||
JVMWrapper("JVM_GetLastErrorString");
|
JVMWrapper("JVM_GetLastErrorString");
|
||||||
return hpi::lasterror(buf, len);
|
return (jint)os::lasterror(buf, len);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
|
@ -661,7 +657,7 @@ JVM_END
|
||||||
|
|
||||||
JVM_LEAF(char*, JVM_NativePath(char* path))
|
JVM_LEAF(char*, JVM_NativePath(char* path))
|
||||||
JVMWrapper2("JVM_NativePath (%s)", path);
|
JVMWrapper2("JVM_NativePath (%s)", path);
|
||||||
return hpi::native_path(path);
|
return os::native_path(path);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
|
@ -2487,7 +2483,7 @@ JVM_LEAF(jint, JVM_Open(const char *fname, jint flags, jint mode))
|
||||||
JVMWrapper2("JVM_Open (%s)", fname);
|
JVMWrapper2("JVM_Open (%s)", fname);
|
||||||
|
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
int result = hpi::open(fname, flags, mode);
|
int result = os::open(fname, flags, mode);
|
||||||
if (result >= 0) {
|
if (result >= 0) {
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2504,7 +2500,7 @@ JVM_END
|
||||||
JVM_LEAF(jint, JVM_Close(jint fd))
|
JVM_LEAF(jint, JVM_Close(jint fd))
|
||||||
JVMWrapper2("JVM_Close (0x%x)", fd);
|
JVMWrapper2("JVM_Close (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::close(fd);
|
return os::close(fd);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
|
@ -2512,7 +2508,7 @@ JVM_LEAF(jint, JVM_Read(jint fd, char *buf, jint nbytes))
|
||||||
JVMWrapper2("JVM_Read (0x%x)", fd);
|
JVMWrapper2("JVM_Read (0x%x)", fd);
|
||||||
|
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return (jint)hpi::read(fd, buf, nbytes);
|
return (jint)os::restartable_read(fd, buf, nbytes);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
|
@ -2520,34 +2516,34 @@ JVM_LEAF(jint, JVM_Write(jint fd, char *buf, jint nbytes))
|
||||||
JVMWrapper2("JVM_Write (0x%x)", fd);
|
JVMWrapper2("JVM_Write (0x%x)", fd);
|
||||||
|
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return (jint)hpi::write(fd, buf, nbytes);
|
return (jint)os::write(fd, buf, nbytes);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_Available(jint fd, jlong *pbytes))
|
JVM_LEAF(jint, JVM_Available(jint fd, jlong *pbytes))
|
||||||
JVMWrapper2("JVM_Available (0x%x)", fd);
|
JVMWrapper2("JVM_Available (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::available(fd, pbytes);
|
return os::available(fd, pbytes);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jlong, JVM_Lseek(jint fd, jlong offset, jint whence))
|
JVM_LEAF(jlong, JVM_Lseek(jint fd, jlong offset, jint whence))
|
||||||
JVMWrapper4("JVM_Lseek (0x%x, %Ld, %d)", fd, offset, whence);
|
JVMWrapper4("JVM_Lseek (0x%x, %Ld, %d)", fd, offset, whence);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::lseek(fd, offset, whence);
|
return os::lseek(fd, offset, whence);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_SetLength(jint fd, jlong length))
|
JVM_LEAF(jint, JVM_SetLength(jint fd, jlong length))
|
||||||
JVMWrapper3("JVM_SetLength (0x%x, %Ld)", fd, length);
|
JVMWrapper3("JVM_SetLength (0x%x, %Ld)", fd, length);
|
||||||
return hpi::ftruncate(fd, length);
|
return os::ftruncate(fd, length);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_Sync(jint fd))
|
JVM_LEAF(jint, JVM_Sync(jint fd))
|
||||||
JVMWrapper2("JVM_Sync (0x%x)", fd);
|
JVMWrapper2("JVM_Sync (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::fsync(fd);
|
return os::fsync(fd);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
|
@ -3457,146 +3453,125 @@ JVM_END
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_InitializeSocketLibrary())
|
JVM_LEAF(jint, JVM_InitializeSocketLibrary())
|
||||||
JVMWrapper("JVM_InitializeSocketLibrary");
|
JVMWrapper("JVM_InitializeSocketLibrary");
|
||||||
return hpi::initialize_socket_library();
|
return 0;
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_Socket(jint domain, jint type, jint protocol))
|
JVM_LEAF(jint, JVM_Socket(jint domain, jint type, jint protocol))
|
||||||
JVMWrapper("JVM_Socket");
|
JVMWrapper("JVM_Socket");
|
||||||
return hpi::socket(domain, type, protocol);
|
return os::socket(domain, type, protocol);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_SocketClose(jint fd))
|
JVM_LEAF(jint, JVM_SocketClose(jint fd))
|
||||||
JVMWrapper2("JVM_SocketClose (0x%x)", fd);
|
JVMWrapper2("JVM_SocketClose (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::socket_close(fd);
|
return os::socket_close(fd);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_SocketShutdown(jint fd, jint howto))
|
JVM_LEAF(jint, JVM_SocketShutdown(jint fd, jint howto))
|
||||||
JVMWrapper2("JVM_SocketShutdown (0x%x)", fd);
|
JVMWrapper2("JVM_SocketShutdown (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::socket_shutdown(fd, howto);
|
return os::socket_shutdown(fd, howto);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_Recv(jint fd, char *buf, jint nBytes, jint flags))
|
JVM_LEAF(jint, JVM_Recv(jint fd, char *buf, jint nBytes, jint flags))
|
||||||
JVMWrapper2("JVM_Recv (0x%x)", fd);
|
JVMWrapper2("JVM_Recv (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::recv(fd, buf, nBytes, flags);
|
return os::recv(fd, buf, nBytes, flags);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_Send(jint fd, char *buf, jint nBytes, jint flags))
|
JVM_LEAF(jint, JVM_Send(jint fd, char *buf, jint nBytes, jint flags))
|
||||||
JVMWrapper2("JVM_Send (0x%x)", fd);
|
JVMWrapper2("JVM_Send (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::send(fd, buf, nBytes, flags);
|
return os::send(fd, buf, nBytes, flags);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_Timeout(int fd, long timeout))
|
JVM_LEAF(jint, JVM_Timeout(int fd, long timeout))
|
||||||
JVMWrapper2("JVM_Timeout (0x%x)", fd);
|
JVMWrapper2("JVM_Timeout (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::timeout(fd, timeout);
|
return os::timeout(fd, timeout);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_Listen(jint fd, jint count))
|
JVM_LEAF(jint, JVM_Listen(jint fd, jint count))
|
||||||
JVMWrapper2("JVM_Listen (0x%x)", fd);
|
JVMWrapper2("JVM_Listen (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::listen(fd, count);
|
return os::listen(fd, count);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_Connect(jint fd, struct sockaddr *him, jint len))
|
JVM_LEAF(jint, JVM_Connect(jint fd, struct sockaddr *him, jint len))
|
||||||
JVMWrapper2("JVM_Connect (0x%x)", fd);
|
JVMWrapper2("JVM_Connect (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::connect(fd, him, len);
|
return os::connect(fd, him, len);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_Bind(jint fd, struct sockaddr *him, jint len))
|
JVM_LEAF(jint, JVM_Bind(jint fd, struct sockaddr *him, jint len))
|
||||||
JVMWrapper2("JVM_Bind (0x%x)", fd);
|
JVMWrapper2("JVM_Bind (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::bind(fd, him, len);
|
return os::bind(fd, him, len);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_Accept(jint fd, struct sockaddr *him, jint *len))
|
JVM_LEAF(jint, JVM_Accept(jint fd, struct sockaddr *him, jint *len))
|
||||||
JVMWrapper2("JVM_Accept (0x%x)", fd);
|
JVMWrapper2("JVM_Accept (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::accept(fd, him, (int *)len);
|
return os::accept(fd, him, (int *)len);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_RecvFrom(jint fd, char *buf, int nBytes, int flags, struct sockaddr *from, int *fromlen))
|
JVM_LEAF(jint, JVM_RecvFrom(jint fd, char *buf, int nBytes, int flags, struct sockaddr *from, int *fromlen))
|
||||||
JVMWrapper2("JVM_RecvFrom (0x%x)", fd);
|
JVMWrapper2("JVM_RecvFrom (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::recvfrom(fd, buf, nBytes, flags, from, fromlen);
|
return os::recvfrom(fd, buf, nBytes, flags, from, fromlen);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_GetSockName(jint fd, struct sockaddr *him, int *len))
|
JVM_LEAF(jint, JVM_GetSockName(jint fd, struct sockaddr *him, int *len))
|
||||||
JVMWrapper2("JVM_GetSockName (0x%x)", fd);
|
JVMWrapper2("JVM_GetSockName (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::get_sock_name(fd, him, len);
|
return os::get_sock_name(fd, him, len);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_SendTo(jint fd, char *buf, int len, int flags, struct sockaddr *to, int tolen))
|
JVM_LEAF(jint, JVM_SendTo(jint fd, char *buf, int len, int flags, struct sockaddr *to, int tolen))
|
||||||
JVMWrapper2("JVM_SendTo (0x%x)", fd);
|
JVMWrapper2("JVM_SendTo (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::sendto(fd, buf, len, flags, to, tolen);
|
return os::sendto(fd, buf, len, flags, to, tolen);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_SocketAvailable(jint fd, jint *pbytes))
|
JVM_LEAF(jint, JVM_SocketAvailable(jint fd, jint *pbytes))
|
||||||
JVMWrapper2("JVM_SocketAvailable (0x%x)", fd);
|
JVMWrapper2("JVM_SocketAvailable (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::socket_available(fd, pbytes);
|
return os::socket_available(fd, pbytes);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen))
|
JVM_LEAF(jint, JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen))
|
||||||
JVMWrapper2("JVM_GetSockOpt (0x%x)", fd);
|
JVMWrapper2("JVM_GetSockOpt (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::get_sock_opt(fd, level, optname, optval, optlen);
|
return os::get_sock_opt(fd, level, optname, optval, optlen);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(jint, JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen))
|
JVM_LEAF(jint, JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen))
|
||||||
JVMWrapper2("JVM_GetSockOpt (0x%x)", fd);
|
JVMWrapper2("JVM_GetSockOpt (0x%x)", fd);
|
||||||
//%note jvm_r6
|
//%note jvm_r6
|
||||||
return hpi::set_sock_opt(fd, level, optname, optval, optlen);
|
return os::set_sock_opt(fd, level, optname, optval, optlen);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
JVM_LEAF(int, JVM_GetHostName(char* name, int namelen))
|
JVM_LEAF(int, JVM_GetHostName(char* name, int namelen))
|
||||||
JVMWrapper("JVM_GetHostName");
|
JVMWrapper("JVM_GetHostName");
|
||||||
return hpi::get_host_name(name, namelen);
|
return os::get_host_name(name, namelen);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
|
||||||
|
|
||||||
JVM_LEAF(struct hostent*, JVM_GetHostByAddr(const char* name, int len, int type))
|
|
||||||
JVMWrapper("JVM_GetHostByAddr");
|
|
||||||
return hpi::get_host_by_addr(name, len, type);
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(struct hostent*, JVM_GetHostByName(char* name))
|
|
||||||
JVMWrapper("JVM_GetHostByName");
|
|
||||||
return hpi::get_host_by_name(name);
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(struct protoent*, JVM_GetProtoByName(char* name))
|
|
||||||
JVMWrapper("JVM_GetProtoByName");
|
|
||||||
return hpi::get_proto_by_name(name);
|
|
||||||
JVM_END
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Library support ///////////////////////////////////////////////////////////////////////////
|
// Library support ///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
JVM_ENTRY_NO_ENV(void*, JVM_LoadLibrary(const char* name))
|
JVM_ENTRY_NO_ENV(void*, JVM_LoadLibrary(const char* name))
|
||||||
|
@ -3606,7 +3581,7 @@ JVM_ENTRY_NO_ENV(void*, JVM_LoadLibrary(const char* name))
|
||||||
void *load_result;
|
void *load_result;
|
||||||
{
|
{
|
||||||
ThreadToNativeFromVM ttnfvm(thread);
|
ThreadToNativeFromVM ttnfvm(thread);
|
||||||
load_result = hpi::dll_load(name, ebuf, sizeof ebuf);
|
load_result = os::dll_load(name, ebuf, sizeof ebuf);
|
||||||
}
|
}
|
||||||
if (load_result == NULL) {
|
if (load_result == NULL) {
|
||||||
char msg[1024];
|
char msg[1024];
|
||||||
|
@ -3628,13 +3603,13 @@ JVM_END
|
||||||
|
|
||||||
JVM_LEAF(void, JVM_UnloadLibrary(void* handle))
|
JVM_LEAF(void, JVM_UnloadLibrary(void* handle))
|
||||||
JVMWrapper("JVM_UnloadLibrary");
|
JVMWrapper("JVM_UnloadLibrary");
|
||||||
hpi::dll_unload(handle);
|
os::dll_unload(handle);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
|
|
||||||
JVM_LEAF(void*, JVM_FindLibraryEntry(void* handle, const char* name))
|
JVM_LEAF(void*, JVM_FindLibraryEntry(void* handle, const char* name))
|
||||||
JVMWrapper2("JVM_FindLibraryEntry (%s)", name);
|
JVMWrapper2("JVM_FindLibraryEntry (%s)", name);
|
||||||
return hpi::dll_lookup(handle, name);
|
return os::dll_lookup(handle, name);
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
||||||
// Floating point support ////////////////////////////////////////////////////////////////////
|
// Floating point support ////////////////////////////////////////////////////////////////////
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue