Skip to content

Commit

Permalink
Move argument memory size parsing into j9argscan
Browse files Browse the repository at this point in the history
Previously, parsing methods were only accessible within the GC. Moving these methods into j9argscan enables them to be used generally by VM, and JIT.

Signed-off-by: AlenBadel <[email protected]>
  • Loading branch information
AlenBadel authored and AlenBadel committed Aug 26, 2020
1 parent 2d0b03a commit 1707149
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 74 deletions.
93 changes: 24 additions & 69 deletions runtime/gc_modron_startup/mmparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "j9cfg.h"
#include "j9protos.h"
#include "j9consts.h"
#include "j9argscan.h"
#include "jni.h"
#include "jvminit.h"
#include "j9port.h"
Expand Down Expand Up @@ -1355,95 +1356,49 @@ scan_hex_helper(J9JavaVM *javaVM, char **cursor, UDATA *value, const char *argNa
}

/**
* Wrapper for scan_udata_helper, that provides parsing for memory sizes.
* User should be able to specify the size in GiBs, MiBs, or KiBs (with G,g,M,m,K,k suffixes) or
* in bytes (no suffix)
* Wrapper for scan_udata_memory_size, that provides readable error messages.
* @param cursor address of the pointer to the string to parse for the udata.
* @param value address of the storage for the udata to be read.
* @param argName string containing the argument name to be used in error reporting.
* @return true if parsing was successful, false otherwise.
*/
bool
scan_udata_memory_size_helper(J9JavaVM *javaVM, char **cursor, UDATA *value, const char *argName)
{
PORT_ACCESS_FROM_JAVAVM(javaVM);
UDATA result = scan_udata_memory_size(cursor, value);

if(!scan_udata_helper(javaVM, cursor, value, argName)) {
return false;
}

if(try_scan(cursor, "T") || try_scan(cursor, "t")) {
if (0 != *value) {
#if defined(J9VM_ENV_DATA64)
if (*value <= (((UDATA)-1) >> 40)) {
*value <<= 40;
} else
#endif /* defined(J9VM_ENV_DATA64) */
{
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_VALUE_OVERFLOWED, argName);
return false;
}
}
} else if(try_scan(cursor, "G") || try_scan(cursor, "g")) {
if (*value <= (((UDATA)-1) >> 30)) {
*value <<= 30;
} else {
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_VALUE_OVERFLOWED, argName);
return false;
}
} else if(try_scan(cursor, "M") || try_scan(cursor, "m")) {
if (*value <= (((UDATA)-1) >> 20)) {
*value <<= 20;
} else {
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_VALUE_OVERFLOWED, argName);
return false;
}
} else if(try_scan(cursor, "K") || try_scan(cursor, "k")) {
if (*value <= (((UDATA)-1) >> 10)) {
*value <<= 10;
} else {
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_VALUE_OVERFLOWED, argName);
return false;
}
/* Report Errors */
if (1 == result) {
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_MUST_BE_NUMBER, argName);
} else if (2 == result) {
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_VALUE_OVERFLOWED, argName);
}
return true;

return 0 == result;
}

/**
* Wrapper for scan_u64_helper, that provides parsing for memory sizes.
* User should be able to specify the size in GiBs, MiBs, or KiBs (with G,g,M,m,K,k suffixes) or
* in bytes (no suffix)
* Wrapper for scan_u64_helper, that provides readable error messages.
* @param cursor address of the pointer to the string to parse for the udata.
* @param value address of the storage for the udata to be read.
* @param argName string containing the argument name to be used in error reporting.
* @return true if parsing was successful, false otherwise.
*/
bool
scan_u64_memory_size_helper(J9JavaVM *javaVM, char **cursor, U_64 *value, const char *argName)
{
PORT_ACCESS_FROM_JAVAVM(javaVM);
U_64 result = scan_u64_memory_size(cursor, value);

if(!scan_u64_helper(javaVM, cursor, value, argName)) {
return false;
/* Report Errors */
if (1 == result) {
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_MUST_BE_NUMBER, argName);
} else if (2 == result) {
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_VALUE_OVERFLOWED, argName);
}

if(try_scan(cursor, "G") || try_scan(cursor, "g")) {
if (*value <= (((U_64)-1) >> 30)) {
*value <<= 30;
} else {
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_VALUE_OVERFLOWED, argName);
return false;
}
} else if(try_scan(cursor, "M") || try_scan(cursor, "m")) {
if (*value <= (((U_64)-1) >> 20)) {
*value <<= 20;
} else {
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_VALUE_OVERFLOWED, argName);
return false;
}
} else if(try_scan(cursor, "K") || try_scan(cursor, "k")) {
if (*value <= (((U_64)-1) >> 10)) {
*value <<= 10;
} else {
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_VALUE_OVERFLOWED, argName);
return false;
}
}
return true;
return 0 == result;
}

/**
Expand Down
18 changes: 17 additions & 1 deletion runtime/oti/j9argscan.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2001, 2018 IBM Corp. and others
* Copyright (c) 2001, 2020 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -158,6 +158,22 @@ uintptr_t scan_u64(char **scan_start, uint64_t* result);
*/
uintptr_t scan_u32(char **scan_start, uint32_t* result);

/**
* @brief
* @param **scan_start
* @param result
* @return uintptr_t
*/
uintptr_t scan_u64_memory_size(char **scan_start, uint64_t* result);

/**
* @brief
* @param **scan_start
* @param result
* @return uintptr_t
*/
uintptr_t scan_udata_memory_size(char **scan_start, uintptr_t* result);

#ifdef __cplusplus
} /* extern "C" */
#endif
Expand Down
103 changes: 99 additions & 4 deletions runtime/util_core/j9argscan.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1991, 2018 IBM Corp. and others
* Copyright (c) 1991, 2020 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -385,6 +385,104 @@ scan_hex_caseflag_u64(char **scan_start, BOOLEAN uppercaseAllowed, uint64_t* res
return bits;
}

/**
* Scan the next unsigned number off of the argument string, and parses for memory sizes.
* Specify the size in GiBs, MiBs, or KiBs (with G,g,M,m,K,k suffixes) or in bytes (no suffix).
* @param[in] scan_start The string to be scanned
* @param[out] result The result
* @return returns 0 on success, 1 if the argument string is not a number, or 2 if overflow occurs.
*/
uintptr_t
scan_u64_memory_size(char **scan_start, uint64_t* result)
{
uintptr_t rc = scan_u64(scan_start, result);

/* Report any errors from scan */
if (0 != rc) {
return rc;
}

if(try_scan(scan_start, "T") || try_scan(scan_start, "t")) {
if (0 != *result) {
if (*result <= (((U_64)-1) >> 40)) {
*result <<= 40;
} else {
return 2;
}
}
} else if(try_scan(scan_start, "G") || try_scan(scan_start, "g")) {
if (*result <= (((U_64)-1) >> 30)) {
*result <<= 30;
} else {
return 2;
}
} else if(try_scan(scan_start, "M") || try_scan(scan_start, "m")) {
if (*result <= (((U_64)-1) >> 20)) {
*result <<= 20;
} else {
return 2;
}
} else if(try_scan(scan_start, "K") || try_scan(scan_start, "k")) {
if (*result <= (((U_64)-1) >> 10)) {
*result <<= 10;
} else {
return 2;
}
}
return 0; /* Success */
}

/**
* Scan the next unsigned number off of the argument string, and parses for memory sizes.
* Specify the size in GiBs, MiBs, or KiBs (with G,g,M,m,K,k suffixes) or in bytes (no suffix).
* @param[in] scan_start The string to be scanned
* @param[out] result The result
* @return returns 0 on success, 1 if the argument string is not a number, or 2 if overflow occurs.
*/
uintptr_t
scan_udata_memory_size(char **scan_start, uintptr_t* result)
{
uintptr_t rc = scan_udata(scan_start, result);

/* Report any Errors from Scan */
if (0 != rc) {
return rc;
}

/* Scan Memory String, and check for overflow */
if(try_scan(scan_start, "T") || try_scan(scan_start, "t")) {
if (0 != *result) {
#if defined(J9VM_ENV_DATA64)
if (*result <= (((UDATA)-1) >> 40)) {
*result <<= 40;
} else
#endif /* defined(J9VM_ENV_DATA64) */
{
return 2;
}
}
} else if(try_scan(scan_start, "G") || try_scan(scan_start, "g")) {
if (*result <= (((UDATA)-1) >> 30)) {
*result <<= 30;
} else {
return 2;
}
} else if(try_scan(scan_start, "M") || try_scan(scan_start, "m")) {
if (*result <= (((UDATA)-1) >> 20)) {
*result <<= 20;
} else {
return 2;
}
} else if(try_scan(scan_start, "K") || try_scan(scan_start, "k")) {
if (*result <= (((UDATA)-1) >> 10)) {
*result <<= 10;
} else {
return 2;
}
}

return 0; /* Success */
}

/*
* Print an error message indicating that an option was not recognized
Expand All @@ -404,6 +502,3 @@ void scan_failed_unsupported(J9PortLibrary * portLibrary, char* module, char *sc
PORT_ACCESS_FROM_PORT(portLibrary);
j9tty_printf(PORTLIB, "<%s: system configuration does not support option --> '%s'>\n", module, scan_start);
}



0 comments on commit 1707149

Please sign in to comment.