提交 05d15943 编写于 作者: A amurillo

Merge

/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
* *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
* *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
* *
*/ */
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
* *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
* *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
* *
*/ */
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
* *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
* *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
* *
*/ */
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
* *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
* *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
* *
*/ */
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
* *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
* *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
* *
*/ */
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
* *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
* *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
* *
*/ */
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
* *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
* *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
* *
*/ */
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
* *
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
* *
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
* *
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
* *
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
* *
*/ */
......
...@@ -36,7 +36,7 @@ WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \ ...@@ -36,7 +36,7 @@ WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \
$(patsubst %.java,%.class,$(WB_JAVA_SRCS))) $(patsubst %.java,%.class,$(WB_JAVA_SRCS)))
$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR) $(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR)
$(REMOTE) $(COMPILE.JAVAC) -nowarn -d $(WB_JAVA_CLASSDIR) $< $(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $<
$(WB_JAR): $(WB_JAVA_CLASSES) $(WB_JAR): $(WB_JAVA_CLASSES)
$(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ . $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
......
...@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2011 ...@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2011
HS_MAJOR_VER=24 HS_MAJOR_VER=24
HS_MINOR_VER=0 HS_MINOR_VER=0
HS_BUILD_NUMBER=06 HS_BUILD_NUMBER=07
JDK_MAJOR_VER=1 JDK_MAJOR_VER=1
JDK_MINOR_VER=8 JDK_MINOR_VER=8
......
...@@ -36,7 +36,7 @@ WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \ ...@@ -36,7 +36,7 @@ WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \
$(patsubst %.java,%.class,$(WB_JAVA_SRCS))) $(patsubst %.java,%.class,$(WB_JAVA_SRCS)))
$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR) $(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR)
$(REMOTE) $(COMPILE.JAVAC) -nowarn -d $(WB_JAVA_CLASSDIR) $< $(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $<
$(WB_JAR): $(WB_JAVA_CLASSES) $(WB_JAR): $(WB_JAVA_CLASSES)
$(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ . $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
......
...@@ -36,7 +36,7 @@ WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \ ...@@ -36,7 +36,7 @@ WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \
$(patsubst %.java,%.class,$(WB_JAVA_SRCS))) $(patsubst %.java,%.class,$(WB_JAVA_SRCS)))
$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR) $(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR)
$(REMOTE) $(COMPILE.JAVAC) -nowarn -d $(WB_JAVA_CLASSDIR) $< $(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $<
$(WB_JAR): $(WB_JAVA_CLASSES) $(WB_JAR): $(WB_JAVA_CLASSES)
$(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ . $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
......
...@@ -80,6 +80,8 @@ if [ -d "${ALTSRC}/share/vm/jfr" ]; then ...@@ -80,6 +80,8 @@ if [ -d "${ALTSRC}/share/vm/jfr" ]; then
BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr" BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr"
fi fi
BASE_PATHS="${BASE_PATHS} ${COMMONSRC}/share/vm/prims/wbtestmethods"
CORE_PATHS="${BASE_PATHS}" CORE_PATHS="${BASE_PATHS}"
# shared is already in BASE_PATHS. Should add vm/memory but that one is also in BASE_PATHS. # shared is already in BASE_PATHS. Should add vm/memory but that one is also in BASE_PATHS.
if [ -d "${ALTSRC}/share/vm/gc_implementation" ]; then if [ -d "${ALTSRC}/share/vm/gc_implementation" ]; then
......
...@@ -51,6 +51,7 @@ ProjectCreatorIncludesPRIVATE=\ ...@@ -51,6 +51,7 @@ ProjectCreatorIncludesPRIVATE=\
-relativeInclude src\closed\cpu\$(Platform_arch)\vm \ -relativeInclude src\closed\cpu\$(Platform_arch)\vm \
-relativeInclude src\share\vm \ -relativeInclude src\share\vm \
-relativeInclude src\share\vm\precompiled \ -relativeInclude src\share\vm\precompiled \
-relativeInclude src\share\vm\prims\wbtestmethods \
-relativeInclude src\share\vm\prims \ -relativeInclude src\share\vm\prims \
-relativeInclude src\os\windows\vm \ -relativeInclude src\os\windows\vm \
-relativeInclude src\os_cpu\windows_$(Platform_arch)\vm \ -relativeInclude src\os_cpu\windows_$(Platform_arch)\vm \
......
...@@ -172,6 +172,7 @@ VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/asm ...@@ -172,6 +172,7 @@ VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/asm
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/memory VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/memory
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/oops VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/oops
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/prims VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/prims
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/prims/wbtestmethods
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/runtime VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/runtime
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/services VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/services
VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/trace VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/trace
...@@ -269,6 +270,9 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi ...@@ -269,6 +270,9 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi
{$(COMMONSRC)\share\vm\prims}.cpp.obj:: {$(COMMONSRC)\share\vm\prims}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
{$(COMMONSRC)\share\vm\prims\wbtestmethods}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
{$(COMMONSRC)\share\vm\runtime}.cpp.obj:: {$(COMMONSRC)\share\vm\runtime}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
...@@ -349,6 +353,9 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi ...@@ -349,6 +353,9 @@ bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWi
{$(ALTSRC)\share\vm\prims}.cpp.obj:: {$(ALTSRC)\share\vm\prims}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
{$(ALTSRC)\share\vm\prims\wbtestmethods}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
{$(ALTSRC)\share\vm\runtime}.cpp.obj:: {$(ALTSRC)\share\vm\runtime}.cpp.obj::
$(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $<
......
...@@ -40,7 +40,7 @@ wb_java_srcs: $(WorkSpace)\src\share\tools\whitebox\sun\hotspot\*.java $(WB_CLAS ...@@ -40,7 +40,7 @@ wb_java_srcs: $(WorkSpace)\src\share\tools\whitebox\sun\hotspot\*.java $(WB_CLAS
{$(WorkSpace)\src\share\tools\whitebox\sun\hotspot}.java.class:: {$(WorkSpace)\src\share\tools\whitebox\sun\hotspot}.java.class::
$(COMPILE_JAVAC) -d $(WB_CLASSES) $< $(COMPILE_JAVAC) -sourcepath $(WBSRCDIR) -d $(WB_CLASSES) $<
$(WB_JAR): wb_java_srcs $(WB_JAR): wb_java_srcs
$(RUN_JAR) cf $@ -C $(WB_CLASSES) . $(RUN_JAR) cf $@ -C $(WB_CLASSES) .
......
...@@ -528,10 +528,12 @@ address Assembler::locate_operand(address inst, WhichOperand which) { ...@@ -528,10 +528,12 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
if (which == end_pc_operand) return ip + (is_64bit ? 8 : 4); if (which == end_pc_operand) return ip + (is_64bit ? 8 : 4);
// these asserts are somewhat nonsensical // these asserts are somewhat nonsensical
#ifndef _LP64 #ifndef _LP64
assert(which == imm_operand || which == disp32_operand, ""); assert(which == imm_operand || which == disp32_operand,
err_msg("which %d is_64_bit %d ip " INTPTR_FORMAT, which, is_64bit, ip));
#else #else
assert((which == call32_operand || which == imm_operand) && is_64bit || assert((which == call32_operand || which == imm_operand) && is_64bit ||
which == narrow_oop_operand && !is_64bit, ""); which == narrow_oop_operand && !is_64bit,
err_msg("which %d is_64_bit %d ip " INTPTR_FORMAT, which, is_64bit, ip));
#endif // _LP64 #endif // _LP64
return ip; return ip;
......
...@@ -3369,15 +3369,6 @@ operand immP0() ...@@ -3369,15 +3369,6 @@ operand immP0()
interface(CONST_INTER); interface(CONST_INTER);
%} %}
operand immP_poll() %{
predicate(n->get_ptr() != 0 && n->get_ptr() == (intptr_t)os::get_polling_page());
match(ConP);
// formats are generated automatically for constants and base registers
format %{ %}
interface(CONST_INTER);
%}
// Pointer Immediate // Pointer Immediate
operand immN() %{ operand immN() %{
match(ConN); match(ConN);
...@@ -5726,16 +5717,6 @@ instruct loadConP0(rRegP dst, immP0 src, rFlagsReg cr) ...@@ -5726,16 +5717,6 @@ instruct loadConP0(rRegP dst, immP0 src, rFlagsReg cr)
ins_pipe(ialu_reg); ins_pipe(ialu_reg);
%} %}
instruct loadConP_poll(rRegP dst, immP_poll src) %{
match(Set dst src);
format %{ "movq $dst, $src\t!ptr" %}
ins_encode %{
AddressLiteral polling_page(os::get_polling_page(), relocInfo::poll_type);
__ lea($dst$$Register, polling_page);
%}
ins_pipe(ialu_reg_fat);
%}
instruct loadConP31(rRegP dst, immP31 src, rFlagsReg cr) instruct loadConP31(rRegP dst, immP31 src, rFlagsReg cr)
%{ %{
match(Set dst src); match(Set dst src);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
package sun.hotspot; package sun.hotspot;
import java.security.BasicPermission; import java.security.BasicPermission;
import sun.hotspot.parser.DiagnosticCommand;
public class WhiteBox { public class WhiteBox {
...@@ -67,4 +68,5 @@ public class WhiteBox { ...@@ -67,4 +68,5 @@ public class WhiteBox {
public native boolean g1IsHumongous(Object o); public native boolean g1IsHumongous(Object o);
public native long g1NumFreeRegions(); public native long g1NumFreeRegions();
public native int g1RegionSize(); public native int g1RegionSize();
public native Object[] parseCommandLine(String commandline, DiagnosticCommand[] args);
} }
package sun.hotspot.parser;
public class DiagnosticCommand {
public enum DiagnosticArgumentType {
JLONG, BOOLEAN, STRING, NANOTIME, STRINGARRAY, MEMORYSIZE
}
private String name;
private String desc;
private DiagnosticArgumentType type;
private boolean mandatory;
private String defaultValue;
public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type,
boolean mandatory, String defaultValue) {
this.name = name;
this.desc = desc;
this.type = type;
this.mandatory = mandatory;
this.defaultValue = defaultValue;
}
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
public DiagnosticArgumentType getType() {
return type;
}
public boolean isMandatory() {
return mandatory;
}
public String getDefaultValue() {
return defaultValue;
}
}
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
#define JAVA_7_VERSION 51 #define JAVA_7_VERSION 51
void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int length, TRAPS) { void ClassFileParser::parse_constant_pool_entries(Handle class_loader, constantPoolHandle cp, int length, TRAPS) {
// Use a local copy of ClassFileStream. It helps the C++ compiler to optimize // Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
// this function (_current can be allocated in a register, with scalar // this function (_current can be allocated in a register, with scalar
// replacement of aggregates). The _current pointer is copied back to // replacement of aggregates). The _current pointer is copied back to
...@@ -272,7 +272,7 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len ...@@ -272,7 +272,7 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len
indices[names_count] = index; indices[names_count] = index;
hashValues[names_count++] = hash; hashValues[names_count++] = hash;
if (names_count == SymbolTable::symbol_alloc_batch_size) { if (names_count == SymbolTable::symbol_alloc_batch_size) {
SymbolTable::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); SymbolTable::new_symbols(class_loader, cp, names_count, names, lengths, indices, hashValues, CHECK);
names_count = 0; names_count = 0;
} }
} else { } else {
...@@ -289,7 +289,7 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len ...@@ -289,7 +289,7 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len
// Allocate the remaining symbols // Allocate the remaining symbols
if (names_count > 0) { if (names_count > 0) {
SymbolTable::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); SymbolTable::new_symbols(class_loader, cp, names_count, names, lengths, indices, hashValues, CHECK);
} }
// Copy _current pointer of local copy back to stream(). // Copy _current pointer of local copy back to stream().
...@@ -318,7 +318,7 @@ class ConstantPoolCleaner : public StackObj { ...@@ -318,7 +318,7 @@ class ConstantPoolCleaner : public StackObj {
bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); }
constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { constantPoolHandle ClassFileParser::parse_constant_pool(Handle class_loader, TRAPS) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
constantPoolHandle nullHandle; constantPoolHandle nullHandle;
...@@ -337,7 +337,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { ...@@ -337,7 +337,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
ConstantPoolCleaner cp_in_error(cp); // set constant pool to be cleaned up. ConstantPoolCleaner cp_in_error(cp); // set constant pool to be cleaned up.
// parsing constant pool entries // parsing constant pool entries
parse_constant_pool_entries(cp, length, CHECK_(nullHandle)); parse_constant_pool_entries(class_loader, cp, length, CHECK_(nullHandle));
int index = 1; // declared outside of loops for portability int index = 1; // declared outside of loops for portability
...@@ -2803,7 +2803,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -2803,7 +2803,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
_relax_verify = Verifier::relax_verify_for(class_loader()); _relax_verify = Verifier::relax_verify_for(class_loader());
// Constant pool // Constant pool
constantPoolHandle cp = parse_constant_pool(CHECK_(nullHandle)); constantPoolHandle cp = parse_constant_pool(class_loader, CHECK_(nullHandle));
ConstantPoolCleaner error_handler(cp); // set constant pool to be cleaned up. ConstantPoolCleaner error_handler(cp); // set constant pool to be cleaned up.
int cp_size = cp->length(); int cp_size = cp->length();
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -68,9 +68,10 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -68,9 +68,10 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
void set_stream(ClassFileStream* st) { _stream = st; } void set_stream(ClassFileStream* st) { _stream = st; }
// Constant pool parsing // Constant pool parsing
void parse_constant_pool_entries(constantPoolHandle cp, int length, TRAPS); void parse_constant_pool_entries(Handle class_loader,
constantPoolHandle cp, int length, TRAPS);
constantPoolHandle parse_constant_pool(TRAPS); constantPoolHandle parse_constant_pool(Handle class_loader, TRAPS);
// Interface parsing // Interface parsing
objArrayHandle parse_interfaces(constantPoolHandle cp, objArrayHandle parse_interfaces(constantPoolHandle cp,
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "classfile/symbolTable.hpp" #include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "gc_interface/collectedHeap.inline.hpp" #include "gc_interface/collectedHeap.inline.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp" #include "memory/filemap.hpp"
#include "memory/gcLocker.inline.hpp" #include "memory/gcLocker.inline.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
...@@ -37,34 +38,35 @@ ...@@ -37,34 +38,35 @@
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
SymbolTable* SymbolTable::_the_table = NULL; SymbolTable* SymbolTable::_the_table = NULL;
// Static arena for symbols that are not deallocated
Arena* SymbolTable::_arena = NULL;
Symbol* SymbolTable::allocate_symbol(const u1* name, int len, TRAPS) { Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) {
// Don't allow symbols to be created which cannot fit in a Symbol*. // Don't allow symbols to be created which cannot fit in a Symbol*.
if (len > Symbol::max_length()) { if (len > Symbol::max_length()) {
THROW_MSG_0(vmSymbols::java_lang_InternalError(), THROW_MSG_0(vmSymbols::java_lang_InternalError(),
"name is too long to represent"); "name is too long to represent");
} }
Symbol* sym = new (len) Symbol(name, len); Symbol* sym;
// Allocate symbols in the C heap when dumping shared spaces in case there
// are temporary symbols we can remove.
if (c_heap || DumpSharedSpaces) {
// refcount starts as 1
sym = new (len, THREAD) Symbol(name, len, 1);
} else {
sym = new (len, arena(), THREAD) Symbol(name, len, -1);
}
assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
return sym; return sym;
} }
bool SymbolTable::allocate_symbols(int names_count, const u1** names, void SymbolTable::initialize_symbols(int arena_alloc_size) {
int* lengths, Symbol** syms, TRAPS) { // Initialize the arena for global symbols, size passed in depends on CDS.
for (int i = 0; i< names_count; i++) { if (arena_alloc_size == 0) {
if (lengths[i] > Symbol::max_length()) { _arena = new Arena();
THROW_MSG_0(vmSymbols::java_lang_InternalError(), } else {
"name is too long to represent"); _arena = new Arena(arena_alloc_size);
}
}
for (int i = 0; i< names_count; i++) {
int len = lengths[i];
syms[i] = new (len) Symbol(names[i], len);
assert(syms[i] != NULL, "new should call vm_exit_out_of_memory if "
"C_HEAP is exhausted");
} }
return true;
} }
// Call function for all symbols in the symbol table. // Call function for all symbols in the symbol table.
...@@ -83,8 +85,7 @@ int SymbolTable::symbols_removed = 0; ...@@ -83,8 +85,7 @@ int SymbolTable::symbols_removed = 0;
int SymbolTable::symbols_counted = 0; int SymbolTable::symbols_counted = 0;
// Remove unreferenced symbols from the symbol table // Remove unreferenced symbols from the symbol table
// This is done late during GC. This doesn't use the hash table unlink because // This is done late during GC.
// it assumes that the literals are oops.
void SymbolTable::unlink() { void SymbolTable::unlink() {
int removed = 0; int removed = 0;
int total = 0; int total = 0;
...@@ -156,7 +157,7 @@ Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) { ...@@ -156,7 +157,7 @@ Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) {
if (s != NULL) return s; if (s != NULL) return s;
// Otherwise, add to symbol to table // Otherwise, add to symbol to table
return the_table()->basic_add(index, (u1*)name, len, hashValue, CHECK_NULL); return the_table()->basic_add(index, (u1*)name, len, hashValue, true, CHECK_NULL);
} }
Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) { Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) {
...@@ -192,7 +193,7 @@ Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) { ...@@ -192,7 +193,7 @@ Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) {
// We can't include the code in No_Safepoint_Verifier because of the // We can't include the code in No_Safepoint_Verifier because of the
// ResourceMark. // ResourceMark.
return the_table()->basic_add(index, (u1*)buffer, len, hashValue, CHECK_NULL); return the_table()->basic_add(index, (u1*)buffer, len, hashValue, true, CHECK_NULL);
} }
Symbol* SymbolTable::lookup_only(const char* name, int len, Symbol* SymbolTable::lookup_only(const char* name, int len,
...@@ -256,71 +257,81 @@ Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, ...@@ -256,71 +257,81 @@ Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length,
} }
} }
void SymbolTable::add(constantPoolHandle cp, int names_count, void SymbolTable::add(Handle class_loader, constantPoolHandle cp,
int names_count,
const char** names, int* lengths, int* cp_indices, const char** names, int* lengths, int* cp_indices,
unsigned int* hashValues, TRAPS) { unsigned int* hashValues, TRAPS) {
SymbolTable* table = the_table(); SymbolTable* table = the_table();
bool added = table->basic_add(cp, names_count, names, lengths, bool added = table->basic_add(class_loader, cp, names_count, names, lengths,
cp_indices, hashValues, CHECK); cp_indices, hashValues, CHECK);
if (!added) { if (!added) {
// do it the hard way // do it the hard way
for (int i=0; i<names_count; i++) { for (int i=0; i<names_count; i++) {
int index = table->hash_to_index(hashValues[i]); int index = table->hash_to_index(hashValues[i]);
Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], bool c_heap = class_loader() != NULL;
hashValues[i], CHECK); Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], hashValues[i], c_heap, CHECK);
cp->symbol_at_put(cp_indices[i], sym); cp->symbol_at_put(cp_indices[i], sym);
} }
} }
} }
Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) {
unsigned int hash;
Symbol* result = SymbolTable::lookup_only((char*)name, (int)strlen(name), hash);
if (result != NULL) {
return result;
}
SymbolTable* table = the_table();
int index = table->hash_to_index(hash);
return table->basic_add(index, (u1*)name, (int)strlen(name), hash, false, THREAD);
}
Symbol* SymbolTable::basic_add(int index, u1 *name, int len, Symbol* SymbolTable::basic_add(int index, u1 *name, int len,
unsigned int hashValue, TRAPS) { unsigned int hashValue, bool c_heap, TRAPS) {
assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
"proposed name of symbol must be stable"); "proposed name of symbol must be stable");
// We assume that lookup() has been called already, that it failed, // Grab SymbolTable_lock first.
// and symbol was not found. We create the symbol here.
Symbol* sym = allocate_symbol(name, len, CHECK_NULL);
// Allocation must be done before grabbing the SymbolTable_lock lock
MutexLocker ml(SymbolTable_lock, THREAD); MutexLocker ml(SymbolTable_lock, THREAD);
assert(sym->equals((char*)name, len), "symbol must be properly initialized");
// Since look-up was done lock-free, we need to check if another // Since look-up was done lock-free, we need to check if another
// thread beat us in the race to insert the symbol. // thread beat us in the race to insert the symbol.
Symbol* test = lookup(index, (char*)name, len, hashValue); Symbol* test = lookup(index, (char*)name, len, hashValue);
if (test != NULL) { if (test != NULL) {
// A race occurred and another thread introduced the symbol, this one // A race occurred and another thread introduced the symbol.
// will be dropped and collected.
delete sym;
assert(test->refcount() != 0, "lookup should have incremented the count"); assert(test->refcount() != 0, "lookup should have incremented the count");
return test; return test;
} }
// Create a new symbol.
Symbol* sym = allocate_symbol(name, len, c_heap, CHECK_NULL);
assert(sym->equals((char*)name, len), "symbol must be properly initialized");
HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym); HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym);
sym->increment_refcount();
add_entry(index, entry); add_entry(index, entry);
return sym; return sym;
} }
bool SymbolTable::basic_add(constantPoolHandle cp, int names_count, // This version of basic_add adds symbols in batch from the constant pool
// parsing.
bool SymbolTable::basic_add(Handle class_loader, constantPoolHandle cp,
int names_count,
const char** names, int* lengths, const char** names, int* lengths,
int* cp_indices, unsigned int* hashValues, int* cp_indices, unsigned int* hashValues,
TRAPS) { TRAPS) {
Symbol* syms[symbol_alloc_batch_size];
bool allocated = allocate_symbols(names_count, (const u1**)names, lengths, // Check symbol names are not too long. If any are too long, don't add any.
syms, CHECK_false); for (int i = 0; i< names_count; i++) {
if (!allocated) { if (lengths[i] > Symbol::max_length()) {
return false; THROW_MSG_0(vmSymbols::java_lang_InternalError(),
"name is too long to represent");
}
} }
// Allocation must be done before grabbing the SymbolTable_lock lock // Hold SymbolTable_lock through the symbol creation
MutexLocker ml(SymbolTable_lock, THREAD); MutexLocker ml(SymbolTable_lock, THREAD);
for (int i=0; i<names_count; i++) { for (int i=0; i<names_count; i++) {
assert(syms[i]->equals(names[i], lengths[i]), "symbol must be properly initialized");
// Since look-up was done lock-free, we need to check if another // Since look-up was done lock-free, we need to check if another
// thread beat us in the race to insert the symbol. // thread beat us in the race to insert the symbol.
int index = hash_to_index(hashValues[i]); int index = hash_to_index(hashValues[i]);
...@@ -330,16 +341,17 @@ bool SymbolTable::basic_add(constantPoolHandle cp, int names_count, ...@@ -330,16 +341,17 @@ bool SymbolTable::basic_add(constantPoolHandle cp, int names_count,
// will be dropped and collected. Use test instead. // will be dropped and collected. Use test instead.
cp->symbol_at_put(cp_indices[i], test); cp->symbol_at_put(cp_indices[i], test);
assert(test->refcount() != 0, "lookup should have incremented the count"); assert(test->refcount() != 0, "lookup should have incremented the count");
delete syms[i];
} else { } else {
Symbol* sym = syms[i]; // Create a new symbol. The null class loader is never unloaded so these
// are allocated specially in a permanent arena.
bool c_heap = class_loader() != NULL;
Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false));
assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be???
HashtableEntry<Symbol*>* entry = new_entry(hashValues[i], sym); HashtableEntry<Symbol*>* entry = new_entry(hashValues[i], sym);
sym->increment_refcount(); // increment refcount in external hashtable
add_entry(index, entry); add_entry(index, entry);
cp->symbol_at_put(cp_indices[i], sym); cp->symbol_at_put(cp_indices[i], sym);
} }
} }
return true; return true;
} }
...@@ -406,6 +418,8 @@ void SymbolTable::print_histogram() { ...@@ -406,6 +418,8 @@ void SymbolTable::print_histogram() {
((float)symbols_removed/(float)symbols_counted)* 100); ((float)symbols_removed/(float)symbols_counted)* 100);
} }
tty->print_cr("Reference counts %5d", Symbol::_total_count); tty->print_cr("Reference counts %5d", Symbol::_total_count);
tty->print_cr("Symbol arena size %5d used %5d",
arena()->size_in_bytes(), arena()->used());
tty->print_cr("Histogram of symbol length:"); tty->print_cr("Histogram of symbol length:");
tty->print_cr("%8s %5d", "Total ", total); tty->print_cr("%8s %5d", "Total ", total);
tty->print_cr("%8s %5d", "Maximum", max_symbols); tty->print_cr("%8s %5d", "Maximum", max_symbols);
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -82,24 +82,24 @@ private: ...@@ -82,24 +82,24 @@ private:
static int symbols_removed; static int symbols_removed;
static int symbols_counted; static int symbols_counted;
Symbol* allocate_symbol(const u1* name, int len, TRAPS); // Assumes no characters larger than 0x7F Symbol* allocate_symbol(const u1* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F
bool allocate_symbols(int names_count, const u1** names, int* lengths, Symbol** syms, TRAPS);
// Adding elements // Adding elements
Symbol* basic_add(int index, u1* name, int len, Symbol* basic_add(int index, u1* name, int len, unsigned int hashValue,
unsigned int hashValue, TRAPS); bool c_heap, TRAPS);
bool basic_add(constantPoolHandle cp, int names_count,
bool basic_add(Handle class_loader, constantPoolHandle cp, int names_count,
const char** names, int* lengths, int* cp_indices, const char** names, int* lengths, int* cp_indices,
unsigned int* hashValues, TRAPS); unsigned int* hashValues, TRAPS);
static void new_symbols(constantPoolHandle cp, int names_count, static void new_symbols(Handle class_loader, constantPoolHandle cp,
int names_count,
const char** name, int* lengths, const char** name, int* lengths,
int* cp_indices, unsigned int* hashValues, int* cp_indices, unsigned int* hashValues,
TRAPS) { TRAPS) {
add(cp, names_count, name, lengths, cp_indices, hashValues, THREAD); add(class_loader, cp, names_count, name, lengths, cp_indices, hashValues, THREAD);
} }
// Table size // Table size
enum { enum {
symbol_table_size = 20011 symbol_table_size = 20011
...@@ -114,10 +114,16 @@ private: ...@@ -114,10 +114,16 @@ private:
: Hashtable<Symbol*>(symbol_table_size, sizeof (HashtableEntry<Symbol*>), t, : Hashtable<Symbol*>(symbol_table_size, sizeof (HashtableEntry<Symbol*>), t,
number_of_entries) {} number_of_entries) {}
// Arena for permanent symbols (null class loader) that are never unloaded
static Arena* _arena;
static Arena* arena() { return _arena; } // called for statistics
static void initialize_symbols(int arena_alloc_size = 0);
public: public:
enum { enum {
symbol_alloc_batch_size = 8 symbol_alloc_batch_size = 8,
// Pick initial size based on java -version size measurements
symbol_alloc_arena_size = 360*K
}; };
// The symbol table // The symbol table
...@@ -126,6 +132,7 @@ public: ...@@ -126,6 +132,7 @@ public:
static void create_table() { static void create_table() {
assert(_the_table == NULL, "One symbol table allowed."); assert(_the_table == NULL, "One symbol table allowed.");
_the_table = new SymbolTable(); _the_table = new SymbolTable();
initialize_symbols(symbol_alloc_arena_size);
} }
static void create_table(HashtableBucket* t, int length, static void create_table(HashtableBucket* t, int length,
...@@ -134,6 +141,9 @@ public: ...@@ -134,6 +141,9 @@ public:
assert(length == symbol_table_size * sizeof(HashtableBucket), assert(length == symbol_table_size * sizeof(HashtableBucket),
"bad shared symbol size."); "bad shared symbol size.");
_the_table = new SymbolTable(t, number_of_entries); _the_table = new SymbolTable(t, number_of_entries);
// if CDS give symbol table a default arena size since most symbols
// are already allocated in the shared misc section.
initialize_symbols();
} }
static Symbol* lookup(const char* name, int len, TRAPS); static Symbol* lookup(const char* name, int len, TRAPS);
...@@ -151,7 +161,7 @@ public: ...@@ -151,7 +161,7 @@ public:
static Symbol* lookup_unicode(const jchar* name, int len, TRAPS); static Symbol* lookup_unicode(const jchar* name, int len, TRAPS);
static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash); static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
static void add(constantPoolHandle cp, int names_count, static void add(Handle class_loader, constantPoolHandle cp, int names_count,
const char** names, int* lengths, int* cp_indices, const char** names, int* lengths, int* cp_indices,
unsigned int* hashValues, TRAPS); unsigned int* hashValues, TRAPS);
...@@ -174,6 +184,9 @@ public: ...@@ -174,6 +184,9 @@ public:
return lookup(sym, begin, end, THREAD); return lookup(sym, begin, end, THREAD);
} }
// Create a symbol in the arena for symbols that are not deleted
static Symbol* new_permanent_symbol(const char* name, TRAPS);
// Symbol lookup // Symbol lookup
static Symbol* lookup(int index, const char* name, int len, TRAPS); static Symbol* lookup(int index, const char* name, int len, TRAPS);
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -79,7 +79,7 @@ void vmSymbols::initialize(TRAPS) { ...@@ -79,7 +79,7 @@ void vmSymbols::initialize(TRAPS) {
if (!UseSharedSpaces) { if (!UseSharedSpaces) {
const char* string = &vm_symbol_bodies[0]; const char* string = &vm_symbol_bodies[0];
for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) {
Symbol* sym = SymbolTable::new_symbol(string, CHECK); Symbol* sym = SymbolTable::new_permanent_symbol(string, CHECK);
_symbols[index] = sym; _symbols[index] = sym;
string += strlen(string); // skip string body string += strlen(string); // skip string body
string += 1; // skip trailing null string += 1; // skip trailing null
...@@ -128,7 +128,7 @@ void vmSymbols::initialize(TRAPS) { ...@@ -128,7 +128,7 @@ void vmSymbols::initialize(TRAPS) {
// Spot-check correspondence between strings, symbols, and enums: // Spot-check correspondence between strings, symbols, and enums:
assert(_symbols[NO_SID] == NULL, "must be"); assert(_symbols[NO_SID] == NULL, "must be");
const char* str = "java/lang/Object"; const char* str = "java/lang/Object";
TempNewSymbol jlo = SymbolTable::new_symbol(str, CHECK); TempNewSymbol jlo = SymbolTable::new_permanent_symbol(str, CHECK);
assert(strncmp(str, (char*)jlo->base(), jlo->utf8_length()) == 0, ""); assert(strncmp(str, (char*)jlo->base(), jlo->utf8_length()) == 0, "");
assert(jlo == java_lang_Object(), ""); assert(jlo == java_lang_Object(), "");
SID sid = VM_SYMBOL_ENUM_NAME(java_lang_Object); SID sid = VM_SYMBOL_ENUM_NAME(java_lang_Object);
...@@ -147,7 +147,7 @@ void vmSymbols::initialize(TRAPS) { ...@@ -147,7 +147,7 @@ void vmSymbols::initialize(TRAPS) {
// The string "format" happens (at the moment) not to be a vmSymbol, // The string "format" happens (at the moment) not to be a vmSymbol,
// though it is a method name in java.lang.String. // though it is a method name in java.lang.String.
str = "format"; str = "format";
TempNewSymbol fmt = SymbolTable::new_symbol(str, CHECK); TempNewSymbol fmt = SymbolTable::new_permanent_symbol(str, CHECK);
sid = find_sid(fmt); sid = find_sid(fmt);
assert(sid == NO_SID, "symbol index works (negative test)"); assert(sid == NO_SID, "symbol index works (negative test)");
} }
......
...@@ -553,7 +553,7 @@ public: ...@@ -553,7 +553,7 @@ public:
static void oops_do_marking_prologue(); static void oops_do_marking_prologue();
static void oops_do_marking_epilogue(); static void oops_do_marking_epilogue();
static bool oops_do_marking_is_active() { return _oops_do_mark_nmethods != NULL; } static bool oops_do_marking_is_active() { return _oops_do_mark_nmethods != NULL; }
DEBUG_ONLY(bool test_oops_do_mark() { return _oops_do_mark_link != NULL; }) bool test_oops_do_mark() { return _oops_do_mark_link != NULL; }
// ScopeDesc for an instruction // ScopeDesc for an instruction
ScopeDesc* scope_desc_at(address pc); ScopeDesc* scope_desc_at(address pc);
......
...@@ -42,9 +42,7 @@ typedef GenericTaskQueueSet<CMTaskQueue> CMTaskQueueSet; ...@@ -42,9 +42,7 @@ typedef GenericTaskQueueSet<CMTaskQueue> CMTaskQueueSet;
class G1CMIsAliveClosure: public BoolObjectClosure { class G1CMIsAliveClosure: public BoolObjectClosure {
G1CollectedHeap* _g1; G1CollectedHeap* _g1;
public: public:
G1CMIsAliveClosure(G1CollectedHeap* g1) : G1CMIsAliveClosure(G1CollectedHeap* g1) : _g1(g1) { }
_g1(g1)
{}
void do_object(oop obj) { void do_object(oop obj) {
ShouldNotCallThis(); ShouldNotCallThis();
...@@ -111,11 +109,6 @@ class CMBitMapRO VALUE_OBJ_CLASS_SPEC { ...@@ -111,11 +109,6 @@ class CMBitMapRO VALUE_OBJ_CLASS_SPEC {
return offsetToHeapWord(heapWordToOffset(addr) + 1); return offsetToHeapWord(heapWordToOffset(addr) + 1);
} }
void mostly_disjoint_range_union(BitMap* from_bitmap,
size_t from_start_index,
HeapWord* to_start_word,
size_t word_num);
// debugging // debugging
NOT_PRODUCT(bool covers(ReservedSpace rs) const;) NOT_PRODUCT(bool covers(ReservedSpace rs) const;)
}; };
...@@ -258,60 +251,6 @@ class CMMarkStack VALUE_OBJ_CLASS_SPEC { ...@@ -258,60 +251,6 @@ class CMMarkStack VALUE_OBJ_CLASS_SPEC {
void oops_do(OopClosure* f); void oops_do(OopClosure* f);
}; };
class CMRegionStack VALUE_OBJ_CLASS_SPEC {
MemRegion* _base;
jint _capacity;
jint _index;
jint _oops_do_bound;
bool _overflow;
public:
CMRegionStack();
~CMRegionStack();
void allocate(size_t size);
// This is lock-free; assumes that it will only be called in parallel
// with other "push" operations (no pops).
void push_lock_free(MemRegion mr);
// Lock-free; assumes that it will only be called in parallel
// with other "pop" operations (no pushes).
MemRegion pop_lock_free();
#if 0
// The routines that manipulate the region stack with a lock are
// not currently used. They should be retained, however, as a
// diagnostic aid.
// These two are the implementations that use a lock. They can be
// called concurrently with each other but they should not be called
// concurrently with the lock-free versions (push() / pop()).
void push_with_lock(MemRegion mr);
MemRegion pop_with_lock();
#endif
bool isEmpty() { return _index == 0; }
bool isFull() { return _index == _capacity; }
bool overflow() { return _overflow; }
void clear_overflow() { _overflow = false; }
int size() { return _index; }
// It iterates over the entries in the region stack and it
// invalidates (i.e. assigns MemRegion()) the ones that point to
// regions in the collection set.
bool invalidate_entries_into_cset();
// This gives an upper bound up to which the iteration in
// invalidate_entries_into_cset() will reach. This prevents
// newly-added entries to be unnecessarily scanned.
void set_oops_do_bound() {
_oops_do_bound = _index;
}
void setEmpty() { _index = 0; clear_overflow(); }
};
class ForceOverflowSettings VALUE_OBJ_CLASS_SPEC { class ForceOverflowSettings VALUE_OBJ_CLASS_SPEC {
private: private:
#ifndef PRODUCT #ifndef PRODUCT
...@@ -408,7 +347,6 @@ class ConcurrentMark : public CHeapObj { ...@@ -408,7 +347,6 @@ class ConcurrentMark : public CHeapObj {
friend class ConcurrentMarkThread; friend class ConcurrentMarkThread;
friend class CMTask; friend class CMTask;
friend class CMBitMapClosure; friend class CMBitMapClosure;
friend class CSetMarkOopClosure;
friend class CMGlobalObjectClosure; friend class CMGlobalObjectClosure;
friend class CMRemarkTask; friend class CMRemarkTask;
friend class CMConcurrentMarkingTask; friend class CMConcurrentMarkingTask;
...@@ -443,7 +381,6 @@ protected: ...@@ -443,7 +381,6 @@ protected:
CMBitMap _markBitMap2; CMBitMap _markBitMap2;
CMBitMapRO* _prevMarkBitMap; // completed mark bitmap CMBitMapRO* _prevMarkBitMap; // completed mark bitmap
CMBitMap* _nextMarkBitMap; // under-construction mark bitmap CMBitMap* _nextMarkBitMap; // under-construction mark bitmap
bool _at_least_one_mark_complete;
BitMap _region_bm; BitMap _region_bm;
BitMap _card_bm; BitMap _card_bm;
...@@ -457,7 +394,6 @@ protected: ...@@ -457,7 +394,6 @@ protected:
// For gray objects // For gray objects
CMMarkStack _markStack; // Grey objects behind global finger. CMMarkStack _markStack; // Grey objects behind global finger.
CMRegionStack _regionStack; // Grey regions behind global finger.
HeapWord* volatile _finger; // the global finger, region aligned, HeapWord* volatile _finger; // the global finger, region aligned,
// always points to the end of the // always points to the end of the
// last claimed region // last claimed region
...@@ -502,18 +438,6 @@ protected: ...@@ -502,18 +438,6 @@ protected:
// verbose level // verbose level
CMVerboseLevel _verbose_level; CMVerboseLevel _verbose_level;
// These two fields are used to implement the optimisation that
// avoids pushing objects on the global/region stack if there are
// no collection set regions above the lowest finger.
// This is the lowest finger (among the global and local fingers),
// which is calculated before a new collection set is chosen.
HeapWord* _min_finger;
// If this flag is true, objects/regions that are marked below the
// finger should be pushed on the stack(s). If this is flag is
// false, it is safe not to push them on the stack(s).
bool _should_gray_objects;
// All of these times are in ms. // All of these times are in ms.
NumberSeq _init_times; NumberSeq _init_times;
NumberSeq _remark_times; NumberSeq _remark_times;
...@@ -604,7 +528,7 @@ protected: ...@@ -604,7 +528,7 @@ protected:
CMTaskQueueSet* task_queues() { return _task_queues; } CMTaskQueueSet* task_queues() { return _task_queues; }
// Access / manipulation of the overflow flag which is set to // Access / manipulation of the overflow flag which is set to
// indicate that the global stack or region stack has overflown // indicate that the global stack has overflown
bool has_overflown() { return _has_overflown; } bool has_overflown() { return _has_overflown; }
void set_has_overflown() { _has_overflown = true; } void set_has_overflown() { _has_overflown = true; }
void clear_has_overflown() { _has_overflown = false; } void clear_has_overflown() { _has_overflown = false; }
...@@ -684,68 +608,6 @@ public: ...@@ -684,68 +608,6 @@ public:
bool mark_stack_overflow() { return _markStack.overflow(); } bool mark_stack_overflow() { return _markStack.overflow(); }
bool mark_stack_empty() { return _markStack.isEmpty(); } bool mark_stack_empty() { return _markStack.isEmpty(); }
// (Lock-free) Manipulation of the region stack
bool region_stack_push_lock_free(MemRegion mr) {
// Currently we only call the lock-free version during evacuation
// pauses.
assert(SafepointSynchronize::is_at_safepoint(), "world should be stopped");
_regionStack.push_lock_free(mr);
if (_regionStack.overflow()) {
set_has_overflown();
return false;
}
return true;
}
// Lock-free version of region-stack pop. Should only be
// called in tandem with other lock-free pops.
MemRegion region_stack_pop_lock_free() {
return _regionStack.pop_lock_free();
}
#if 0
// The routines that manipulate the region stack with a lock are
// not currently used. They should be retained, however, as a
// diagnostic aid.
bool region_stack_push_with_lock(MemRegion mr) {
// Currently we only call the lock-based version during either
// concurrent marking or remark.
assert(!SafepointSynchronize::is_at_safepoint() || !concurrent(),
"if we are at a safepoint it should be the remark safepoint");
_regionStack.push_with_lock(mr);
if (_regionStack.overflow()) {
set_has_overflown();
return false;
}
return true;
}
MemRegion region_stack_pop_with_lock() {
// Currently we only call the lock-based version during either
// concurrent marking or remark.
assert(!SafepointSynchronize::is_at_safepoint() || !concurrent(),
"if we are at a safepoint it should be the remark safepoint");
return _regionStack.pop_with_lock();
}
#endif
int region_stack_size() { return _regionStack.size(); }
bool region_stack_overflow() { return _regionStack.overflow(); }
bool region_stack_empty() { return _regionStack.isEmpty(); }
// Iterate over any regions that were aborted while draining the
// region stack (any such regions are saved in the corresponding
// CMTask) and invalidate (i.e. assign to the empty MemRegion())
// any regions that point into the collection set.
bool invalidate_aborted_regions_in_cset();
// Returns true if there are any aborted memory regions.
bool has_aborted_regions();
CMRootRegions* root_regions() { return &_root_regions; } CMRootRegions* root_regions() { return &_root_regions; }
bool concurrent_marking_in_progress() { bool concurrent_marking_in_progress() {
...@@ -774,10 +636,6 @@ public: ...@@ -774,10 +636,6 @@ public:
return _task_queues->steal(task_num, hash_seed, obj); return _task_queues->steal(task_num, hash_seed, obj);
} }
// It grays an object by first marking it. Then, if it's behind the
// global finger, it also pushes it on the global stack.
void deal_with_reference(oop obj);
ConcurrentMark(ReservedSpace rs, int max_regions); ConcurrentMark(ReservedSpace rs, int max_regions);
~ConcurrentMark(); ~ConcurrentMark();
...@@ -810,22 +668,6 @@ public: ...@@ -810,22 +668,6 @@ public:
inline void grayRoot(oop obj, size_t word_size, inline void grayRoot(oop obj, size_t word_size,
uint worker_id, HeapRegion* hr = NULL); uint worker_id, HeapRegion* hr = NULL);
// It's used during evacuation pauses to gray a region, if
// necessary, and it's MT-safe. It assumes that the caller has
// marked any objects on that region. If _should_gray_objects is
// true and we're still doing concurrent marking, the region is
// pushed on the region stack, if it is located below the global
// finger, otherwise we do nothing.
void grayRegionIfNecessary(MemRegion mr);
// It's used during evacuation pauses to mark and, if necessary,
// gray a single object and it's MT-safe. It assumes the caller did
// not mark the object. If _should_gray_objects is true and we're
// still doing concurrent marking, the objects is pushed on the
// global stack, if it is located below the global finger, otherwise
// we do nothing.
void markAndGrayObjectIfNecessary(oop p);
// It iterates over the heap and for each object it comes across it // It iterates over the heap and for each object it comes across it
// will dump the contents of its reference fields, as well as // will dump the contents of its reference fields, as well as
// liveness information for the object and its referents. The dump // liveness information for the object and its referents. The dump
...@@ -869,10 +711,6 @@ public: ...@@ -869,10 +711,6 @@ public:
// Do concurrent phase of marking, to a tentative transitive closure. // Do concurrent phase of marking, to a tentative transitive closure.
void markFromRoots(); void markFromRoots();
// Process all unprocessed SATB buffers. It is called at the
// beginning of an evacuation pause.
void drainAllSATBBuffers();
void checkpointRootsFinal(bool clear_all_soft_refs); void checkpointRootsFinal(bool clear_all_soft_refs);
void checkpointRootsFinalWork(); void checkpointRootsFinalWork();
void cleanup(); void cleanup();
...@@ -899,10 +737,6 @@ public: ...@@ -899,10 +737,6 @@ public:
_markStack.note_end_of_gc(); _markStack.note_end_of_gc();
} }
// Iterate over the oops in the mark stack and all local queues. It
// also calls invalidate_entries_into_cset() on the region stack.
void oops_do(OopClosure* f);
// Verify that there are no CSet oops on the stacks (taskqueues / // Verify that there are no CSet oops on the stacks (taskqueues /
// global mark stack), enqueued SATB buffers, per-thread SATB // global mark stack), enqueued SATB buffers, per-thread SATB
// buffers, and fingers (global / per-task). The boolean parameters // buffers, and fingers (global / per-task). The boolean parameters
...@@ -919,40 +753,6 @@ public: ...@@ -919,40 +753,6 @@ public:
// unless the force parameter is true. // unless the force parameter is true.
void update_g1_committed(bool force = false); void update_g1_committed(bool force = false);
void complete_marking_in_collection_set();
// It indicates that a new collection set is being chosen.
void newCSet();
// It registers a collection set heap region with CM. This is used
// to determine whether any heap regions are located above the finger.
void registerCSetRegion(HeapRegion* hr);
// Resets the region fields of any active CMTask whose region fields
// are in the collection set (i.e. the region currently claimed by
// the CMTask will be evacuated and may be used, subsequently, as
// an alloc region). When this happens the region fields in the CMTask
// are stale and, hence, should be cleared causing the worker thread
// to claim a new region.
void reset_active_task_region_fields_in_cset();
// Registers the maximum region-end associated with a set of
// regions with CM. Again this is used to determine whether any
// heap regions are located above the finger.
void register_collection_set_finger(HeapWord* max_finger) {
// max_finger is the highest heap region end of the regions currently
// contained in the collection set. If this value is larger than
// _min_finger then we need to gray objects.
// This routine is like registerCSetRegion but for an entire
// collection of regions.
if (max_finger > _min_finger) {
_should_gray_objects = true;
}
}
// Returns "true" if at least one mark has been completed.
bool at_least_one_mark_complete() { return _at_least_one_mark_complete; }
bool isMarked(oop p) const { bool isMarked(oop p) const {
assert(p != NULL && p->is_oop(), "expected an oop"); assert(p != NULL && p->is_oop(), "expected an oop");
HeapWord* addr = (HeapWord*)p; HeapWord* addr = (HeapWord*)p;
...@@ -1164,23 +964,6 @@ private: ...@@ -1164,23 +964,6 @@ private:
// limit of the region this task is scanning, NULL if we're not scanning one // limit of the region this task is scanning, NULL if we're not scanning one
HeapWord* _region_limit; HeapWord* _region_limit;
// This is used only when we scan regions popped from the region
// stack. It records what the last object on such a region we
// scanned was. It is used to ensure that, if we abort region
// iteration, we do not rescan the first part of the region. This
// should be NULL when we're not scanning a region from the region
// stack.
HeapWord* _region_finger;
// If we abort while scanning a region we record the remaining
// unscanned portion and check this field when marking restarts.
// This avoids having to push on the region stack while other
// marking threads may still be popping regions.
// If we were to push the unscanned portion directly to the
// region stack then we would need to using locking versions
// of the push and pop operations.
MemRegion _aborted_region;
// the number of words this task has scanned // the number of words this task has scanned
size_t _words_scanned; size_t _words_scanned;
// When _words_scanned reaches this limit, the regular clock is // When _words_scanned reaches this limit, the regular clock is
...@@ -1268,8 +1051,6 @@ private: ...@@ -1268,8 +1051,6 @@ private:
int _global_transfers_to; int _global_transfers_to;
int _global_transfers_from; int _global_transfers_from;
int _region_stack_pops;
int _regions_claimed; int _regions_claimed;
int _objs_found_on_bitmap; int _objs_found_on_bitmap;
...@@ -1347,15 +1128,6 @@ public: ...@@ -1347,15 +1128,6 @@ public:
bool has_timed_out() { return _has_timed_out; } bool has_timed_out() { return _has_timed_out; }
bool claimed() { return _claimed; } bool claimed() { return _claimed; }
// Support routines for the partially scanned region that may be
// recorded as a result of aborting while draining the CMRegionStack
MemRegion aborted_region() { return _aborted_region; }
void set_aborted_region(MemRegion mr)
{ _aborted_region = mr; }
// Clears any recorded partially scanned region
void clear_aborted_region() { set_aborted_region(MemRegion()); }
void set_cm_oop_closure(G1CMOopClosure* cm_oop_closure); void set_cm_oop_closure(G1CMOopClosure* cm_oop_closure);
// It grays the object by marking it and, if necessary, pushing it // It grays the object by marking it and, if necessary, pushing it
...@@ -1385,22 +1157,12 @@ public: ...@@ -1385,22 +1157,12 @@ public:
// buffers are available. // buffers are available.
void drain_satb_buffers(); void drain_satb_buffers();
// It keeps popping regions from the region stack and processing
// them until the region stack is empty.
void drain_region_stack(BitMapClosure* closure);
// moves the local finger to a new location // moves the local finger to a new location
inline void move_finger_to(HeapWord* new_finger) { inline void move_finger_to(HeapWord* new_finger) {
assert(new_finger >= _finger && new_finger < _region_limit, "invariant"); assert(new_finger >= _finger && new_finger < _region_limit, "invariant");
_finger = new_finger; _finger = new_finger;
} }
// moves the region finger to a new location
inline void move_region_finger_to(HeapWord* new_finger) {
assert(new_finger < _cm->finger(), "invariant");
_region_finger = new_finger;
}
CMTask(int task_num, ConcurrentMark *cm, CMTask(int task_num, ConcurrentMark *cm,
size_t* marked_bytes, BitMap* card_bm, size_t* marked_bytes, BitMap* card_bm,
CMTaskQueue* task_queue, CMTaskQueueSet* task_queues); CMTaskQueue* task_queue, CMTaskQueueSet* task_queues);
......
...@@ -4355,7 +4355,8 @@ G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, ...@@ -4355,7 +4355,8 @@ G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1,
_during_initial_mark(_g1->g1_policy()->during_initial_mark_pause()), _during_initial_mark(_g1->g1_policy()->during_initial_mark_pause()),
_mark_in_progress(_g1->mark_in_progress()) { } _mark_in_progress(_g1->mark_in_progress()) { }
void G1ParCopyHelper::mark_object(oop obj) { template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
void G1ParCopyClosure<do_gen_barrier, barrier, do_mark_object>::mark_object(oop obj) {
#ifdef ASSERT #ifdef ASSERT
HeapRegion* hr = _g1->heap_region_containing(obj); HeapRegion* hr = _g1->heap_region_containing(obj);
assert(hr != NULL, "sanity"); assert(hr != NULL, "sanity");
...@@ -4366,7 +4367,9 @@ void G1ParCopyHelper::mark_object(oop obj) { ...@@ -4366,7 +4367,9 @@ void G1ParCopyHelper::mark_object(oop obj) {
_cm->grayRoot(obj, (size_t) obj->size(), _worker_id); _cm->grayRoot(obj, (size_t) obj->size(), _worker_id);
} }
void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) { template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
void G1ParCopyClosure<do_gen_barrier, barrier, do_mark_object>
::mark_forwarded_object(oop from_obj, oop to_obj) {
#ifdef ASSERT #ifdef ASSERT
assert(from_obj->is_forwarded(), "from obj should be forwarded"); assert(from_obj->is_forwarded(), "from obj should be forwarded");
assert(from_obj->forwardee() == to_obj, "to obj should be the forwardee"); assert(from_obj->forwardee() == to_obj, "to obj should be the forwardee");
...@@ -4388,7 +4391,9 @@ void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) { ...@@ -4388,7 +4391,9 @@ void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) {
_cm->grayRoot(to_obj, (size_t) from_obj->size(), _worker_id); _cm->grayRoot(to_obj, (size_t) from_obj->size(), _worker_id);
} }
oop G1ParCopyHelper::copy_to_survivor_space(oop old) { template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
oop G1ParCopyClosure<do_gen_barrier, barrier, do_mark_object>
::copy_to_survivor_space(oop old) {
size_t word_sz = old->size(); size_t word_sz = old->size();
HeapRegion* from_region = _g1->heap_region_containing_raw(old); HeapRegion* from_region = _g1->heap_region_containing_raw(old);
// +1 to make the -1 indexes valid... // +1 to make the -1 indexes valid...
...@@ -4457,8 +4462,8 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) { ...@@ -4457,8 +4462,8 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) {
} else { } else {
// No point in using the slower heap_region_containing() method, // No point in using the slower heap_region_containing() method,
// given that we know obj is in the heap. // given that we know obj is in the heap.
_scanner->set_region(_g1->heap_region_containing_raw(obj)); _scanner.set_region(_g1->heap_region_containing_raw(obj));
obj->oop_iterate_backwards(_scanner); obj->oop_iterate_backwards(&_scanner);
} }
} else { } else {
_par_scan_state->undo_allocation(alloc_purpose, obj_ptr, word_sz); _par_scan_state->undo_allocation(alloc_purpose, obj_ptr, word_sz);
...@@ -4675,67 +4680,74 @@ public: ...@@ -4675,67 +4680,74 @@ public:
double start_time_ms = os::elapsedTime() * 1000.0; double start_time_ms = os::elapsedTime() * 1000.0;
_g1h->g1_policy()->record_gc_worker_start_time(worker_id, start_time_ms); _g1h->g1_policy()->record_gc_worker_start_time(worker_id, start_time_ms);
ResourceMark rm; {
HandleMark hm; ResourceMark rm;
HandleMark hm;
ReferenceProcessor* rp = _g1h->ref_processor_stw(); ReferenceProcessor* rp = _g1h->ref_processor_stw();
G1ParScanThreadState pss(_g1h, worker_id); G1ParScanThreadState pss(_g1h, worker_id);
G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss, rp); G1ParScanHeapEvacClosure scan_evac_cl(_g1h, &pss, rp);
G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, rp); G1ParScanHeapEvacFailureClosure evac_failure_cl(_g1h, &pss, rp);
G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss, rp); G1ParScanPartialArrayClosure partial_scan_cl(_g1h, &pss, rp);
pss.set_evac_closure(&scan_evac_cl); pss.set_evac_closure(&scan_evac_cl);
pss.set_evac_failure_closure(&evac_failure_cl); pss.set_evac_failure_closure(&evac_failure_cl);
pss.set_partial_scan_closure(&partial_scan_cl); pss.set_partial_scan_closure(&partial_scan_cl);
G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss, rp); G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss, rp);
G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss, rp); G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss, rp);
G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss, rp); G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss, rp);
G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss, rp); G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss, rp);
OopClosure* scan_root_cl = &only_scan_root_cl; OopClosure* scan_root_cl = &only_scan_root_cl;
OopsInHeapRegionClosure* scan_perm_cl = &only_scan_perm_cl; OopsInHeapRegionClosure* scan_perm_cl = &only_scan_perm_cl;
if (_g1h->g1_policy()->during_initial_mark_pause()) { if (_g1h->g1_policy()->during_initial_mark_pause()) {
// We also need to mark copied objects. // We also need to mark copied objects.
scan_root_cl = &scan_mark_root_cl; scan_root_cl = &scan_mark_root_cl;
scan_perm_cl = &scan_mark_perm_cl; scan_perm_cl = &scan_mark_perm_cl;
} }
G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss); G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss);
pss.start_strong_roots(); pss.start_strong_roots();
_g1h->g1_process_strong_roots(/* not collecting perm */ false, _g1h->g1_process_strong_roots(/* not collecting perm */ false,
SharedHeap::SO_AllClasses, SharedHeap::SO_AllClasses,
scan_root_cl, scan_root_cl,
&push_heap_rs_cl, &push_heap_rs_cl,
scan_perm_cl, scan_perm_cl,
worker_id); worker_id);
pss.end_strong_roots(); pss.end_strong_roots();
{ {
double start = os::elapsedTime(); double start = os::elapsedTime();
G1ParEvacuateFollowersClosure evac(_g1h, &pss, _queues, &_terminator); G1ParEvacuateFollowersClosure evac(_g1h, &pss, _queues, &_terminator);
evac.do_void(); evac.do_void();
double elapsed_ms = (os::elapsedTime()-start)*1000.0; double elapsed_ms = (os::elapsedTime()-start)*1000.0;
double term_ms = pss.term_time()*1000.0; double term_ms = pss.term_time()*1000.0;
_g1h->g1_policy()->record_obj_copy_time(worker_id, elapsed_ms-term_ms); _g1h->g1_policy()->record_obj_copy_time(worker_id, elapsed_ms-term_ms);
_g1h->g1_policy()->record_termination(worker_id, term_ms, pss.term_attempts()); _g1h->g1_policy()->record_termination(worker_id, term_ms, pss.term_attempts());
} }
_g1h->g1_policy()->record_thread_age_table(pss.age_table()); _g1h->g1_policy()->record_thread_age_table(pss.age_table());
_g1h->update_surviving_young_words(pss.surviving_young_words()+1); _g1h->update_surviving_young_words(pss.surviving_young_words()+1);
// Clean up any par-expanded rem sets. // Clean up any par-expanded rem sets.
HeapRegionRemSet::par_cleanup(); HeapRegionRemSet::par_cleanup();
if (ParallelGCVerbose) { if (ParallelGCVerbose) {
MutexLocker x(stats_lock()); MutexLocker x(stats_lock());
pss.print_termination_stats(worker_id); pss.print_termination_stats(worker_id);
}
assert(pss.refs()->is_empty(), "should be empty");
// Close the inner scope so that the ResourceMark and HandleMark
// destructors are executed here and are included as part of the
// "GC Worker Time".
} }
assert(pss.refs()->is_empty(), "should be empty");
double end_time_ms = os::elapsedTime() * 1000.0; double end_time_ms = os::elapsedTime() * 1000.0;
_g1h->g1_policy()->record_gc_worker_end_time(worker_id, end_time_ms); _g1h->g1_policy()->record_gc_worker_end_time(worker_id, end_time_ms);
} }
...@@ -4743,6 +4755,67 @@ public: ...@@ -4743,6 +4755,67 @@ public:
// *** Common G1 Evacuation Stuff // *** Common G1 Evacuation Stuff
// Closures that support the filtering of CodeBlobs scanned during
// external root scanning.
// Closure applied to reference fields in code blobs (specifically nmethods)
// to determine whether an nmethod contains references that point into
// the collection set. Used as a predicate when walking code roots so
// that only nmethods that point into the collection set are added to the
// 'marked' list.
class G1FilteredCodeBlobToOopClosure : public CodeBlobToOopClosure {
class G1PointsIntoCSOopClosure : public OopClosure {
G1CollectedHeap* _g1;
bool _points_into_cs;
public:
G1PointsIntoCSOopClosure(G1CollectedHeap* g1) :
_g1(g1), _points_into_cs(false) { }
bool points_into_cs() const { return _points_into_cs; }
template <class T>
void do_oop_nv(T* p) {
if (!_points_into_cs) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop) &&
_g1->in_cset_fast_test(oopDesc::decode_heap_oop_not_null(heap_oop))) {
_points_into_cs = true;
}
}
}
virtual void do_oop(oop* p) { do_oop_nv(p); }
virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
};
G1CollectedHeap* _g1;
public:
G1FilteredCodeBlobToOopClosure(G1CollectedHeap* g1, OopClosure* cl) :
CodeBlobToOopClosure(cl, true), _g1(g1) { }
virtual void do_code_blob(CodeBlob* cb) {
nmethod* nm = cb->as_nmethod_or_null();
if (nm != NULL && !(nm->test_oops_do_mark())) {
G1PointsIntoCSOopClosure predicate_cl(_g1);
nm->oops_do(&predicate_cl);
if (predicate_cl.points_into_cs()) {
// At least one of the reference fields or the oop relocations
// in the nmethod points into the collection set. We have to
// 'mark' this nmethod.
// Note: Revisit the following if CodeBlobToOopClosure::do_code_blob()
// or MarkingCodeBlobClosure::do_code_blob() change.
if (!nm->test_set_oops_do_mark()) {
do_newly_marked_nmethod(nm);
}
}
}
}
};
// This method is run in a GC worker. // This method is run in a GC worker.
void void
...@@ -4764,7 +4837,7 @@ g1_process_strong_roots(bool collecting_perm_gen, ...@@ -4764,7 +4837,7 @@ g1_process_strong_roots(bool collecting_perm_gen,
// Walk the code cache w/o buffering, because StarTask cannot handle // Walk the code cache w/o buffering, because StarTask cannot handle
// unaligned oop locations. // unaligned oop locations.
CodeBlobToOopClosure eager_scan_code_roots(scan_non_heap_roots, /*do_marking=*/ true); G1FilteredCodeBlobToOopClosure eager_scan_code_roots(this, scan_non_heap_roots);
process_strong_roots(false, // no scoping; this is parallel code process_strong_roots(false, // no scoping; this is parallel code
collecting_perm_gen, so, collecting_perm_gen, so,
...@@ -5378,25 +5451,39 @@ void G1CollectedHeap::evacuate_collection_set() { ...@@ -5378,25 +5451,39 @@ void G1CollectedHeap::evacuate_collection_set() {
rem_set()->prepare_for_younger_refs_iterate(true); rem_set()->prepare_for_younger_refs_iterate(true);
assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty"); assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty");
double start_par = os::elapsedTime(); double start_par_time_sec = os::elapsedTime();
double end_par_time_sec;
if (G1CollectedHeap::use_parallel_gc_threads()) { {
// The individual threads will set their evac-failure closures.
StrongRootsScope srs(this);
if (ParallelGCVerbose) G1ParScanThreadState::print_termination_stats_hdr();
// These tasks use ShareHeap::_process_strong_tasks
assert(UseDynamicNumberOfGCThreads ||
workers()->active_workers() == workers()->total_workers(),
"If not dynamic should be using all the workers");
workers()->run_task(&g1_par_task);
} else {
StrongRootsScope srs(this); StrongRootsScope srs(this);
g1_par_task.set_for_termination(n_workers);
g1_par_task.work(0); if (G1CollectedHeap::use_parallel_gc_threads()) {
// The individual threads will set their evac-failure closures.
if (ParallelGCVerbose) G1ParScanThreadState::print_termination_stats_hdr();
// These tasks use ShareHeap::_process_strong_tasks
assert(UseDynamicNumberOfGCThreads ||
workers()->active_workers() == workers()->total_workers(),
"If not dynamic should be using all the workers");
workers()->run_task(&g1_par_task);
} else {
g1_par_task.set_for_termination(n_workers);
g1_par_task.work(0);
}
end_par_time_sec = os::elapsedTime();
// Closing the inner scope will execute the destructor
// for the StrongRootsScope object. We record the current
// elapsed time before closing the scope so that time
// taken for the SRS destructor is NOT included in the
// reported parallel time.
} }
double par_time = (os::elapsedTime() - start_par) * 1000.0; double par_time_ms = (end_par_time_sec - start_par_time_sec) * 1000.0;
g1_policy()->record_par_time(par_time); g1_policy()->record_par_time(par_time_ms);
double code_root_fixup_time_ms =
(os::elapsedTime() - end_par_time_sec) * 1000.0;
g1_policy()->record_code_root_fixup_time(code_root_fixup_time_ms);
set_par_threads(0); set_par_threads(0);
......
...@@ -199,7 +199,8 @@ class G1CollectedHeap : public SharedHeap { ...@@ -199,7 +199,8 @@ class G1CollectedHeap : public SharedHeap {
friend class OldGCAllocRegion; friend class OldGCAllocRegion;
// Closures used in implementation. // Closures used in implementation.
friend class G1ParCopyHelper; template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
friend class G1ParCopyClosure;
friend class G1IsAliveClosure; friend class G1IsAliveClosure;
friend class G1EvacuateFollowersClosure; friend class G1EvacuateFollowersClosure;
friend class G1ParScanThreadState; friend class G1ParScanThreadState;
...@@ -1676,202 +1677,6 @@ protected: ...@@ -1676,202 +1677,6 @@ protected:
size_t _max_heap_capacity; size_t _max_heap_capacity;
}; };
#define use_local_bitmaps 1
#define verify_local_bitmaps 0
#define oop_buffer_length 256
#ifndef PRODUCT
class GCLabBitMap;
class GCLabBitMapClosure: public BitMapClosure {
private:
ConcurrentMark* _cm;
GCLabBitMap* _bitmap;
public:
GCLabBitMapClosure(ConcurrentMark* cm,
GCLabBitMap* bitmap) {
_cm = cm;
_bitmap = bitmap;
}
virtual bool do_bit(size_t offset);
};
#endif // !PRODUCT
class GCLabBitMap: public BitMap {
private:
ConcurrentMark* _cm;
int _shifter;
size_t _bitmap_word_covers_words;
// beginning of the heap
HeapWord* _heap_start;
// this is the actual start of the GCLab
HeapWord* _real_start_word;
// this is the actual end of the GCLab
HeapWord* _real_end_word;
// this is the first word, possibly located before the actual start
// of the GCLab, that corresponds to the first bit of the bitmap
HeapWord* _start_word;
// size of a GCLab in words
size_t _gclab_word_size;
static int shifter() {
return MinObjAlignment - 1;
}
// how many heap words does a single bitmap word corresponds to?
static size_t bitmap_word_covers_words() {
return BitsPerWord << shifter();
}
size_t gclab_word_size() const {
return _gclab_word_size;
}
// Calculates actual GCLab size in words
size_t gclab_real_word_size() const {
return bitmap_size_in_bits(pointer_delta(_real_end_word, _start_word))
/ BitsPerWord;
}
static size_t bitmap_size_in_bits(size_t gclab_word_size) {
size_t bits_in_bitmap = gclab_word_size >> shifter();
// We are going to ensure that the beginning of a word in this
// bitmap also corresponds to the beginning of a word in the
// global marking bitmap. To handle the case where a GCLab
// starts from the middle of the bitmap, we need to add enough
// space (i.e. up to a bitmap word) to ensure that we have
// enough bits in the bitmap.
return bits_in_bitmap + BitsPerWord - 1;
}
public:
GCLabBitMap(HeapWord* heap_start, size_t gclab_word_size)
: BitMap(bitmap_size_in_bits(gclab_word_size)),
_cm(G1CollectedHeap::heap()->concurrent_mark()),
_shifter(shifter()),
_bitmap_word_covers_words(bitmap_word_covers_words()),
_heap_start(heap_start),
_gclab_word_size(gclab_word_size),
_real_start_word(NULL),
_real_end_word(NULL),
_start_word(NULL) {
guarantee(false, "GCLabBitMap::GCLabBitmap(): don't call this any more");
}
inline unsigned heapWordToOffset(HeapWord* addr) {
unsigned offset = (unsigned) pointer_delta(addr, _start_word) >> _shifter;
assert(offset < size(), "offset should be within bounds");
return offset;
}
inline HeapWord* offsetToHeapWord(size_t offset) {
HeapWord* addr = _start_word + (offset << _shifter);
assert(_real_start_word <= addr && addr < _real_end_word, "invariant");
return addr;
}
bool fields_well_formed() {
bool ret1 = (_real_start_word == NULL) &&
(_real_end_word == NULL) &&
(_start_word == NULL);
if (ret1)
return true;
bool ret2 = _real_start_word >= _start_word &&
_start_word < _real_end_word &&
(_real_start_word + _gclab_word_size) == _real_end_word &&
(_start_word + _gclab_word_size + _bitmap_word_covers_words)
> _real_end_word;
return ret2;
}
inline bool mark(HeapWord* addr) {
guarantee(use_local_bitmaps, "invariant");
assert(fields_well_formed(), "invariant");
if (addr >= _real_start_word && addr < _real_end_word) {
assert(!isMarked(addr), "should not have already been marked");
// first mark it on the bitmap
at_put(heapWordToOffset(addr), true);
return true;
} else {
return false;
}
}
inline bool isMarked(HeapWord* addr) {
guarantee(use_local_bitmaps, "invariant");
assert(fields_well_formed(), "invariant");
return at(heapWordToOffset(addr));
}
void set_buffer(HeapWord* start) {
guarantee(false, "set_buffer(): don't call this any more");
guarantee(use_local_bitmaps, "invariant");
clear();
assert(start != NULL, "invariant");
_real_start_word = start;
_real_end_word = start + _gclab_word_size;
size_t diff =
pointer_delta(start, _heap_start) % _bitmap_word_covers_words;
_start_word = start - diff;
assert(fields_well_formed(), "invariant");
}
#ifndef PRODUCT
void verify() {
// verify that the marks have been propagated
GCLabBitMapClosure cl(_cm, this);
iterate(&cl);
}
#endif // PRODUCT
void retire() {
guarantee(false, "retire(): don't call this any more");
guarantee(use_local_bitmaps, "invariant");
assert(fields_well_formed(), "invariant");
if (_start_word != NULL) {
CMBitMap* mark_bitmap = _cm->nextMarkBitMap();
// this means that the bitmap was set up for the GCLab
assert(_real_start_word != NULL && _real_end_word != NULL, "invariant");
mark_bitmap->mostly_disjoint_range_union(this,
0, // always start from the start of the bitmap
_start_word,
gclab_real_word_size());
_cm->grayRegionIfNecessary(MemRegion(_real_start_word, _real_end_word));
#ifndef PRODUCT
if (use_local_bitmaps && verify_local_bitmaps)
verify();
#endif // PRODUCT
} else {
assert(_real_start_word == NULL && _real_end_word == NULL, "invariant");
}
}
size_t bitmap_size_in_words() const {
return (bitmap_size_in_bits(gclab_word_size()) + BitsPerWord - 1) / BitsPerWord;
}
};
class G1ParGCAllocBuffer: public ParGCAllocBuffer { class G1ParGCAllocBuffer: public ParGCAllocBuffer {
private: private:
bool _retired; bool _retired;
......
...@@ -140,7 +140,6 @@ G1CollectorPolicy::G1CollectorPolicy() : ...@@ -140,7 +140,6 @@ G1CollectorPolicy::G1CollectorPolicy() :
_summary(new Summary()), _summary(new Summary()),
_cur_clear_ct_time_ms(0.0), _cur_clear_ct_time_ms(0.0),
_mark_closure_time_ms(0.0),
_root_region_scan_wait_time_ms(0.0), _root_region_scan_wait_time_ms(0.0),
_cur_ref_proc_time_ms(0.0), _cur_ref_proc_time_ms(0.0),
...@@ -944,9 +943,6 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec, ...@@ -944,9 +943,6 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec,
_cur_aux_times_set[i] = false; _cur_aux_times_set[i] = false;
} }
// This is initialized to zero here and is set during
// the evacuation pause if marking is in progress.
_cur_satb_drain_time_ms = 0.0;
// This is initialized to zero here and is set during the evacuation // This is initialized to zero here and is set during the evacuation
// pause if we actually waited for the root region scanning to finish. // pause if we actually waited for the root region scanning to finish.
_root_region_scan_wait_time_ms = 0.0; _root_region_scan_wait_time_ms = 0.0;
...@@ -1246,11 +1242,6 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) { ...@@ -1246,11 +1242,6 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
double other_time_ms = elapsed_ms; double other_time_ms = elapsed_ms;
// Subtract the SATB drain time. It's initialized to zero at the
// start of the pause and is updated during the pause if marking
// is in progress.
other_time_ms -= _cur_satb_drain_time_ms;
// Subtract the root region scanning wait time. It's initialized to // Subtract the root region scanning wait time. It's initialized to
// zero at the start of the pause. // zero at the start of the pause.
other_time_ms -= _root_region_scan_wait_time_ms; other_time_ms -= _root_region_scan_wait_time_ms;
...@@ -1261,15 +1252,13 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) { ...@@ -1261,15 +1252,13 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
other_time_ms -= known_time; other_time_ms -= known_time;
} }
// Now subtract the time taken to fix up roots in generated code
other_time_ms -= _cur_collection_code_root_fixup_time_ms;
// Subtract the time taken to clean the card table from the // Subtract the time taken to clean the card table from the
// current value of "other time" // current value of "other time"
other_time_ms -= _cur_clear_ct_time_ms; other_time_ms -= _cur_clear_ct_time_ms;
// Subtract the time spent completing marking in the collection
// set. Note if marking is not in progress during the pause
// the value of _mark_closure_time_ms will be zero.
other_time_ms -= _mark_closure_time_ms;
// TraceGen0Time and TraceGen1Time summary info updating. // TraceGen0Time and TraceGen1Time summary info updating.
_all_pause_times_ms->add(elapsed_ms); _all_pause_times_ms->add(elapsed_ms);
...@@ -1280,16 +1269,8 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) { ...@@ -1280,16 +1269,8 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
MainBodySummary* body_summary = _summary->main_body_summary(); MainBodySummary* body_summary = _summary->main_body_summary();
assert(body_summary != NULL, "should not be null!"); assert(body_summary != NULL, "should not be null!");
// This will be non-zero iff marking is currently in progress (i.e.
// _g1->mark_in_progress() == true) and the currrent pause was not
// an initial mark pause. Since the body_summary items are NumberSeqs,
// however, they have to be consistent and updated in lock-step with
// each other. Therefore we unconditionally record the SATB drain
// time - even if it's zero.
body_summary->record_satb_drain_time_ms(_cur_satb_drain_time_ms);
body_summary->record_root_region_scan_wait_time_ms( body_summary->record_root_region_scan_wait_time_ms(
_root_region_scan_wait_time_ms); _root_region_scan_wait_time_ms);
body_summary->record_ext_root_scan_time_ms(ext_root_scan_time); body_summary->record_ext_root_scan_time_ms(ext_root_scan_time);
body_summary->record_satb_filtering_time_ms(satb_filtering_time); body_summary->record_satb_filtering_time_ms(satb_filtering_time);
body_summary->record_update_rs_time_ms(update_rs_time); body_summary->record_update_rs_time_ms(update_rs_time);
...@@ -1305,7 +1286,6 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) { ...@@ -1305,7 +1286,6 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
body_summary->record_parallel_other_time_ms(parallel_other_time); body_summary->record_parallel_other_time_ms(parallel_other_time);
} }
body_summary->record_mark_closure_time_ms(_mark_closure_time_ms);
body_summary->record_clear_ct_time_ms(_cur_clear_ct_time_ms); body_summary->record_clear_ct_time_ms(_cur_clear_ct_time_ms);
// We exempt parallel collection from this check because Alloc Buffer // We exempt parallel collection from this check because Alloc Buffer
...@@ -1401,10 +1381,10 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) { ...@@ -1401,10 +1381,10 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms); print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms);
print_par_stats(2, "Termination", _par_last_termination_times_ms); print_par_stats(2, "Termination", _par_last_termination_times_ms);
print_par_sizes(3, "Termination Attempts", _par_last_termination_attempts); print_par_sizes(3, "Termination Attempts", _par_last_termination_attempts);
print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms);
for (int i = 0; i < _parallel_gc_threads; i++) { for (int i = 0; i < _parallel_gc_threads; i++) {
_par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] - _par_last_gc_worker_start_times_ms[i]; _par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] -
_par_last_gc_worker_start_times_ms[i];
double worker_known_time = _par_last_ext_root_scan_times_ms[i] + double worker_known_time = _par_last_ext_root_scan_times_ms[i] +
_par_last_satb_filtering_times_ms[i] + _par_last_satb_filtering_times_ms[i] +
...@@ -1413,10 +1393,13 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) { ...@@ -1413,10 +1393,13 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
_par_last_obj_copy_times_ms[i] + _par_last_obj_copy_times_ms[i] +
_par_last_termination_times_ms[i]; _par_last_termination_times_ms[i];
_par_last_gc_worker_other_times_ms[i] = _cur_collection_par_time_ms - worker_known_time; _par_last_gc_worker_other_times_ms[i] = _par_last_gc_worker_times_ms[i] -
worker_known_time;
} }
print_par_stats(2, "GC Worker", _par_last_gc_worker_times_ms);
print_par_stats(2, "GC Worker Other", _par_last_gc_worker_other_times_ms); print_par_stats(2, "GC Worker Other", _par_last_gc_worker_other_times_ms);
print_par_stats(2, "GC Worker Total", _par_last_gc_worker_times_ms);
print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms);
} else { } else {
print_stats(1, "Ext Root Scanning", ext_root_scan_time); print_stats(1, "Ext Root Scanning", ext_root_scan_time);
if (print_marking_info) { if (print_marking_info) {
...@@ -1427,9 +1410,7 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) { ...@@ -1427,9 +1410,7 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
print_stats(1, "Scan RS", scan_rs_time); print_stats(1, "Scan RS", scan_rs_time);
print_stats(1, "Object Copying", obj_copy_time); print_stats(1, "Object Copying", obj_copy_time);
} }
if (print_marking_info) { print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms);
print_stats(1, "Complete CSet Marking", _mark_closure_time_ms);
}
print_stats(1, "Clear CT", _cur_clear_ct_time_ms); print_stats(1, "Clear CT", _cur_clear_ct_time_ms);
#ifndef PRODUCT #ifndef PRODUCT
print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms); print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms);
...@@ -1577,8 +1558,7 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) { ...@@ -1577,8 +1558,7 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
} }
double all_other_time_ms = pause_time_ms - double all_other_time_ms = pause_time_ms -
(update_rs_time + scan_rs_time + obj_copy_time + (update_rs_time + scan_rs_time + obj_copy_time + termination_time);
_mark_closure_time_ms + termination_time);
double young_other_time_ms = 0.0; double young_other_time_ms = 0.0;
if (young_cset_region_length() > 0) { if (young_cset_region_length() > 0) {
...@@ -1705,41 +1685,6 @@ void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time, ...@@ -1705,41 +1685,6 @@ void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time,
dcqs.notify_if_necessary(); dcqs.notify_if_necessary();
} }
double
G1CollectorPolicy::
predict_young_collection_elapsed_time_ms(size_t adjustment) {
guarantee( adjustment == 0 || adjustment == 1, "invariant" );
G1CollectedHeap* g1h = G1CollectedHeap::heap();
size_t young_num = g1h->young_list()->length();
if (young_num == 0)
return 0.0;
young_num += adjustment;
size_t pending_cards = predict_pending_cards();
size_t rs_lengths = g1h->young_list()->sampled_rs_lengths() +
predict_rs_length_diff();
size_t card_num;
if (gcs_are_young()) {
card_num = predict_young_card_num(rs_lengths);
} else {
card_num = predict_non_young_card_num(rs_lengths);
}
size_t young_byte_size = young_num * HeapRegion::GrainBytes;
double accum_yg_surv_rate =
_short_lived_surv_rate_group->accum_surv_rate(adjustment);
size_t bytes_to_copy =
(size_t) (accum_yg_surv_rate * (double) HeapRegion::GrainBytes);
return
predict_rs_update_time_ms(pending_cards) +
predict_rs_scan_time_ms(card_num) +
predict_object_copy_time_ms(bytes_to_copy) +
predict_young_other_time_ms(young_num) +
predict_constant_other_time_ms();
}
double double
G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards) { G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards) {
size_t rs_length = predict_rs_length_diff(); size_t rs_length = predict_rs_length_diff();
...@@ -1973,7 +1918,6 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const { ...@@ -1973,7 +1918,6 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const {
print_summary(1, "Object Copy", body_summary->get_obj_copy_seq()); print_summary(1, "Object Copy", body_summary->get_obj_copy_seq());
} }
} }
print_summary(1, "Mark Closure", body_summary->get_mark_closure_seq());
print_summary(1, "Clear CT", body_summary->get_clear_ct_seq()); print_summary(1, "Clear CT", body_summary->get_clear_ct_seq());
print_summary(1, "Other", summary->get_other_seq()); print_summary(1, "Other", summary->get_other_seq());
{ {
...@@ -1982,17 +1926,15 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const { ...@@ -1982,17 +1926,15 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const {
if (parallel) { if (parallel) {
// parallel // parallel
NumberSeq* other_parts[] = { NumberSeq* other_parts[] = {
body_summary->get_satb_drain_seq(),
body_summary->get_root_region_scan_wait_seq(), body_summary->get_root_region_scan_wait_seq(),
body_summary->get_parallel_seq(), body_summary->get_parallel_seq(),
body_summary->get_clear_ct_seq() body_summary->get_clear_ct_seq()
}; };
calc_other_times_ms = NumberSeq(summary->get_total_seq(), calc_other_times_ms = NumberSeq(summary->get_total_seq(),
4, other_parts); 3, other_parts);
} else { } else {
// serial // serial
NumberSeq* other_parts[] = { NumberSeq* other_parts[] = {
body_summary->get_satb_drain_seq(),
body_summary->get_root_region_scan_wait_seq(), body_summary->get_root_region_scan_wait_seq(),
body_summary->get_update_rs_seq(), body_summary->get_update_rs_seq(),
body_summary->get_ext_root_scan_seq(), body_summary->get_ext_root_scan_seq(),
...@@ -2001,7 +1943,7 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const { ...@@ -2001,7 +1943,7 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const {
body_summary->get_obj_copy_seq() body_summary->get_obj_copy_seq()
}; };
calc_other_times_ms = NumberSeq(summary->get_total_seq(), calc_other_times_ms = NumberSeq(summary->get_total_seq(),
7, other_parts); 6, other_parts);
} }
check_other_times(1, summary->get_other_seq(), &calc_other_times_ms); check_other_times(1, summary->get_other_seq(), &calc_other_times_ms);
} }
......
...@@ -64,7 +64,6 @@ public: ...@@ -64,7 +64,6 @@ public:
}; };
class MainBodySummary: public CHeapObj { class MainBodySummary: public CHeapObj {
define_num_seq(satb_drain) // optional
define_num_seq(root_region_scan_wait) define_num_seq(root_region_scan_wait)
define_num_seq(parallel) // parallel only define_num_seq(parallel) // parallel only
define_num_seq(ext_root_scan) define_num_seq(ext_root_scan)
...@@ -74,7 +73,6 @@ class MainBodySummary: public CHeapObj { ...@@ -74,7 +73,6 @@ class MainBodySummary: public CHeapObj {
define_num_seq(obj_copy) define_num_seq(obj_copy)
define_num_seq(termination) // parallel only define_num_seq(termination) // parallel only
define_num_seq(parallel_other) // parallel only define_num_seq(parallel_other) // parallel only
define_num_seq(mark_closure)
define_num_seq(clear_ct) define_num_seq(clear_ct)
}; };
...@@ -179,7 +177,9 @@ private: ...@@ -179,7 +177,9 @@ private:
size_t _cur_collection_pause_used_at_start_bytes; size_t _cur_collection_pause_used_at_start_bytes;
size_t _cur_collection_pause_used_regions_at_start; size_t _cur_collection_pause_used_regions_at_start;
double _cur_collection_par_time_ms; double _cur_collection_par_time_ms;
double _cur_satb_drain_time_ms;
double _cur_collection_code_root_fixup_time_ms;
double _cur_clear_ct_time_ms; double _cur_clear_ct_time_ms;
double _cur_ref_proc_time_ms; double _cur_ref_proc_time_ms;
double _cur_ref_enq_time_ms; double _cur_ref_enq_time_ms;
...@@ -226,8 +226,8 @@ private: ...@@ -226,8 +226,8 @@ private:
double* _par_last_gc_worker_times_ms; double* _par_last_gc_worker_times_ms;
// Each workers 'other' time i.e. the elapsed time of the parallel // Each workers 'other' time i.e. the elapsed time of the parallel
// phase of the pause minus the sum of the individual sub-phase // code executed by a worker minus the sum of the individual sub-phase
// times for a given worker thread. // times for that worker thread.
double* _par_last_gc_worker_other_times_ms; double* _par_last_gc_worker_other_times_ms;
// indicates whether we are in young or mixed GC mode // indicates whether we are in young or mixed GC mode
...@@ -488,7 +488,6 @@ public: ...@@ -488,7 +488,6 @@ public:
get_new_prediction(_non_young_other_cost_per_region_ms_seq); get_new_prediction(_non_young_other_cost_per_region_ms_seq);
} }
double predict_young_collection_elapsed_time_ms(size_t adjustment);
double predict_base_elapsed_time_ms(size_t pending_cards); double predict_base_elapsed_time_ms(size_t pending_cards);
double predict_base_elapsed_time_ms(size_t pending_cards, double predict_base_elapsed_time_ms(size_t pending_cards,
size_t scanned_cards); size_t scanned_cards);
...@@ -709,7 +708,6 @@ private: ...@@ -709,7 +708,6 @@ private:
double _cur_mark_stop_world_time_ms; double _cur_mark_stop_world_time_ms;
double _mark_remark_start_sec; double _mark_remark_start_sec;
double _mark_cleanup_start_sec; double _mark_cleanup_start_sec;
double _mark_closure_time_ms;
double _root_region_scan_wait_time_ms; double _root_region_scan_wait_time_ms;
// Update the young list target length either by setting it to the // Update the young list target length either by setting it to the
...@@ -809,10 +807,6 @@ public: ...@@ -809,10 +807,6 @@ public:
void record_concurrent_mark_init_end(double void record_concurrent_mark_init_end(double
mark_init_elapsed_time_ms); mark_init_elapsed_time_ms);
void record_mark_closure_time(double mark_closure_time_ms) {
_mark_closure_time_ms = mark_closure_time_ms;
}
void record_root_region_scan_wait_time(double time_ms) { void record_root_region_scan_wait_time(double time_ms) {
_root_region_scan_wait_time_ms = time_ms; _root_region_scan_wait_time_ms = time_ms;
} }
...@@ -846,11 +840,6 @@ public: ...@@ -846,11 +840,6 @@ public:
_par_last_satb_filtering_times_ms[worker_i] = ms; _par_last_satb_filtering_times_ms[worker_i] = ms;
} }
void record_satb_drain_time(double ms) {
assert(_g1->mark_in_progress(), "shouldn't be here otherwise");
_cur_satb_drain_time_ms = ms;
}
void record_update_rs_time(int thread, double ms) { void record_update_rs_time(int thread, double ms) {
_par_last_update_rs_times_ms[thread] = ms; _par_last_update_rs_times_ms[thread] = ms;
} }
...@@ -897,6 +886,10 @@ public: ...@@ -897,6 +886,10 @@ public:
_cur_collection_par_time_ms = ms; _cur_collection_par_time_ms = ms;
} }
void record_code_root_fixup_time(double ms) {
_cur_collection_code_root_fixup_time_ms = ms;
}
void record_aux_start_time(int i) { void record_aux_start_time(int i) {
guarantee(i < _aux_num, "should be within range"); guarantee(i < _aux_num, "should be within range");
_cur_aux_start_times_ms[i] = os::elapsedTime() * 1000.0; _cur_aux_start_times_ms[i] = os::elapsedTime() * 1000.0;
......
...@@ -118,9 +118,11 @@ public: ...@@ -118,9 +118,11 @@ public:
virtual void do_oop(narrowOop* p) { do_oop_nv(p); } virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
}; };
template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
class G1ParCopyClosure : public G1ParClosureSuper {
G1ParScanClosure _scanner;
template <class T> void do_oop_work(T* p);
class G1ParCopyHelper : public G1ParClosureSuper {
G1ParScanClosure *_scanner;
protected: protected:
// Mark the object if it's not already marked. This is used to mark // Mark the object if it's not already marked. This is used to mark
// objects pointed to by roots that are guaranteed not to move // objects pointed to by roots that are guaranteed not to move
...@@ -134,23 +136,11 @@ protected: ...@@ -134,23 +136,11 @@ protected:
oop copy_to_survivor_space(oop obj); oop copy_to_survivor_space(oop obj);
public:
G1ParCopyHelper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state,
G1ParScanClosure *scanner) :
G1ParClosureSuper(g1, par_scan_state), _scanner(scanner) { }
};
template <bool do_gen_barrier, G1Barrier barrier, bool do_mark_object>
class G1ParCopyClosure : public G1ParCopyHelper {
G1ParScanClosure _scanner;
template <class T> void do_oop_work(T* p);
public: public:
G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, G1ParCopyClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state,
ReferenceProcessor* rp) : ReferenceProcessor* rp) :
_scanner(g1, par_scan_state, rp), _scanner(g1, par_scan_state, rp),
G1ParCopyHelper(g1, par_scan_state, &_scanner) { G1ParClosureSuper(g1, par_scan_state) {
assert(_ref_processor == NULL, "sanity"); assert(_ref_processor == NULL, "sanity");
} }
......
...@@ -69,9 +69,6 @@ ...@@ -69,9 +69,6 @@
diagnostic(bool, G1TraceConcRefinement, false, \ diagnostic(bool, G1TraceConcRefinement, false, \
"Trace G1 concurrent refinement") \ "Trace G1 concurrent refinement") \
\ \
product(intx, G1MarkRegionStackSize, 1024 * 1024, \
"Size of the region stack for concurrent marking.") \
\
product(double, G1ConcMarkStepDurationMillis, 10.0, \ product(double, G1ConcMarkStepDurationMillis, 10.0, \
"Target duration of individual concurrent marking steps " \ "Target duration of individual concurrent marking steps " \
"in milliseconds.") \ "in milliseconds.") \
......
...@@ -373,10 +373,9 @@ class HeapRegion: public G1OffsetTableContigSpace { ...@@ -373,10 +373,9 @@ class HeapRegion: public G1OffsetTableContigSpace {
ScrubRemSetClaimValue = 3, ScrubRemSetClaimValue = 3,
ParVerifyClaimValue = 4, ParVerifyClaimValue = 4,
RebuildRSClaimValue = 5, RebuildRSClaimValue = 5,
CompleteMarkCSetClaimValue = 6, ParEvacFailureClaimValue = 6,
ParEvacFailureClaimValue = 7, AggregateCountClaimValue = 7,
AggregateCountClaimValue = 8, VerifyCountClaimValue = 8
VerifyCountClaimValue = 9
}; };
inline HeapWord* par_allocate_no_bot_updates(size_t word_size) { inline HeapWord* par_allocate_no_bot_updates(size_t word_size) {
......
...@@ -181,6 +181,8 @@ public: ...@@ -181,6 +181,8 @@ public:
// within the heap, this function tells whether they are met. // within the heap, this function tells whether they are met.
virtual bool is_aligned(HeapWord* addr) = 0; virtual bool is_aligned(HeapWord* addr) = 0;
// Print a description of the memory for the barrier set
virtual void print_on(outputStream* st) const = 0;
}; };
#endif // SHARE_VM_MEMORY_BARRIERSET_HPP #endif // SHARE_VM_MEMORY_BARRIERSET_HPP
...@@ -711,6 +711,11 @@ void CardTableModRefBS::verify_dirty_region(MemRegion mr) { ...@@ -711,6 +711,11 @@ void CardTableModRefBS::verify_dirty_region(MemRegion mr) {
} }
#endif #endif
void CardTableModRefBS::print_on(outputStream* st) const {
st->print_cr("Card table byte_map: [" INTPTR_FORMAT "," INTPTR_FORMAT "] byte_map_base: " INTPTR_FORMAT,
_byte_map, _byte_map + _byte_map_size, byte_map_base);
}
bool CardTableModRefBSForCTRS::card_will_be_scanned(jbyte cv) { bool CardTableModRefBSForCTRS::card_will_be_scanned(jbyte cv) {
return return
CardTableModRefBS::card_will_be_scanned(cv) || CardTableModRefBS::card_will_be_scanned(cv) ||
......
...@@ -472,6 +472,9 @@ public: ...@@ -472,6 +472,9 @@ public:
return _byte_map + card_index; return _byte_map + card_index;
} }
// Print a description of the memory for the barrier set
virtual void print_on(outputStream* st) const;
void verify(); void verify();
void verify_guard(); void verify_guard();
......
/* /*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1488,12 +1488,11 @@ void GenCollectedHeap::preload_and_dump(TRAPS) { ...@@ -1488,12 +1488,11 @@ void GenCollectedHeap::preload_and_dump(TRAPS) {
// sun.io.Converters // sun.io.Converters
static const char obj_array_sig[] = "[[Ljava/lang/Object;"; static const char obj_array_sig[] = "[[Ljava/lang/Object;";
SymbolTable::lookup(obj_array_sig, (int)strlen(obj_array_sig), THREAD); (void)SymbolTable::new_permanent_symbol(obj_array_sig, THREAD);
// java.util.HashMap // java.util.HashMap
static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;"; static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;";
SymbolTable::lookup(map_entry_array_sig, (int)strlen(map_entry_array_sig), (void)SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD);
THREAD);
tty->print("Loading classes to share ... "); tty->print("Loading classes to share ... ");
while ((fgets(class_name, sizeof class_name, file)) != NULL) { while ((fgets(class_name, sizeof class_name, file)) != NULL) {
...@@ -1512,7 +1511,7 @@ void GenCollectedHeap::preload_and_dump(TRAPS) { ...@@ -1512,7 +1511,7 @@ void GenCollectedHeap::preload_and_dump(TRAPS) {
computed_jsum = jsum(computed_jsum, class_name, (const int)name_len - 1); computed_jsum = jsum(computed_jsum, class_name, (const int)name_len - 1);
// Got a class name - load it. // Got a class name - load it.
TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name, THREAD); Symbol* class_name_symbol = SymbolTable::new_permanent_symbol(class_name, THREAD);
guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol."); guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
klassOop klass = SystemDictionary::resolve_or_null(class_name_symbol, klassOop klass = SystemDictionary::resolve_or_null(class_name_symbol,
THREAD); THREAD);
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -137,7 +137,7 @@ klassOop objArrayKlassKlass::allocate_objArray_klass_impl(objArrayKlassKlassHand ...@@ -137,7 +137,7 @@ klassOop objArrayKlassKlass::allocate_objArray_klass_impl(objArrayKlassKlassHand
new_str[idx++] = ';'; new_str[idx++] = ';';
} }
new_str[idx++] = '\0'; new_str[idx++] = '\0';
name = SymbolTable::new_symbol(new_str, CHECK_0); name = SymbolTable::new_permanent_symbol(new_str, CHECK_0);
if (element_klass->oop_is_instance()) { if (element_klass->oop_is_instance()) {
instanceKlass* ik = instanceKlass::cast(element_klass()); instanceKlass* ik = instanceKlass::cast(element_klass());
ik->set_array_name(name); ik->set_array_name(name);
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -29,15 +29,25 @@ ...@@ -29,15 +29,25 @@
#include "runtime/os.hpp" #include "runtime/os.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
Symbol::Symbol(const u1* name, int length) : _refcount(0), _length(length) { Symbol::Symbol(const u1* name, int length, int refcount) : _refcount(refcount), _length(length) {
_identity_hash = os::random(); _identity_hash = os::random();
for (int i = 0; i < _length; i++) { for (int i = 0; i < _length; i++) {
byte_at_put(i, name[i]); byte_at_put(i, name[i]);
} }
} }
void* Symbol::operator new(size_t size, int len) { void* Symbol::operator new(size_t sz, int len, TRAPS) {
return (void *) AllocateHeap(object_size(len) * HeapWordSize, "symbol"); int alloc_size = object_size(len)*HeapWordSize;
address res = (address) AllocateHeap(alloc_size, "symbol");
DEBUG_ONLY(set_allocation_type(res, ResourceObj::C_HEAP);)
return res;
}
void* Symbol::operator new(size_t sz, int len, Arena* arena, TRAPS) {
int alloc_size = object_size(len)*HeapWordSize;
address res = (address)arena->Amalloc(alloc_size);
DEBUG_ONLY(set_allocation_type(res, ResourceObj::ARENA);)
return res;
} }
// ------------------------------------------------------------------ // ------------------------------------------------------------------
...@@ -206,26 +216,5 @@ void Symbol::print_value_on(outputStream* st) const { ...@@ -206,26 +216,5 @@ void Symbol::print_value_on(outputStream* st) const {
} }
} }
void Symbol::increment_refcount() { // SymbolTable prints this in its statistics
// Only increment the refcount if positive. If negative either
// overflow has occurred or it is a permanent symbol in a read only
// shared archive.
if (_refcount >= 0) {
Atomic::inc(&_refcount);
NOT_PRODUCT(Atomic::inc(&_total_count);)
}
}
void Symbol::decrement_refcount() {
if (_refcount >= 0) {
Atomic::dec(&_refcount);
#ifdef ASSERT
if (_refcount < 0) {
print();
assert(false, "reference count underflow for symbol");
}
#endif
}
}
NOT_PRODUCT(int Symbol::_total_count = 0;) NOT_PRODUCT(int Symbol::_total_count = 0;)
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "utilities/utf8.hpp" #include "utilities/utf8.hpp"
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "runtime/atomic.hpp"
// A Symbol is a canonicalized string. // A Symbol is a canonicalized string.
// All Symbols reside in global SymbolTable and are reference counted. // All Symbols reside in global SymbolTable and are reference counted.
...@@ -95,7 +96,7 @@ ...@@ -95,7 +96,7 @@
// TempNewSymbol (passed in as a parameter) so the reference count on its symbol // TempNewSymbol (passed in as a parameter) so the reference count on its symbol
// will be decremented when it goes out of scope. // will be decremented when it goes out of scope.
class Symbol : public CHeapObj { class Symbol : public ResourceObj {
friend class VMStructs; friend class VMStructs;
friend class SymbolTable; friend class SymbolTable;
friend class MoveSymbols; friend class MoveSymbols;
...@@ -111,7 +112,7 @@ class Symbol : public CHeapObj { ...@@ -111,7 +112,7 @@ class Symbol : public CHeapObj {
}; };
static int object_size(int length) { static int object_size(int length) {
size_t size = heap_word_size(sizeof(Symbol) + length); size_t size = heap_word_size(sizeof(Symbol) + (length > 0 ? length - 1 : 0));
return align_object_size(size); return align_object_size(size);
} }
...@@ -120,28 +121,25 @@ class Symbol : public CHeapObj { ...@@ -120,28 +121,25 @@ class Symbol : public CHeapObj {
_body[index] = value; _body[index] = value;
} }
Symbol(const u1* name, int length); Symbol(const u1* name, int length, int refcount);
void* operator new(size_t size, int len); void* operator new(size_t size, int len, TRAPS);
void* operator new(size_t size, int len, Arena* arena, TRAPS);
public: public:
// Low-level access (used with care, since not GC-safe) // Low-level access (used with care, since not GC-safe)
const jbyte* base() const { return &_body[0]; } const jbyte* base() const { return &_body[0]; }
int object_size() { return object_size(utf8_length()); } int object_size() { return object_size(utf8_length()); }
// Returns the largest size symbol we can safely hold. // Returns the largest size symbol we can safely hold.
static int max_length() { static int max_length() { return max_symbol_length; }
return max_symbol_length;
}
int identity_hash() { int identity_hash() { return _identity_hash; }
return _identity_hash;
}
// Reference counting. See comments above this class for when to use. // Reference counting. See comments above this class for when to use.
int refcount() const { return _refcount; } int refcount() const { return _refcount; }
void increment_refcount(); inline void increment_refcount();
void decrement_refcount(); inline void decrement_refcount();
int byte_at(int index) const { int byte_at(int index) const {
assert(index >=0 && index < _length, "symbol index overflow"); assert(index >=0 && index < _length, "symbol index overflow");
...@@ -220,4 +218,26 @@ int Symbol::fast_compare(Symbol* other) const { ...@@ -220,4 +218,26 @@ int Symbol::fast_compare(Symbol* other) const {
return (((uintptr_t)this < (uintptr_t)other) ? -1 return (((uintptr_t)this < (uintptr_t)other) ? -1
: ((uintptr_t)this == (uintptr_t) other) ? 0 : 1); : ((uintptr_t)this == (uintptr_t) other) ? 0 : 1);
} }
inline void Symbol::increment_refcount() {
// Only increment the refcount if positive. If negative either
// overflow has occurred or it is a permanent symbol in a read only
// shared archive.
if (_refcount >= 0) {
Atomic::inc(&_refcount);
NOT_PRODUCT(Atomic::inc(&_total_count);)
}
}
inline void Symbol::decrement_refcount() {
if (_refcount >= 0) {
Atomic::dec(&_refcount);
#ifdef ASSERT
if (_refcount < 0) {
print();
assert(false, "reference count underflow for symbol");
}
#endif
}
}
#endif // SHARE_VM_OOPS_SYMBOL_HPP #endif // SHARE_VM_OOPS_SYMBOL_HPP
...@@ -55,7 +55,7 @@ klassOop typeArrayKlass::create_klass(BasicType type, int scale, ...@@ -55,7 +55,7 @@ klassOop typeArrayKlass::create_klass(BasicType type, int scale,
Symbol* sym = NULL; Symbol* sym = NULL;
if (name_str != NULL) { if (name_str != NULL) {
sym = SymbolTable::new_symbol(name_str, CHECK_NULL); sym = SymbolTable::new_permanent_symbol(name_str, CHECK_NULL);
} }
KlassHandle klassklass (THREAD, Universe::typeArrayKlassKlassObj()); KlassHandle klassklass (THREAD, Universe::typeArrayKlassKlassObj());
......
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "classfile/symbolTable.hpp"
#include "prims/jni.h"
#include "prims/whitebox.hpp"
#include "prims/wbtestmethods/parserTests.hpp"
#include "runtime/interfaceSupport.hpp"
#include "memory/oopFactory.hpp"
#include "services/diagnosticArgument.hpp"
#include "services/diagnosticFramework.hpp"
//There's no way of beforeahnd knowing an upper size
//Of the length of a string representation of
//the value of an argument.
#define VALUE_MAXLEN 256
// DiagnosticFramework test utility methods
/*
* The DiagnosticArgumentType class contains an enum that says which type
* this argument represents. (JLONG, BOOLEAN etc).
* This method Returns a char* representation of that enum value.
*/
static const char* lookup_diagnosticArgumentEnum(const char* field_name, oop object) {
Thread* THREAD = Thread::current();
const char* enum_sig = "Lsun/hotspot/parser/DiagnosticCommand$DiagnosticArgumentType;";
TempNewSymbol enumSigSymbol = SymbolTable::lookup(enum_sig, (int) strlen(enum_sig), THREAD);
int offset = WhiteBox::offset_for_field(field_name, object, enumSigSymbol);
oop enumOop = object->obj_field(offset);
const char* ret = WhiteBox::lookup_jstring("name", enumOop);
return ret;
}
/*
* Takes an oop to a DiagnosticArgumentType-instance and
* reads the fields from it. Fills an native DCmdParser with
* this info.
*/
static void fill_in_parser(DCmdParser* parser, oop argument)
{
const char* name = WhiteBox::lookup_jstring("name", argument);
const char* desc = WhiteBox::lookup_jstring("desc", argument);
const char* default_value = WhiteBox::lookup_jstring("defaultValue", argument);
bool mandatory = WhiteBox::lookup_bool("mandatory", argument);
const char* type = lookup_diagnosticArgumentEnum("type", argument);
if (strcmp(type, "STRING") == 0) {
DCmdArgument<char*>* argument = new DCmdArgument<char*>(
name, desc,
"STRING", mandatory, default_value);
parser->add_dcmd_option(argument);
} else if (strcmp(type, "NANOTIME") == 0) {
DCmdArgument<NanoTimeArgument>* argument = new DCmdArgument<NanoTimeArgument>(
name, desc,
"NANOTIME", mandatory, default_value);
parser->add_dcmd_option(argument);
} else if (strcmp(type, "JLONG") == 0) {
DCmdArgument<jlong>* argument = new DCmdArgument<jlong>(
name, desc,
"JLONG", mandatory, default_value);
parser->add_dcmd_option(argument);
} else if (strcmp(type, "BOOLEAN") == 0) {
DCmdArgument<bool>* argument = new DCmdArgument<bool>(
name, desc,
"BOOLEAN", mandatory, default_value);
parser->add_dcmd_option(argument);
} else if (strcmp(type, "MEMORYSIZE") == 0) {
DCmdArgument<MemorySizeArgument>* argument = new DCmdArgument<MemorySizeArgument>(
name, desc,
"MEMORY SIZE", mandatory, default_value);
parser->add_dcmd_option(argument);
} else if (strcmp(type, "STRINGARRAY") == 0) {
DCmdArgument<StringArrayArgument*>* argument = new DCmdArgument<StringArrayArgument*>(
name, desc,
"STRING SET", mandatory);
parser->add_dcmd_option(argument);
}
}
/*
* Will Fill in a java object array with alternating names of parsed command line options and
* the value that has been parsed for it:
* { name, value, name, value ... }
* This can then be checked from java.
*/
WB_ENTRY(jobjectArray, WB_ParseCommandLine(JNIEnv* env, jobject o, jstring j_cmdline, jobjectArray arguments))
ResourceMark rm;
DCmdParser parser;
const char* c_cmdline = java_lang_String::as_utf8_string(JNIHandles::resolve(j_cmdline));
objArrayOop argumentArray = objArrayOop(JNIHandles::resolve_non_null(arguments));
int length = argumentArray->length();
for (int i = 0; i < length; i++) {
oop argument_oop = argumentArray->obj_at(i);
fill_in_parser(&parser, argument_oop);
}
CmdLine cmdline(c_cmdline, strlen(c_cmdline), true);
parser.parse(&cmdline,',',CHECK_NULL);
klassOop k = SystemDictionary::Object_klass();
objArrayOop returnvalue_array = oopFactory::new_objArray(k, parser.num_arguments() * 2, CHECK_NULL);
GrowableArray<const char *>*parsedArgNames = parser.argument_name_array();
for (int i = 0; i < parser.num_arguments(); i++) {
oop parsedName = java_lang_String::create_oop_from_str(parsedArgNames->at(i), CHECK_NULL);
returnvalue_array->obj_at_put(i*2, parsedName);
GenDCmdArgument* arg = parser.lookup_dcmd_option(parsedArgNames->at(i), strlen(parsedArgNames->at(i)));
char buf[VALUE_MAXLEN];
arg->value_as_str(buf, sizeof(buf));
oop parsedValue = java_lang_String::create_oop_from_str(buf, CHECK_NULL);
returnvalue_array->obj_at_put(i*2+1, parsedValue);
}
return (jobjectArray) JNIHandles::make_local(returnvalue_array);
WB_END
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#ifndef SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H
#define SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H
#include "prims/jni.h"
#include "prims/whitebox.hpp"
WB_METHOD_DECLARE WB_ParseCommandLine(JNIEnv* env, jobject o, jstring args, jobjectArray arguments);
#endif //SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H
...@@ -24,11 +24,14 @@ ...@@ -24,11 +24,14 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "jni.h"
#include "memory/universe.hpp" #include "memory/universe.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "classfile/symbolTable.hpp"
#include "prims/whitebox.hpp" #include "prims/whitebox.hpp"
#include "prims/wbtestmethods/parserTests.hpp"
#include "runtime/interfaceSupport.hpp" #include "runtime/interfaceSupport.hpp"
#include "runtime/os.hpp" #include "runtime/os.hpp"
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
...@@ -41,13 +44,6 @@ ...@@ -41,13 +44,6 @@
bool WhiteBox::_used = false; bool WhiteBox::_used = false;
// Entry macro to transition from JNI to VM state.
#define WB_ENTRY(result_type, header) JNI_ENTRY(result_type, header)
#define WB_END JNI_END
// Definitions of functions exposed via Whitebox API
WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj)) WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
return (jlong)(void*)JNIHandles::resolve(obj); return (jlong)(void*)JNIHandles::resolve(obj);
WB_END WB_END
...@@ -81,11 +77,63 @@ WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o)) ...@@ -81,11 +77,63 @@ WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
WB_END WB_END
#endif // !SERIALGC #endif // !SERIALGC
//Some convenience methods to deal with objects from java
int WhiteBox::offset_for_field(const char* field_name, oop object,
Symbol* signature_symbol) {
assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid");
Thread* THREAD = Thread::current();
//Get the class of our object
klassOop arg_klass = object->klass();
//Turn it into an instance-klass
instanceKlass* ik = instanceKlass::cast(arg_klass);
//Create symbols to look for in the class
TempNewSymbol name_symbol = SymbolTable::lookup(field_name, (int) strlen(field_name),
THREAD);
//To be filled in with an offset of the field we're looking for
fieldDescriptor fd;
klassOop res = ik->find_field(name_symbol, signature_symbol, &fd);
if (res == NULL) {
tty->print_cr("Invalid layout of %s at %s", ik->external_name(),
name_symbol->as_C_string());
fatal("Invalid layout of preloaded class");
}
//fetch the field at the offset we've found
int dest_offset = fd.offset();
return dest_offset;
}
const char* WhiteBox::lookup_jstring(const char* field_name, oop object) {
int offset = offset_for_field(field_name, object,
vmSymbols::string_signature());
oop string = object->obj_field(offset);
const char* ret = java_lang_String::as_utf8_string(string);
return ret;
}
bool WhiteBox::lookup_bool(const char* field_name, oop object) {
int offset =
offset_for_field(field_name, object, vmSymbols::bool_signature());
bool ret = (object->bool_field(offset) == JNI_TRUE);
return ret;
}
#define CC (char*) #define CC (char*)
static JNINativeMethod methods[] = { static JNINativeMethod methods[] = {
{CC"getObjectAddress", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress }, {CC"getObjectAddress", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress },
{CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize }, {CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize },
{CC "parseCommandLine",
CC "(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
(void*) &WB_ParseCommandLine
},
#ifndef SERIALGC #ifndef SERIALGC
{CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark}, {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark},
{CC"g1IsHumongous", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous }, {CC"g1IsHumongous", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous },
......
...@@ -25,12 +25,29 @@ ...@@ -25,12 +25,29 @@
#ifndef SHARE_VM_PRIMS_WHITEBOX_HPP #ifndef SHARE_VM_PRIMS_WHITEBOX_HPP
#define SHARE_VM_PRIMS_WHITEBOX_HPP #define SHARE_VM_PRIMS_WHITEBOX_HPP
#include "prims/jni.h"
#include "memory/allocation.hpp"
#include "oops/oopsHierarchy.hpp"
// Entry macro to transition from JNI to VM state.
#define WB_ENTRY(result_type, header) JNI_ENTRY(result_type, header)
#define WB_END JNI_END
#define WB_METHOD_DECLARE extern "C" jobjectArray JNICALL
class WhiteBox : public AllStatic { class WhiteBox : public AllStatic {
private: private:
static bool _used; static bool _used;
public: public:
static bool used() { return _used; } static bool used() { return _used; }
static void set_used() { _used = true; } static void set_used() { _used = true; }
static int offset_for_field(const char* field_name, oop object,
Symbol* signature_symbol);
static const char* lookup_jstring(const char* field_name, oop object);
static bool lookup_bool(const char* field_name, oop object);
}; };
#endif // SHARE_VM_PRIMS_WHITEBOX_HPP #endif // SHARE_VM_PRIMS_WHITEBOX_HPP
...@@ -3807,7 +3807,7 @@ class CommandLineFlags { ...@@ -3807,7 +3807,7 @@ class CommandLineFlags {
product(uintx, SharedReadOnlySize, 10*M, \ product(uintx, SharedReadOnlySize, 10*M, \
"Size of read-only space in permanent generation (in bytes)") \ "Size of read-only space in permanent generation (in bytes)") \
\ \
product(uintx, SharedMiscDataSize, NOT_LP64(4*M) LP64_ONLY(5*M), \ product(uintx, SharedMiscDataSize, NOT_LP64(4*M) LP64_ONLY(5*M) NOT_PRODUCT(+1*M), \
"Size of the shared data area adjacent to the heap (in bytes)") \ "Size of the shared data area adjacent to the heap (in bytes)") \
\ \
product(uintx, SharedMiscCodeSize, 4*M, \ product(uintx, SharedMiscCodeSize, 4*M, \
......
...@@ -43,6 +43,47 @@ void GenDCmdArgument::read_value(const char* str, size_t len, TRAPS) { ...@@ -43,6 +43,47 @@ void GenDCmdArgument::read_value(const char* str, size_t len, TRAPS) {
set_is_set(true); set_is_set(true);
} }
void GenDCmdArgument::to_string(jlong l, char* buf, size_t len) {
jio_snprintf(buf, len, INT64_FORMAT, l);
}
void GenDCmdArgument::to_string(bool b, char* buf, size_t len) {
jio_snprintf(buf, len, b ? "true" : "false");
}
void GenDCmdArgument::to_string(NanoTimeArgument n, char* buf, size_t len) {
jio_snprintf(buf, len, INT64_FORMAT, n._nanotime);
}
void GenDCmdArgument::to_string(MemorySizeArgument m, char* buf, size_t len) {
jio_snprintf(buf, len, INT64_FORMAT, m._size);
}
void GenDCmdArgument::to_string(char* c, char* buf, size_t len) {
jio_snprintf(buf, len, "%s", c);
}
void GenDCmdArgument::to_string(StringArrayArgument* f, char* buf, size_t len) {
int length = f->array()->length();
size_t written = 0;
buf[0] = 0;
for (int i = 0; i < length; i++) {
char* next_str = f->array()->at(i);
size_t next_size = strlen(next_str);
//Check if there's room left to write next element
if (written + next_size > len) {
return;
}
//Actually write element
strcat(buf, next_str);
written += next_size;
//Check if there's room left for the comma
if (i < length-1 && len - written > 0) {
strcat(buf, ",");
}
}
}
template <> void DCmdArgument<jlong>::parse_value(const char* str, template <> void DCmdArgument<jlong>::parse_value(const char* str,
size_t len, TRAPS) { size_t len, TRAPS) {
if (str == NULL || sscanf(str, INT64_FORMAT, &_value) != 1) { if (str == NULL || sscanf(str, INT64_FORMAT, &_value) != 1) {
......
...@@ -110,12 +110,20 @@ public: ...@@ -110,12 +110,20 @@ public:
virtual void init_value(TRAPS) = 0; virtual void init_value(TRAPS) = 0;
virtual void reset(TRAPS) = 0; virtual void reset(TRAPS) = 0;
virtual void cleanup() = 0; virtual void cleanup() = 0;
virtual void value_as_str(char* buf, size_t len) = 0;
void set_next(GenDCmdArgument* arg) { void set_next(GenDCmdArgument* arg) {
_next = arg; _next = arg;
} }
GenDCmdArgument* next() { GenDCmdArgument* next() {
return _next; return _next;
} }
void to_string(jlong l, char* buf, size_t len);
void to_string(bool b, char* buf, size_t len);
void to_string(char* c, char* buf, size_t len);
void to_string(NanoTimeArgument n, char* buf, size_t len);
void to_string(MemorySizeArgument f, char* buf, size_t len);
void to_string(StringArrayArgument* s, char* buf, size_t len);
}; };
template <class ArgType> class DCmdArgument: public GenDCmdArgument { template <class ArgType> class DCmdArgument: public GenDCmdArgument {
...@@ -143,6 +151,7 @@ public: ...@@ -143,6 +151,7 @@ public:
void parse_value(const char* str, size_t len, TRAPS); void parse_value(const char* str, size_t len, TRAPS);
void init_value(TRAPS); void init_value(TRAPS);
void destroy_value(); void destroy_value();
void value_as_str(char *buf, size_t len) { return to_string(_value, buf, len);}
}; };
#endif /* SHARE_VM_SERVICES_DIAGNOSTICARGUMENT_HPP */ #endif /* SHARE_VM_SERVICES_DIAGNOSTICARGUMENT_HPP */
...@@ -163,8 +163,8 @@ static Handle createGcInfo(GCMemoryManager *gcManager, GCStatInfo *gcStatInfo,TR ...@@ -163,8 +163,8 @@ static Handle createGcInfo(GCMemoryManager *gcManager, GCStatInfo *gcStatInfo,TR
constructor_args.push_oop(gcInfo_instance); constructor_args.push_oop(gcInfo_instance);
constructor_args.push_oop(getGcInfoBuilder(gcManager,THREAD)); constructor_args.push_oop(getGcInfoBuilder(gcManager,THREAD));
constructor_args.push_long(gcStatInfo->gc_index()); constructor_args.push_long(gcStatInfo->gc_index());
constructor_args.push_long(gcStatInfo->start_time()); constructor_args.push_long(Management::ticks_to_ms(gcStatInfo->start_time()));
constructor_args.push_long(gcStatInfo->end_time()); constructor_args.push_long(Management::ticks_to_ms(gcStatInfo->end_time()));
constructor_args.push_oop(usage_before_gc_ah); constructor_args.push_oop(usage_before_gc_ah);
constructor_args.push_oop(usage_after_gc_ah); constructor_args.push_oop(usage_after_gc_ah);
constructor_args.push_oop(extra_array); constructor_args.push_oop(extra_array);
......
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -179,64 +179,6 @@ void BitMap::clear_large_range(idx_t beg, idx_t end) { ...@@ -179,64 +179,6 @@ void BitMap::clear_large_range(idx_t beg, idx_t end) {
clear_range_within_word(bit_index(end_full_word), end); clear_range_within_word(bit_index(end_full_word), end);
} }
void BitMap::mostly_disjoint_range_union(BitMap* from_bitmap,
idx_t from_start_index,
idx_t to_start_index,
size_t word_num) {
// Ensure that the parameters are correct.
// These shouldn't be that expensive to check, hence I left them as
// guarantees.
guarantee(from_bitmap->bit_in_word(from_start_index) == 0,
"it should be aligned on a word boundary");
guarantee(bit_in_word(to_start_index) == 0,
"it should be aligned on a word boundary");
guarantee(word_num >= 2, "word_num should be at least 2");
intptr_t* from = (intptr_t*) from_bitmap->word_addr(from_start_index);
intptr_t* to = (intptr_t*) word_addr(to_start_index);
if (*from != 0) {
// if it's 0, then there's no point in doing the CAS
while (true) {
intptr_t old_value = *to;
intptr_t new_value = old_value | *from;
intptr_t res = Atomic::cmpxchg_ptr(new_value, to, old_value);
if (res == old_value) break;
}
}
++from;
++to;
for (size_t i = 0; i < word_num - 2; ++i) {
if (*from != 0) {
// if it's 0, then there's no point in doing the CAS
assert(*to == 0, "nobody else should be writing here");
intptr_t new_value = *from;
*to = new_value;
}
++from;
++to;
}
if (*from != 0) {
// if it's 0, then there's no point in doing the CAS
while (true) {
intptr_t old_value = *to;
intptr_t new_value = old_value | *from;
intptr_t res = Atomic::cmpxchg_ptr(new_value, to, old_value);
if (res == old_value) break;
}
}
// the -1 is because we didn't advance them after the final CAS
assert(from ==
(intptr_t*) from_bitmap->word_addr(from_start_index) + word_num - 1,
"invariant");
assert(to == (intptr_t*) word_addr(to_start_index) + word_num - 1,
"invariant");
}
void BitMap::at_put(idx_t offset, bool value) { void BitMap::at_put(idx_t offset, bool value) {
if (value) { if (value) {
set_bit(offset); set_bit(offset);
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -192,31 +192,6 @@ class BitMap VALUE_OBJ_CLASS_SPEC { ...@@ -192,31 +192,6 @@ class BitMap VALUE_OBJ_CLASS_SPEC {
void par_set_range(idx_t beg, idx_t end, RangeSizeHint hint); void par_set_range(idx_t beg, idx_t end, RangeSizeHint hint);
void par_clear_range (idx_t beg, idx_t end, RangeSizeHint hint); void par_clear_range (idx_t beg, idx_t end, RangeSizeHint hint);
// It performs the union operation between subsets of equal length
// of two bitmaps (the target bitmap of the method and the
// from_bitmap) and stores the result to the target bitmap. The
// from_start_index represents the first bit index of the subrange
// of the from_bitmap. The to_start_index is the equivalent of the
// target bitmap. Both indexes should be word-aligned, i.e. they
// should correspond to the first bit on a bitmap word (it's up to
// the caller to ensure this; the method does check it). The length
// of the subset is specified with word_num and it is in number of
// bitmap words. The caller should ensure that this is at least 2
// (smaller ranges are not support to save extra checks). Again,
// this is checked in the method.
//
// Atomicity concerns: it is assumed that any contention on the
// target bitmap with other threads will happen on the first and
// last words; the ones in between will be "owned" exclusively by
// the calling thread and, in fact, they will already be 0. So, the
// method performs a CAS on the first word, copies the next
// word_num-2 words, and finally performs a CAS on the last word.
void mostly_disjoint_range_union(BitMap* from_bitmap,
idx_t from_start_index,
idx_t to_start_index,
size_t word_num);
// Clearing // Clearing
void clear_large(); void clear_large();
inline void clear(); inline void clear();
......
...@@ -685,6 +685,12 @@ void VMError::report(outputStream* st) { ...@@ -685,6 +685,12 @@ void VMError::report(outputStream* st) {
// extended (i.e., more detailed) version. // extended (i.e., more detailed) version.
Universe::print_on(st, true /* extended */); Universe::print_on(st, true /* extended */);
st->cr(); st->cr();
Universe::heap()->barrier_set()->print_on(st);
st->cr();
st->print_cr("Polling page: " INTPTR_FORMAT, os::get_polling_page());
st->cr();
} }
STEP(195, "(printing code cache information)" ) STEP(195, "(printing code cache information)" )
......
/*
* @test ParserTest
* @summary verify that whitebox functions can be linked and executed
* @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI ParserTest.java
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ParserTest
*/
import java.math.BigInteger;
import sun.hotspot.parser.DiagnosticCommand;
import sun.hotspot.parser.DiagnosticCommand.DiagnosticArgumentType;
import sun.hotspot.WhiteBox;
public class ParserTest {
WhiteBox wb;
public ParserTest() throws Exception {
wb = WhiteBox.getWhiteBox();
testNanoTime();
testJLong();
testBool();
testMemorySize();
}
public static void main(String... args) throws Exception {
new ParserTest();
}
public void testNanoTime() throws Exception {
String name = "name";
DiagnosticCommand arg = new DiagnosticCommand(name,
"desc", DiagnosticArgumentType.NANOTIME,
false, "0");
DiagnosticCommand[] args = {arg};
BigInteger bi = new BigInteger("7");
//These should work
parse(name, bi.toString(), name + "=7ns", args);
bi = bi.multiply(BigInteger.valueOf(1000));
parse(name, bi.toString(), name + "=7us", args);
bi = bi.multiply(BigInteger.valueOf(1000));
parse(name, bi.toString(), name + "=7ms", args);
bi = bi.multiply(BigInteger.valueOf(1000));
parse(name, bi.toString(), name + "=7s", args);
bi = bi.multiply(BigInteger.valueOf(60));
parse(name, bi.toString() , name + "=7m", args);
bi = bi.multiply(BigInteger.valueOf(60));
parse(name, bi.toString() , name + "=7h", args);
bi = bi.multiply(BigInteger.valueOf(24));
parse(name, bi.toString() , name + "=7d", args);
parse(name, "0", name + "=0", args);
shouldFail(name + "=7xs", args);
shouldFail(name + "=7mms", args);
shouldFail(name + "=7f", args);
//Currently, only value 0 is allowed without unit
shouldFail(name + "=7", args);
}
public void testJLong() throws Exception {
String name = "name";
DiagnosticCommand arg = new DiagnosticCommand(name,
"desc", DiagnosticArgumentType.JLONG,
false, "0");
DiagnosticCommand[] args = {arg};
wb.parseCommandLine(name + "=10", args);
parse(name, "10", name + "=10", args);
parse(name, "-5", name + "=-5", args);
//shouldFail(name + "=12m", args); <-- should fail, doesn't
}
public void testBool() throws Exception {
String name = "name";
DiagnosticCommand arg = new DiagnosticCommand(name,
"desc", DiagnosticArgumentType.BOOLEAN,
false, "false");
DiagnosticCommand[] args = {arg};
parse(name, "true", name + "=true", args);
parse(name, "false", name + "=false", args);
parse(name, "true", name, args);
//Empty commandline to parse, tests default value
//of the parameter "name"
parse(name, "false", "", args);
}
public void testMemorySize() throws Exception {
String name = "name";
String defaultValue = "1024";
DiagnosticCommand arg = new DiagnosticCommand(name,
"desc", DiagnosticArgumentType.MEMORYSIZE,
false, defaultValue);
DiagnosticCommand[] args = {arg};
BigInteger bi = new BigInteger("7");
parse(name, bi.toString(), name + "=7b", args);
bi = bi.multiply(BigInteger.valueOf(1024));
parse(name, bi.toString(), name + "=7k", args);
bi = bi.multiply(BigInteger.valueOf(1024));
parse(name, bi.toString(), name + "=7m", args);
bi = bi.multiply(BigInteger.valueOf(1024));
parse(name, bi.toString(), name + "=7g", args);
parse(name, defaultValue, "", args);
//shouldFail(name + "=7gg", args); <---- should fail, doesn't
//shouldFail(name + "=7t", args); <----- should fail, doesn't
}
public void parse(String searchName, String expectedValue,
String cmdLine, DiagnosticCommand[] argumentTypes) throws Exception {
//parseCommandLine will return an object array that looks like
//{<name of parsed object>, <of parsed object> ... }
Object[] res = wb.parseCommandLine(cmdLine, argumentTypes);
for (int i = 0; i < res.length-1; i+=2) {
String parsedName = (String) res[i];
if (searchName.equals(parsedName)) {
String parsedValue = (String) res[i+1];
if (expectedValue.equals(parsedValue)) {
return;
} else {
throw new Exception("Parsing of cmdline '" + cmdLine + "' failed!\n"
+ searchName + " parsed as " + parsedValue
+ "! Expected: " + expectedValue);
}
}
}
throw new Exception(searchName + " not found as a parsed Argument!");
}
private void shouldFail(String argument, DiagnosticCommand[] argumentTypes) throws Exception {
try {
wb.parseCommandLine(argument, argumentTypes);
throw new Exception("Parser accepted argument: " + argument);
} catch (IllegalArgumentException e) {
//expected
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册