# HG changeset patch # User jbachorik # Date 1417188837 -3600 # Node ID 4193852820445f70021dcc61ed9d402489d86b9d # Parent c12b0a02beee325a4a1d204beb80b3623e5ec365 8065783: DCMD parser fails to recognize one character argument when it's positioned last Reviewed-by: sla, egahlin, fparain diff -r c12b0a02beee -r 419385282044 hotspot/src/share/vm/prims/wbtestmethods/parserTests.cpp --- a/hotspot/src/share/vm/prims/wbtestmethods/parserTests.cpp Wed Nov 26 19:46:33 2014 +0000 +++ b/hotspot/src/share/vm/prims/wbtestmethods/parserTests.cpp Fri Nov 28 16:33:57 2014 +0100 @@ -70,38 +70,63 @@ const char* desc = WhiteBox::lookup_jstring("desc", argument); const char* default_value = WhiteBox::lookup_jstring("defaultValue", argument); bool mandatory = WhiteBox::lookup_bool("mandatory", argument); + bool isarg = WhiteBox::lookup_bool("argument", argument); const char* type = lookup_diagnosticArgumentEnum("type", argument); if (strcmp(type, "STRING") == 0) { DCmdArgument* argument = new DCmdArgument( name, desc, "STRING", mandatory, default_value); - parser->add_dcmd_option(argument); + if (isarg) { + parser->add_dcmd_argument(argument); + } else { + parser->add_dcmd_option(argument); + } } else if (strcmp(type, "NANOTIME") == 0) { DCmdArgument* argument = new DCmdArgument( name, desc, "NANOTIME", mandatory, default_value); - parser->add_dcmd_option(argument); + if (isarg) { + parser->add_dcmd_argument(argument); + } else { + parser->add_dcmd_option(argument); + } } else if (strcmp(type, "JLONG") == 0) { DCmdArgument* argument = new DCmdArgument( name, desc, "JLONG", mandatory, default_value); - parser->add_dcmd_option(argument); + if (isarg) { + parser->add_dcmd_argument(argument); + } else { + parser->add_dcmd_option(argument); + } } else if (strcmp(type, "BOOLEAN") == 0) { DCmdArgument* argument = new DCmdArgument( name, desc, "BOOLEAN", mandatory, default_value); - parser->add_dcmd_option(argument); + if (isarg) { + parser->add_dcmd_argument(argument); + } else { + parser->add_dcmd_option(argument); + } } else if (strcmp(type, "MEMORYSIZE") == 0) { DCmdArgument* argument = new DCmdArgument( name, desc, "MEMORY SIZE", mandatory, default_value); - parser->add_dcmd_option(argument); + if (isarg) { + parser->add_dcmd_argument(argument); + } else { + parser->add_dcmd_option(argument); + } } else if (strcmp(type, "STRINGARRAY") == 0) { DCmdArgument* argument = new DCmdArgument( name, desc, "STRING SET", mandatory); - parser->add_dcmd_option(argument); + if (isarg) { + parser->add_dcmd_argument(argument); + } else { + parser->add_dcmd_option(argument); + } } } @@ -111,11 +136,12 @@ * { 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)) +WB_ENTRY(jobjectArray, WB_ParseCommandLine(JNIEnv* env, jobject o, jstring j_cmdline, jchar j_delim, jobjectArray arguments)) ResourceMark rm; DCmdParser parser; const char* c_cmdline = java_lang_String::as_utf8_string(JNIHandles::resolve(j_cmdline)); + const char c_delim = j_delim & 0xff; objArrayOop argumentArray = objArrayOop(JNIHandles::resolve_non_null(arguments)); objArrayHandle argumentArray_ah(THREAD, argumentArray); @@ -127,20 +153,29 @@ } CmdLine cmdline(c_cmdline, strlen(c_cmdline), true); - parser.parse(&cmdline,',',CHECK_NULL); + parser.parse(&cmdline,c_delim,CHECK_NULL); Klass* k = SystemDictionary::Object_klass(); objArrayOop returnvalue_array = oopFactory::new_objArray(k, parser.num_arguments() * 2, CHECK_NULL); objArrayHandle returnvalue_array_ah(THREAD, returnvalue_array); GrowableArray*parsedArgNames = parser.argument_name_array(); + GenDCmdArgument* arglist = parser.arguments_list(); 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_ah->obj_at_put(i*2, parsedName); GenDCmdArgument* arg = parser.lookup_dcmd_option(parsedArgNames->at(i), strlen(parsedArgNames->at(i))); + if (!arg) { + arg = arglist; + arglist = arglist->next(); + } char buf[VALUE_MAXLEN]; - arg->value_as_str(buf, sizeof(buf)); + if (arg) { + arg->value_as_str(buf, sizeof(buf)); + } else { + sprintf(buf, ""); + } oop parsedValue = java_lang_String::create_oop_from_str(buf, CHECK_NULL); returnvalue_array_ah->obj_at_put(i*2+1, parsedValue); } diff -r c12b0a02beee -r 419385282044 hotspot/src/share/vm/prims/wbtestmethods/parserTests.hpp --- a/hotspot/src/share/vm/prims/wbtestmethods/parserTests.hpp Wed Nov 26 19:46:33 2014 +0000 +++ b/hotspot/src/share/vm/prims/wbtestmethods/parserTests.hpp Fri Nov 28 16:33:57 2014 +0100 @@ -27,6 +27,6 @@ #include "prims/jni.h" #include "prims/whitebox.hpp" -WB_METHOD_DECLARE(jobjectArray) WB_ParseCommandLine(JNIEnv* env, jobject o, jstring args, jobjectArray arguments); +WB_METHOD_DECLARE(jobjectArray) WB_ParseCommandLine(JNIEnv* env, jobject o, jstring args, jchar delim, jobjectArray arguments); #endif //SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H diff -r c12b0a02beee -r 419385282044 hotspot/src/share/vm/prims/whitebox.cpp --- a/hotspot/src/share/vm/prims/whitebox.cpp Wed Nov 26 19:46:33 2014 +0000 +++ b/hotspot/src/share/vm/prims/whitebox.cpp Fri Nov 28 16:33:57 2014 +0100 @@ -1127,7 +1127,7 @@ {CC"getVMPageSize", CC"()I", (void*)&WB_GetVMPageSize }, {CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive }, {CC"parseCommandLine", - CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;", + CC"(Ljava/lang/String;C[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;", (void*) &WB_ParseCommandLine }, {CC"addToBootstrapClassLoaderSearch", CC"(Ljava/lang/String;)V", diff -r c12b0a02beee -r 419385282044 hotspot/src/share/vm/services/diagnosticFramework.cpp --- a/hotspot/src/share/vm/services/diagnosticFramework.cpp Wed Nov 26 19:46:33 2014 +0000 +++ b/hotspot/src/share/vm/services/diagnosticFramework.cpp Fri Nov 28 16:33:57 2014 +0100 @@ -60,16 +60,15 @@ bool DCmdArgIter::next(TRAPS) { if (_len == 0) return false; - // skipping spaces + // skipping delimiters while (_cursor < _len - 1 && _buffer[_cursor] == _delim) { _cursor++; } // handling end of command line - if (_cursor >= _len - 1) { - _cursor = _len - 1; - _key_addr = &_buffer[_len - 1]; + if (_cursor == _len - 1 && _buffer[_cursor] == _delim) { + _key_addr = &_buffer[_cursor]; _key_len = 0; - _value_addr = &_buffer[_len - 1]; + _value_addr = &_buffer[_cursor]; _value_len = 0; return false; } diff -r c12b0a02beee -r 419385282044 hotspot/test/serviceability/ParserTest.java --- a/hotspot/test/serviceability/ParserTest.java Wed Nov 26 19:46:33 2014 +0000 +++ b/hotspot/test/serviceability/ParserTest.java Fri Nov 28 16:33:57 2014 +0100 @@ -48,6 +48,7 @@ testBool(); testQuotes(); testMemorySize(); + testSingleLetterArg(); } public static void main(String... args) throws Exception { @@ -99,7 +100,7 @@ false, "0"); DiagnosticCommand[] args = {arg}; - wb.parseCommandLine(name + "=10", args); + wb.parseCommandLine(name + "=10", ',', args); parse(name, "10", name + "=10", args); parse(name, "-5", name + "=-5", args); @@ -149,6 +150,15 @@ parse(name, "Recording 1", "\"" + name + "\"" + "=\"Recording 1\",arg=value", args); } + public void testSingleLetterArg() throws Exception { + DiagnosticCommand[] args = new DiagnosticCommand[]{ + new DiagnosticCommand("flag", "desc", DiagnosticArgumentType.STRING, true, false, null), + new DiagnosticCommand("value", "desc", DiagnosticArgumentType.STRING, true, false, null) + }; + parse("flag", "flag", "flag v", ' ', args); + parse("value", "v", "flag v", ' ', args); + } + public void testMemorySize() throws Exception { String name = "name"; String defaultValue = "1024"; @@ -176,9 +186,13 @@ public void parse(String searchName, String expectedValue, String cmdLine, DiagnosticCommand[] argumentTypes) throws Exception { + parse(searchName, expectedValue, cmdLine, ',', argumentTypes); + } + public void parse(String searchName, String expectedValue, + String cmdLine, char delim, DiagnosticCommand[] argumentTypes) throws Exception { //parseCommandLine will return an object array that looks like //{, ... } - Object[] res = wb.parseCommandLine(cmdLine, argumentTypes); + Object[] res = wb.parseCommandLine(cmdLine, delim, argumentTypes); for (int i = 0; i < res.length-1; i+=2) { String parsedName = (String) res[i]; if (searchName.equals(parsedName)) { @@ -196,8 +210,11 @@ } private void shouldFail(String argument, DiagnosticCommand[] argumentTypes) throws Exception { + shouldFail(argument, ',', argumentTypes); + } + private void shouldFail(String argument, char delim, DiagnosticCommand[] argumentTypes) throws Exception { try { - wb.parseCommandLine(argument, argumentTypes); + wb.parseCommandLine(argument, delim, argumentTypes); throw new Exception("Parser accepted argument: " + argument); } catch (IllegalArgumentException e) { //expected diff -r c12b0a02beee -r 419385282044 hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java --- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Wed Nov 26 19:46:33 2014 +0000 +++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Fri Nov 28 16:33:57 2014 +0100 @@ -94,7 +94,7 @@ public native boolean g1IsHumongous(Object o); public native long g1NumFreeRegions(); public native int g1RegionSize(); - public native Object[] parseCommandLine(String commandline, DiagnosticCommand[] args); + public native Object[] parseCommandLine(String commandline, char delim, DiagnosticCommand[] args); // NMT public native long NMTMalloc(long size); diff -r c12b0a02beee -r 419385282044 hotspot/test/testlibrary/whitebox/sun/hotspot/parser/DiagnosticCommand.java --- a/hotspot/test/testlibrary/whitebox/sun/hotspot/parser/DiagnosticCommand.java Wed Nov 26 19:46:33 2014 +0000 +++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/parser/DiagnosticCommand.java Fri Nov 28 16:33:57 2014 +0100 @@ -34,14 +34,21 @@ private DiagnosticArgumentType type; private boolean mandatory; private String defaultValue; + private boolean argument; public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type, boolean mandatory, String defaultValue) { + this(name, desc, type, false, mandatory, defaultValue); + } + + public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type, + boolean argument, boolean mandatory, String defaultValue) { this.name = name; this.desc = desc; this.type = type; this.mandatory = mandatory; this.defaultValue = defaultValue; + this.argument = argument; } public String getName() { @@ -60,6 +67,10 @@ return mandatory; } + public boolean isArgument() { + return argument; + } + public String getDefaultValue() { return defaultValue; }