This commit is contained in:
Zhengyu Gu 2010-12-11 13:46:36 -05:00
commit 86f7ad735d
124 changed files with 5920 additions and 6593 deletions

View file

@ -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) {

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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); }; \
}

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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 $@

View file

@ -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 #
################################################# #################################################

View file

@ -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)

View file

@ -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=\

View file

@ -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

View file

@ -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

View 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:$@ $**

View file

@ -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

View file

@ -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::

View file

@ -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

View file

@ -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

View file

@ -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");

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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");
}

View file

@ -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

View file

@ -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);
} }

View file

@ -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

View file

@ -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
}

View file

@ -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

View 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

View file

@ -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

View file

@ -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");
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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.

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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);
} }

View file

@ -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"

View file

@ -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"

View file

@ -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_ */

View 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);
}

View 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 */

View 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;
*/

View 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 */

View file

@ -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
// //

View file

@ -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

View file

@ -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 {

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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);
} }
} }

View file

@ -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");
{ {

View file

@ -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

View file

@ -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

View file

@ -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) {

View file

@ -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) {

View file

@ -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");

View file

@ -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

View file

@ -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 {

View file

@ -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;

View file

@ -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.

View file

@ -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() {

View file

@ -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();

View file

@ -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"

View file

@ -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"

View file

@ -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)
{ {

View file

@ -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);

View file

@ -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
} }

View file

@ -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

View file

@ -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

View file

@ -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);
} }

View file

@ -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>

View file

@ -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;
} }

View file

@ -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) {

View file

@ -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

View file

@ -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

View file

@ -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;
} }

View file

@ -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);

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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*);

View file

@ -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

View file

@ -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