Thu, 15 Mar 2012 13:37:13 +0100
7148488: Whitebox tests for the Diagnostic Framework Parser
Reviewed-by: brutisso, sla, mgerdin
1.1 --- a/make/bsd/makefiles/wb.make Tue Mar 20 16:46:39 2012 -0400 1.2 +++ b/make/bsd/makefiles/wb.make Thu Mar 15 13:37:13 2012 +0100 1.3 @@ -36,7 +36,7 @@ 1.4 $(patsubst %.java,%.class,$(WB_JAVA_SRCS))) 1.5 1.6 $(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR) 1.7 - $(REMOTE) $(COMPILE.JAVAC) -nowarn -d $(WB_JAVA_CLASSDIR) $< 1.8 + $(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $< 1.9 1.10 $(WB_JAR): $(WB_JAVA_CLASSES) 1.11 $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
2.1 --- a/make/linux/makefiles/wb.make Tue Mar 20 16:46:39 2012 -0400 2.2 +++ b/make/linux/makefiles/wb.make Thu Mar 15 13:37:13 2012 +0100 2.3 @@ -36,7 +36,7 @@ 2.4 $(patsubst %.java,%.class,$(WB_JAVA_SRCS))) 2.5 2.6 $(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR) 2.7 - $(REMOTE) $(COMPILE.JAVAC) -nowarn -d $(WB_JAVA_CLASSDIR) $< 2.8 + $(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $< 2.9 2.10 $(WB_JAR): $(WB_JAVA_CLASSES) 2.11 $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
3.1 --- a/make/solaris/makefiles/wb.make Tue Mar 20 16:46:39 2012 -0400 3.2 +++ b/make/solaris/makefiles/wb.make Thu Mar 15 13:37:13 2012 +0100 3.3 @@ -36,7 +36,7 @@ 3.4 $(patsubst %.java,%.class,$(WB_JAVA_SRCS))) 3.5 3.6 $(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR) 3.7 - $(REMOTE) $(COMPILE.JAVAC) -nowarn -d $(WB_JAVA_CLASSDIR) $< 3.8 + $(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $< 3.9 3.10 $(WB_JAR): $(WB_JAVA_CLASSES) 3.11 $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
4.1 --- a/make/windows/create_obj_files.sh Tue Mar 20 16:46:39 2012 -0400 4.2 +++ b/make/windows/create_obj_files.sh Thu Mar 15 13:37:13 2012 +0100 4.3 @@ -80,6 +80,8 @@ 4.4 BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr" 4.5 fi 4.6 4.7 +BASE_PATHS="${BASE_PATHS} ${COMMONSRC}/share/vm/prims/wbtestmethods" 4.8 + 4.9 CORE_PATHS="${BASE_PATHS}" 4.10 # shared is already in BASE_PATHS. Should add vm/memory but that one is also in BASE_PATHS. 4.11 if [ -d "${ALTSRC}/share/vm/gc_implementation" ]; then
5.1 --- a/make/windows/makefiles/projectcreator.make Tue Mar 20 16:46:39 2012 -0400 5.2 +++ b/make/windows/makefiles/projectcreator.make Thu Mar 15 13:37:13 2012 +0100 5.3 @@ -51,6 +51,7 @@ 5.4 -relativeInclude src\closed\cpu\$(Platform_arch)\vm \ 5.5 -relativeInclude src\share\vm \ 5.6 -relativeInclude src\share\vm\precompiled \ 5.7 + -relativeInclude src\share\vm\prims\wbtestmethods \ 5.8 -relativeInclude src\share\vm\prims \ 5.9 -relativeInclude src\os\windows\vm \ 5.10 -relativeInclude src\os_cpu\windows_$(Platform_arch)\vm \
6.1 --- a/make/windows/makefiles/vm.make Tue Mar 20 16:46:39 2012 -0400 6.2 +++ b/make/windows/makefiles/vm.make Thu Mar 15 13:37:13 2012 +0100 6.3 @@ -172,6 +172,7 @@ 6.4 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/memory 6.5 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/oops 6.6 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/prims 6.7 +VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/prims/wbtestmethods 6.8 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/runtime 6.9 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/services 6.10 VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/trace 6.11 @@ -269,6 +270,9 @@ 6.12 {$(COMMONSRC)\share\vm\prims}.cpp.obj:: 6.13 $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< 6.14 6.15 +{$(COMMONSRC)\share\vm\prims\wbtestmethods}.cpp.obj:: 6.16 + $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< 6.17 + 6.18 {$(COMMONSRC)\share\vm\runtime}.cpp.obj:: 6.19 $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< 6.20 6.21 @@ -349,6 +353,9 @@ 6.22 {$(ALTSRC)\share\vm\prims}.cpp.obj:: 6.23 $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< 6.24 6.25 +{$(ALTSRC)\share\vm\prims\wbtestmethods}.cpp.obj:: 6.26 + $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< 6.27 + 6.28 {$(ALTSRC)\share\vm\runtime}.cpp.obj:: 6.29 $(CXX) $(CXX_FLAGS) $(CXX_USE_PCH) /c $< 6.30
7.1 --- a/make/windows/makefiles/wb.make Tue Mar 20 16:46:39 2012 -0400 7.2 +++ b/make/windows/makefiles/wb.make Thu Mar 15 13:37:13 2012 +0100 7.3 @@ -40,7 +40,7 @@ 7.4 7.5 7.6 {$(WorkSpace)\src\share\tools\whitebox\sun\hotspot}.java.class:: 7.7 - $(COMPILE_JAVAC) -d $(WB_CLASSES) $< 7.8 + $(COMPILE_JAVAC) -sourcepath $(WBSRCDIR) -d $(WB_CLASSES) $< 7.9 7.10 $(WB_JAR): wb_java_srcs 7.11 $(RUN_JAR) cf $@ -C $(WB_CLASSES) .
8.1 --- a/src/share/tools/whitebox/sun/hotspot/WhiteBox.java Tue Mar 20 16:46:39 2012 -0400 8.2 +++ b/src/share/tools/whitebox/sun/hotspot/WhiteBox.java Thu Mar 15 13:37:13 2012 +0100 8.3 @@ -24,6 +24,7 @@ 8.4 8.5 package sun.hotspot; 8.6 import java.security.BasicPermission; 8.7 +import sun.hotspot.parser.DiagnosticCommand; 8.8 8.9 public class WhiteBox { 8.10 8.11 @@ -67,4 +68,5 @@ 8.12 public native boolean g1IsHumongous(Object o); 8.13 public native long g1NumFreeRegions(); 8.14 public native int g1RegionSize(); 8.15 + public native Object[] parseCommandLine(String commandline, DiagnosticCommand[] args); 8.16 }
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/src/share/tools/whitebox/sun/hotspot/parser/DiagnosticCommand.java Thu Mar 15 13:37:13 2012 +0100 9.3 @@ -0,0 +1,43 @@ 9.4 +package sun.hotspot.parser; 9.5 + 9.6 +public class DiagnosticCommand { 9.7 + 9.8 + public enum DiagnosticArgumentType { 9.9 + JLONG, BOOLEAN, STRING, NANOTIME, STRINGARRAY, MEMORYSIZE 9.10 + } 9.11 + 9.12 + private String name; 9.13 + private String desc; 9.14 + private DiagnosticArgumentType type; 9.15 + private boolean mandatory; 9.16 + private String defaultValue; 9.17 + 9.18 + public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type, 9.19 + boolean mandatory, String defaultValue) { 9.20 + this.name = name; 9.21 + this.desc = desc; 9.22 + this.type = type; 9.23 + this.mandatory = mandatory; 9.24 + this.defaultValue = defaultValue; 9.25 + } 9.26 + 9.27 + public String getName() { 9.28 + return name; 9.29 + } 9.30 + 9.31 + public String getDesc() { 9.32 + return desc; 9.33 + } 9.34 + 9.35 + public DiagnosticArgumentType getType() { 9.36 + return type; 9.37 + } 9.38 + 9.39 + public boolean isMandatory() { 9.40 + return mandatory; 9.41 + } 9.42 + 9.43 + public String getDefaultValue() { 9.44 + return defaultValue; 9.45 + } 9.46 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/src/share/vm/prims/wbtestmethods/parserTests.cpp Thu Mar 15 13:37:13 2012 +0100 10.3 @@ -0,0 +1,148 @@ 10.4 +/* 10.5 + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 10.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10.7 + * 10.8 + * This code is free software; you can redistribute it and/or modify it 10.9 + * under the terms of the GNU General Public License version 2 only, as 10.10 + * published by the Free Software Foundation. 10.11 + * 10.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 10.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 10.15 + * version 2 for more details (a copy is included in the LICENSE file that 10.16 + * accompanied this code). 10.17 + * 10.18 + * You should have received a copy of the GNU General Public License version 10.19 + * 2 along with this work; if not, write to the Free Software Foundation, 10.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 10.21 + * 10.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 10.23 + * or visit www.oracle.com if you need additional information or have any 10.24 + * questions. 10.25 + * 10.26 + */ 10.27 + 10.28 +#include "precompiled.hpp" 10.29 + 10.30 +#include "classfile/symbolTable.hpp" 10.31 + 10.32 +#include "prims/jni.h" 10.33 +#include "prims/whitebox.hpp" 10.34 +#include "prims/wbtestmethods/parserTests.hpp" 10.35 +#include "runtime/interfaceSupport.hpp" 10.36 + 10.37 +#include "memory/oopFactory.hpp" 10.38 + 10.39 +#include "services/diagnosticArgument.hpp" 10.40 +#include "services/diagnosticFramework.hpp" 10.41 + 10.42 +//There's no way of beforeahnd knowing an upper size 10.43 +//Of the length of a string representation of 10.44 +//the value of an argument. 10.45 +#define VALUE_MAXLEN 256 10.46 + 10.47 +// DiagnosticFramework test utility methods 10.48 + 10.49 +/* 10.50 + * The DiagnosticArgumentType class contains an enum that says which type 10.51 + * this argument represents. (JLONG, BOOLEAN etc). 10.52 + * This method Returns a char* representation of that enum value. 10.53 + */ 10.54 +static const char* lookup_diagnosticArgumentEnum(const char* field_name, oop object) { 10.55 + Thread* THREAD = Thread::current(); 10.56 + const char* enum_sig = "Lsun/hotspot/parser/DiagnosticCommand$DiagnosticArgumentType;"; 10.57 + TempNewSymbol enumSigSymbol = SymbolTable::lookup(enum_sig, (int) strlen(enum_sig), THREAD); 10.58 + int offset = WhiteBox::offset_for_field(field_name, object, enumSigSymbol); 10.59 + oop enumOop = object->obj_field(offset); 10.60 + 10.61 + const char* ret = WhiteBox::lookup_jstring("name", enumOop); 10.62 + return ret; 10.63 +} 10.64 + 10.65 +/* 10.66 + * Takes an oop to a DiagnosticArgumentType-instance and 10.67 + * reads the fields from it. Fills an native DCmdParser with 10.68 + * this info. 10.69 + */ 10.70 +static void fill_in_parser(DCmdParser* parser, oop argument) 10.71 +{ 10.72 + const char* name = WhiteBox::lookup_jstring("name", argument); 10.73 + const char* desc = WhiteBox::lookup_jstring("desc", argument); 10.74 + const char* default_value = WhiteBox::lookup_jstring("defaultValue", argument); 10.75 + bool mandatory = WhiteBox::lookup_bool("mandatory", argument); 10.76 + const char* type = lookup_diagnosticArgumentEnum("type", argument); 10.77 + 10.78 + if (strcmp(type, "STRING") == 0) { 10.79 + DCmdArgument<char*>* argument = new DCmdArgument<char*>( 10.80 + name, desc, 10.81 + "STRING", mandatory, default_value); 10.82 + parser->add_dcmd_option(argument); 10.83 + } else if (strcmp(type, "NANOTIME") == 0) { 10.84 + DCmdArgument<NanoTimeArgument>* argument = new DCmdArgument<NanoTimeArgument>( 10.85 + name, desc, 10.86 + "NANOTIME", mandatory, default_value); 10.87 + parser->add_dcmd_option(argument); 10.88 + } else if (strcmp(type, "JLONG") == 0) { 10.89 + DCmdArgument<jlong>* argument = new DCmdArgument<jlong>( 10.90 + name, desc, 10.91 + "JLONG", mandatory, default_value); 10.92 + parser->add_dcmd_option(argument); 10.93 + } else if (strcmp(type, "BOOLEAN") == 0) { 10.94 + DCmdArgument<bool>* argument = new DCmdArgument<bool>( 10.95 + name, desc, 10.96 + "BOOLEAN", mandatory, default_value); 10.97 + parser->add_dcmd_option(argument); 10.98 + } else if (strcmp(type, "MEMORYSIZE") == 0) { 10.99 + DCmdArgument<MemorySizeArgument>* argument = new DCmdArgument<MemorySizeArgument>( 10.100 + name, desc, 10.101 + "MEMORY SIZE", mandatory, default_value); 10.102 + parser->add_dcmd_option(argument); 10.103 + } else if (strcmp(type, "STRINGARRAY") == 0) { 10.104 + DCmdArgument<StringArrayArgument*>* argument = new DCmdArgument<StringArrayArgument*>( 10.105 + name, desc, 10.106 + "STRING SET", mandatory); 10.107 + parser->add_dcmd_option(argument); 10.108 + } 10.109 +} 10.110 + 10.111 +/* 10.112 + * Will Fill in a java object array with alternating names of parsed command line options and 10.113 + * the value that has been parsed for it: 10.114 + * { name, value, name, value ... } 10.115 + * This can then be checked from java. 10.116 + */ 10.117 +WB_ENTRY(jobjectArray, WB_ParseCommandLine(JNIEnv* env, jobject o, jstring j_cmdline, jobjectArray arguments)) 10.118 + ResourceMark rm; 10.119 + DCmdParser parser; 10.120 + 10.121 + const char* c_cmdline = java_lang_String::as_utf8_string(JNIHandles::resolve(j_cmdline)); 10.122 + objArrayOop argumentArray = objArrayOop(JNIHandles::resolve_non_null(arguments)); 10.123 + 10.124 + int length = argumentArray->length(); 10.125 + 10.126 + for (int i = 0; i < length; i++) { 10.127 + oop argument_oop = argumentArray->obj_at(i); 10.128 + fill_in_parser(&parser, argument_oop); 10.129 + } 10.130 + 10.131 + CmdLine cmdline(c_cmdline, strlen(c_cmdline), true); 10.132 + parser.parse(&cmdline,',',CHECK_NULL); 10.133 + 10.134 + klassOop k = SystemDictionary::Object_klass(); 10.135 + objArrayOop returnvalue_array = oopFactory::new_objArray(k, parser.num_arguments() * 2, CHECK_NULL); 10.136 + 10.137 + GrowableArray<const char *>*parsedArgNames = parser.argument_name_array(); 10.138 + 10.139 + for (int i = 0; i < parser.num_arguments(); i++) { 10.140 + oop parsedName = java_lang_String::create_oop_from_str(parsedArgNames->at(i), CHECK_NULL); 10.141 + returnvalue_array->obj_at_put(i*2, parsedName); 10.142 + GenDCmdArgument* arg = parser.lookup_dcmd_option(parsedArgNames->at(i), strlen(parsedArgNames->at(i))); 10.143 + char buf[VALUE_MAXLEN]; 10.144 + arg->value_as_str(buf, sizeof(buf)); 10.145 + oop parsedValue = java_lang_String::create_oop_from_str(buf, CHECK_NULL); 10.146 + returnvalue_array->obj_at_put(i*2+1, parsedValue); 10.147 + } 10.148 + 10.149 + return (jobjectArray) JNIHandles::make_local(returnvalue_array); 10.150 + 10.151 +WB_END
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/src/share/vm/prims/wbtestmethods/parserTests.hpp Thu Mar 15 13:37:13 2012 +0100 11.3 @@ -0,0 +1,32 @@ 11.4 +/* 11.5 + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 11.7 + * 11.8 + * This code is free software; you can redistribute it and/or modify it 11.9 + * under the terms of the GNU General Public License version 2 only, as 11.10 + * published by the Free Software Foundation. 11.11 + * 11.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 11.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11.15 + * version 2 for more details (a copy is included in the LICENSE file that 11.16 + * accompanied this code). 11.17 + * 11.18 + * You should have received a copy of the GNU General Public License version 11.19 + * 2 along with this work; if not, write to the Free Software Foundation, 11.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 11.21 + * 11.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 11.23 + * or visit www.oracle.com if you need additional information or have any 11.24 + * questions. 11.25 + */ 11.26 + 11.27 +#ifndef SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H 11.28 +#define SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H 11.29 + 11.30 +#include "prims/jni.h" 11.31 +#include "prims/whitebox.hpp" 11.32 + 11.33 +WB_METHOD_DECLARE WB_ParseCommandLine(JNIEnv* env, jobject o, jstring args, jobjectArray arguments); 11.34 + 11.35 +#endif //SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H
12.1 --- a/src/share/vm/prims/whitebox.cpp Tue Mar 20 16:46:39 2012 -0400 12.2 +++ b/src/share/vm/prims/whitebox.cpp Thu Mar 15 13:37:13 2012 +0100 12.3 @@ -24,11 +24,14 @@ 12.4 12.5 #include "precompiled.hpp" 12.6 12.7 -#include "jni.h" 12.8 - 12.9 #include "memory/universe.hpp" 12.10 #include "oops/oop.inline.hpp" 12.11 + 12.12 +#include "classfile/symbolTable.hpp" 12.13 + 12.14 #include "prims/whitebox.hpp" 12.15 +#include "prims/wbtestmethods/parserTests.hpp" 12.16 + 12.17 #include "runtime/interfaceSupport.hpp" 12.18 #include "runtime/os.hpp" 12.19 #include "utilities/debug.hpp" 12.20 @@ -41,13 +44,6 @@ 12.21 12.22 bool WhiteBox::_used = false; 12.23 12.24 -// Entry macro to transition from JNI to VM state. 12.25 - 12.26 -#define WB_ENTRY(result_type, header) JNI_ENTRY(result_type, header) 12.27 -#define WB_END JNI_END 12.28 - 12.29 -// Definitions of functions exposed via Whitebox API 12.30 - 12.31 WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj)) 12.32 return (jlong)(void*)JNIHandles::resolve(obj); 12.33 WB_END 12.34 @@ -81,11 +77,63 @@ 12.35 WB_END 12.36 #endif // !SERIALGC 12.37 12.38 +//Some convenience methods to deal with objects from java 12.39 +int WhiteBox::offset_for_field(const char* field_name, oop object, 12.40 + Symbol* signature_symbol) { 12.41 + assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid"); 12.42 + Thread* THREAD = Thread::current(); 12.43 + 12.44 + //Get the class of our object 12.45 + klassOop arg_klass = object->klass(); 12.46 + //Turn it into an instance-klass 12.47 + instanceKlass* ik = instanceKlass::cast(arg_klass); 12.48 + 12.49 + //Create symbols to look for in the class 12.50 + TempNewSymbol name_symbol = SymbolTable::lookup(field_name, (int) strlen(field_name), 12.51 + THREAD); 12.52 + 12.53 + //To be filled in with an offset of the field we're looking for 12.54 + fieldDescriptor fd; 12.55 + 12.56 + klassOop res = ik->find_field(name_symbol, signature_symbol, &fd); 12.57 + if (res == NULL) { 12.58 + tty->print_cr("Invalid layout of %s at %s", ik->external_name(), 12.59 + name_symbol->as_C_string()); 12.60 + fatal("Invalid layout of preloaded class"); 12.61 + } 12.62 + 12.63 + //fetch the field at the offset we've found 12.64 + int dest_offset = fd.offset(); 12.65 + 12.66 + return dest_offset; 12.67 +} 12.68 + 12.69 + 12.70 +const char* WhiteBox::lookup_jstring(const char* field_name, oop object) { 12.71 + int offset = offset_for_field(field_name, object, 12.72 + vmSymbols::string_signature()); 12.73 + oop string = object->obj_field(offset); 12.74 + const char* ret = java_lang_String::as_utf8_string(string); 12.75 + return ret; 12.76 +} 12.77 + 12.78 +bool WhiteBox::lookup_bool(const char* field_name, oop object) { 12.79 + int offset = 12.80 + offset_for_field(field_name, object, vmSymbols::bool_signature()); 12.81 + bool ret = (object->bool_field(offset) == JNI_TRUE); 12.82 + return ret; 12.83 +} 12.84 + 12.85 + 12.86 #define CC (char*) 12.87 12.88 static JNINativeMethod methods[] = { 12.89 {CC"getObjectAddress", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress }, 12.90 {CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize }, 12.91 + {CC "parseCommandLine", 12.92 + CC "(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;", 12.93 + (void*) &WB_ParseCommandLine 12.94 + }, 12.95 #ifndef SERIALGC 12.96 {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark}, 12.97 {CC"g1IsHumongous", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous },
13.1 --- a/src/share/vm/prims/whitebox.hpp Tue Mar 20 16:46:39 2012 -0400 13.2 +++ b/src/share/vm/prims/whitebox.hpp Thu Mar 15 13:37:13 2012 +0100 13.3 @@ -25,12 +25,29 @@ 13.4 #ifndef SHARE_VM_PRIMS_WHITEBOX_HPP 13.5 #define SHARE_VM_PRIMS_WHITEBOX_HPP 13.6 13.7 +#include "prims/jni.h" 13.8 + 13.9 +#include "memory/allocation.hpp" 13.10 +#include "oops/oopsHierarchy.hpp" 13.11 + 13.12 +// Entry macro to transition from JNI to VM state. 13.13 + 13.14 +#define WB_ENTRY(result_type, header) JNI_ENTRY(result_type, header) 13.15 +#define WB_END JNI_END 13.16 +#define WB_METHOD_DECLARE extern "C" jobjectArray JNICALL 13.17 + 13.18 class WhiteBox : public AllStatic { 13.19 private: 13.20 static bool _used; 13.21 public: 13.22 static bool used() { return _used; } 13.23 static void set_used() { _used = true; } 13.24 + static int offset_for_field(const char* field_name, oop object, 13.25 + Symbol* signature_symbol); 13.26 + static const char* lookup_jstring(const char* field_name, oop object); 13.27 + static bool lookup_bool(const char* field_name, oop object); 13.28 }; 13.29 13.30 + 13.31 + 13.32 #endif // SHARE_VM_PRIMS_WHITEBOX_HPP
14.1 --- a/src/share/vm/services/diagnosticArgument.cpp Tue Mar 20 16:46:39 2012 -0400 14.2 +++ b/src/share/vm/services/diagnosticArgument.cpp Thu Mar 15 13:37:13 2012 +0100 14.3 @@ -43,6 +43,47 @@ 14.4 set_is_set(true); 14.5 } 14.6 14.7 +void GenDCmdArgument::to_string(jlong l, char* buf, size_t len) { 14.8 + jio_snprintf(buf, len, INT64_FORMAT, l); 14.9 +} 14.10 + 14.11 +void GenDCmdArgument::to_string(bool b, char* buf, size_t len) { 14.12 + jio_snprintf(buf, len, b ? "true" : "false"); 14.13 +} 14.14 + 14.15 +void GenDCmdArgument::to_string(NanoTimeArgument n, char* buf, size_t len) { 14.16 + jio_snprintf(buf, len, INT64_FORMAT, n._nanotime); 14.17 +} 14.18 + 14.19 +void GenDCmdArgument::to_string(MemorySizeArgument m, char* buf, size_t len) { 14.20 + jio_snprintf(buf, len, INT64_FORMAT, m._size); 14.21 +} 14.22 + 14.23 +void GenDCmdArgument::to_string(char* c, char* buf, size_t len) { 14.24 + jio_snprintf(buf, len, "%s", c); 14.25 +} 14.26 + 14.27 +void GenDCmdArgument::to_string(StringArrayArgument* f, char* buf, size_t len) { 14.28 + int length = f->array()->length(); 14.29 + size_t written = 0; 14.30 + buf[0] = 0; 14.31 + for (int i = 0; i < length; i++) { 14.32 + char* next_str = f->array()->at(i); 14.33 + size_t next_size = strlen(next_str); 14.34 + //Check if there's room left to write next element 14.35 + if (written + next_size > len) { 14.36 + return; 14.37 + } 14.38 + //Actually write element 14.39 + strcat(buf, next_str); 14.40 + written += next_size; 14.41 + //Check if there's room left for the comma 14.42 + if (i < length-1 && len - written > 0) { 14.43 + strcat(buf, ","); 14.44 + } 14.45 + } 14.46 +} 14.47 + 14.48 template <> void DCmdArgument<jlong>::parse_value(const char* str, 14.49 size_t len, TRAPS) { 14.50 if (str == NULL || sscanf(str, INT64_FORMAT, &_value) != 1) {
15.1 --- a/src/share/vm/services/diagnosticArgument.hpp Tue Mar 20 16:46:39 2012 -0400 15.2 +++ b/src/share/vm/services/diagnosticArgument.hpp Thu Mar 15 13:37:13 2012 +0100 15.3 @@ -110,12 +110,20 @@ 15.4 virtual void init_value(TRAPS) = 0; 15.5 virtual void reset(TRAPS) = 0; 15.6 virtual void cleanup() = 0; 15.7 + virtual void value_as_str(char* buf, size_t len) = 0; 15.8 void set_next(GenDCmdArgument* arg) { 15.9 _next = arg; 15.10 } 15.11 GenDCmdArgument* next() { 15.12 return _next; 15.13 } 15.14 + 15.15 + void to_string(jlong l, char* buf, size_t len); 15.16 + void to_string(bool b, char* buf, size_t len); 15.17 + void to_string(char* c, char* buf, size_t len); 15.18 + void to_string(NanoTimeArgument n, char* buf, size_t len); 15.19 + void to_string(MemorySizeArgument f, char* buf, size_t len); 15.20 + void to_string(StringArrayArgument* s, char* buf, size_t len); 15.21 }; 15.22 15.23 template <class ArgType> class DCmdArgument: public GenDCmdArgument { 15.24 @@ -143,6 +151,7 @@ 15.25 void parse_value(const char* str, size_t len, TRAPS); 15.26 void init_value(TRAPS); 15.27 void destroy_value(); 15.28 + void value_as_str(char *buf, size_t len) { return to_string(_value, buf, len);} 15.29 }; 15.30 15.31 #endif /* SHARE_VM_SERVICES_DIAGNOSTICARGUMENT_HPP */
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/test/serviceability/ParserTest.java Thu Mar 15 13:37:13 2012 +0100 16.3 @@ -0,0 +1,152 @@ 16.4 +/* 16.5 + * @test ParserTest 16.6 + * @summary verify that whitebox functions can be linked and executed 16.7 + * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI ParserTest.java 16.8 + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ParserTest 16.9 + */ 16.10 + 16.11 +import java.math.BigInteger; 16.12 + 16.13 +import sun.hotspot.parser.DiagnosticCommand; 16.14 +import sun.hotspot.parser.DiagnosticCommand.DiagnosticArgumentType; 16.15 +import sun.hotspot.WhiteBox; 16.16 + 16.17 +public class ParserTest { 16.18 + WhiteBox wb; 16.19 + 16.20 + public ParserTest() throws Exception { 16.21 + wb = WhiteBox.getWhiteBox(); 16.22 + 16.23 + testNanoTime(); 16.24 + testJLong(); 16.25 + testBool(); 16.26 + testMemorySize(); 16.27 + } 16.28 + 16.29 + public static void main(String... args) throws Exception { 16.30 + new ParserTest(); 16.31 + } 16.32 + 16.33 + public void testNanoTime() throws Exception { 16.34 + String name = "name"; 16.35 + DiagnosticCommand arg = new DiagnosticCommand(name, 16.36 + "desc", DiagnosticArgumentType.NANOTIME, 16.37 + false, "0"); 16.38 + DiagnosticCommand[] args = {arg}; 16.39 + 16.40 + BigInteger bi = new BigInteger("7"); 16.41 + //These should work 16.42 + parse(name, bi.toString(), name + "=7ns", args); 16.43 + 16.44 + bi = bi.multiply(BigInteger.valueOf(1000)); 16.45 + parse(name, bi.toString(), name + "=7us", args); 16.46 + 16.47 + bi = bi.multiply(BigInteger.valueOf(1000)); 16.48 + parse(name, bi.toString(), name + "=7ms", args); 16.49 + 16.50 + bi = bi.multiply(BigInteger.valueOf(1000)); 16.51 + parse(name, bi.toString(), name + "=7s", args); 16.52 + 16.53 + bi = bi.multiply(BigInteger.valueOf(60)); 16.54 + parse(name, bi.toString() , name + "=7m", args); 16.55 + 16.56 + bi = bi.multiply(BigInteger.valueOf(60)); 16.57 + parse(name, bi.toString() , name + "=7h", args); 16.58 + 16.59 + bi = bi.multiply(BigInteger.valueOf(24)); 16.60 + parse(name, bi.toString() , name + "=7d", args); 16.61 + 16.62 + parse(name, "0", name + "=0", args); 16.63 + 16.64 + shouldFail(name + "=7xs", args); 16.65 + shouldFail(name + "=7mms", args); 16.66 + shouldFail(name + "=7f", args); 16.67 + //Currently, only value 0 is allowed without unit 16.68 + shouldFail(name + "=7", args); 16.69 + } 16.70 + 16.71 + public void testJLong() throws Exception { 16.72 + String name = "name"; 16.73 + DiagnosticCommand arg = new DiagnosticCommand(name, 16.74 + "desc", DiagnosticArgumentType.JLONG, 16.75 + false, "0"); 16.76 + DiagnosticCommand[] args = {arg}; 16.77 + 16.78 + wb.parseCommandLine(name + "=10", args); 16.79 + parse(name, "10", name + "=10", args); 16.80 + parse(name, "-5", name + "=-5", args); 16.81 + 16.82 + //shouldFail(name + "=12m", args); <-- should fail, doesn't 16.83 + } 16.84 + 16.85 + public void testBool() throws Exception { 16.86 + String name = "name"; 16.87 + DiagnosticCommand arg = new DiagnosticCommand(name, 16.88 + "desc", DiagnosticArgumentType.BOOLEAN, 16.89 + false, "false"); 16.90 + DiagnosticCommand[] args = {arg}; 16.91 + 16.92 + parse(name, "true", name + "=true", args); 16.93 + parse(name, "false", name + "=false", args); 16.94 + parse(name, "true", name, args); 16.95 + 16.96 + //Empty commandline to parse, tests default value 16.97 + //of the parameter "name" 16.98 + parse(name, "false", "", args); 16.99 + } 16.100 + 16.101 + public void testMemorySize() throws Exception { 16.102 + String name = "name"; 16.103 + String defaultValue = "1024"; 16.104 + DiagnosticCommand arg = new DiagnosticCommand(name, 16.105 + "desc", DiagnosticArgumentType.MEMORYSIZE, 16.106 + false, defaultValue); 16.107 + DiagnosticCommand[] args = {arg}; 16.108 + 16.109 + BigInteger bi = new BigInteger("7"); 16.110 + parse(name, bi.toString(), name + "=7b", args); 16.111 + 16.112 + bi = bi.multiply(BigInteger.valueOf(1024)); 16.113 + parse(name, bi.toString(), name + "=7k", args); 16.114 + 16.115 + bi = bi.multiply(BigInteger.valueOf(1024)); 16.116 + parse(name, bi.toString(), name + "=7m", args); 16.117 + 16.118 + bi = bi.multiply(BigInteger.valueOf(1024)); 16.119 + parse(name, bi.toString(), name + "=7g", args); 16.120 + parse(name, defaultValue, "", args); 16.121 + 16.122 + //shouldFail(name + "=7gg", args); <---- should fail, doesn't 16.123 + //shouldFail(name + "=7t", args); <----- should fail, doesn't 16.124 + } 16.125 + 16.126 + public void parse(String searchName, String expectedValue, 16.127 + String cmdLine, DiagnosticCommand[] argumentTypes) throws Exception { 16.128 + //parseCommandLine will return an object array that looks like 16.129 + //{<name of parsed object>, <of parsed object> ... } 16.130 + Object[] res = wb.parseCommandLine(cmdLine, argumentTypes); 16.131 + for (int i = 0; i < res.length-1; i+=2) { 16.132 + String parsedName = (String) res[i]; 16.133 + if (searchName.equals(parsedName)) { 16.134 + String parsedValue = (String) res[i+1]; 16.135 + if (expectedValue.equals(parsedValue)) { 16.136 + return; 16.137 + } else { 16.138 + throw new Exception("Parsing of cmdline '" + cmdLine + "' failed!\n" 16.139 + + searchName + " parsed as " + parsedValue 16.140 + + "! Expected: " + expectedValue); 16.141 + } 16.142 + } 16.143 + } 16.144 + throw new Exception(searchName + " not found as a parsed Argument!"); 16.145 + } 16.146 + 16.147 + private void shouldFail(String argument, DiagnosticCommand[] argumentTypes) throws Exception { 16.148 + try { 16.149 + wb.parseCommandLine(argument, argumentTypes); 16.150 + throw new Exception("Parser accepted argument: " + argument); 16.151 + } catch (IllegalArgumentException e) { 16.152 + //expected 16.153 + } 16.154 + } 16.155 +}