7148488: Whitebox tests for the Diagnostic Framework Parser

Thu, 15 Mar 2012 13:37:13 +0100

author
nloodin
date
Thu, 15 Mar 2012 13:37:13 +0100
changeset 3681
51612f0c0a79
parent 3650
80fe40862b02
child 3682
fc9d8850ab8b

7148488: Whitebox tests for the Diagnostic Framework Parser
Reviewed-by: brutisso, sla, mgerdin

make/bsd/makefiles/wb.make file | annotate | diff | comparison | revisions
make/linux/makefiles/wb.make file | annotate | diff | comparison | revisions
make/solaris/makefiles/wb.make file | annotate | diff | comparison | revisions
make/windows/create_obj_files.sh file | annotate | diff | comparison | revisions
make/windows/makefiles/projectcreator.make file | annotate | diff | comparison | revisions
make/windows/makefiles/vm.make file | annotate | diff | comparison | revisions
make/windows/makefiles/wb.make file | annotate | diff | comparison | revisions
src/share/tools/whitebox/sun/hotspot/WhiteBox.java file | annotate | diff | comparison | revisions
src/share/tools/whitebox/sun/hotspot/parser/DiagnosticCommand.java file | annotate | diff | comparison | revisions
src/share/vm/prims/wbtestmethods/parserTests.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/wbtestmethods/parserTests.hpp file | annotate | diff | comparison | revisions
src/share/vm/prims/whitebox.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/whitebox.hpp file | annotate | diff | comparison | revisions
src/share/vm/services/diagnosticArgument.cpp file | annotate | diff | comparison | revisions
src/share/vm/services/diagnosticArgument.hpp file | annotate | diff | comparison | revisions
test/serviceability/ParserTest.java file | annotate | diff | comparison | revisions
     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 +}

mercurial