mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-16 19:03:22 +00:00
Merge
This commit is contained in:
commit
a23159ffac
2
.hgtags
2
.hgtags
@ -15,3 +15,5 @@ c2036bf76829c03b99108fffab52e20910a9be4f jdk7-b37
|
||||
a2879b2837f5a4c87e9542efe69ef138194af8ff jdk7-b38
|
||||
126f365cec6c3c2c72de934fa1c64b5f082b55b5 jdk7-b39
|
||||
3c53424bbe3bb77e01b468b4b0140deec33e11fc jdk7-b40
|
||||
3cb2a607c347934f8e7e86f840a094c28b08d9ea jdk7-b41
|
||||
caf58ffa084568990cbb3441f9ae188e36b31770 jdk7-b42
|
||||
|
||||
@ -15,3 +15,5 @@ bb1ef4ee3d2c8cbf43a37d372325a7952be590b9 jdk7-b33
|
||||
cc47a76899ed33a2c513cb688348244c9b5a1288 jdk7-b38
|
||||
ab523b49de1fc73fefe6855ce1e0349bdbd7af29 jdk7-b39
|
||||
44be42de6693063fb191989bf0e188de2fa51e7c jdk7-b40
|
||||
541bdc5ad32fc33255944d0a044ad992f3d915e8 jdk7-b41
|
||||
94052b87287303527125026fe4b2698cf867ea83 jdk7-b42
|
||||
|
||||
@ -839,7 +839,7 @@
|
||||
<blockquote>
|
||||
All OpenJDK builds require access to least Ant 1.6.5.
|
||||
The Ant tool is available from the
|
||||
<a href="http://ant.apache.org/antlibs/bindownload.cgi" target="_blank">
|
||||
<a href="http://ant.apache.org" target="_blank">
|
||||
Ant download site</a>.
|
||||
You should always make sure <tt>ant</tt> is in your PATH, and
|
||||
on Windows you may also need to set
|
||||
|
||||
@ -15,3 +15,5 @@ ef6af34d75a7b44e77083f1d4ee47631fa09d3b4 jdk7-b31
|
||||
08be802754b0296c91a7713b6d85a015dbcd5349 jdk7-b38
|
||||
55078b6661e286e90387d1d9950bd865f5cc436e jdk7-b39
|
||||
184e21992f47a8d730df1adc5b21a108f3125489 jdk7-b40
|
||||
c90eeda9594ed2983403e2049aed8d503126c62e jdk7-b41
|
||||
ccd6a16502e0650d91d85c4b86be05cbcd461a87 jdk7-b42
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 1999-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2005-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -15,3 +15,5 @@ e91159f921a58af3698e6479ea1fc5818da66d09 jdk7-b36
|
||||
d9bc824aa078573829bb66572af847e26e1bd12e jdk7-b38
|
||||
49ca90d77f34571b0757ebfcb8a7848ef2696b88 jdk7-b39
|
||||
81a0cbe3b28460ce836109934ece03db7afaf9cc jdk7-b40
|
||||
f9d938ede1960d18cb7cf23c645b026519c1a678 jdk7-b41
|
||||
ad8c8ca4ab0f4c86e74c061958f44a8f4a930f2c jdk7-b42
|
||||
|
||||
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2008
|
||||
|
||||
HS_MAJOR_VER=14
|
||||
HS_MINOR_VER=0
|
||||
HS_BUILD_NUMBER=08
|
||||
HS_BUILD_NUMBER=10
|
||||
|
||||
JDK_MAJOR_VER=1
|
||||
JDK_MINOR_VER=7
|
||||
|
||||
@ -7,5 +7,13 @@
|
||||
#
|
||||
# adlc-updater <file> <source-dir> <target-dir>
|
||||
#
|
||||
[ -f $3/$1 ] && cmp -s $2/$1 $3/$1 || \
|
||||
( [ -f $3/$1 ]; echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
|
||||
fix_lines() {
|
||||
# repair bare #line directives in $1 to refer to $2
|
||||
awk < $1 > $1+ '
|
||||
/^#line 999999$/ {print "#line " (NR+1) " \"" F2 "\""; next}
|
||||
{print}
|
||||
' F2=$2
|
||||
mv $1+ $1
|
||||
}
|
||||
[ -f $3/$1 ] && (fix_lines $2/$1 $3/$1; cmp -s $2/$1 $3/$1) || \
|
||||
( [ -f $3/$1 ] && echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
|
||||
|
||||
@ -54,10 +54,12 @@ VPATH += $(Src_Dirs_V:%=%:)
|
||||
Src_Dirs_I = ${Src_Dirs} $(GENERATED)
|
||||
INCLUDES += $(Src_Dirs_I:%=-I%)
|
||||
|
||||
# Force assertions on.
|
||||
SYSDEFS += -DASSERT
|
||||
# set flags for adlc compilation
|
||||
CPPFLAGS = $(SYSDEFS) $(INCLUDES)
|
||||
|
||||
# Force assertions on.
|
||||
CPPFLAGS += -DASSERT
|
||||
|
||||
# CFLAGS_WARN holds compiler options to suppress/enable warnings.
|
||||
# Suppress warnings (for now)
|
||||
CFLAGS_WARN = -w
|
||||
@ -125,7 +127,15 @@ $(GENERATEDFILES): refresh_adfiles
|
||||
# Note that product files are updated via "mv", which is atomic.
|
||||
TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$)
|
||||
|
||||
ADLCFLAGS = -q -T
|
||||
# Pass -D flags into ADLC.
|
||||
ADLCFLAGS += $(SYSDEFS)
|
||||
|
||||
# Note "+="; it is a hook so flags.make can add more flags, like -g or -DFOO.
|
||||
ADLCFLAGS += -q -T
|
||||
|
||||
# Normally, debugging is done directly on the ad_<arch>*.cpp files.
|
||||
# But -g will put #line directives in those files pointing back to <arch>.ad.
|
||||
#ADLCFLAGS += -g
|
||||
|
||||
ifdef LP64
|
||||
ADLCFLAGS += -D_LP64
|
||||
@ -140,6 +150,8 @@ endif
|
||||
#
|
||||
ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/make/$(OS)
|
||||
ADLC_UPDATER = adlc_updater
|
||||
$(ADLC_UPDATER): $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER)
|
||||
$(QUIETLY) cp $< $@; chmod +x $@
|
||||
|
||||
# This action refreshes all generated adlc files simultaneously.
|
||||
# The way it works is this:
|
||||
@ -149,9 +161,8 @@ ADLC_UPDATER = adlc_updater
|
||||
# 4) call $(ADLC_UPDATER) on each generated adlc file. It will selectively update changed or missing files.
|
||||
# 5) If we actually updated any files, echo a notice.
|
||||
#
|
||||
refresh_adfiles: $(EXEC) $(SOURCE.AD)
|
||||
refresh_adfiles: $(EXEC) $(SOURCE.AD) $(ADLC_UPDATER)
|
||||
@rm -rf $(TEMPDIR); mkdir $(TEMPDIR)
|
||||
$(QUIETLY) [ -f $(ADLC_UPDATER) ] || ( cp $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER) . ; chmod +x $(ADLC_UPDATER) )
|
||||
$(QUIETLY) $(EXEC) $(ADLCFLAGS) $(SOURCE.AD) \
|
||||
-c$(TEMPDIR)/ad_$(Platform_arch_model).cpp -h$(TEMPDIR)/ad_$(Platform_arch_model).hpp -a$(TEMPDIR)/dfa_$(Platform_arch_model).cpp -v$(TEMPDIR)/adGlobals_$(Platform_arch_model).hpp \
|
||||
|| { rm -rf $(TEMPDIR); exit 1; }
|
||||
@ -174,7 +185,15 @@ refresh_adfiles: $(EXEC) $(SOURCE.AD)
|
||||
# #########################################################################
|
||||
|
||||
$(SOURCE.AD): $(SOURCES.AD)
|
||||
$(QUIETLY) cat $(SOURCES.AD) > $(SOURCE.AD)
|
||||
$(QUIETLY) $(PROCESS_AD_FILES) $(SOURCES.AD) > $(SOURCE.AD)
|
||||
|
||||
#PROCESS_AD_FILES = cat
|
||||
# Pass through #line directives, in case user enables -g option above:
|
||||
PROCESS_AD_FILES = awk '{ \
|
||||
if (CUR_FN != FILENAME) { CUR_FN=FILENAME; NR_BASE=NR-1; need_lineno=1 } \
|
||||
if (need_lineno && $$0 !~ /\/\//) \
|
||||
{ print "\n\n\#line " (NR-NR_BASE) " \"" FILENAME "\""; need_lineno=0 }; \
|
||||
print }'
|
||||
|
||||
$(OUTDIR)/%.o: %.cpp
|
||||
@echo Compiling $<
|
||||
|
||||
@ -7,5 +7,13 @@
|
||||
#
|
||||
# adlc-updater <file> <source-dir> <target-dir>
|
||||
#
|
||||
[ -f $3/$1 ] && cmp -s $2/$1 $3/$1 || \
|
||||
( [ -f $3/$1 ]; echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
|
||||
fix_lines() {
|
||||
# repair bare #line directives in $1 to refer to $2
|
||||
awk < $1 > $1+ '
|
||||
/^#line 999999$/ {print "#line " (NR+1) " \"" F2 "\""; next}
|
||||
{print}
|
||||
' F2=$2
|
||||
mv $1+ $1
|
||||
}
|
||||
[ -f $3/$1 ] && (fix_lines $2/$1 $3/$1; cmp -s $2/$1 $3/$1) || \
|
||||
( [ -f $3/$1 ] && echo Updating $3/$1 ; touch $2/made-change ; mv $2/$1 $3/$1 )
|
||||
|
||||
@ -54,10 +54,12 @@ VPATH += $(Src_Dirs_V:%=%:)
|
||||
Src_Dirs_I = ${Src_Dirs} $(GENERATED)
|
||||
INCLUDES += $(Src_Dirs_I:%=-I%)
|
||||
|
||||
# Force assertions on.
|
||||
SYSDEFS += -DASSERT
|
||||
# set flags for adlc compilation
|
||||
CPPFLAGS = $(SYSDEFS) $(INCLUDES)
|
||||
|
||||
# Force assertions on.
|
||||
CPPFLAGS += -DASSERT
|
||||
|
||||
ifndef USE_GCC
|
||||
# We need libCstd.so for adlc
|
||||
CFLAGS += -library=Cstd -g
|
||||
@ -141,7 +143,15 @@ $(GENERATEDFILES): refresh_adfiles
|
||||
# Note that product files are updated via "mv", which is atomic.
|
||||
TEMPDIR := $(OUTDIR)/mktmp$(shell echo $$$$)
|
||||
|
||||
ADLCFLAGS = -q -T
|
||||
# Pass -D flags into ADLC.
|
||||
ADLCFLAGS += $(SYSDEFS)
|
||||
|
||||
# Note "+="; it is a hook so flags.make can add more flags, like -g or -DFOO.
|
||||
ADLCFLAGS += -q -T
|
||||
|
||||
# Normally, debugging is done directly on the ad_<arch>*.cpp files.
|
||||
# But -g will put #line directives in those files pointing back to <arch>.ad.
|
||||
#ADLCFLAGS += -g
|
||||
|
||||
ifdef LP64
|
||||
ADLCFLAGS += -D_LP64
|
||||
@ -156,6 +166,8 @@ endif
|
||||
#
|
||||
ADLC_UPDATER_DIRECTORY = $(GAMMADIR)/make/$(OS)
|
||||
ADLC_UPDATER = adlc_updater
|
||||
$(ADLC_UPDATER): $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER)
|
||||
$(QUIETLY) cp $< $@; chmod +x $@
|
||||
|
||||
# This action refreshes all generated adlc files simultaneously.
|
||||
# The way it works is this:
|
||||
@ -165,9 +177,8 @@ ADLC_UPDATER = adlc_updater
|
||||
# 4) call $(ADLC_UPDATER) on each generated adlc file. It will selectively update changed or missing files.
|
||||
# 5) If we actually updated any files, echo a notice.
|
||||
#
|
||||
refresh_adfiles: $(EXEC) $(SOURCE.AD)
|
||||
refresh_adfiles: $(EXEC) $(SOURCE.AD) $(ADLC_UPDATER)
|
||||
@rm -rf $(TEMPDIR); mkdir $(TEMPDIR)
|
||||
$(QUIETLY) [ -f $(ADLC_UPDATER) ] || ( cp $(ADLC_UPDATER_DIRECTORY)/$(ADLC_UPDATER) . ; chmod +x $(ADLC_UPDATER) )
|
||||
$(QUIETLY) $(EXEC) $(ADLCFLAGS) $(SOURCE.AD) \
|
||||
-c$(TEMPDIR)/ad_$(Platform_arch_model).cpp -h$(TEMPDIR)/ad_$(Platform_arch_model).hpp -a$(TEMPDIR)/dfa_$(Platform_arch_model).cpp -v$(TEMPDIR)/adGlobals_$(Platform_arch_model).hpp \
|
||||
|| { rm -rf $(TEMPDIR); exit 1; }
|
||||
@ -190,7 +201,15 @@ refresh_adfiles: $(EXEC) $(SOURCE.AD)
|
||||
# #########################################################################
|
||||
|
||||
$(SOURCE.AD): $(SOURCES.AD)
|
||||
$(QUIETLY) cat $(SOURCES.AD) > $(SOURCE.AD)
|
||||
$(QUIETLY) $(PROCESS_AD_FILES) $(SOURCES.AD) > $(SOURCE.AD)
|
||||
|
||||
#PROCESS_AD_FILES = cat
|
||||
# Pass through #line directives, in case user enables -g option above:
|
||||
PROCESS_AD_FILES = awk '{ \
|
||||
if (CUR_FN != FILENAME) { CUR_FN=FILENAME; NR_BASE=NR-1; need_lineno=1 } \
|
||||
if (need_lineno && $$0 !~ /\/\//) \
|
||||
{ print "\n\n\#line " (NR-NR_BASE) " \"" FILENAME "\""; need_lineno=0 }; \
|
||||
print }'
|
||||
|
||||
$(OUTDIR)/%.o: %.cpp
|
||||
@echo Compiling $<
|
||||
|
||||
@ -200,29 +200,6 @@ BUILD_WIN_SA = 0
|
||||
checkSA::
|
||||
@echo Not building SA: ARCH = ia64
|
||||
|
||||
!elseif exist("$(MSVCDIR)\PlatformSDK\Include\dbgeng.h")
|
||||
# These don't have to be set because the default
|
||||
# setting of INCLUDE and LIB already contain the needed dirs.
|
||||
SA_INCLUDE =
|
||||
SA_LIB =
|
||||
|
||||
!elseif exist("$(SYSTEMROOT)\..\Program Files\Microsoft SDK\include\dbgeng.h")
|
||||
# These don't have to be set because the default
|
||||
# setting of INCLUDE and LIB already contain the needed dirs.
|
||||
SA_INCLUDE =
|
||||
SA_LIB =
|
||||
|
||||
!else
|
||||
checkSA::
|
||||
@echo .
|
||||
@echo ERROR: Can't build SA because dbgeng.h does not exist here:
|
||||
@echo $(MSVCDIR)\PlatformSDK\Include\dbgeng.h
|
||||
@echo nor here:
|
||||
@echo $(SYSTEMROOT)\..\Program Files\Microsoft SDK\include\dbgeng.h
|
||||
@echo You must use Vis. Studio .Net 2003 on Win 32, and you must
|
||||
@echo have the Microsoft SDK installed on Win amd64.
|
||||
@echo You can disable building of SA by specifying BUILD_WIN_SA = 0
|
||||
@echo . && false
|
||||
!endif # ! "$(BUILD_WIN_SA)" != "1"
|
||||
|
||||
#########################################################################
|
||||
|
||||
@ -119,7 +119,7 @@ endif
|
||||
# we want to release it. If we build it here,
|
||||
# the SDK makefiles will copy it over and put it into
|
||||
# the created image.
|
||||
BUILD_WIN_SA = 0
|
||||
BUILD_WIN_SA = 1
|
||||
ifneq ($(ALT_BUILD_WIN_SA),)
|
||||
BUILD_WIN_SA = $(ALT_BUILD_WIN_SA)
|
||||
endif
|
||||
|
||||
@ -49,6 +49,9 @@ SA_PROPERTIES = $(SA_CLASSDIR)\sa.properties
|
||||
|
||||
default:: $(GENERATED)\sa-jdi.jar
|
||||
|
||||
# Remove the space between $(SA_BUILD_VERSION_PROP) and > below as it adds a white space
|
||||
# at the end of SA version string and causes a version mismatch with the target VM version.
|
||||
|
||||
$(GENERATED)\sa-jdi.jar: $(AGENT_FILES1:/=\) $(AGENT_FILES2:/=\)
|
||||
@if not exist $(SA_CLASSDIR) mkdir $(SA_CLASSDIR)
|
||||
@echo ...Building sa-jdi.jar
|
||||
@ -56,15 +59,15 @@ $(GENERATED)\sa-jdi.jar: $(AGENT_FILES1:/=\) $(AGENT_FILES2:/=\)
|
||||
@$(COMPILE_JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES1:/=\)
|
||||
@$(COMPILE_JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES2:/=\)
|
||||
$(COMPILE_RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
|
||||
$(QUIETLY) echo $(SA_BUILD_VERSION_PROP) > $(SA_PROPERTIES)
|
||||
$(RUN_JAR) cf $@ -C saclasses .
|
||||
$(RUN_JAR) uf $@ -C $(AGENT_SRC_DIR:/=\) META-INF\services\com.sun.jdi.connect.Connector
|
||||
$(QUIETLY) echo $(SA_BUILD_VERSION_PROP)> $(SA_PROPERTIES)
|
||||
$(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js
|
||||
$(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/utilities/soql/sa.js $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql
|
||||
$(QUIETLY) mkdir -p $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources
|
||||
$(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/*
|
||||
$(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/ui/resources/*.png $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources/
|
||||
$(QUIETLY) cp -r $(AGENT_SRC_DIR)/images/* $(SA_CLASSDIR)/
|
||||
$(QUIETLY) rm -rf $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources
|
||||
$(QUIETLY) mkdir $(SA_CLASSDIR)\sun\jvm\hotspot\ui\resources
|
||||
$(QUIETLY) cp $(AGENT_SRC_DIR)/sun/jvm/hotspot/ui/resources/*.png $(SA_CLASSDIR)/sun/jvm/hotspot/ui/resources
|
||||
$(QUIETLY) cp -r $(AGENT_SRC_DIR)/images/* $(SA_CLASSDIR)
|
||||
$(RUN_JAR) cf $@ -C saclasses .
|
||||
$(RUN_JAR) uf $@ -C $(AGENT_SRC_DIR:/=\) META-INF\services\com.sun.jdi.connect.Connector
|
||||
$(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.windbg.WindbgDebuggerLocal
|
||||
$(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.x86.X86ThreadContext
|
||||
$(RUN_JAVAH) -classpath $(SA_CLASSDIR) -jni sun.jvm.hotspot.debugger.ia64.IA64ThreadContext
|
||||
@ -93,7 +96,7 @@ SA_LINK_FLAGS = bufferoverflowU.lib
|
||||
SA_CFLAGS = /nologo $(MS_RUNTIME_OPTION) /W3 /Gm $(GX_OPTION) /ZI /Od /D "WIN32" /D "_WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
!endif
|
||||
!if "$(MT)" != ""
|
||||
SA_LINK_FLAGS = /manifest $(SA_LINK_FLAGS)
|
||||
SA_LINK_FLAGS = /manifest $(SA_LINK_FLAGS)
|
||||
!endif
|
||||
SASRCFILE = $(AGENT_DIR)/src/os/win32/windbg/sawindbg.cpp
|
||||
SA_LFLAGS = $(SA_LINK_FLAGS) /nologo /subsystem:console /map /debug /machine:$(MACHINE)
|
||||
|
||||
@ -2085,7 +2085,7 @@ void TemplateTable::jvmti_post_field_access(Register Rcache,
|
||||
} else {
|
||||
if (has_tos) {
|
||||
// save object pointer before call_VM() clobbers it
|
||||
__ mov(Otos_i, Lscratch);
|
||||
__ push_ptr(Otos_i); // put object on tos where GC wants it.
|
||||
} else {
|
||||
// Load top of stack (do not pop the value off the stack);
|
||||
__ ld_ptr(Lesp, Interpreter::expr_offset_in_bytes(0), Otos_i);
|
||||
@ -2097,7 +2097,7 @@ void TemplateTable::jvmti_post_field_access(Register Rcache,
|
||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access),
|
||||
Otos_i, Rcache);
|
||||
if (!is_static && has_tos) {
|
||||
__ mov(Lscratch, Otos_i); // restore object pointer
|
||||
__ pop_ptr(Otos_i); // restore object pointer
|
||||
__ verify_oop(Otos_i);
|
||||
}
|
||||
__ get_cache_and_index_at_bcp(Rcache, index, 1);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2003-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2005-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -2272,7 +2272,9 @@ void os::free_memory(char *addr, size_t bytes) {
|
||||
uncommit_memory(addr, bytes);
|
||||
}
|
||||
|
||||
void os::numa_make_global(char *addr, size_t bytes) { }
|
||||
void os::numa_make_global(char *addr, size_t bytes) {
|
||||
Linux::numa_interleave_memory(addr, bytes);
|
||||
}
|
||||
|
||||
void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) {
|
||||
Linux::numa_tonode_memory(addr, bytes, lgrp_hint);
|
||||
@ -2314,7 +2316,7 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info
|
||||
extern "C" void numa_warn(int number, char *where, ...) { }
|
||||
extern "C" void numa_error(char *where) { }
|
||||
|
||||
void os::Linux::libnuma_init() {
|
||||
bool os::Linux::libnuma_init() {
|
||||
// sched_getcpu() should be in libc.
|
||||
set_sched_getcpu(CAST_TO_FN_PTR(sched_getcpu_func_t,
|
||||
dlsym(RTLD_DEFAULT, "sched_getcpu")));
|
||||
@ -2330,31 +2332,51 @@ void os::Linux::libnuma_init() {
|
||||
dlsym(handle, "numa_available")));
|
||||
set_numa_tonode_memory(CAST_TO_FN_PTR(numa_tonode_memory_func_t,
|
||||
dlsym(handle, "numa_tonode_memory")));
|
||||
set_numa_interleave_memory(CAST_TO_FN_PTR(numa_interleave_memory_func_t,
|
||||
dlsym(handle, "numa_interleave_memory")));
|
||||
|
||||
|
||||
if (numa_available() != -1) {
|
||||
set_numa_all_nodes((unsigned long*)dlsym(handle, "numa_all_nodes"));
|
||||
// Create a cpu -> node mapping
|
||||
_cpu_to_node = new (ResourceObj::C_HEAP) GrowableArray<int>(0, true);
|
||||
rebuild_cpu_to_node_map();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id.
|
||||
// The table is later used in get_node_by_cpu().
|
||||
void os::Linux::rebuild_cpu_to_node_map() {
|
||||
int cpu_num = os::active_processor_count();
|
||||
const size_t NCPUS = 32768; // Since the buffer size computation is very obscure
|
||||
// in libnuma (possible values are starting from 16,
|
||||
// and continuing up with every other power of 2, but less
|
||||
// than the maximum number of CPUs supported by kernel), and
|
||||
// is a subject to change (in libnuma version 2 the requirements
|
||||
// are more reasonable) we'll just hardcode the number they use
|
||||
// in the library.
|
||||
const size_t BitsPerCLong = sizeof(long) * CHAR_BIT;
|
||||
|
||||
size_t cpu_num = os::active_processor_count();
|
||||
size_t cpu_map_size = NCPUS / BitsPerCLong;
|
||||
size_t cpu_map_valid_size =
|
||||
MIN2((cpu_num + BitsPerCLong - 1) / BitsPerCLong, cpu_map_size);
|
||||
|
||||
cpu_to_node()->clear();
|
||||
cpu_to_node()->at_grow(cpu_num - 1);
|
||||
int node_num = numa_get_groups_num();
|
||||
int cpu_map_size = (cpu_num + BitsPerLong - 1) / BitsPerLong;
|
||||
size_t node_num = numa_get_groups_num();
|
||||
|
||||
unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size);
|
||||
for (int i = 0; i < node_num; i++) {
|
||||
for (size_t i = 0; i < node_num; i++) {
|
||||
if (numa_node_to_cpus(i, cpu_map, cpu_map_size * sizeof(unsigned long)) != -1) {
|
||||
for (int j = 0; j < cpu_map_size; j++) {
|
||||
for (size_t j = 0; j < cpu_map_valid_size; j++) {
|
||||
if (cpu_map[j] != 0) {
|
||||
for (int k = 0; k < BitsPerLong; k++) {
|
||||
for (size_t k = 0; k < BitsPerCLong; k++) {
|
||||
if (cpu_map[j] & (1UL << k)) {
|
||||
cpu_to_node()->at_put(j * BitsPerLong + k, i);
|
||||
cpu_to_node()->at_put(j * BitsPerCLong + k, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2377,7 +2399,8 @@ os::Linux::numa_node_to_cpus_func_t os::Linux::_numa_node_to_cpus;
|
||||
os::Linux::numa_max_node_func_t os::Linux::_numa_max_node;
|
||||
os::Linux::numa_available_func_t os::Linux::_numa_available;
|
||||
os::Linux::numa_tonode_memory_func_t os::Linux::_numa_tonode_memory;
|
||||
|
||||
os::Linux::numa_interleave_memory_func_t os::Linux::_numa_interleave_memory;
|
||||
unsigned long* os::Linux::_numa_all_nodes;
|
||||
|
||||
bool os::uncommit_memory(char* addr, size_t size) {
|
||||
return ::mmap(addr, size,
|
||||
@ -2477,7 +2500,7 @@ bool os::guard_memory(char* addr, size_t size) {
|
||||
}
|
||||
|
||||
bool os::unguard_memory(char* addr, size_t size) {
|
||||
return linux_mprotect(addr, size, PROT_READ|PROT_WRITE|PROT_EXEC);
|
||||
return linux_mprotect(addr, size, PROT_READ|PROT_WRITE);
|
||||
}
|
||||
|
||||
// Large page support
|
||||
@ -3695,7 +3718,17 @@ jint os::init_2(void)
|
||||
}
|
||||
|
||||
if (UseNUMA) {
|
||||
Linux::libnuma_init();
|
||||
if (!Linux::libnuma_init()) {
|
||||
UseNUMA = false;
|
||||
} else {
|
||||
if ((Linux::numa_max_node() < 1)) {
|
||||
// There's only one node(they start from 0), disable NUMA.
|
||||
UseNUMA = false;
|
||||
}
|
||||
}
|
||||
if (!UseNUMA && ForceNUMA) {
|
||||
UseNUMA = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (MaxFDLimit) {
|
||||
|
||||
@ -146,7 +146,7 @@ class Linux {
|
||||
static bool is_floating_stack() { return _is_floating_stack; }
|
||||
|
||||
static void libpthread_init();
|
||||
static void libnuma_init();
|
||||
static bool libnuma_init();
|
||||
|
||||
// Minimum stack size a thread can be created with (allowing
|
||||
// the VM to completely create the thread and enter user code)
|
||||
@ -240,20 +240,23 @@ private:
|
||||
typedef int (*numa_max_node_func_t)(void);
|
||||
typedef int (*numa_available_func_t)(void);
|
||||
typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node);
|
||||
|
||||
typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask);
|
||||
|
||||
static sched_getcpu_func_t _sched_getcpu;
|
||||
static numa_node_to_cpus_func_t _numa_node_to_cpus;
|
||||
static numa_max_node_func_t _numa_max_node;
|
||||
static numa_available_func_t _numa_available;
|
||||
static numa_tonode_memory_func_t _numa_tonode_memory;
|
||||
static numa_interleave_memory_func_t _numa_interleave_memory;
|
||||
static unsigned long* _numa_all_nodes;
|
||||
|
||||
static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; }
|
||||
static void set_numa_node_to_cpus(numa_node_to_cpus_func_t func) { _numa_node_to_cpus = func; }
|
||||
static void set_numa_max_node(numa_max_node_func_t func) { _numa_max_node = func; }
|
||||
static void set_numa_available(numa_available_func_t func) { _numa_available = func; }
|
||||
static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; }
|
||||
|
||||
static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; }
|
||||
static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; }
|
||||
public:
|
||||
static int sched_getcpu() { return _sched_getcpu != NULL ? _sched_getcpu() : -1; }
|
||||
static int numa_node_to_cpus(int node, unsigned long *buffer, int bufferlen) {
|
||||
@ -264,6 +267,11 @@ public:
|
||||
static int numa_tonode_memory(void *start, size_t size, int node) {
|
||||
return _numa_tonode_memory != NULL ? _numa_tonode_memory(start, size, node) : -1;
|
||||
}
|
||||
static void numa_interleave_memory(void *start, size_t size) {
|
||||
if (_numa_interleave_memory != NULL && _numa_all_nodes != NULL) {
|
||||
_numa_interleave_memory(start, size, _numa_all_nodes);
|
||||
}
|
||||
}
|
||||
static int get_node_by_cpu(int cpu_id);
|
||||
};
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2005-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1638,16 +1638,24 @@ inline hrtime_t oldgetTimeNanos() {
|
||||
// getTimeNanos is guaranteed to not move backward on Solaris
|
||||
inline hrtime_t getTimeNanos() {
|
||||
if (VM_Version::supports_cx8()) {
|
||||
bool retry = false;
|
||||
hrtime_t newtime = gethrtime();
|
||||
hrtime_t oldmaxtime = max_hrtime;
|
||||
hrtime_t retmaxtime = oldmaxtime;
|
||||
while ((newtime > retmaxtime) && (retry == false || retmaxtime != oldmaxtime)) {
|
||||
oldmaxtime = retmaxtime;
|
||||
retmaxtime = Atomic::cmpxchg(newtime, (volatile jlong *)&max_hrtime, oldmaxtime);
|
||||
retry = true;
|
||||
}
|
||||
return (newtime > retmaxtime) ? newtime : retmaxtime;
|
||||
const hrtime_t now = gethrtime();
|
||||
const hrtime_t prev = max_hrtime;
|
||||
if (now <= prev) return prev; // same or retrograde time;
|
||||
const hrtime_t obsv = Atomic::cmpxchg(now, (volatile jlong*)&max_hrtime, prev);
|
||||
assert(obsv >= prev, "invariant"); // Monotonicity
|
||||
// If the CAS succeeded then we're done and return "now".
|
||||
// If the CAS failed and the observed value "obs" is >= now then
|
||||
// we should return "obs". If the CAS failed and now > obs > prv then
|
||||
// some other thread raced this thread and installed a new value, in which case
|
||||
// we could either (a) retry the entire operation, (b) retry trying to install now
|
||||
// or (c) just return obs. We use (c). No loop is required although in some cases
|
||||
// we might discard a higher "now" value in deference to a slightly lower but freshly
|
||||
// installed obs value. That's entirely benign -- it admits no new orderings compared
|
||||
// to (a) or (b) -- and greatly reduces coherence traffic.
|
||||
// We might also condition (c) on the magnitude of the delta between obs and now.
|
||||
// Avoiding excessive CAS operations to hot RW locations is critical.
|
||||
// See http://blogs.sun.com/dave/entry/cas_and_cache_trivia_invalidate
|
||||
return (prev == obsv) ? now : obsv ;
|
||||
} else {
|
||||
return oldgetTimeNanos();
|
||||
}
|
||||
@ -3026,6 +3034,8 @@ static bool solaris_mprotect(char* addr, size_t bytes, int prot) {
|
||||
|
||||
// Protect memory (Used to pass readonly pages through
|
||||
// JNI GetArray<type>Elements with empty arrays.)
|
||||
// Also, used for serialization page and for compressed oops null pointer
|
||||
// checking.
|
||||
bool os::protect_memory(char* addr, size_t bytes, ProtType prot,
|
||||
bool is_committed) {
|
||||
unsigned int p = 0;
|
||||
@ -3049,7 +3059,7 @@ bool os::guard_memory(char* addr, size_t bytes) {
|
||||
}
|
||||
|
||||
bool os::unguard_memory(char* addr, size_t bytes) {
|
||||
return solaris_mprotect(addr, bytes, PROT_READ|PROT_WRITE|PROT_EXEC);
|
||||
return solaris_mprotect(addr, bytes, PROT_READ|PROT_WRITE);
|
||||
}
|
||||
|
||||
// Large page support
|
||||
@ -4638,7 +4648,7 @@ void os::Solaris::synchronization_init() {
|
||||
}
|
||||
}
|
||||
|
||||
void os::Solaris::liblgrp_init() {
|
||||
bool os::Solaris::liblgrp_init() {
|
||||
void *handle = dlopen("liblgrp.so.1", RTLD_LAZY);
|
||||
if (handle != NULL) {
|
||||
os::Solaris::set_lgrp_home(CAST_TO_FN_PTR(lgrp_home_func_t, dlsym(handle, "lgrp_home")));
|
||||
@ -4653,9 +4663,9 @@ void os::Solaris::liblgrp_init() {
|
||||
|
||||
lgrp_cookie_t c = lgrp_init(LGRP_VIEW_CALLER);
|
||||
set_lgrp_cookie(c);
|
||||
} else {
|
||||
warning("your OS does not support NUMA");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void os::Solaris::misc_sym_init() {
|
||||
@ -4824,9 +4834,25 @@ jint os::init_2(void) {
|
||||
vm_page_size()));
|
||||
|
||||
Solaris::libthread_init();
|
||||
|
||||
if (UseNUMA) {
|
||||
Solaris::liblgrp_init();
|
||||
if (!Solaris::liblgrp_init()) {
|
||||
UseNUMA = false;
|
||||
} else {
|
||||
size_t lgrp_limit = os::numa_get_groups_num();
|
||||
int *lgrp_ids = NEW_C_HEAP_ARRAY(int, lgrp_limit);
|
||||
size_t lgrp_num = os::numa_get_leaf_groups(lgrp_ids, lgrp_limit);
|
||||
FREE_C_HEAP_ARRAY(int, lgrp_ids);
|
||||
if (lgrp_num < 2) {
|
||||
// There's only one locality group, disable NUMA.
|
||||
UseNUMA = false;
|
||||
}
|
||||
}
|
||||
if (!UseNUMA && ForceNUMA) {
|
||||
UseNUMA = true;
|
||||
}
|
||||
}
|
||||
|
||||
Solaris::misc_sym_init();
|
||||
Solaris::signal_sets_init();
|
||||
Solaris::init_signal_mem();
|
||||
|
||||
@ -176,7 +176,7 @@ class Solaris {
|
||||
public:
|
||||
static void libthread_init();
|
||||
static void synchronization_init();
|
||||
static void liblgrp_init();
|
||||
static bool liblgrp_init();
|
||||
// Load miscellaneous symbols.
|
||||
static void misc_sym_init();
|
||||
// This boolean allows users to forward their own non-matching signals
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2005-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -2020,10 +2020,11 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
||||
if (UnguardOnExecutionViolation > 0 && addr != last_addr &&
|
||||
(UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
|
||||
|
||||
// Unguard and retry
|
||||
// Set memory to RWX and retry
|
||||
address page_start =
|
||||
(address) align_size_down((intptr_t) addr, (intptr_t) page_size);
|
||||
bool res = os::unguard_memory((char*) page_start, page_size);
|
||||
bool res = os::protect_memory((char*) page_start, page_size,
|
||||
os::MEM_PROT_RWX);
|
||||
|
||||
if (PrintMiscellaneous && Verbose) {
|
||||
char buf[256];
|
||||
@ -2217,15 +2218,10 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
||||
// We only expect null pointers in the stubs (vtable)
|
||||
// the rest are checked explicitly now.
|
||||
//
|
||||
CodeBlob* cb = CodeCache::find_blob(pc);
|
||||
if (cb != NULL) {
|
||||
if (VtableStubs::stub_containing(pc) != NULL) {
|
||||
if (((uintptr_t)addr) < os::vm_page_size() ) {
|
||||
// an access to the first page of VM--assume it is a null pointer
|
||||
return Handle_Exception(exceptionInfo,
|
||||
SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL));
|
||||
}
|
||||
}
|
||||
if (((uintptr_t)addr) < os::vm_page_size() ) {
|
||||
// an access to the first page of VM--assume it is a null pointer
|
||||
address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
|
||||
if (stub != NULL) return Handle_Exception(exceptionInfo, stub);
|
||||
}
|
||||
}
|
||||
} // in_java
|
||||
@ -2241,9 +2237,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
||||
// Windows 98 reports faulting addresses incorrectly
|
||||
if (!MacroAssembler::needs_explicit_null_check((intptr_t)addr) ||
|
||||
!os::win32::is_nt()) {
|
||||
|
||||
return Handle_Exception(exceptionInfo,
|
||||
SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL));
|
||||
address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
|
||||
if (stub != NULL) return Handle_Exception(exceptionInfo, stub);
|
||||
}
|
||||
report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord,
|
||||
exceptionInfo->ContextRecord);
|
||||
@ -2761,12 +2756,12 @@ bool os::protect_memory(char* addr, size_t bytes, ProtType prot,
|
||||
|
||||
bool os::guard_memory(char* addr, size_t bytes) {
|
||||
DWORD old_status;
|
||||
return VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE | PAGE_GUARD, &old_status) != 0;
|
||||
return VirtualProtect(addr, bytes, PAGE_READWRITE | PAGE_GUARD, &old_status) != 0;
|
||||
}
|
||||
|
||||
bool os::unguard_memory(char* addr, size_t bytes) {
|
||||
DWORD old_status;
|
||||
return VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &old_status) != 0;
|
||||
return VirtualProtect(addr, bytes, PAGE_READWRITE, &old_status) != 0;
|
||||
}
|
||||
|
||||
void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { }
|
||||
@ -3353,6 +3348,10 @@ jint os::init_2(void) {
|
||||
// initialize thread priority policy
|
||||
prio_init();
|
||||
|
||||
if (UseNUMA && !ForceNUMA) {
|
||||
UseNUMA = false; // Currently unsupported.
|
||||
}
|
||||
|
||||
return JNI_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
// Copyright 1999-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -422,10 +422,11 @@ JVM_handle_linux_signal(int sig,
|
||||
if (addr != last_addr &&
|
||||
(UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
|
||||
|
||||
// Unguard and retry
|
||||
// Set memory to RWX and retry
|
||||
address page_start =
|
||||
(address) align_size_down((intptr_t) addr, (intptr_t) page_size);
|
||||
bool res = os::unguard_memory((char*) page_start, page_size);
|
||||
bool res = os::protect_memory((char*) page_start, page_size,
|
||||
os::MEM_PROT_RWX);
|
||||
|
||||
if (PrintMiscellaneous && Verbose) {
|
||||
char buf[256];
|
||||
|
||||
@ -203,10 +203,10 @@ frame os::get_sender_for_C_frame(frame* fr) {
|
||||
return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
|
||||
}
|
||||
|
||||
extern "C" intptr_t *_get_previous_fp(); // in .il file.
|
||||
extern "C" intptr_t *_get_current_fp(); // in .il file
|
||||
|
||||
frame os::current_frame() {
|
||||
intptr_t* fp = _get_previous_fp();
|
||||
intptr_t* fp = _get_current_fp(); // it's inlined so want current fp
|
||||
frame myframe((intptr_t*)os::current_stack_pointer(),
|
||||
(intptr_t*)fp,
|
||||
CAST_FROM_FN_PTR(address, os::current_frame));
|
||||
@ -576,10 +576,11 @@ int JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, int abort_
|
||||
if (addr != last_addr &&
|
||||
(UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {
|
||||
|
||||
// Unguard and retry
|
||||
// Make memory rwx and retry
|
||||
address page_start =
|
||||
(address) align_size_down((intptr_t) addr, (intptr_t) page_size);
|
||||
bool res = os::unguard_memory((char*) page_start, page_size);
|
||||
bool res = os::protect_memory((char*) page_start, page_size,
|
||||
os::MEM_PROT_RWX);
|
||||
|
||||
if (PrintMiscellaneous && Verbose) {
|
||||
char buf[256];
|
||||
|
||||
@ -37,10 +37,10 @@
|
||||
movl %gs:0, %eax
|
||||
.end
|
||||
|
||||
// Get callers fp
|
||||
.inline _get_previous_fp,0
|
||||
// Get current fp
|
||||
.inline _get_current_fp,0
|
||||
.volatile
|
||||
movl %ebp, %eax
|
||||
movl %eax, %eax
|
||||
.end
|
||||
|
||||
// Support for jint Atomic::add(jint inc, volatile jint* dest)
|
||||
|
||||
@ -30,10 +30,10 @@
|
||||
movq %fs:0, %rax
|
||||
.end
|
||||
|
||||
// Get the frame pointer from previous frame.
|
||||
.inline _get_previous_fp,0
|
||||
// Get the frame pointer from current frame.
|
||||
.inline _get_current_fp,0
|
||||
.volatile
|
||||
movq %rbp, %rax
|
||||
movq %rax, %rax
|
||||
.end
|
||||
|
||||
// Support for jint Atomic::add(jint add_value, volatile jint* dest)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. 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
|
||||
@ -108,6 +108,7 @@ void ADLParser::parse() {
|
||||
else if (!strcmp(ident, "pipeline")) pipe_parse();
|
||||
else if (!strcmp(ident, "definitions")) definitions_parse();
|
||||
else if (!strcmp(ident, "peephole")) peep_parse();
|
||||
else if (!strcmp(ident, "#line")) preproc_line();
|
||||
else if (!strcmp(ident, "#define")) preproc_define();
|
||||
else if (!strcmp(ident, "#undef")) preproc_undef();
|
||||
else {
|
||||
@ -786,9 +787,11 @@ void ADLParser::reg_parse(void) {
|
||||
parse_err(SYNERR, "missing identifier inside register block.\n");
|
||||
return;
|
||||
}
|
||||
if (strcmp(token,"reg_def")==0) { reg_def_parse(); }
|
||||
if (strcmp(token,"reg_class")==0) { reg_class_parse(); }
|
||||
if (strcmp(token,"alloc_class")==0) { alloc_class_parse(); }
|
||||
if (strcmp(token,"reg_def")==0) { reg_def_parse(); }
|
||||
else if (strcmp(token,"reg_class")==0) { reg_class_parse(); }
|
||||
else if (strcmp(token,"alloc_class")==0) { alloc_class_parse(); }
|
||||
else if (strcmp(token,"#define")==0) { preproc_define(); }
|
||||
else { parse_err(SYNERR, "bad token %s inside register block.\n", token); break; }
|
||||
skipws();
|
||||
}
|
||||
}
|
||||
@ -903,11 +906,7 @@ void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) {
|
||||
skipws_no_preproc(); // Skip leading whitespace
|
||||
// Prepend location descriptor, for debugging; cf. ADLParser::find_cpp_block
|
||||
if (_AD._adlocation_debug) {
|
||||
const char* file = _AD._ADL_file._name;
|
||||
int line = linenum();
|
||||
char* location = (char *)malloc(strlen(file) + 100);
|
||||
sprintf(location, "#line %d \"%s\"\n", line, file);
|
||||
encoding->add_code(location);
|
||||
encoding->add_code(get_line_string());
|
||||
}
|
||||
|
||||
// Collect the parts of the encode description
|
||||
@ -948,6 +947,10 @@ void ADLParser::enc_class_parse_block(EncClass* encoding, char* ec_name) {
|
||||
|
||||
skipws();
|
||||
|
||||
if (_AD._adlocation_debug) {
|
||||
encoding->add_code(end_line_marker());
|
||||
}
|
||||
|
||||
// Debug Stuff
|
||||
if (_AD._adl_debug > 1) fprintf(stderr,"EncodingClass Form: %s\n", ec_name);
|
||||
}
|
||||
@ -2349,7 +2352,11 @@ void ADLParser::reg_class_parse(void) {
|
||||
return;
|
||||
}
|
||||
RegDef *regDef = _AD._register->getRegDef(rname);
|
||||
reg_class->addReg(regDef); // add regDef to regClass
|
||||
if (!regDef) {
|
||||
parse_err(SEMERR, "unknown identifier %s inside reg_class list.\n", rname);
|
||||
} else {
|
||||
reg_class->addReg(regDef); // add regDef to regClass
|
||||
}
|
||||
|
||||
// Check for ',' and position to next token.
|
||||
skipws();
|
||||
@ -2746,7 +2753,8 @@ Predicate *ADLParser::pred_parse(void) {
|
||||
char *rule = NULL; // String representation of predicate
|
||||
|
||||
skipws(); // Skip leading whitespace
|
||||
if ( (rule = get_paren_expr("pred expression")) == NULL ) {
|
||||
int line = linenum();
|
||||
if ( (rule = get_paren_expr("pred expression", true)) == NULL ) {
|
||||
parse_err(SYNERR, "incorrect or missing expression for 'predicate'\n");
|
||||
return NULL;
|
||||
}
|
||||
@ -3407,7 +3415,12 @@ FormatRule* ADLParser::format_parse(void) {
|
||||
// Check if there is a string to pass through to output
|
||||
char *start = _ptr; // Record start of the next string
|
||||
while ((_curchar != '$') && (_curchar != '"') && (_curchar != '%') && (_curchar != '\n')) {
|
||||
if (_curchar == '\\') next_char(); // superquote
|
||||
if (_curchar == '\\') {
|
||||
next_char(); // superquote
|
||||
if ((_curchar == '$') || (_curchar == '%'))
|
||||
// hack to avoid % escapes and warnings about undefined \ escapes
|
||||
*(_ptr-1) = _curchar;
|
||||
}
|
||||
if (_curchar == '\n') parse_err(SYNERR, "newline in string"); // unimplemented!
|
||||
next_char();
|
||||
}
|
||||
@ -3942,8 +3955,7 @@ char* ADLParser::find_cpp_block(const char* description) {
|
||||
next_char(); // Skip block delimiter
|
||||
skipws_no_preproc(); // Skip leading whitespace
|
||||
cppBlock = _ptr; // Point to start of expression
|
||||
const char* file = _AD._ADL_file._name;
|
||||
int line = linenum();
|
||||
int line = linenum();
|
||||
next = _ptr + 1;
|
||||
while(((_curchar != '%') || (*next != '}')) && (_curchar != '\0')) {
|
||||
next_char_or_line();
|
||||
@ -3958,15 +3970,16 @@ char* ADLParser::find_cpp_block(const char* description) {
|
||||
_curchar = *_ptr; // Maintain invariant
|
||||
|
||||
// Prepend location descriptor, for debugging.
|
||||
char* location = (char *)malloc(strlen(file) + 100);
|
||||
*location = '\0';
|
||||
if (_AD._adlocation_debug)
|
||||
sprintf(location, "#line %d \"%s\"\n", line, file);
|
||||
char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + 1);
|
||||
strcpy(result, location);
|
||||
strcat(result, cppBlock);
|
||||
cppBlock = result;
|
||||
free(location);
|
||||
if (_AD._adlocation_debug) {
|
||||
char* location = get_line_string(line);
|
||||
char* end_loc = end_line_marker();
|
||||
char* result = (char *)malloc(strlen(location) + strlen(cppBlock) + strlen(end_loc) + 1);
|
||||
strcpy(result, location);
|
||||
strcat(result, cppBlock);
|
||||
strcat(result, end_loc);
|
||||
cppBlock = result;
|
||||
free(location);
|
||||
}
|
||||
}
|
||||
|
||||
return cppBlock;
|
||||
@ -4036,13 +4049,26 @@ char* ADLParser::get_expr(const char *desc, const char *stop_chars) {
|
||||
|
||||
// Helper function around get_expr
|
||||
// Sets _curchar to '(' so that get_paren_expr will search for a matching ')'
|
||||
char *ADLParser::get_paren_expr(const char *description) {
|
||||
char *ADLParser::get_paren_expr(const char *description, bool include_location) {
|
||||
int line = linenum();
|
||||
if (_curchar != '(') // Escape if not valid starting position
|
||||
return NULL;
|
||||
next_char(); // Skip the required initial paren.
|
||||
char *token2 = get_expr(description, ")");
|
||||
if (_curchar == ')')
|
||||
next_char(); // Skip required final paren.
|
||||
int junk = 0;
|
||||
if (include_location && _AD._adlocation_debug && !is_int_token(token2, junk)) {
|
||||
// Prepend location descriptor, for debugging.
|
||||
char* location = get_line_string(line);
|
||||
char* end_loc = end_line_marker();
|
||||
char* result = (char *)malloc(strlen(location) + strlen(token2) + strlen(end_loc) + 1);
|
||||
strcpy(result, location);
|
||||
strcat(result, token2);
|
||||
strcat(result, end_loc);
|
||||
token2 = result;
|
||||
free(location);
|
||||
}
|
||||
return token2;
|
||||
}
|
||||
|
||||
@ -4082,10 +4108,16 @@ char *ADLParser::get_ident_common(bool do_preproc) {
|
||||
if (do_preproc && start != NULL) {
|
||||
const char* def = _AD.get_preproc_def(start);
|
||||
if (def != NULL && strcmp(def, start)) {
|
||||
const char* def2 = _AD.get_preproc_def(def);
|
||||
if (def2 != NULL && strcmp(def2, def)) {
|
||||
parse_err(SYNERR, "unimplemented: using %s defined as %s => %s",
|
||||
start, def, def2);
|
||||
const char* def1 = def;
|
||||
const char* def2 = _AD.get_preproc_def(def1);
|
||||
// implement up to 2 levels of #define
|
||||
if (def2 != NULL && strcmp(def2, def1)) {
|
||||
def = def2;
|
||||
const char* def3 = _AD.get_preproc_def(def2);
|
||||
if (def3 != NULL && strcmp(def3, def2) && strcmp(def3, def1)) {
|
||||
parse_err(SYNERR, "unimplemented: using %s defined as %s => %s => %s",
|
||||
start, def1, def2, def3);
|
||||
}
|
||||
}
|
||||
start = strdup(def);
|
||||
}
|
||||
@ -4431,6 +4463,35 @@ void ADLParser::get_effectlist(FormDict &effects, FormDict &operands) {
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------preproc_line----------------------------------
|
||||
// A "#line" keyword has been seen, so parse the rest of the line.
|
||||
void ADLParser::preproc_line(void) {
|
||||
int line = get_int();
|
||||
skipws_no_preproc();
|
||||
const char* file = NULL;
|
||||
if (_curchar == '"') {
|
||||
next_char(); // Move past the initial '"'
|
||||
file = _ptr;
|
||||
while (true) {
|
||||
if (_curchar == '\n') {
|
||||
parse_err(SYNERR, "missing '\"' at end of #line directive");
|
||||
return;
|
||||
}
|
||||
if (_curchar == '"') {
|
||||
*_ptr = '\0'; // Terminate the string
|
||||
next_char();
|
||||
skipws_no_preproc();
|
||||
break;
|
||||
}
|
||||
next_char();
|
||||
}
|
||||
}
|
||||
ensure_end_of_line();
|
||||
if (file != NULL)
|
||||
_AD._ADL_file._name = file;
|
||||
_buf.set_linenum(line);
|
||||
}
|
||||
|
||||
//------------------------------preproc_define---------------------------------
|
||||
// A "#define" keyword has been seen, so parse the rest of the line.
|
||||
void ADLParser::preproc_define(void) {
|
||||
@ -4494,6 +4555,7 @@ void ADLParser::parse_err(int flag, const char *fmt, ...) {
|
||||
// A preprocessor directive has been encountered. Be sure it has fallen at
|
||||
// the begining of a line, or else report an error.
|
||||
void ADLParser::ensure_start_of_line(void) {
|
||||
if (_curchar == '\n') { next_line(); return; }
|
||||
assert( _ptr >= _curline && _ptr < _curline+strlen(_curline),
|
||||
"Must be able to find which line we are in" );
|
||||
|
||||
@ -4662,6 +4724,7 @@ char ADLParser::cur_char() {
|
||||
|
||||
//---------------------------next_char-----------------------------------------
|
||||
void ADLParser::next_char() {
|
||||
if (_curchar == '\n') parse_err(WARN, "must call next_line!");
|
||||
_curchar = *++_ptr;
|
||||
// if ( _curchar == '\n' ) {
|
||||
// next_line();
|
||||
@ -4682,6 +4745,18 @@ void ADLParser::next_char_or_line() {
|
||||
//---------------------------next_line-----------------------------------------
|
||||
void ADLParser::next_line() {
|
||||
_curline = _buf.get_line();
|
||||
_curchar = ' ';
|
||||
}
|
||||
|
||||
//------------------------get_line_string--------------------------------------
|
||||
// Prepended location descriptor, for debugging.
|
||||
// Must return a malloced string (that can be freed if desired).
|
||||
char* ADLParser::get_line_string(int linenum) {
|
||||
const char* file = _AD._ADL_file._name;
|
||||
int line = linenum ? linenum : this->linenum();
|
||||
char* location = (char *)malloc(strlen(file) + 100);
|
||||
sprintf(location, "\n#line %d \"%s\"\n", line, file);
|
||||
return location;
|
||||
}
|
||||
|
||||
//-------------------------is_literal_constant---------------------------------
|
||||
@ -4722,6 +4797,66 @@ bool ADLParser::is_int_token(const char* token, int& intval) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char* skip_expr_ws(const char* str) {
|
||||
const char * cp = str;
|
||||
while (cp[0]) {
|
||||
if (cp[0] <= ' ') {
|
||||
++cp;
|
||||
} else if (cp[0] == '#') {
|
||||
++cp;
|
||||
while (cp[0] == ' ') ++cp;
|
||||
assert(0 == strncmp(cp, "line", 4), "must be a #line directive");
|
||||
const char* eol = strchr(cp, '\n');
|
||||
assert(eol != NULL, "must find end of line");
|
||||
if (eol == NULL) eol = cp + strlen(cp);
|
||||
cp = eol;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
//-----------------------equivalent_expressions--------------------------------
|
||||
bool ADLParser::equivalent_expressions(const char* str1, const char* str2) {
|
||||
if (str1 == str2)
|
||||
return true;
|
||||
else if (str1 == NULL || str2 == NULL)
|
||||
return false;
|
||||
const char* cp1 = str1;
|
||||
const char* cp2 = str2;
|
||||
char in_quote = '\0';
|
||||
while (cp1[0] && cp2[0]) {
|
||||
if (!in_quote) {
|
||||
// skip spaces and/or cpp directives
|
||||
const char* cp1a = skip_expr_ws(cp1);
|
||||
const char* cp2a = skip_expr_ws(cp2);
|
||||
if (cp1a > cp1 && cp2a > cp2) {
|
||||
cp1 = cp1a; cp2 = cp2a;
|
||||
continue;
|
||||
}
|
||||
if (cp1a > cp1 || cp2a > cp2) break; // fail
|
||||
}
|
||||
// match one non-space char
|
||||
if (cp1[0] != cp2[0]) break; // fail
|
||||
char ch = cp1[0];
|
||||
cp1++; cp2++;
|
||||
// watch for quotes
|
||||
if (in_quote && ch == '\\') {
|
||||
if (cp1[0] != cp2[0]) break; // fail
|
||||
if (!cp1[0]) break;
|
||||
cp1++; cp2++;
|
||||
}
|
||||
if (in_quote && ch == in_quote) {
|
||||
in_quote = '\0';
|
||||
} else if (!in_quote && (ch == '"' || ch == '\'')) {
|
||||
in_quote = ch;
|
||||
}
|
||||
}
|
||||
return (!cp1[0] && !cp2[0]);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------trim------------------------------------------
|
||||
void ADLParser::trim(char* &token) {
|
||||
while (*token <= ' ') token++;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. 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
|
||||
@ -93,6 +93,7 @@ protected:
|
||||
void pipe_parse(void); // Parse pipeline section
|
||||
void definitions_parse(void); // Parse definitions section
|
||||
void peep_parse(void); // Parse peephole rule definitions
|
||||
void preproc_line(void); // Parse a #line statement
|
||||
void preproc_define(void); // Parse a #define statement
|
||||
void preproc_undef(void); // Parse an #undef statement
|
||||
|
||||
@ -226,7 +227,7 @@ protected:
|
||||
void get_effectlist(FormDict &effects, FormDict &operands); // Parse effect-operand pairs
|
||||
// Return the contents of a parenthesized expression.
|
||||
// Requires initial '(' and consumes final ')', which is replaced by '\0'.
|
||||
char *get_paren_expr(const char *description);
|
||||
char *get_paren_expr(const char *description, bool include_location = false);
|
||||
// Return expression up to next stop-char, which terminator replaces.
|
||||
// Does not require initial '('. Does not consume final stop-char.
|
||||
// Final stop-char is left in _curchar, but is also is replaced by '\0'.
|
||||
@ -234,6 +235,11 @@ protected:
|
||||
char *find_cpp_block(const char *description); // Parse a C++ code block
|
||||
// Issue parser error message & go to EOL
|
||||
void parse_err(int flag, const char *fmt, ...);
|
||||
// Create a location marker for this file and line.
|
||||
char *get_line_string(int linenum = 0);
|
||||
// Return a location marker which tells the C preprocessor to
|
||||
// forget the previous location marker. (Requires awk postprocessing.)
|
||||
char *end_line_marker() { return (char*)"\n#line 999999\n"; }
|
||||
|
||||
// Return pointer to current character
|
||||
inline char cur_char(void);
|
||||
@ -268,5 +274,6 @@ public:
|
||||
static bool is_literal_constant(const char *hex_string);
|
||||
static bool is_hex_digit(char digit);
|
||||
static bool is_int_token(const char* token, int& intval);
|
||||
static bool equivalent_expressions(const char* str1, const char* str2);
|
||||
static void trim(char* &token); // trim leading & trailing spaces
|
||||
};
|
||||
|
||||
@ -140,7 +140,7 @@ bool MatchList::search(const char *opc, const char *res, const char *lch,
|
||||
if ((rch == _rchild) || (rch && _rchild && !strcmp(rch, _rchild))) {
|
||||
char * predStr = get_pred();
|
||||
char * prStr = pr?pr->_pred:NULL;
|
||||
if ((prStr == predStr) || (prStr && predStr && !strcmp(prStr, predStr))) {
|
||||
if (ADLParser::equivalent_expressions(prStr, predStr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -458,7 +458,7 @@ void ArchDesc::buildDFA(FILE* fp) {
|
||||
|
||||
|
||||
class dfa_shared_preds {
|
||||
enum { count = 2 };
|
||||
enum { count = 4 };
|
||||
|
||||
static bool _found[count];
|
||||
static const char* _type [count];
|
||||
@ -479,12 +479,15 @@ class dfa_shared_preds {
|
||||
char c = *prev;
|
||||
switch( c ) {
|
||||
case ' ':
|
||||
case '\n':
|
||||
return dfa_shared_preds::valid_loc(pred, prev);
|
||||
case '!':
|
||||
case '(':
|
||||
case '<':
|
||||
case '=':
|
||||
return true;
|
||||
case '"': // such as: #line 10 "myfile.ad"\n mypredicate
|
||||
return true;
|
||||
case '|':
|
||||
if( prev != pred && *(prev-1) == '|' ) return true;
|
||||
case '&':
|
||||
@ -564,10 +567,14 @@ public:
|
||||
}
|
||||
};
|
||||
// shared predicates, _var and _pred entry should be the same length
|
||||
bool dfa_shared_preds::_found[dfa_shared_preds::count] = { false, false };
|
||||
const char* dfa_shared_preds::_type[dfa_shared_preds::count] = { "int", "bool" };
|
||||
const char* dfa_shared_preds::_var [dfa_shared_preds::count] = { "_n_get_int__", "Compile__current____select_24_bit_instr__" };
|
||||
const char* dfa_shared_preds::_pred[dfa_shared_preds::count] = { "n->get_int()", "Compile::current()->select_24_bit_instr()" };
|
||||
bool dfa_shared_preds::_found[dfa_shared_preds::count]
|
||||
= { false, false, false, false };
|
||||
const char* dfa_shared_preds::_type[dfa_shared_preds::count]
|
||||
= { "int", "jlong", "intptr_t", "bool" };
|
||||
const char* dfa_shared_preds::_var [dfa_shared_preds::count]
|
||||
= { "_n_get_int__", "_n_get_long__", "_n_get_intptr_t__", "Compile__current____select_24_bit_instr__" };
|
||||
const char* dfa_shared_preds::_pred[dfa_shared_preds::count]
|
||||
= { "n->get_int()", "n->get_long()", "n->get_intptr_t()", "Compile::current()->select_24_bit_instr()" };
|
||||
|
||||
|
||||
void ArchDesc::gen_dfa_state_body(FILE* fp, Dict &minimize, ProductionState &status, Dict &operands_chained_from, int i) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2002 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2004 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. 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
|
||||
@ -68,6 +68,7 @@ class FileBuff {
|
||||
// and increments bufeol and filepos to point at the end of that line.
|
||||
char *get_line(void);
|
||||
int linenum() const { return _linenum; }
|
||||
void set_linenum(int line) { _linenum = line; }
|
||||
|
||||
// This converts a pointer into the buffer to a file offset. It only works
|
||||
// when the pointer is valid (i.e. just obtained from getline()).
|
||||
|
||||
@ -1102,10 +1102,7 @@ bool equivalent_predicates( const InstructForm *instr1, const InstructForm *inst
|
||||
}
|
||||
if( pred1 != NULL && pred2 != NULL ) {
|
||||
// compare the predicates
|
||||
const char *str1 = pred1->_pred;
|
||||
const char *str2 = pred2->_pred;
|
||||
if( (str1 == NULL && str2 == NULL)
|
||||
|| (str1 != NULL && str2 != NULL && strcmp(str1,str2) == 0) ) {
|
||||
if (ADLParser::equivalent_expressions(pred1->_pred, pred2->_pred)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. 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
|
||||
@ -676,21 +676,6 @@ GraphBuilder::ScopeData::ScopeData(ScopeData* parent)
|
||||
}
|
||||
|
||||
|
||||
void GraphBuilder::kill_field(ciField* field) {
|
||||
if (UseLocalValueNumbering) {
|
||||
vmap()->kill_field(field);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GraphBuilder::kill_array(Value value) {
|
||||
if (UseLocalValueNumbering) {
|
||||
vmap()->kill_array(value->type());
|
||||
}
|
||||
_memory->store_value(value);
|
||||
}
|
||||
|
||||
|
||||
void GraphBuilder::kill_all() {
|
||||
if (UseLocalValueNumbering) {
|
||||
vmap()->kill_all();
|
||||
@ -987,8 +972,8 @@ void GraphBuilder::store_indexed(BasicType type) {
|
||||
length = append(new ArrayLength(array, lock_stack()));
|
||||
}
|
||||
StoreIndexed* result = new StoreIndexed(array, index, length, type, value, lock_stack());
|
||||
kill_array(value); // invalidate all CSEs that are memory accesses of the same type
|
||||
append(result);
|
||||
_memory->store_value(value);
|
||||
}
|
||||
|
||||
|
||||
@ -1478,9 +1463,6 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
|
||||
case Bytecodes::_putstatic:
|
||||
{ Value val = pop(type);
|
||||
append(new StoreField(append(obj), offset, field, val, true, lock_stack(), state_copy, is_loaded, is_initialized));
|
||||
if (UseLocalValueNumbering) {
|
||||
vmap()->kill_field(field); // invalidate all CSEs that are memory accesses
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Bytecodes::_getfield :
|
||||
@ -1503,7 +1485,6 @@ void GraphBuilder::access_field(Bytecodes::Code code) {
|
||||
if (is_loaded) store = _memory->store(store);
|
||||
if (store != NULL) {
|
||||
append(store);
|
||||
kill_field(field); // invalidate all CSEs that are accesses of this field
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1900,6 +1881,8 @@ Instruction* GraphBuilder::append_with_bci(Instruction* instr, int bci) {
|
||||
assert(i2->bci() != -1, "should already be linked");
|
||||
return i2;
|
||||
}
|
||||
ValueNumberingEffects vne(vmap());
|
||||
i1->visit(&vne);
|
||||
}
|
||||
|
||||
if (i1->as_Phi() == NULL && i1->as_Local() == NULL) {
|
||||
@ -1926,14 +1909,8 @@ Instruction* GraphBuilder::append_with_bci(Instruction* instr, int bci) {
|
||||
assert(_last == i1, "adjust code below");
|
||||
StateSplit* s = i1->as_StateSplit();
|
||||
if (s != NULL && i1->as_BlockEnd() == NULL) {
|
||||
// Continue CSE across certain intrinsics
|
||||
Intrinsic* intrinsic = s->as_Intrinsic();
|
||||
if (UseLocalValueNumbering) {
|
||||
if (intrinsic == NULL || !intrinsic->preserves_state()) {
|
||||
vmap()->kill_all(); // for now, hopefully we need this only for calls eventually
|
||||
}
|
||||
}
|
||||
if (EliminateFieldAccess) {
|
||||
Intrinsic* intrinsic = s->as_Intrinsic();
|
||||
if (s->as_Invoke() != NULL || (intrinsic && !intrinsic->preserves_state())) {
|
||||
_memory->kill();
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -283,8 +283,6 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
|
||||
Dependencies* dependency_recorder() const; // = compilation()->dependencies()
|
||||
bool direct_compare(ciKlass* k);
|
||||
|
||||
void kill_field(ciField* field);
|
||||
void kill_array(Value value);
|
||||
void kill_all();
|
||||
|
||||
ValueStack* lock_stack();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1210,8 +1210,8 @@ LIR_Opr LIRGenerator::load_constant(LIR_Const* c) {
|
||||
break;
|
||||
case T_LONG:
|
||||
case T_DOUBLE:
|
||||
if (c->as_jint_hi_bits() != other->as_jint_lo_bits()) continue;
|
||||
if (c->as_jint_lo_bits() != other->as_jint_hi_bits()) continue;
|
||||
if (c->as_jint_hi_bits() != other->as_jint_hi_bits()) continue;
|
||||
if (c->as_jint_lo_bits() != other->as_jint_lo_bits()) continue;
|
||||
break;
|
||||
case T_OBJECT:
|
||||
if (c->as_jobject() != other->as_jobject()) continue;
|
||||
|
||||
@ -327,8 +327,6 @@ class BlockMerger: public BlockClosure {
|
||||
BlockBegin* fsux = if_->fsux();
|
||||
if (swapped) {
|
||||
cond = Instruction::mirror(cond);
|
||||
tsux = if_->fsux();
|
||||
fsux = if_->tsux();
|
||||
}
|
||||
|
||||
BlockBegin* tblock = tval->compare(cond, con, tsux, fsux);
|
||||
|
||||
@ -842,6 +842,13 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i
|
||||
if (TracePatching) {
|
||||
tty->print_cr("Deoptimizing for patching volatile field reference");
|
||||
}
|
||||
// It's possible the nmethod was invalidated in the last
|
||||
// safepoint, but if it's still alive then make it not_entrant.
|
||||
nmethod* nm = CodeCache::find_nmethod(caller_frame.pc());
|
||||
if (nm != NULL) {
|
||||
nm->make_not_entrant();
|
||||
}
|
||||
|
||||
VM_DeoptimizeFrame deopt(thread, caller_frame.id());
|
||||
VMThread::execute(&deopt);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -133,53 +133,77 @@ class ValueNumberingVisitor: public InstructionVisitor {
|
||||
virtual void kill_array(ValueType* type) = 0;
|
||||
|
||||
// visitor functions
|
||||
void do_StoreField (StoreField* x) { kill_field(x->field()); };
|
||||
void do_StoreIndexed (StoreIndexed* x) { kill_array(x->type()); };
|
||||
void do_MonitorEnter (MonitorEnter* x) { kill_memory(); };
|
||||
void do_MonitorExit (MonitorExit* x) { kill_memory(); };
|
||||
void do_Invoke (Invoke* x) { kill_memory(); };
|
||||
void do_UnsafePutRaw (UnsafePutRaw* x) { kill_memory(); };
|
||||
void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); };
|
||||
void do_Intrinsic (Intrinsic* x) { if (!x->preserves_state()) kill_memory(); };
|
||||
void do_StoreField (StoreField* x) {
|
||||
if (!x->is_initialized()) {
|
||||
kill_memory();
|
||||
} else {
|
||||
kill_field(x->field());
|
||||
}
|
||||
}
|
||||
void do_StoreIndexed (StoreIndexed* x) { kill_array(x->type()); }
|
||||
void do_MonitorEnter (MonitorEnter* x) { kill_memory(); }
|
||||
void do_MonitorExit (MonitorExit* x) { kill_memory(); }
|
||||
void do_Invoke (Invoke* x) { kill_memory(); }
|
||||
void do_UnsafePutRaw (UnsafePutRaw* x) { kill_memory(); }
|
||||
void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); }
|
||||
void do_Intrinsic (Intrinsic* x) { if (!x->preserves_state()) kill_memory(); }
|
||||
|
||||
void do_Phi (Phi* x) { /* nothing to do */ };
|
||||
void do_Local (Local* x) { /* nothing to do */ };
|
||||
void do_Constant (Constant* x) { /* nothing to do */ };
|
||||
void do_LoadField (LoadField* x) { /* nothing to do */ };
|
||||
void do_ArrayLength (ArrayLength* x) { /* nothing to do */ };
|
||||
void do_LoadIndexed (LoadIndexed* x) { /* nothing to do */ };
|
||||
void do_NegateOp (NegateOp* x) { /* nothing to do */ };
|
||||
void do_ArithmeticOp (ArithmeticOp* x) { /* nothing to do */ };
|
||||
void do_ShiftOp (ShiftOp* x) { /* nothing to do */ };
|
||||
void do_LogicOp (LogicOp* x) { /* nothing to do */ };
|
||||
void do_CompareOp (CompareOp* x) { /* nothing to do */ };
|
||||
void do_IfOp (IfOp* x) { /* nothing to do */ };
|
||||
void do_Convert (Convert* x) { /* nothing to do */ };
|
||||
void do_NullCheck (NullCheck* x) { /* nothing to do */ };
|
||||
void do_NewInstance (NewInstance* x) { /* nothing to do */ };
|
||||
void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ };
|
||||
void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ };
|
||||
void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ };
|
||||
void do_CheckCast (CheckCast* x) { /* nothing to do */ };
|
||||
void do_InstanceOf (InstanceOf* x) { /* nothing to do */ };
|
||||
void do_BlockBegin (BlockBegin* x) { /* nothing to do */ };
|
||||
void do_Goto (Goto* x) { /* nothing to do */ };
|
||||
void do_If (If* x) { /* nothing to do */ };
|
||||
void do_IfInstanceOf (IfInstanceOf* x) { /* nothing to do */ };
|
||||
void do_TableSwitch (TableSwitch* x) { /* nothing to do */ };
|
||||
void do_LookupSwitch (LookupSwitch* x) { /* nothing to do */ };
|
||||
void do_Return (Return* x) { /* nothing to do */ };
|
||||
void do_Throw (Throw* x) { /* nothing to do */ };
|
||||
void do_Base (Base* x) { /* nothing to do */ };
|
||||
void do_OsrEntry (OsrEntry* x) { /* nothing to do */ };
|
||||
void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ };
|
||||
void do_RoundFP (RoundFP* x) { /* nothing to do */ };
|
||||
void do_UnsafeGetRaw (UnsafeGetRaw* x) { /* nothing to do */ };
|
||||
void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ };
|
||||
void do_UnsafePrefetchRead (UnsafePrefetchRead* x) { /* nothing to do */ };
|
||||
void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ };
|
||||
void do_ProfileCall (ProfileCall* x) { /* nothing to do */ };
|
||||
void do_ProfileCounter (ProfileCounter* x) { /* nothing to do */ };
|
||||
void do_Phi (Phi* x) { /* nothing to do */ }
|
||||
void do_Local (Local* x) { /* nothing to do */ }
|
||||
void do_Constant (Constant* x) { /* nothing to do */ }
|
||||
void do_LoadField (LoadField* x) {
|
||||
if (!x->is_initialized()) {
|
||||
kill_memory();
|
||||
}
|
||||
}
|
||||
void do_ArrayLength (ArrayLength* x) { /* nothing to do */ }
|
||||
void do_LoadIndexed (LoadIndexed* x) { /* nothing to do */ }
|
||||
void do_NegateOp (NegateOp* x) { /* nothing to do */ }
|
||||
void do_ArithmeticOp (ArithmeticOp* x) { /* nothing to do */ }
|
||||
void do_ShiftOp (ShiftOp* x) { /* nothing to do */ }
|
||||
void do_LogicOp (LogicOp* x) { /* nothing to do */ }
|
||||
void do_CompareOp (CompareOp* x) { /* nothing to do */ }
|
||||
void do_IfOp (IfOp* x) { /* nothing to do */ }
|
||||
void do_Convert (Convert* x) { /* nothing to do */ }
|
||||
void do_NullCheck (NullCheck* x) { /* nothing to do */ }
|
||||
void do_NewInstance (NewInstance* x) { /* nothing to do */ }
|
||||
void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ }
|
||||
void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ }
|
||||
void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ }
|
||||
void do_CheckCast (CheckCast* x) { /* nothing to do */ }
|
||||
void do_InstanceOf (InstanceOf* x) { /* nothing to do */ }
|
||||
void do_BlockBegin (BlockBegin* x) { /* nothing to do */ }
|
||||
void do_Goto (Goto* x) { /* nothing to do */ }
|
||||
void do_If (If* x) { /* nothing to do */ }
|
||||
void do_IfInstanceOf (IfInstanceOf* x) { /* nothing to do */ }
|
||||
void do_TableSwitch (TableSwitch* x) { /* nothing to do */ }
|
||||
void do_LookupSwitch (LookupSwitch* x) { /* nothing to do */ }
|
||||
void do_Return (Return* x) { /* nothing to do */ }
|
||||
void do_Throw (Throw* x) { /* nothing to do */ }
|
||||
void do_Base (Base* x) { /* nothing to do */ }
|
||||
void do_OsrEntry (OsrEntry* x) { /* nothing to do */ }
|
||||
void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ }
|
||||
void do_RoundFP (RoundFP* x) { /* nothing to do */ }
|
||||
void do_UnsafeGetRaw (UnsafeGetRaw* x) { /* nothing to do */ }
|
||||
void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ }
|
||||
void do_UnsafePrefetchRead (UnsafePrefetchRead* x) { /* nothing to do */ }
|
||||
void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ }
|
||||
void do_ProfileCall (ProfileCall* x) { /* nothing to do */ }
|
||||
void do_ProfileCounter (ProfileCounter* x) { /* nothing to do */ }
|
||||
};
|
||||
|
||||
|
||||
class ValueNumberingEffects: public ValueNumberingVisitor {
|
||||
private:
|
||||
ValueMap* _map;
|
||||
|
||||
public:
|
||||
// implementation for abstract methods of ValueNumberingVisitor
|
||||
void kill_memory() { _map->kill_memory(); }
|
||||
void kill_field(ciField* field) { _map->kill_field(field); }
|
||||
void kill_array(ValueType* type) { _map->kill_array(type); }
|
||||
|
||||
ValueNumberingEffects(ValueMap* map): _map(map) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2000-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -581,7 +581,8 @@ objArrayHandle ClassFileParser::parse_interfaces(constantPoolHandle cp,
|
||||
interf = KlassHandle(THREAD, k);
|
||||
vmtimer->resume();
|
||||
|
||||
cp->klass_at_put(interface_index, interf()); // eagerly resolve
|
||||
if (LinkWellKnownClasses) // my super type is well known to me
|
||||
cp->klass_at_put(interface_index, interf()); // eagerly resolve
|
||||
}
|
||||
|
||||
if (!Klass::cast(interf())->is_interface()) {
|
||||
@ -2699,7 +2700,8 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
||||
CHECK_(nullHandle));
|
||||
KlassHandle kh (THREAD, k);
|
||||
super_klass = instanceKlassHandle(THREAD, kh());
|
||||
cp->klass_at_put(super_class_index, super_klass()); // eagerly resolve
|
||||
if (LinkWellKnownClasses) // my super class is well known to me
|
||||
cp->klass_at_put(super_class_index, super_klass()); // eagerly resolve
|
||||
}
|
||||
if (super_klass.not_null()) {
|
||||
if (super_klass->is_interface()) {
|
||||
@ -3128,7 +3130,8 @@ instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
|
||||
this_klass->set_method_ordering(method_ordering());
|
||||
this_klass->set_initial_method_idnum(methods->length());
|
||||
this_klass->set_name(cp->klass_name_at(this_class_index));
|
||||
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
|
||||
if (LinkWellKnownClasses) // I am well known to myself
|
||||
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
|
||||
this_klass->set_protection_domain(protection_domain());
|
||||
this_klass->set_fields_annotations(fields_annotations());
|
||||
this_klass->set_methods_annotations(methods_annotations());
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -325,24 +325,30 @@ class Par_PushOrMarkClosure: public OopClosure {
|
||||
// For objects in CMS generation, this closure marks
|
||||
// given objects (transitively) as being reachable/live.
|
||||
// This is currently used during the (weak) reference object
|
||||
// processing phase of the CMS final checkpoint step.
|
||||
// processing phase of the CMS final checkpoint step, as
|
||||
// well as during the concurrent precleaning of the discovered
|
||||
// reference lists.
|
||||
class CMSKeepAliveClosure: public OopClosure {
|
||||
private:
|
||||
CMSCollector* _collector;
|
||||
const MemRegion _span;
|
||||
CMSMarkStack* _mark_stack;
|
||||
CMSBitMap* _bit_map;
|
||||
bool _concurrent_precleaning;
|
||||
protected:
|
||||
DO_OOP_WORK_DEFN
|
||||
public:
|
||||
CMSKeepAliveClosure(CMSCollector* collector, MemRegion span,
|
||||
CMSBitMap* bit_map, CMSMarkStack* mark_stack):
|
||||
CMSBitMap* bit_map, CMSMarkStack* mark_stack,
|
||||
bool cpc):
|
||||
_collector(collector),
|
||||
_span(span),
|
||||
_bit_map(bit_map),
|
||||
_mark_stack(mark_stack) {
|
||||
_mark_stack(mark_stack),
|
||||
_concurrent_precleaning(cpc) {
|
||||
assert(!_span.is_empty(), "Empty span could spell trouble");
|
||||
}
|
||||
bool concurrent_precleaning() const { return _concurrent_precleaning; }
|
||||
virtual void do_oop(oop* p);
|
||||
virtual void do_oop(narrowOop* p);
|
||||
inline void do_oop_nv(oop* p) { CMSKeepAliveClosure::do_oop_work(p); }
|
||||
|
||||
@ -538,6 +538,7 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen,
|
||||
_survivor_chunk_capacity(0), // -- ditto --
|
||||
_survivor_chunk_index(0), // -- ditto --
|
||||
_ser_pmc_preclean_ovflw(0),
|
||||
_ser_kac_preclean_ovflw(0),
|
||||
_ser_pmc_remark_ovflw(0),
|
||||
_par_pmc_remark_ovflw(0),
|
||||
_ser_kac_ovflw(0),
|
||||
@ -1960,6 +1961,7 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) {
|
||||
|
||||
ref_processor()->set_enqueuing_is_done(false);
|
||||
ref_processor()->enable_discovery();
|
||||
ref_processor()->setup_policy(clear_all_soft_refs);
|
||||
// If an asynchronous collection finishes, the _modUnionTable is
|
||||
// all clear. If we are assuming the collection from an asynchronous
|
||||
// collection, clear the _modUnionTable.
|
||||
@ -2383,6 +2385,9 @@ void CMSCollector::collect_in_foreground(bool clear_all_soft_refs) {
|
||||
Universe::verify(true);
|
||||
}
|
||||
|
||||
// Snapshot the soft reference policy to be used in this collection cycle.
|
||||
ref_processor()->setup_policy(clear_all_soft_refs);
|
||||
|
||||
bool init_mark_was_synchronous = false; // until proven otherwise
|
||||
while (_collectorState != Idling) {
|
||||
if (TraceCMSState) {
|
||||
@ -4388,10 +4393,10 @@ size_t CMSCollector::preclean_work(bool clean_refs, bool clean_survivor) {
|
||||
CMSPrecleanRefsYieldClosure yield_cl(this);
|
||||
assert(rp->span().equals(_span), "Spans should be equal");
|
||||
CMSKeepAliveClosure keep_alive(this, _span, &_markBitMap,
|
||||
&_markStack);
|
||||
&_markStack, true /* preclean */);
|
||||
CMSDrainMarkingStackClosure complete_trace(this,
|
||||
_span, &_markBitMap, &_markStack,
|
||||
&keep_alive);
|
||||
_span, &_markBitMap, &_markStack,
|
||||
&keep_alive, true /* preclean */);
|
||||
|
||||
// We don't want this step to interfere with a young
|
||||
// collection because we don't want to take CPU
|
||||
@ -4590,11 +4595,11 @@ size_t CMSCollector::preclean_mod_union_table(
|
||||
if (!dirtyRegion.is_empty()) {
|
||||
assert(numDirtyCards > 0, "consistency check");
|
||||
HeapWord* stop_point = NULL;
|
||||
stopTimer();
|
||||
CMSTokenSyncWithLocks ts(true, gen->freelistLock(),
|
||||
bitMapLock());
|
||||
startTimer();
|
||||
{
|
||||
stopTimer();
|
||||
CMSTokenSyncWithLocks ts(true, gen->freelistLock(),
|
||||
bitMapLock());
|
||||
startTimer();
|
||||
verify_work_stacks_empty();
|
||||
verify_overflow_empty();
|
||||
sample_eden();
|
||||
@ -4611,10 +4616,6 @@ size_t CMSCollector::preclean_mod_union_table(
|
||||
assert((CMSPermGenPrecleaningEnabled && (gen == _permGen)) ||
|
||||
(_collectorState == AbortablePreclean && should_abort_preclean()),
|
||||
"Unparsable objects should only be in perm gen.");
|
||||
|
||||
stopTimer();
|
||||
CMSTokenSyncWithLocks ts(true, bitMapLock());
|
||||
startTimer();
|
||||
_modUnionTable.mark_range(MemRegion(stop_point, dirtyRegion.end()));
|
||||
if (should_abort_preclean()) {
|
||||
break; // out of preclean loop
|
||||
@ -4852,17 +4853,19 @@ void CMSCollector::checkpointRootsFinalWork(bool asynch,
|
||||
// recurrence of that condition.
|
||||
assert(_markStack.isEmpty(), "No grey objects");
|
||||
size_t ser_ovflw = _ser_pmc_remark_ovflw + _ser_pmc_preclean_ovflw +
|
||||
_ser_kac_ovflw;
|
||||
_ser_kac_ovflw + _ser_kac_preclean_ovflw;
|
||||
if (ser_ovflw > 0) {
|
||||
if (PrintCMSStatistics != 0) {
|
||||
gclog_or_tty->print_cr("Marking stack overflow (benign) "
|
||||
"(pmc_pc="SIZE_FORMAT", pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT")",
|
||||
"(pmc_pc="SIZE_FORMAT", pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT
|
||||
", kac_preclean="SIZE_FORMAT")",
|
||||
_ser_pmc_preclean_ovflw, _ser_pmc_remark_ovflw,
|
||||
_ser_kac_ovflw);
|
||||
_ser_kac_ovflw, _ser_kac_preclean_ovflw);
|
||||
}
|
||||
_markStack.expand();
|
||||
_ser_pmc_remark_ovflw = 0;
|
||||
_ser_pmc_preclean_ovflw = 0;
|
||||
_ser_kac_preclean_ovflw = 0;
|
||||
_ser_kac_ovflw = 0;
|
||||
}
|
||||
if (_par_pmc_remark_ovflw > 0 || _par_kac_ovflw > 0) {
|
||||
@ -5675,40 +5678,29 @@ void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) {
|
||||
|
||||
ResourceMark rm;
|
||||
HandleMark hm;
|
||||
ReferencePolicy* soft_ref_policy;
|
||||
|
||||
assert(!ref_processor()->enqueuing_is_done(), "Enqueuing should not be complete");
|
||||
// Process weak references.
|
||||
if (clear_all_soft_refs) {
|
||||
soft_ref_policy = new AlwaysClearPolicy();
|
||||
} else {
|
||||
#ifdef COMPILER2
|
||||
soft_ref_policy = new LRUMaxHeapPolicy();
|
||||
#else
|
||||
soft_ref_policy = new LRUCurrentHeapPolicy();
|
||||
#endif // COMPILER2
|
||||
}
|
||||
verify_work_stacks_empty();
|
||||
|
||||
ReferenceProcessor* rp = ref_processor();
|
||||
assert(rp->span().equals(_span), "Spans should be equal");
|
||||
assert(!rp->enqueuing_is_done(), "Enqueuing should not be complete");
|
||||
// Process weak references.
|
||||
rp->setup_policy(clear_all_soft_refs);
|
||||
verify_work_stacks_empty();
|
||||
|
||||
CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap,
|
||||
&_markStack);
|
||||
&_markStack, false /* !preclean */);
|
||||
CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this,
|
||||
_span, &_markBitMap, &_markStack,
|
||||
&cmsKeepAliveClosure);
|
||||
&cmsKeepAliveClosure, false /* !preclean */);
|
||||
{
|
||||
TraceTime t("weak refs processing", PrintGCDetails, false, gclog_or_tty);
|
||||
if (rp->processing_is_mt()) {
|
||||
CMSRefProcTaskExecutor task_executor(*this);
|
||||
rp->process_discovered_references(soft_ref_policy,
|
||||
&_is_alive_closure,
|
||||
rp->process_discovered_references(&_is_alive_closure,
|
||||
&cmsKeepAliveClosure,
|
||||
&cmsDrainMarkingStackClosure,
|
||||
&task_executor);
|
||||
} else {
|
||||
rp->process_discovered_references(soft_ref_policy,
|
||||
&_is_alive_closure,
|
||||
rp->process_discovered_references(&_is_alive_closure,
|
||||
&cmsKeepAliveClosure,
|
||||
&cmsDrainMarkingStackClosure,
|
||||
NULL);
|
||||
@ -6163,8 +6155,8 @@ void CMSCollector::verify_ok_to_terminate() const {
|
||||
#endif
|
||||
|
||||
size_t CMSCollector::block_size_using_printezis_bits(HeapWord* addr) const {
|
||||
assert(_markBitMap.isMarked(addr) && _markBitMap.isMarked(addr + 1),
|
||||
"missing Printezis mark?");
|
||||
assert(_markBitMap.isMarked(addr) && _markBitMap.isMarked(addr + 1),
|
||||
"missing Printezis mark?");
|
||||
HeapWord* nextOneAddr = _markBitMap.getNextMarkedWordAddress(addr + 2);
|
||||
size_t size = pointer_delta(nextOneAddr + 1, addr);
|
||||
assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
|
||||
@ -8302,8 +8294,29 @@ void CMSKeepAliveClosure::do_oop(oop obj) {
|
||||
}
|
||||
)
|
||||
if (simulate_overflow || !_mark_stack->push(obj)) {
|
||||
_collector->push_on_overflow_list(obj);
|
||||
_collector->_ser_kac_ovflw++;
|
||||
if (_concurrent_precleaning) {
|
||||
// We dirty the overflown object and let the remark
|
||||
// phase deal with it.
|
||||
assert(_collector->overflow_list_is_empty(), "Error");
|
||||
// In the case of object arrays, we need to dirty all of
|
||||
// the cards that the object spans. No locking or atomics
|
||||
// are needed since no one else can be mutating the mod union
|
||||
// table.
|
||||
if (obj->is_objArray()) {
|
||||
size_t sz = obj->size();
|
||||
HeapWord* end_card_addr =
|
||||
(HeapWord*)round_to((intptr_t)(addr+sz), CardTableModRefBS::card_size);
|
||||
MemRegion redirty_range = MemRegion(addr, end_card_addr);
|
||||
assert(!redirty_range.is_empty(), "Arithmetical tautology");
|
||||
_collector->_modUnionTable.mark_range(redirty_range);
|
||||
} else {
|
||||
_collector->_modUnionTable.mark(addr);
|
||||
}
|
||||
_collector->_ser_kac_preclean_ovflw++;
|
||||
} else {
|
||||
_collector->push_on_overflow_list(obj);
|
||||
_collector->_ser_kac_ovflw++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8400,6 +8413,8 @@ const char* CMSExpansionCause::to_string(CMSExpansionCause::Cause cause) {
|
||||
void CMSDrainMarkingStackClosure::do_void() {
|
||||
// the max number to take from overflow list at a time
|
||||
const size_t num = _mark_stack->capacity()/4;
|
||||
assert(!_concurrent_precleaning || _collector->overflow_list_is_empty(),
|
||||
"Overflow list should be NULL during concurrent phases");
|
||||
while (!_mark_stack->isEmpty() ||
|
||||
// if stack is empty, check the overflow list
|
||||
_collector->take_from_overflow_list(num, _mark_stack)) {
|
||||
|
||||
@ -592,6 +592,7 @@ class CMSCollector: public CHeapObj {
|
||||
size_t _ser_pmc_preclean_ovflw;
|
||||
size_t _ser_pmc_remark_ovflw;
|
||||
size_t _par_pmc_remark_ovflw;
|
||||
size_t _ser_kac_preclean_ovflw;
|
||||
size_t _ser_kac_ovflw;
|
||||
size_t _par_kac_ovflw;
|
||||
NOT_PRODUCT(size_t _num_par_pushes;)
|
||||
@ -1749,21 +1750,30 @@ class SweepClosure: public BlkClosureCareful {
|
||||
// work-routine/closure used to complete transitive
|
||||
// marking of objects as live after a certain point
|
||||
// in which an initial set has been completely accumulated.
|
||||
// This closure is currently used both during the final
|
||||
// remark stop-world phase, as well as during the concurrent
|
||||
// precleaning of the discovered reference lists.
|
||||
class CMSDrainMarkingStackClosure: public VoidClosure {
|
||||
CMSCollector* _collector;
|
||||
MemRegion _span;
|
||||
CMSMarkStack* _mark_stack;
|
||||
CMSBitMap* _bit_map;
|
||||
CMSKeepAliveClosure* _keep_alive;
|
||||
bool _concurrent_precleaning;
|
||||
public:
|
||||
CMSDrainMarkingStackClosure(CMSCollector* collector, MemRegion span,
|
||||
CMSBitMap* bit_map, CMSMarkStack* mark_stack,
|
||||
CMSKeepAliveClosure* keep_alive):
|
||||
CMSKeepAliveClosure* keep_alive,
|
||||
bool cpc):
|
||||
_collector(collector),
|
||||
_span(span),
|
||||
_bit_map(bit_map),
|
||||
_mark_stack(mark_stack),
|
||||
_keep_alive(keep_alive) { }
|
||||
_keep_alive(keep_alive),
|
||||
_concurrent_precleaning(cpc) {
|
||||
assert(_concurrent_precleaning == _keep_alive->concurrent_precleaning(),
|
||||
"Mismatch");
|
||||
}
|
||||
|
||||
void do_void();
|
||||
};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
@ -811,6 +811,7 @@ void ConcurrentMark::checkpointRootsInitialPost() {
|
||||
ReferenceProcessor* rp = g1h->ref_processor();
|
||||
rp->verify_no_references_recorded();
|
||||
rp->enable_discovery(); // enable ("weak") refs discovery
|
||||
rp->setup_policy(false); // snapshot the soft ref policy to be used in this cycle
|
||||
|
||||
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
|
||||
satb_mq_set.set_process_completed_threshold(G1SATBProcessCompletedThreshold);
|
||||
@ -1829,32 +1830,21 @@ class G1CMDrainMarkingStackClosure: public VoidClosure {
|
||||
void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
|
||||
ResourceMark rm;
|
||||
HandleMark hm;
|
||||
ReferencePolicy* soft_ref_policy;
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
ReferenceProcessor* rp = g1h->ref_processor();
|
||||
|
||||
// Process weak references.
|
||||
if (clear_all_soft_refs) {
|
||||
soft_ref_policy = new AlwaysClearPolicy();
|
||||
} else {
|
||||
#ifdef COMPILER2
|
||||
soft_ref_policy = new LRUMaxHeapPolicy();
|
||||
#else
|
||||
soft_ref_policy = new LRUCurrentHeapPolicy();
|
||||
#endif
|
||||
}
|
||||
rp->setup_policy(clear_all_soft_refs);
|
||||
assert(_markStack.isEmpty(), "mark stack should be empty");
|
||||
|
||||
G1CollectedHeap* g1 = G1CollectedHeap::heap();
|
||||
G1CMIsAliveClosure g1IsAliveClosure(g1);
|
||||
|
||||
G1CMKeepAliveClosure g1KeepAliveClosure(g1, this, nextMarkBitMap());
|
||||
G1CMIsAliveClosure g1IsAliveClosure (g1h);
|
||||
G1CMKeepAliveClosure g1KeepAliveClosure(g1h, this, nextMarkBitMap());
|
||||
G1CMDrainMarkingStackClosure
|
||||
g1DrainMarkingStackClosure(nextMarkBitMap(), &_markStack,
|
||||
&g1KeepAliveClosure);
|
||||
|
||||
// XXXYYY Also: copy the parallel ref processing code from CMS.
|
||||
ReferenceProcessor* rp = g1->ref_processor();
|
||||
rp->process_discovered_references(soft_ref_policy,
|
||||
&g1IsAliveClosure,
|
||||
rp->process_discovered_references(&g1IsAliveClosure,
|
||||
&g1KeepAliveClosure,
|
||||
&g1DrainMarkingStackClosure,
|
||||
NULL);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
@ -891,6 +891,7 @@ void G1CollectedHeap::do_collection(bool full, bool clear_all_soft_refs,
|
||||
ReferenceProcessorIsAliveMutator rp_is_alive_null(ref_processor(), NULL);
|
||||
|
||||
ref_processor()->enable_discovery();
|
||||
ref_processor()->setup_policy(clear_all_soft_refs);
|
||||
|
||||
// Do collection work
|
||||
{
|
||||
@ -2463,7 +2464,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(HeapRegion* popular_region) {
|
||||
|
||||
COMPILER2_PRESENT(DerivedPointerTable::clear());
|
||||
|
||||
// We want to turn off ref discovere, 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.
|
||||
bool was_enabled = ref_processor()->discovery_enabled();
|
||||
if (was_enabled) ref_processor()->disable_discovery();
|
||||
@ -2953,7 +2954,7 @@ public:
|
||||
// The object has been either evacuated or is dead. Fill it with a
|
||||
// dummy object.
|
||||
MemRegion mr((HeapWord*)obj, obj->size());
|
||||
SharedHeap::fill_region_with_object(mr);
|
||||
CollectedHeap::fill_with_object(mr);
|
||||
_cm->clearRangeBothMaps(mr);
|
||||
}
|
||||
}
|
||||
@ -3224,7 +3225,7 @@ void G1CollectedHeap::par_allocate_remaining_space(HeapRegion* r) {
|
||||
// Otherwise, try to claim it.
|
||||
block = r->par_allocate(free_words);
|
||||
} while (block == NULL);
|
||||
SharedHeap::fill_region_with_object(MemRegion(block, free_words));
|
||||
fill_with_object(block, free_words);
|
||||
}
|
||||
|
||||
#define use_local_bitmaps 1
|
||||
@ -3618,9 +3619,8 @@ public:
|
||||
guarantee(alloc_buffer(purpose)->contains(obj + word_sz - 1),
|
||||
"should contain whole object");
|
||||
alloc_buffer(purpose)->undo_allocation(obj, word_sz);
|
||||
}
|
||||
else {
|
||||
SharedHeap::fill_region_with_object(MemRegion(obj, word_sz));
|
||||
} else {
|
||||
CollectedHeap::fill_with_object(obj, word_sz);
|
||||
add_to_undo_waste(word_sz);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
@ -33,8 +33,9 @@ void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp,
|
||||
|
||||
// hook up weak ref data so it can be used during Mark-Sweep
|
||||
assert(GenMarkSweep::ref_processor() == NULL, "no stomping");
|
||||
GenMarkSweep::_ref_processor = rp;
|
||||
assert(rp != NULL, "should be non-NULL");
|
||||
GenMarkSweep::_ref_processor = rp;
|
||||
rp->setup_policy(clear_all_softrefs);
|
||||
|
||||
// When collecting the permanent generation methodOops may be moving,
|
||||
// so we either have to flush all bcp data or convert it into bci.
|
||||
@ -121,23 +122,12 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
|
||||
&GenMarkSweep::follow_root_closure);
|
||||
|
||||
// Process reference objects found during marking
|
||||
ReferencePolicy *soft_ref_policy;
|
||||
if (clear_all_softrefs) {
|
||||
soft_ref_policy = new AlwaysClearPolicy();
|
||||
} else {
|
||||
#ifdef COMPILER2
|
||||
soft_ref_policy = new LRUMaxHeapPolicy();
|
||||
#else
|
||||
soft_ref_policy = new LRUCurrentHeapPolicy();
|
||||
#endif
|
||||
}
|
||||
assert(soft_ref_policy != NULL,"No soft reference policy");
|
||||
GenMarkSweep::ref_processor()->process_discovered_references(
|
||||
soft_ref_policy,
|
||||
&GenMarkSweep::is_alive,
|
||||
&GenMarkSweep::keep_alive,
|
||||
&GenMarkSweep::follow_stack_closure,
|
||||
NULL);
|
||||
ReferenceProcessor* rp = GenMarkSweep::ref_processor();
|
||||
rp->setup_policy(clear_all_softrefs);
|
||||
rp->process_discovered_references(&GenMarkSweep::is_alive,
|
||||
&GenMarkSweep::keep_alive,
|
||||
&GenMarkSweep::follow_stack_closure,
|
||||
NULL);
|
||||
|
||||
// Follow system dictionary roots and unload classes
|
||||
bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::is_alive);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -181,7 +181,7 @@ public:
|
||||
|
||||
void scrub(CardTableModRefBS* ctbs, BitMap* card_bm) {
|
||||
HeapWord* hr_bot = hr()->bottom();
|
||||
int hr_first_card_index = ctbs->index_for(hr_bot);
|
||||
size_t hr_first_card_index = ctbs->index_for(hr_bot);
|
||||
bm()->set_intersection_at_offset(*card_bm, hr_first_card_index);
|
||||
#if PRT_COUNT_OCCUPIED
|
||||
recount_occupied();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
@ -102,7 +102,7 @@ HeapRegionSeq::alloc_obj_from_region_index(int ind, size_t word_size) {
|
||||
HeapWord* tmp = hr->allocate(sz);
|
||||
assert(tmp != NULL, "Humongous allocation failure");
|
||||
MemRegion mr = MemRegion(tmp, sz);
|
||||
SharedHeap::fill_region_with_object(mr);
|
||||
CollectedHeap::fill_with_object(mr);
|
||||
hr->declare_filled_region_to_BOT(mr);
|
||||
if (i == first) {
|
||||
first_hr->set_startsHumongous();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
// Copyright 2004-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -51,14 +51,14 @@ void ParGCAllocBuffer::retire(bool end_of_gc, bool retain) {
|
||||
if (_retained) {
|
||||
// If the buffer had been retained shorten the previous filler object.
|
||||
assert(_retained_filler.end() <= _top, "INVARIANT");
|
||||
SharedHeap::fill_region_with_object(_retained_filler);
|
||||
CollectedHeap::fill_with_object(_retained_filler);
|
||||
// Wasted space book-keeping, otherwise (normally) done in invalidate()
|
||||
_wasted += _retained_filler.word_size();
|
||||
_retained = false;
|
||||
}
|
||||
assert(!end_of_gc || !_retained, "At this point, end_of_gc ==> !_retained.");
|
||||
if (_top < _hard_end) {
|
||||
SharedHeap::fill_region_with_object(MemRegion(_top, _hard_end));
|
||||
CollectedHeap::fill_with_object(_top, _hard_end);
|
||||
if (!retain) {
|
||||
invalidate();
|
||||
} else {
|
||||
@ -155,7 +155,7 @@ ParGCAllocBufferWithBOT::ParGCAllocBufferWithBOT(size_t word_sz,
|
||||
// modifying the _next_threshold state in the BOT.
|
||||
void ParGCAllocBufferWithBOT::fill_region_with_block(MemRegion mr,
|
||||
bool contig) {
|
||||
SharedHeap::fill_region_with_object(mr);
|
||||
CollectedHeap::fill_with_object(mr);
|
||||
if (contig) {
|
||||
_bt.alloc_block(mr.start(), mr.end());
|
||||
} else {
|
||||
@ -171,7 +171,7 @@ HeapWord* ParGCAllocBufferWithBOT::allocate_slow(size_t word_sz) {
|
||||
"or else _true_end should be equal to _hard_end");
|
||||
assert(_retained, "or else _true_end should be equal to _hard_end");
|
||||
assert(_retained_filler.end() <= _top, "INVARIANT");
|
||||
SharedHeap::fill_region_with_object(_retained_filler);
|
||||
CollectedHeap::fill_with_object(_retained_filler);
|
||||
if (_top < _hard_end) {
|
||||
fill_region_with_block(MemRegion(_top, _hard_end), true);
|
||||
}
|
||||
@ -316,11 +316,9 @@ void ParGCAllocBufferWithBOT::retire(bool end_of_gc, bool retain) {
|
||||
while (_top <= chunk_boundary) {
|
||||
assert(pointer_delta(_hard_end, chunk_boundary) >= AlignmentReserve,
|
||||
"Consequence of last card handling above.");
|
||||
MemRegion chunk_portion(chunk_boundary, _hard_end);
|
||||
_bt.BlockOffsetArray::alloc_block(chunk_portion.start(),
|
||||
chunk_portion.end());
|
||||
SharedHeap::fill_region_with_object(chunk_portion);
|
||||
_hard_end = chunk_portion.start();
|
||||
_bt.BlockOffsetArray::alloc_block(chunk_boundary, _hard_end);
|
||||
CollectedHeap::fill_with_object(chunk_boundary, _hard_end);
|
||||
_hard_end = chunk_boundary;
|
||||
chunk_boundary -= ChunkSizeInWords;
|
||||
}
|
||||
_end = _hard_end - AlignmentReserve;
|
||||
|
||||
@ -201,7 +201,7 @@ void ParScanThreadState::undo_alloc_in_to_space(HeapWord* obj,
|
||||
"Should contain whole object.");
|
||||
to_space_alloc_buffer()->undo_allocation(obj, word_sz);
|
||||
} else {
|
||||
SharedHeap::fill_region_with_object(MemRegion(obj, word_sz));
|
||||
CollectedHeap::fill_with_object(obj, word_sz);
|
||||
}
|
||||
}
|
||||
|
||||
@ -759,17 +759,12 @@ void ParNewGeneration::collect(bool full,
|
||||
thread_state_set.steals(),
|
||||
thread_state_set.pops()+thread_state_set.steals());
|
||||
}
|
||||
assert(thread_state_set.pushes() == thread_state_set.pops() + thread_state_set.steals(),
|
||||
assert(thread_state_set.pushes() == thread_state_set.pops()
|
||||
+ thread_state_set.steals(),
|
||||
"Or else the queues are leaky.");
|
||||
|
||||
// For now, process discovered weak refs sequentially.
|
||||
#ifdef COMPILER2
|
||||
ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
|
||||
#else
|
||||
ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
|
||||
#endif // COMPILER2
|
||||
|
||||
// Process (weak) reference objects found during scavenge.
|
||||
ReferenceProcessor* rp = ref_processor();
|
||||
IsAliveClosure is_alive(this);
|
||||
ScanWeakRefClosure scan_weak_ref(this);
|
||||
KeepAliveClosure keep_alive(&scan_weak_ref);
|
||||
@ -778,18 +773,17 @@ void ParNewGeneration::collect(bool full,
|
||||
set_promo_failure_scan_stack_closure(&scan_without_gc_barrier);
|
||||
EvacuateFollowersClosureGeneral evacuate_followers(gch, _level,
|
||||
&scan_without_gc_barrier, &scan_with_gc_barrier);
|
||||
if (ref_processor()->processing_is_mt()) {
|
||||
rp->setup_policy(clear_all_soft_refs);
|
||||
if (rp->processing_is_mt()) {
|
||||
ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
|
||||
ref_processor()->process_discovered_references(
|
||||
soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers,
|
||||
&task_executor);
|
||||
rp->process_discovered_references(&is_alive, &keep_alive,
|
||||
&evacuate_followers, &task_executor);
|
||||
} else {
|
||||
thread_state_set.flush();
|
||||
gch->set_par_threads(0); // 0 ==> non-parallel.
|
||||
gch->save_marks();
|
||||
ref_processor()->process_discovered_references(
|
||||
soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers,
|
||||
NULL);
|
||||
rp->process_discovered_references(&is_alive, &keep_alive,
|
||||
&evacuate_followers, NULL);
|
||||
}
|
||||
if (!promotion_failed()) {
|
||||
// Swap the survivor spaces.
|
||||
@ -851,14 +845,14 @@ void ParNewGeneration::collect(bool full,
|
||||
|
||||
SpecializationStats::print();
|
||||
|
||||
ref_processor()->set_enqueuing_is_done(true);
|
||||
if (ref_processor()->processing_is_mt()) {
|
||||
rp->set_enqueuing_is_done(true);
|
||||
if (rp->processing_is_mt()) {
|
||||
ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
|
||||
ref_processor()->enqueue_discovered_references(&task_executor);
|
||||
rp->enqueue_discovered_references(&task_executor);
|
||||
} else {
|
||||
ref_processor()->enqueue_discovered_references(NULL);
|
||||
rp->enqueue_discovered_references(NULL);
|
||||
}
|
||||
ref_processor()->verify_no_references_recorded();
|
||||
rp->verify_no_references_recorded();
|
||||
}
|
||||
|
||||
static int sum;
|
||||
@ -1211,7 +1205,7 @@ ParNewGeneration::take_from_overflow_list(ParScanThreadState* par_scan_state) {
|
||||
int n = 0;
|
||||
while (cur != NULL) {
|
||||
oop obj_to_push = cur->forwardee();
|
||||
oop next = oop(cur->klass());
|
||||
oop next = oop(cur->klass_or_null());
|
||||
cur->set_klass(obj_to_push->klass());
|
||||
if (par_scan_state->should_be_partially_scanned(obj_to_push, cur)) {
|
||||
obj_to_push = cur;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2005-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2005-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
||||
@ -172,6 +172,7 @@ void PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) {
|
||||
COMPILER2_PRESENT(DerivedPointerTable::clear());
|
||||
|
||||
ref_processor()->enable_discovery();
|
||||
ref_processor()->setup_policy(clear_all_softrefs);
|
||||
|
||||
mark_sweep_phase1(clear_all_softrefs);
|
||||
|
||||
@ -388,7 +389,7 @@ bool PSMarkSweep::absorb_live_data_from_eden(PSAdaptiveSizePolicy* size_policy,
|
||||
// full GC.
|
||||
const size_t alignment = old_gen->virtual_space()->alignment();
|
||||
const size_t eden_used = eden_space->used_in_bytes();
|
||||
const size_t promoted = (size_t)(size_policy->avg_promoted()->padded_average());
|
||||
const size_t promoted = (size_t)size_policy->avg_promoted()->padded_average();
|
||||
const size_t absorb_size = align_size_up(eden_used + promoted, alignment);
|
||||
const size_t eden_capacity = eden_space->capacity_in_bytes();
|
||||
|
||||
@ -415,16 +416,14 @@ bool PSMarkSweep::absorb_live_data_from_eden(PSAdaptiveSizePolicy* size_policy,
|
||||
|
||||
// Fill the unused part of the old gen.
|
||||
MutableSpace* const old_space = old_gen->object_space();
|
||||
MemRegion old_gen_unused(old_space->top(), old_space->end());
|
||||
HeapWord* const unused_start = old_space->top();
|
||||
size_t const unused_words = pointer_delta(old_space->end(), unused_start);
|
||||
|
||||
// If the unused part of the old gen cannot be filled, skip
|
||||
// absorbing eden.
|
||||
if (old_gen_unused.word_size() < SharedHeap::min_fill_size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!old_gen_unused.is_empty()) {
|
||||
SharedHeap::fill_region_with_object(old_gen_unused);
|
||||
if (unused_words > 0) {
|
||||
if (unused_words < CollectedHeap::min_fill_size()) {
|
||||
return false; // If the old gen cannot be filled, must give up.
|
||||
}
|
||||
CollectedHeap::fill_with_objects(unused_start, unused_words);
|
||||
}
|
||||
|
||||
// Take the live data from eden and set both top and end in the old gen to
|
||||
@ -440,9 +439,8 @@ bool PSMarkSweep::absorb_live_data_from_eden(PSAdaptiveSizePolicy* size_policy,
|
||||
|
||||
// Update the object start array for the filler object and the data from eden.
|
||||
ObjectStartArray* const start_array = old_gen->start_array();
|
||||
HeapWord* const start = old_gen_unused.start();
|
||||
for (HeapWord* addr = start; addr < new_top; addr += oop(addr)->size()) {
|
||||
start_array->allocate_block(addr);
|
||||
for (HeapWord* p = unused_start; p < new_top; p += oop(p)->size()) {
|
||||
start_array->allocate_block(p);
|
||||
}
|
||||
|
||||
// Could update the promoted average here, but it is not typically updated at
|
||||
@ -517,20 +515,9 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
|
||||
|
||||
// Process reference objects found during marking
|
||||
{
|
||||
ReferencePolicy *soft_ref_policy;
|
||||
if (clear_all_softrefs) {
|
||||
soft_ref_policy = new AlwaysClearPolicy();
|
||||
} else {
|
||||
#ifdef COMPILER2
|
||||
soft_ref_policy = new LRUMaxHeapPolicy();
|
||||
#else
|
||||
soft_ref_policy = new LRUCurrentHeapPolicy();
|
||||
#endif // COMPILER2
|
||||
}
|
||||
assert(soft_ref_policy != NULL,"No soft reference policy");
|
||||
ref_processor()->setup_policy(clear_all_softrefs);
|
||||
ref_processor()->process_discovered_references(
|
||||
soft_ref_policy, is_alive_closure(), mark_and_push_closure(),
|
||||
follow_stack_closure(), NULL);
|
||||
is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL);
|
||||
}
|
||||
|
||||
// Follow system dictionary roots and unload classes
|
||||
|
||||
@ -275,22 +275,9 @@ bool PSMarkSweepDecorator::insert_deadspace(size_t& allowed_deadspace_words,
|
||||
HeapWord* q, size_t deadlength) {
|
||||
if (allowed_deadspace_words >= deadlength) {
|
||||
allowed_deadspace_words -= deadlength;
|
||||
oop(q)->set_mark(markOopDesc::prototype()->set_marked());
|
||||
const size_t aligned_min_int_array_size =
|
||||
align_object_size(typeArrayOopDesc::header_size(T_INT));
|
||||
if (deadlength >= aligned_min_int_array_size) {
|
||||
oop(q)->set_klass(Universe::intArrayKlassObj());
|
||||
assert(((deadlength - aligned_min_int_array_size) * (HeapWordSize/sizeof(jint))) < (size_t)max_jint,
|
||||
"deadspace too big for Arrayoop");
|
||||
typeArrayOop(q)->set_length((int)((deadlength - aligned_min_int_array_size)
|
||||
* (HeapWordSize/sizeof(jint))));
|
||||
} else {
|
||||
assert((int) deadlength == instanceOopDesc::header_size(),
|
||||
"size for smallest fake dead object doesn't match");
|
||||
oop(q)->set_klass(SystemDictionary::object_klass());
|
||||
}
|
||||
assert((int) deadlength == oop(q)->size(),
|
||||
"make sure size for fake dead object match");
|
||||
CollectedHeap::fill_with_object(q, deadlength);
|
||||
oop(q)->set_mark(oop(q)->mark()->set_marked());
|
||||
assert((int) deadlength == oop(q)->size(), "bad filler object size");
|
||||
// Recall that we required "q == compaction_top".
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2002 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -36,6 +36,123 @@ class PreGCValues;
|
||||
class MoveAndUpdateClosure;
|
||||
class RefProcTaskExecutor;
|
||||
|
||||
// The SplitInfo class holds the information needed to 'split' a source region
|
||||
// so that the live data can be copied to two destination *spaces*. Normally,
|
||||
// all the live data in a region is copied to a single destination space (e.g.,
|
||||
// everything live in a region in eden is copied entirely into the old gen).
|
||||
// However, when the heap is nearly full, all the live data in eden may not fit
|
||||
// into the old gen. Copying only some of the regions from eden to old gen
|
||||
// requires finding a region that does not contain a partial object (i.e., no
|
||||
// live object crosses the region boundary) somewhere near the last object that
|
||||
// does fit into the old gen. Since it's not always possible to find such a
|
||||
// region, splitting is necessary for predictable behavior.
|
||||
//
|
||||
// A region is always split at the end of the partial object. This avoids
|
||||
// additional tests when calculating the new location of a pointer, which is a
|
||||
// very hot code path. The partial object and everything to its left will be
|
||||
// copied to another space (call it dest_space_1). The live data to the right
|
||||
// of the partial object will be copied either within the space itself, or to a
|
||||
// different destination space (distinct from dest_space_1).
|
||||
//
|
||||
// Split points are identified during the summary phase, when region
|
||||
// destinations are computed: data about the split, including the
|
||||
// partial_object_size, is recorded in a SplitInfo record and the
|
||||
// partial_object_size field in the summary data is set to zero. The zeroing is
|
||||
// possible (and necessary) since the partial object will move to a different
|
||||
// destination space than anything to its right, thus the partial object should
|
||||
// not affect the locations of any objects to its right.
|
||||
//
|
||||
// The recorded data is used during the compaction phase, but only rarely: when
|
||||
// the partial object on the split region will be copied across a destination
|
||||
// region boundary. This test is made once each time a region is filled, and is
|
||||
// a simple address comparison, so the overhead is negligible (see
|
||||
// PSParallelCompact::first_src_addr()).
|
||||
//
|
||||
// Notes:
|
||||
//
|
||||
// Only regions with partial objects are split; a region without a partial
|
||||
// object does not need any extra bookkeeping.
|
||||
//
|
||||
// At most one region is split per space, so the amount of data required is
|
||||
// constant.
|
||||
//
|
||||
// A region is split only when the destination space would overflow. Once that
|
||||
// happens, the destination space is abandoned and no other data (even from
|
||||
// other source spaces) is targeted to that destination space. Abandoning the
|
||||
// destination space may leave a somewhat large unused area at the end, if a
|
||||
// large object caused the overflow.
|
||||
//
|
||||
// Future work:
|
||||
//
|
||||
// More bookkeeping would be required to continue to use the destination space.
|
||||
// The most general solution would allow data from regions in two different
|
||||
// source spaces to be "joined" in a single destination region. At the very
|
||||
// least, additional code would be required in next_src_region() to detect the
|
||||
// join and skip to an out-of-order source region. If the join region was also
|
||||
// the last destination region to which a split region was copied (the most
|
||||
// likely case), then additional work would be needed to get fill_region() to
|
||||
// stop iteration and switch to a new source region at the right point. Basic
|
||||
// idea would be to use a fake value for the top of the source space. It is
|
||||
// doable, if a bit tricky.
|
||||
//
|
||||
// A simpler (but less general) solution would fill the remainder of the
|
||||
// destination region with a dummy object and continue filling the next
|
||||
// destination region.
|
||||
|
||||
class SplitInfo
|
||||
{
|
||||
public:
|
||||
// Return true if this split info is valid (i.e., if a split has been
|
||||
// recorded). The very first region cannot have a partial object and thus is
|
||||
// never split, so 0 is the 'invalid' value.
|
||||
bool is_valid() const { return _src_region_idx > 0; }
|
||||
|
||||
// Return true if this split holds data for the specified source region.
|
||||
inline bool is_split(size_t source_region) const;
|
||||
|
||||
// The index of the split region, the size of the partial object on that
|
||||
// region and the destination of the partial object.
|
||||
size_t src_region_idx() const { return _src_region_idx; }
|
||||
size_t partial_obj_size() const { return _partial_obj_size; }
|
||||
HeapWord* destination() const { return _destination; }
|
||||
|
||||
// The destination count of the partial object referenced by this split
|
||||
// (either 1 or 2). This must be added to the destination count of the
|
||||
// remainder of the source region.
|
||||
unsigned int destination_count() const { return _destination_count; }
|
||||
|
||||
// If a word within the partial object will be written to the first word of a
|
||||
// destination region, this is the address of the destination region;
|
||||
// otherwise this is NULL.
|
||||
HeapWord* dest_region_addr() const { return _dest_region_addr; }
|
||||
|
||||
// If a word within the partial object will be written to the first word of a
|
||||
// destination region, this is the address of that word within the partial
|
||||
// object; otherwise this is NULL.
|
||||
HeapWord* first_src_addr() const { return _first_src_addr; }
|
||||
|
||||
// Record the data necessary to split the region src_region_idx.
|
||||
void record(size_t src_region_idx, size_t partial_obj_size,
|
||||
HeapWord* destination);
|
||||
|
||||
void clear();
|
||||
|
||||
DEBUG_ONLY(void verify_clear();)
|
||||
|
||||
private:
|
||||
size_t _src_region_idx;
|
||||
size_t _partial_obj_size;
|
||||
HeapWord* _destination;
|
||||
unsigned int _destination_count;
|
||||
HeapWord* _dest_region_addr;
|
||||
HeapWord* _first_src_addr;
|
||||
};
|
||||
|
||||
inline bool SplitInfo::is_split(size_t region_idx) const
|
||||
{
|
||||
return _src_region_idx == region_idx && is_valid();
|
||||
}
|
||||
|
||||
class SpaceInfo
|
||||
{
|
||||
public:
|
||||
@ -58,18 +175,23 @@ class SpaceInfo
|
||||
// is no start array.
|
||||
ObjectStartArray* start_array() const { return _start_array; }
|
||||
|
||||
SplitInfo& split_info() { return _split_info; }
|
||||
|
||||
void set_space(MutableSpace* s) { _space = s; }
|
||||
void set_new_top(HeapWord* addr) { _new_top = addr; }
|
||||
void set_min_dense_prefix(HeapWord* addr) { _min_dense_prefix = addr; }
|
||||
void set_dense_prefix(HeapWord* addr) { _dense_prefix = addr; }
|
||||
void set_start_array(ObjectStartArray* s) { _start_array = s; }
|
||||
|
||||
void publish_new_top() const { _space->set_top(_new_top); }
|
||||
|
||||
private:
|
||||
MutableSpace* _space;
|
||||
HeapWord* _new_top;
|
||||
HeapWord* _min_dense_prefix;
|
||||
HeapWord* _dense_prefix;
|
||||
ObjectStartArray* _start_array;
|
||||
SplitInfo _split_info;
|
||||
};
|
||||
|
||||
class ParallelCompactData
|
||||
@ -230,9 +352,14 @@ public:
|
||||
// must be region-aligned; end need not be.
|
||||
void summarize_dense_prefix(HeapWord* beg, HeapWord* end);
|
||||
|
||||
bool summarize(HeapWord* target_beg, HeapWord* target_end,
|
||||
HeapWord* summarize_split_space(size_t src_region, SplitInfo& split_info,
|
||||
HeapWord* destination, HeapWord* target_end,
|
||||
HeapWord** target_next);
|
||||
bool summarize(SplitInfo& split_info,
|
||||
HeapWord* source_beg, HeapWord* source_end,
|
||||
HeapWord** target_next, HeapWord** source_next = 0);
|
||||
HeapWord** source_next,
|
||||
HeapWord* target_beg, HeapWord* target_end,
|
||||
HeapWord** target_next);
|
||||
|
||||
void clear();
|
||||
void clear_range(size_t beg_region, size_t end_region);
|
||||
@ -838,13 +965,31 @@ class PSParallelCompact : AllStatic {
|
||||
// non-empty.
|
||||
static void fill_dense_prefix_end(SpaceId id);
|
||||
|
||||
// Clear the summary data source_region field for the specified addresses.
|
||||
static void clear_source_region(HeapWord* beg_addr, HeapWord* end_addr);
|
||||
|
||||
#ifndef PRODUCT
|
||||
// Routines to provoke splitting a young gen space (ParallelOldGCSplitALot).
|
||||
|
||||
// Fill the region [start, start + words) with live object(s). Only usable
|
||||
// for the old and permanent generations.
|
||||
static void fill_with_live_objects(SpaceId id, HeapWord* const start,
|
||||
size_t words);
|
||||
// Include the new objects in the summary data.
|
||||
static void summarize_new_objects(SpaceId id, HeapWord* start);
|
||||
|
||||
// Add live objects to a survivor space since it's rare that both survivors
|
||||
// are non-empty.
|
||||
static void provoke_split_fill_survivor(SpaceId id);
|
||||
|
||||
// Add live objects and/or choose the dense prefix to provoke splitting.
|
||||
static void provoke_split(bool & maximum_compaction);
|
||||
#endif
|
||||
|
||||
static void summarize_spaces_quick();
|
||||
static void summarize_space(SpaceId id, bool maximum_compaction);
|
||||
static void summary_phase(ParCompactionManager* cm, bool maximum_compaction);
|
||||
|
||||
// The space that is compacted after space_id.
|
||||
static SpaceId next_compaction_space_id(SpaceId space_id);
|
||||
|
||||
// Adjust addresses in roots. Does not adjust addresses in heap.
|
||||
static void adjust_roots();
|
||||
|
||||
@ -999,6 +1144,7 @@ class PSParallelCompact : AllStatic {
|
||||
// Return the address of the word to be copied to dest_addr, which must be
|
||||
// aligned to a region boundary.
|
||||
static HeapWord* first_src_addr(HeapWord* const dest_addr,
|
||||
SpaceId src_space_id,
|
||||
size_t src_region_idx);
|
||||
|
||||
// Determine the next source region, set closure.source() to the start of the
|
||||
@ -1012,8 +1158,10 @@ class PSParallelCompact : AllStatic {
|
||||
HeapWord* end_addr);
|
||||
|
||||
// Decrement the destination count for each non-empty source region in the
|
||||
// range [beg_region, region(region_align_up(end_addr))).
|
||||
// range [beg_region, region(region_align_up(end_addr))). If the destination
|
||||
// count for a region goes to 0 and it needs to be filled, enqueue it.
|
||||
static void decrement_destination_counts(ParCompactionManager* cm,
|
||||
SpaceId src_space_id,
|
||||
size_t beg_region,
|
||||
HeapWord* end_addr);
|
||||
|
||||
@ -1081,9 +1229,15 @@ class PSParallelCompact : AllStatic {
|
||||
const SpaceId id,
|
||||
const bool maximum_compaction,
|
||||
HeapWord* const addr);
|
||||
static void summary_phase_msg(SpaceId dst_space_id,
|
||||
HeapWord* dst_beg, HeapWord* dst_end,
|
||||
SpaceId src_space_id,
|
||||
HeapWord* src_beg, HeapWord* src_end);
|
||||
#endif // #ifndef PRODUCT
|
||||
|
||||
#ifdef ASSERT
|
||||
// Sanity check the new location of a word in the heap.
|
||||
static inline void check_new_location(HeapWord* old_addr, HeapWord* new_addr);
|
||||
// Verify that all the regions have been emptied.
|
||||
static void verify_complete(SpaceId space_id);
|
||||
#endif // #ifdef ASSERT
|
||||
@ -1251,6 +1405,15 @@ inline void PSParallelCompact::adjust_pointer(T* p,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
inline void
|
||||
PSParallelCompact::check_new_location(HeapWord* old_addr, HeapWord* new_addr)
|
||||
{
|
||||
assert(old_addr >= new_addr || space_id(old_addr) != space_id(new_addr),
|
||||
"must move left or to a different space");
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
class MoveAndUpdateClosure: public ParMarkBitMapClosure {
|
||||
public:
|
||||
inline MoveAndUpdateClosure(ParMarkBitMap* bitmap, ParCompactionManager* cm,
|
||||
@ -1324,31 +1487,28 @@ inline void UpdateOnlyClosure::do_addr(HeapWord* addr)
|
||||
oop(addr)->update_contents(compaction_manager());
|
||||
}
|
||||
|
||||
class FillClosure: public ParMarkBitMapClosure {
|
||||
public:
|
||||
class FillClosure: public ParMarkBitMapClosure
|
||||
{
|
||||
public:
|
||||
FillClosure(ParCompactionManager* cm, PSParallelCompact::SpaceId space_id) :
|
||||
ParMarkBitMapClosure(PSParallelCompact::mark_bitmap(), cm),
|
||||
_space_id(space_id),
|
||||
_start_array(PSParallelCompact::start_array(space_id)) {
|
||||
assert(_space_id == PSParallelCompact::perm_space_id ||
|
||||
_space_id == PSParallelCompact::old_space_id,
|
||||
_start_array(PSParallelCompact::start_array(space_id))
|
||||
{
|
||||
assert(space_id == PSParallelCompact::perm_space_id ||
|
||||
space_id == PSParallelCompact::old_space_id,
|
||||
"cannot use FillClosure in the young gen");
|
||||
assert(bitmap() != NULL, "need a bitmap");
|
||||
assert(_start_array != NULL, "need a start array");
|
||||
}
|
||||
|
||||
void fill_region(HeapWord* addr, size_t size) {
|
||||
MemRegion region(addr, size);
|
||||
SharedHeap::fill_region_with_object(region);
|
||||
_start_array->allocate_block(addr);
|
||||
}
|
||||
|
||||
virtual IterationStatus do_addr(HeapWord* addr, size_t size) {
|
||||
fill_region(addr, size);
|
||||
CollectedHeap::fill_with_objects(addr, size);
|
||||
HeapWord* const end = addr + size;
|
||||
do {
|
||||
_start_array->allocate_block(addr);
|
||||
addr += oop(addr)->size();
|
||||
} while (addr < end);
|
||||
return ParMarkBitMap::incomplete;
|
||||
}
|
||||
|
||||
private:
|
||||
const PSParallelCompact::SpaceId _space_id;
|
||||
ObjectStartArray* const _start_array;
|
||||
ObjectStartArray* const _start_array;
|
||||
};
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2001-2005 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2001-2008 Sun Microsystems, Inc. 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
|
||||
|
||||
@ -499,26 +499,15 @@ oop PSPromotionManager::copy_to_survivor_space(oop o, bool depth_first) {
|
||||
// We lost, someone else "owns" this object
|
||||
guarantee(o->is_forwarded(), "Object must be forwarded if the cas failed.");
|
||||
|
||||
// Unallocate the space used. NOTE! We may have directly allocated
|
||||
// the object. If so, we cannot deallocate it, so we have to test!
|
||||
// Try to deallocate the space. If it was directly allocated we cannot
|
||||
// deallocate it, so we have to test. If the deallocation fails,
|
||||
// overwrite with a filler object.
|
||||
if (new_obj_is_tenured) {
|
||||
if (!_old_lab.unallocate_object(new_obj)) {
|
||||
// The promotion lab failed to unallocate the object.
|
||||
// We need to overwrite the object with a filler that
|
||||
// contains no interior pointers.
|
||||
MemRegion mr((HeapWord*)new_obj, new_obj_size);
|
||||
// Clean this up and move to oopFactory (see bug 4718422)
|
||||
SharedHeap::fill_region_with_object(mr);
|
||||
}
|
||||
} else {
|
||||
if (!_young_lab.unallocate_object(new_obj)) {
|
||||
// The promotion lab failed to unallocate the object.
|
||||
// We need to overwrite the object with a filler that
|
||||
// contains no interior pointers.
|
||||
MemRegion mr((HeapWord*)new_obj, new_obj_size);
|
||||
// Clean this up and move to oopFactory (see bug 4718422)
|
||||
SharedHeap::fill_region_with_object(mr);
|
||||
CollectedHeap::fill_with_object((HeapWord*) new_obj, new_obj_size);
|
||||
}
|
||||
} else if (!_young_lab.unallocate_object(new_obj)) {
|
||||
CollectedHeap::fill_with_object((HeapWord*) new_obj, new_obj_size);
|
||||
}
|
||||
|
||||
// don't update this before the unallocation!
|
||||
|
||||
@ -330,6 +330,7 @@ bool PSScavenge::invoke_no_policy() {
|
||||
COMPILER2_PRESENT(DerivedPointerTable::clear());
|
||||
|
||||
reference_processor()->enable_discovery();
|
||||
reference_processor()->setup_policy(false);
|
||||
|
||||
// We track how much was promoted to the next generation for
|
||||
// the AdaptiveSizePolicy.
|
||||
@ -394,24 +395,16 @@ bool PSScavenge::invoke_no_policy() {
|
||||
|
||||
// Process reference objects discovered during scavenge
|
||||
{
|
||||
#ifdef COMPILER2
|
||||
ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
|
||||
#else
|
||||
ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
|
||||
#endif // COMPILER2
|
||||
|
||||
reference_processor()->setup_policy(false); // not always_clear
|
||||
PSKeepAliveClosure keep_alive(promotion_manager);
|
||||
PSEvacuateFollowersClosure evac_followers(promotion_manager);
|
||||
assert(soft_ref_policy != NULL,"No soft reference policy");
|
||||
if (reference_processor()->processing_is_mt()) {
|
||||
PSRefProcTaskExecutor task_executor;
|
||||
reference_processor()->process_discovered_references(
|
||||
soft_ref_policy, &_is_alive_closure, &keep_alive, &evac_followers,
|
||||
&task_executor);
|
||||
&_is_alive_closure, &keep_alive, &evac_followers, &task_executor);
|
||||
} else {
|
||||
reference_processor()->process_discovered_references(
|
||||
soft_ref_policy, &_is_alive_closure, &keep_alive, &evac_followers,
|
||||
NULL);
|
||||
&_is_alive_closure, &keep_alive, &evac_followers, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -76,8 +76,8 @@ void MutableNUMASpace::ensure_parsability() {
|
||||
MutableSpace *s = ls->space();
|
||||
if (s->top() < top()) { // For all spaces preceeding the one containing top()
|
||||
if (s->free_in_words() > 0) {
|
||||
SharedHeap::fill_region_with_object(MemRegion(s->top(), s->end()));
|
||||
size_t area_touched_words = pointer_delta(s->end(), s->top());
|
||||
CollectedHeap::fill_with_object(s->top(), area_touched_words);
|
||||
#ifndef ASSERT
|
||||
if (!ZapUnusedHeapArea) {
|
||||
area_touched_words = MIN2((size_t)align_object_size(typeArrayOopDesc::header_size(T_INT)),
|
||||
@ -414,9 +414,20 @@ size_t MutableNUMASpace::adaptive_chunk_size(int i, size_t limit) {
|
||||
if (limit > 0) {
|
||||
limit = round_down(limit, page_size());
|
||||
if (chunk_size > current_chunk_size(i)) {
|
||||
chunk_size = MIN2((off_t)chunk_size, (off_t)current_chunk_size(i) + (off_t)limit);
|
||||
size_t upper_bound = pages_available * page_size();
|
||||
if (upper_bound > limit &&
|
||||
current_chunk_size(i) < upper_bound - limit) {
|
||||
// The resulting upper bound should not exceed the available
|
||||
// amount of memory (pages_available * page_size()).
|
||||
upper_bound = current_chunk_size(i) + limit;
|
||||
}
|
||||
chunk_size = MIN2(chunk_size, upper_bound);
|
||||
} else {
|
||||
chunk_size = MAX2((off_t)chunk_size, (off_t)current_chunk_size(i) - (off_t)limit);
|
||||
size_t lower_bound = page_size();
|
||||
if (current_chunk_size(i) > limit) { // lower_bound shouldn't underflow.
|
||||
lower_bound = current_chunk_size(i) - limit;
|
||||
}
|
||||
chunk_size = MAX2(chunk_size, lower_bound);
|
||||
}
|
||||
}
|
||||
assert(chunk_size <= pages_available * page_size(), "Chunk size out of range");
|
||||
@ -675,11 +686,11 @@ void MutableNUMASpace::set_top(HeapWord* value) {
|
||||
// a minimal object; assuming that's not the last chunk in which case we don't care.
|
||||
if (i < lgrp_spaces()->length() - 1) {
|
||||
size_t remainder = pointer_delta(s->end(), value);
|
||||
const size_t minimal_object_size = oopDesc::header_size();
|
||||
if (remainder < minimal_object_size && remainder > 0) {
|
||||
// Add a filler object of a minimal size, it will cross the chunk boundary.
|
||||
SharedHeap::fill_region_with_object(MemRegion(value, minimal_object_size));
|
||||
value += minimal_object_size;
|
||||
const size_t min_fill_size = CollectedHeap::min_fill_size();
|
||||
if (remainder < min_fill_size && remainder > 0) {
|
||||
// Add a minimum size filler object; it will cross the chunk boundary.
|
||||
CollectedHeap::fill_with_object(value, min_fill_size);
|
||||
value += min_fill_size;
|
||||
assert(!s->contains(value), "Should be in the next chunk");
|
||||
// Restart the loop from the same chunk, since the value has moved
|
||||
// to the next one.
|
||||
|
||||
@ -30,12 +30,21 @@
|
||||
int CollectedHeap::_fire_out_of_memory_count = 0;
|
||||
#endif
|
||||
|
||||
size_t CollectedHeap::_filler_array_max_size = 0;
|
||||
|
||||
// Memory state functions.
|
||||
|
||||
CollectedHeap::CollectedHeap() :
|
||||
_reserved(), _barrier_set(NULL), _is_gc_active(false),
|
||||
_total_collections(0), _total_full_collections(0),
|
||||
_gc_cause(GCCause::_no_gc), _gc_lastcause(GCCause::_no_gc) {
|
||||
CollectedHeap::CollectedHeap()
|
||||
{
|
||||
const size_t max_len = size_t(arrayOopDesc::max_array_length(T_INT));
|
||||
const size_t elements_per_word = HeapWordSize / sizeof(jint);
|
||||
_filler_array_max_size = align_object_size(filler_array_hdr_size() +
|
||||
max_len * elements_per_word);
|
||||
|
||||
_barrier_set = NULL;
|
||||
_is_gc_active = false;
|
||||
_total_collections = _total_full_collections = 0;
|
||||
_gc_cause = _gc_lastcause = GCCause::_no_gc;
|
||||
NOT_PRODUCT(_promotion_failure_alot_count = 0;)
|
||||
NOT_PRODUCT(_promotion_failure_alot_gc_number = 0;)
|
||||
|
||||
@ -128,6 +137,94 @@ HeapWord* CollectedHeap::allocate_from_tlab_slow(Thread* thread, size_t size) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
size_t CollectedHeap::filler_array_hdr_size() {
|
||||
return size_t(arrayOopDesc::header_size(T_INT));
|
||||
}
|
||||
|
||||
size_t CollectedHeap::filler_array_min_size() {
|
||||
return align_object_size(filler_array_hdr_size());
|
||||
}
|
||||
|
||||
size_t CollectedHeap::filler_array_max_size() {
|
||||
return _filler_array_max_size;
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
void CollectedHeap::fill_args_check(HeapWord* start, size_t words)
|
||||
{
|
||||
assert(words >= min_fill_size(), "too small to fill");
|
||||
assert(words % MinObjAlignment == 0, "unaligned size");
|
||||
assert(Universe::heap()->is_in_reserved(start), "not in heap");
|
||||
assert(Universe::heap()->is_in_reserved(start + words - 1), "not in heap");
|
||||
}
|
||||
|
||||
void CollectedHeap::zap_filler_array(HeapWord* start, size_t words)
|
||||
{
|
||||
if (ZapFillerObjects) {
|
||||
Copy::fill_to_words(start + filler_array_hdr_size(),
|
||||
words - filler_array_hdr_size(), 0XDEAFBABE);
|
||||
}
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
void
|
||||
CollectedHeap::fill_with_array(HeapWord* start, size_t words)
|
||||
{
|
||||
assert(words >= filler_array_min_size(), "too small for an array");
|
||||
assert(words <= filler_array_max_size(), "too big for a single object");
|
||||
|
||||
const size_t payload_size = words - filler_array_hdr_size();
|
||||
const size_t len = payload_size * HeapWordSize / sizeof(jint);
|
||||
|
||||
// Set the length first for concurrent GC.
|
||||
((arrayOop)start)->set_length((int)len);
|
||||
post_allocation_setup_common(Universe::intArrayKlassObj(), start, words);
|
||||
DEBUG_ONLY(zap_filler_array(start, words);)
|
||||
}
|
||||
|
||||
void
|
||||
CollectedHeap::fill_with_object_impl(HeapWord* start, size_t words)
|
||||
{
|
||||
assert(words <= filler_array_max_size(), "too big for a single object");
|
||||
|
||||
if (words >= filler_array_min_size()) {
|
||||
fill_with_array(start, words);
|
||||
} else if (words > 0) {
|
||||
assert(words == min_fill_size(), "unaligned size");
|
||||
post_allocation_setup_common(SystemDictionary::object_klass(), start,
|
||||
words);
|
||||
}
|
||||
}
|
||||
|
||||
void CollectedHeap::fill_with_object(HeapWord* start, size_t words)
|
||||
{
|
||||
DEBUG_ONLY(fill_args_check(start, words);)
|
||||
HandleMark hm; // Free handles before leaving.
|
||||
fill_with_object_impl(start, words);
|
||||
}
|
||||
|
||||
void CollectedHeap::fill_with_objects(HeapWord* start, size_t words)
|
||||
{
|
||||
DEBUG_ONLY(fill_args_check(start, words);)
|
||||
HandleMark hm; // Free handles before leaving.
|
||||
|
||||
#ifdef LP64
|
||||
// A single array can fill ~8G, so multiple objects are needed only in 64-bit.
|
||||
// First fill with arrays, ensuring that any remaining space is big enough to
|
||||
// fill. The remainder is filled with a single object.
|
||||
const size_t min = min_fill_size();
|
||||
const size_t max = filler_array_max_size();
|
||||
while (words > max) {
|
||||
const size_t cur = words - max >= min ? max : max - min;
|
||||
fill_with_array(start, cur);
|
||||
start += cur;
|
||||
words -= cur;
|
||||
}
|
||||
#endif
|
||||
|
||||
fill_with_object_impl(start, words);
|
||||
}
|
||||
|
||||
oop CollectedHeap::new_store_barrier(oop new_obj) {
|
||||
// %%% This needs refactoring. (It was imported from the server compiler.)
|
||||
guarantee(can_elide_tlab_store_barriers(), "store barrier elision not supported");
|
||||
|
||||
@ -47,6 +47,9 @@ class CollectedHeap : public CHeapObj {
|
||||
static int _fire_out_of_memory_count;
|
||||
#endif
|
||||
|
||||
// Used for filler objects (static, but initialized in ctor).
|
||||
static size_t _filler_array_max_size;
|
||||
|
||||
protected:
|
||||
MemRegion _reserved;
|
||||
BarrierSet* _barrier_set;
|
||||
@ -119,6 +122,21 @@ class CollectedHeap : public CHeapObj {
|
||||
// Clears an allocated object.
|
||||
inline static void init_obj(HeapWord* obj, size_t size);
|
||||
|
||||
// Filler object utilities.
|
||||
static inline size_t filler_array_hdr_size();
|
||||
static inline size_t filler_array_min_size();
|
||||
static inline size_t filler_array_max_size();
|
||||
|
||||
DEBUG_ONLY(static void fill_args_check(HeapWord* start, size_t words);)
|
||||
DEBUG_ONLY(static void zap_filler_array(HeapWord* start, size_t words);)
|
||||
|
||||
// Fill with a single array; caller must ensure filler_array_min_size() <=
|
||||
// words <= filler_array_max_size().
|
||||
static inline void fill_with_array(HeapWord* start, size_t words);
|
||||
|
||||
// Fill with a single object (either an int array or a java.lang.Object).
|
||||
static inline void fill_with_object_impl(HeapWord* start, size_t words);
|
||||
|
||||
// Verification functions
|
||||
virtual void check_for_bad_heap_word_value(HeapWord* addr, size_t size)
|
||||
PRODUCT_RETURN;
|
||||
@ -294,6 +312,27 @@ class CollectedHeap : public CHeapObj {
|
||||
// The boundary between a "large" and "small" array of primitives, in words.
|
||||
virtual size_t large_typearray_limit() = 0;
|
||||
|
||||
// Utilities for turning raw memory into filler objects.
|
||||
//
|
||||
// min_fill_size() is the smallest region that can be filled.
|
||||
// fill_with_objects() can fill arbitrary-sized regions of the heap using
|
||||
// multiple objects. fill_with_object() is for regions known to be smaller
|
||||
// than the largest array of integers; it uses a single object to fill the
|
||||
// region and has slightly less overhead.
|
||||
static size_t min_fill_size() {
|
||||
return size_t(align_object_size(oopDesc::header_size()));
|
||||
}
|
||||
|
||||
static void fill_with_objects(HeapWord* start, size_t words);
|
||||
|
||||
static void fill_with_object(HeapWord* start, size_t words);
|
||||
static void fill_with_object(MemRegion region) {
|
||||
fill_with_object(region.start(), region.word_size());
|
||||
}
|
||||
static void fill_with_object(HeapWord* start, HeapWord* end) {
|
||||
fill_with_object(start, pointer_delta(end, start));
|
||||
}
|
||||
|
||||
// Some heaps may offer a contiguous region for shared non-blocking
|
||||
// allocation, via inlined code (by exporting the address of the top and
|
||||
// end fields defining the extent of the contiguous allocation region.)
|
||||
|
||||
@ -34,7 +34,6 @@ void CollectedHeap::post_allocation_setup_common(KlassHandle klass,
|
||||
void CollectedHeap::post_allocation_setup_no_klass_install(KlassHandle klass,
|
||||
HeapWord* objPtr,
|
||||
size_t size) {
|
||||
|
||||
oop obj = (oop)objPtr;
|
||||
|
||||
assert(obj != NULL, "NULL object pointer");
|
||||
@ -44,9 +43,6 @@ void CollectedHeap::post_allocation_setup_no_klass_install(KlassHandle klass,
|
||||
// May be bootstrapping
|
||||
obj->set_mark(markOopDesc::prototype());
|
||||
}
|
||||
|
||||
// support low memory notifications (no-op if not enabled)
|
||||
LowMemoryDetector::detect_low_memory_for_collected_pools();
|
||||
}
|
||||
|
||||
void CollectedHeap::post_allocation_install_obj_klass(KlassHandle klass,
|
||||
@ -65,6 +61,9 @@ void CollectedHeap::post_allocation_install_obj_klass(KlassHandle klass,
|
||||
|
||||
// Support for jvmti and dtrace
|
||||
inline void post_allocation_notify(KlassHandle klass, oop obj) {
|
||||
// support low memory notifications (no-op if not enabled)
|
||||
LowMemoryDetector::detect_low_memory_for_collected_pools();
|
||||
|
||||
// support for JVMTI VMObjectAlloc event (no-op if not enabled)
|
||||
JvmtiExport::vm_object_alloc_event_collector(obj);
|
||||
|
||||
|
||||
@ -2303,6 +2303,7 @@ javaCalls.cpp handles.inline.hpp
|
||||
javaCalls.cpp interfaceSupport.hpp
|
||||
javaCalls.cpp interpreter.hpp
|
||||
javaCalls.cpp javaCalls.hpp
|
||||
javaCalls.cpp jniCheck.hpp
|
||||
javaCalls.cpp linkResolver.hpp
|
||||
javaCalls.cpp mutexLocker.hpp
|
||||
javaCalls.cpp nmethod.hpp
|
||||
@ -3434,6 +3435,7 @@ referenceProcessor.cpp referenceProcessor.hpp
|
||||
referenceProcessor.cpp systemDictionary.hpp
|
||||
|
||||
referenceProcessor.hpp instanceRefKlass.hpp
|
||||
referenceProcessor.hpp referencePolicy.hpp
|
||||
|
||||
reflection.cpp arguments.hpp
|
||||
reflection.cpp handles.inline.hpp
|
||||
|
||||
@ -115,6 +115,8 @@ heapInspection.cpp klassOop.hpp
|
||||
heapInspection.cpp os.hpp
|
||||
heapInspection.cpp resourceArea.hpp
|
||||
|
||||
javaCalls.cpp jniCheck.hpp
|
||||
|
||||
jniCheck.cpp fieldDescriptor.hpp
|
||||
jniCheck.cpp handles.hpp
|
||||
jniCheck.cpp instanceKlass.hpp
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user