Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Support for Hotspot Codecache and Objectheap Options #7476

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions runtime/compiler/control/J9Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1448,21 +1448,23 @@ J9::Options::fePreProcess(void * base)
// fePreProcess is called twice - for AOT and JIT options parsing, which is redundant in terms of
// processing the -Xlp:codecache options.
// We should parse the -Xlp:codecache options only once though to avoid duplicate NLS messages.
static bool parsedXlpCodeCacheOptions = false;
static bool parsedCodeCacheOptions = false;

if (!parsedXlpCodeCacheOptions)
if (!parsedCodeCacheOptions)
{
parsedXlpCodeCacheOptions = true;
parsedCodeCacheOptions = true;

UDATA requestedLargeCodePageSize = 0;
UDATA requestedLargeCodePageFlags = J9PORT_VMEM_PAGE_FLAG_NOT_USED;
UDATA largePageSize = 0;
UDATA largePageFlags = 0;
int32_t xlpCodeCacheIndex = FIND_ARG_IN_VMARGS(STARTSWITH_MATCH, "-Xlp:codecache:", NULL);
int32_t xlpIndex = FIND_ARG_IN_VMARGS(EXACT_MEMORY_MATCH, "-Xlp", NULL);
J9LargePageCompatibilityOptions *largePageOptionConfig = &(vm->largePageOption);
int32_t largePageArgIndex = largePageOptionConfig->optionIndex;

// Parse -Xlp:codecache:pagesize=<size> as the right most option
if (xlpCodeCacheIndex > xlpIndex)
if ((xlpCodeCacheIndex > xlpIndex) && (xlpCodeCacheIndex > largePageArgIndex))
{
TR_XlpCodeCacheOptions parsingState = XLPCC_PARSING_FIRST_OPTION;
UDATA optionNumber = 1;
Expand Down Expand Up @@ -1685,12 +1687,17 @@ J9::Options::fePreProcess(void * base)
j9nls_printf(PORTLIB, J9NLS_INFO, J9NLS_JIT_OPTIONS_XLP_EXTRA_COMMA);
}
// Parse Size -Xlp<size>
else if (xlpIndex >= 0)
else if (xlpIndex > largePageArgIndex)
{
// GET_MEMORY_VALUE macro casts it's second parameter to (char**)&, so a pointer to the option string is passed rather than the string literal.
char *lpOption = "-Xlp";
GET_MEMORY_VALUE(xlpIndex, lpOption, requestedLargeCodePageSize);
}
// Parse -XX:LargePageSizeInBytes=<size>
else if ((largePageArgIndex >= 0) && (largePageOptionConfig->pageSizeRequested != -1))
{
requestedLargeCodePageSize = largePageOptionConfig->pageSizeRequested;
}

if (requestedLargeCodePageSize != 0)
{
Expand Down Expand Up @@ -1739,6 +1746,12 @@ J9::Options::fePreProcess(void * base)
}
}
}
// Handle -XX:+UseLargePages
else if (largePageArgIndex >= 0)
AlenBadel marked this conversation as resolved.
Show resolved Hide resolved
{
// Requesting the preferred large page configured on the system.
j9vmem_default_large_page_size_ex(J9PORT_VMEM_MEMORY_MODE_EXECUTE, &largePageSize, &largePageFlags);
}
// When no -Xlp arguments are passed, we should use preferred page sizes
else
{
Expand Down
216 changes: 156 additions & 60 deletions runtime/gc_modron_startup/mmparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,18 +559,148 @@ xlpSubOptionsParser(J9JavaVM *vm, IDATA xlpIndex, XlpError *xlpError, UDATA *req
return xlpErrorState;
}

/**
* Given the requested size of the large pages to be used, the method will verify that value is supported by the system.
* If the value is not supported, the system will set preffered Large Page size if configured on the system.
* The user will also be notified of the altered value being used.
*/
void
verifyLargePageSize(J9JavaVM *vm, UDATA requestedPageSize, UDATA requestedPageFlags)
{
UDATA pageSize = requestedPageSize;
UDATA pageFlags = requestedPageFlags;
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);
BOOLEAN isRequestedSizeSupported = FALSE;
PORT_ACCESS_FROM_JAVAVM(vm);

IDATA result = j9vmem_find_valid_page_size(0, &pageSize, &pageFlags, &isRequestedSizeSupported);

/*
* j9vmem_find_valid_page_size happened to be changed to always return 0
* However formally the function type still be IDATA so assert if it returns anything else
*/
Assert_MM_true(0 == result);

extensions->requestedPageSize = pageSize;
extensions->requestedPageFlags = pageFlags;

if (!isRequestedSizeSupported) {
/* Print a message indicating requested page size is not supported and a different page size will be used */
const char *oldQualifier, *newQualifier;
const char *oldPageType = NULL;
const char *newPageType = NULL;
UDATA oldSize = requestedPageSize;
UDATA newSize = pageSize;
qualifiedSize(&oldSize, &oldQualifier);
qualifiedSize(&newSize, &newQualifier);
if (0 == (J9PORT_VMEM_PAGE_FLAG_NOT_USED & requestedPageFlags)) {
oldPageType = getPageTypeString(requestedPageFlags);
}
if (0 == (J9PORT_VMEM_PAGE_FLAG_NOT_USED & pageFlags)) {
newPageType = getPageTypeString(pageFlags);
}
if (NULL == oldPageType) {
if (NULL == newPageType) {
j9nls_printf(PORTLIB, J9NLS_INFO, J9NLS_GC_OPTIONS_LARGE_PAGE_SIZE_NOT_SUPPORTED, oldSize, oldQualifier, newSize, newQualifier);
} else {
j9nls_printf(PORTLIB, J9NLS_INFO, J9NLS_GC_OPTIONS_LARGE_PAGE_SIZE_NOT_SUPPORTED_WITH_NEW_PAGETYPE, oldSize, oldQualifier, newSize, newQualifier, newPageType);
}
} else {
if (NULL == newPageType) {
j9nls_printf(PORTLIB, J9NLS_INFO, J9NLS_GC_OPTIONS_LARGE_PAGE_SIZE_NOT_SUPPORTED_WITH_REQUESTED_PAGETYPE, oldSize, oldQualifier, oldPageType, newSize, newQualifier);
} else {
j9nls_printf(PORTLIB, J9NLS_INFO, J9NLS_GC_OPTIONS_LARGE_PAGE_SIZE_NOT_SUPPORTED_WITH_PAGETYPE, oldSize, oldQualifier, oldPageType, newSize, newQualifier, newPageType);
}
}
}
}

/**
*
* Obtains and sets the preferred page size available on the system.
* Returns true if the operation was successful.
*
*/
bool
gcSetPreferredPageSize(J9JavaVM *vm)
{
UDATA defaultLargePageSize = 0;
UDATA defaultLargePageFlags = J9PORT_VMEM_PAGE_FLAG_NOT_USED;
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);
PORT_ACCESS_FROM_JAVAVM(vm);

/* Get the default large page size of non pageable */
j9vmem_default_large_page_size_ex(0, &defaultLargePageSize, &defaultLargePageFlags);

if (0 != defaultLargePageSize) {
extensions->requestedPageSize = defaultLargePageSize;
extensions->requestedPageFlags = defaultLargePageFlags;
} else {
return false;
}

return true;
}

/**
*
* Sets the large page size used within the objectheap when the options -XX:+UseLargePages or -XX:LargePageSizeInBytes=<size> are used.
* The value of the large page size will only be overwritten when these arguments are located in the right most index.
* This is compared to the indices of -Xlp, -Xlp<size>, and -Xlp:objectheap:pagesize=<size>
*
*/
static bool
gcProcessXXLargePageObjectHeapArguments(J9JavaVM *vm)
{
PORT_ACCESS_FROM_JAVAVM(vm);
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);
J9LargePageCompatibilityOptions *optionConfig = &(vm->largePageOption);

if (-1 == optionConfig->pageSizeRequested) {

UDATA defaultLargePageSize = 0;
#if defined(J9ZOS390)
UDATA defaultLargePageFlags = J9PORT_VMEM_PAGE_FLAG_PAGEABLE_PREFERABLE;
#else /* J9ZOS390 */
UDATA defaultLargePageFlags = J9PORT_VMEM_PAGE_FLAG_NOT_USED;
#endif

j9vmem_default_large_page_size_ex(0, &defaultLargePageSize, &defaultLargePageFlags);

if (0 != defaultLargePageSize) {
extensions->requestedPageSize = defaultLargePageSize;
extensions->requestedPageFlags = defaultLargePageFlags;
} else {
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_SYSTEM_CONFIG_OPTION_NOT_SUPPORTED, "-XX:+UseLargePages");
return false;
}
} else {
UDATA largePageSizeRequested = optionConfig->pageSizeRequested;
#if defined(J9ZOS390)
UDATA largePageFlagRequested = J9PORT_VMEM_PAGE_FLAG_PAGEABLE_PREFERABLE;
#else /* J9ZOS390 */
UDATA largePageFlagRequested = J9PORT_VMEM_PAGE_FLAG_NOT_USED;
AlenBadel marked this conversation as resolved.
Show resolved Hide resolved
#endif
verifyLargePageSize(vm, largePageSizeRequested, largePageFlagRequested);
}

return true;
}

/**
* Find and consume -Xlp option(s) from the argument list.
*
* @param vm pointer to Java VM structure
*
* @return false if the option(s) are not consumed properly, true on success.
* @return -1 if the option(s) are not consumed properly,
* -2 if no option was consumed,
* or the index of the right most option consumed.
*/
static bool
static IDATA
gcParseXlpOption(J9JavaVM *vm)
{
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vm);
bool rc = false;
IDATA rc = -2;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would you please add comment before this line to explain in simple words what this return code means

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the intention. Could you address my comments here? #7476 (comment). If you're ok with that change I can go ahead with commenting the codes.

XlpErrorState xlpErrorState = XLP_NO_ERROR;
XlpError xlpError = {NULL, /* xlpOptionErrorString */
0, /* xlpOptionErrorStringSize */
Expand All @@ -587,27 +717,28 @@ gcParseXlpOption(J9JavaVM *vm)
/* Parse -Xlp option.
* -Xlp option enables large pages with the default large page size, but will not
* override any -Xlp<size> or -Xlp:objectheap:pagesize=<size> option.
*
* -XX:+UseLargePages. Has Same behaviour as -Xlp. Check if it has been parsed.
*/
xlpIndex = option_set(vm, "-Xlp", EXACT_MATCH);
if (-1 != xlpIndex) {
UDATA defaultLargePageSize = 0;
UDATA defaultLargePageFlags = J9PORT_VMEM_PAGE_FLAG_NOT_USED;
j9vmem_default_large_page_size_ex(0, &defaultLargePageSize, &defaultLargePageFlags);
if (0 != defaultLargePageSize) {
extensions->requestedPageSize = defaultLargePageSize;
extensions->requestedPageFlags = defaultLargePageFlags;
} else {
/* Keep track of most-right index to return */
rc = xlpIndex;
if (!gcSetPreferredPageSize(vm)) {
xlpErrorState = XLP_OPTION_NOT_SUPPORTED;
xlpError.xlpOptionErrorString = "-Xlp";
/* Cannot report error message here,
* as we may find a valid "-Xlp:objectheap" that overwrites this option
*/
}
}

/* Parse -Xlp<size> option. It overrides -Xlp option. */
xlpMemIndex = FIND_AND_CONSUME_ARG(EXACT_MEMORY_MATCH, "-Xlp", NULL);
if (-1 != xlpMemIndex) {

/* Keep track of most-right index to return */
rc = xlpMemIndex;

/* Reset error state from parsing of previous -Xlp option */
xlpErrorState = XLP_NO_ERROR;

Expand Down Expand Up @@ -652,7 +783,10 @@ gcParseXlpOption(J9JavaVM *vm)
xlpObjectHeapIndex = FIND_AND_CONSUME_ARG(STARTSWITH_MATCH, "-Xlp:objectheap:", NULL);

/* so if -Xlp:objectheap: is specified */
if ((-1 != xlpObjectHeapIndex) && (xlpObjectHeapIndex > xlpMemIndex)) {
if (xlpObjectHeapIndex > xlpMemIndex) {
/* Keep track of most-right index to return */
rc = xlpObjectHeapIndex;

/*
* Parse sub options for -Xlp:objectheap:
*/
Expand All @@ -672,50 +806,7 @@ gcParseXlpOption(J9JavaVM *vm)
/* If a valid -Xlp<size> or -Xlp:objectheap:pagesize=<size> is present, check if the requested page size is supported */
/* We don't need to check error state here - we did goto for all errors */
if ((-1 != xlpMemIndex) || (-1 != xlpObjectHeapIndex)) {
UDATA pageSize = requestedPageSize;
UDATA pageFlags = requestedPageFlags;
BOOLEAN isRequestedSizeSupported = FALSE;

IDATA result = j9vmem_find_valid_page_size(0, &pageSize, &pageFlags, &isRequestedSizeSupported);

/*
* j9vmem_find_valid_page_size happened to be changed to always return 0
* However formally the function type still be IDATA so assert if it returns anything else
*/
Assert_MM_true(0 == result);

extensions->requestedPageSize = pageSize;
extensions->requestedPageFlags = pageFlags;

if (!isRequestedSizeSupported) {
/* Print a message indicating requested page size is not supported and a different page size will be used */
const char *oldQualifier, *newQualifier;
const char *oldPageType = NULL;
const char *newPageType = NULL;
UDATA oldSize = requestedPageSize;
UDATA newSize = pageSize;
qualifiedSize(&oldSize, &oldQualifier);
qualifiedSize(&newSize, &newQualifier);
if (0 == (J9PORT_VMEM_PAGE_FLAG_NOT_USED & requestedPageFlags)) {
oldPageType = getPageTypeString(requestedPageFlags);
}
if (0 == (J9PORT_VMEM_PAGE_FLAG_NOT_USED & pageFlags)) {
newPageType = getPageTypeString(pageFlags);
}
if (NULL == oldPageType) {
if (NULL == newPageType) {
j9nls_printf(PORTLIB, J9NLS_INFO, J9NLS_GC_OPTIONS_LARGE_PAGE_SIZE_NOT_SUPPORTED, oldSize, oldQualifier, newSize, newQualifier);
} else {
j9nls_printf(PORTLIB, J9NLS_INFO, J9NLS_GC_OPTIONS_LARGE_PAGE_SIZE_NOT_SUPPORTED_WITH_NEW_PAGETYPE, oldSize, oldQualifier, newSize, newQualifier, newPageType);
}
} else {
if (NULL == newPageType) {
j9nls_printf(PORTLIB, J9NLS_INFO, J9NLS_GC_OPTIONS_LARGE_PAGE_SIZE_NOT_SUPPORTED_WITH_REQUESTED_PAGETYPE, oldSize, oldQualifier, oldPageType, newSize, newQualifier);
} else {
j9nls_printf(PORTLIB, J9NLS_INFO, J9NLS_GC_OPTIONS_LARGE_PAGE_SIZE_NOT_SUPPORTED_WITH_PAGETYPE, oldSize, oldQualifier, oldPageType, newSize, newQualifier, newPageType);
}
}
}
verifyLargePageSize(vm, requestedPageSize, requestedPageFlags);
}

/*
Expand Down Expand Up @@ -775,7 +866,7 @@ gcParseXlpOption(J9JavaVM *vm)
/* If error occurred during parsing of -Xlp options, report it here. */
if (XLP_NO_ERROR != xlpErrorState) {
/* parsing failed, return false */
rc = false;
rc = -1;

switch(xlpErrorState) {
case XLP_OPTION_NOT_SUPPORTED:
Expand Down Expand Up @@ -817,8 +908,6 @@ gcParseXlpOption(J9JavaVM *vm)
j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_GC_OPTIONS_XLP_PARSING_ERROR);
break;
}
} else {
rc = true;
}

return rc;
Expand All @@ -840,12 +929,19 @@ gcParseSovereignArguments(J9JavaVM *vm)
#endif /* J9VM_GC_LARGE_OBJECT_AREA */
const char *optionFound = NULL;
IDATA index = -1;
J9LargePageCompatibilityOptions *largePageOptionConfig = &(vm->largePageOption);
PORT_ACCESS_FROM_JAVAVM(vm);

if (!gcParseXlpOption(vm)) {
IDATA xlpOptionIndex = gcParseXlpOption(vm);
if (-1 == xlpOptionIndex) {
goto _error;
}

/* Setup to handle additional objectheap arguments */
if ((-1 != largePageOptionConfig->optionIndex) && (largePageOptionConfig->optionIndex > xlpOptionIndex) && (!gcProcessXXLargePageObjectHeapArguments(vm))) {
goto _error;
}

/* Check for explicit specification of GC policy */
gcParseXgcpolicy(extensions);

Expand Down
8 changes: 8 additions & 0 deletions runtime/oti/j9nonbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -4755,6 +4755,13 @@ typedef struct J9VMRuntimeStateListener {
UDATA idleTuningFlags;
} J9VMRuntimeStateListener;

/* J9LargePageCompatibilityOptions contains the index of the large page option to be used. Size is the size requested if applicable. */

typedef struct J9LargePageCompatibilityOptions {
IDATA pageSizeRequested;
IDATA optionIndex;
} J9LargePageCompatibilityOptions;

/* Values for J9VMRuntimeStateListener.vmRuntimeState
* These values are reflected in the Java class library code(RuntimeMXBean)
*/
Expand Down Expand Up @@ -5150,6 +5157,7 @@ typedef struct J9JavaVM {
U_32 minimumReservedRatio;
U_32 cancelAbsoluteThreshold;
U_32 minimumLearningRatio;
J9LargePageCompatibilityOptions largePageOption;
} J9JavaVM;

#define J9VM_PHASE_NOT_STARTUP 2
Expand Down
1 change: 1 addition & 0 deletions runtime/oti/j9port.h
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,7 @@ typedef struct J9CacheInfoQuery {
#define J9PORT_VMEM_ALLOC_DIR_BOTTOM_UP OMRPORT_VMEM_ALLOC_DIR_BOTTOM_UP
#define J9PORT_VMEM_STRICT_ADDRESS OMRPORT_VMEM_STRICT_ADDRESS
#define J9PORT_VMEM_PAGE_FLAG_PAGEABLE OMRPORT_VMEM_PAGE_FLAG_PAGEABLE
#define J9PORT_VMEM_PAGE_FLAG_PAGEABLE_PREFERABLE OMRPORT_VMEM_PAGE_FLAG_PAGEABLE_PREFERABLE
#define J9PORT_VMEM_PAGE_FLAG_FIXED OMRPORT_VMEM_PAGE_FLAG_FIXED
#define J9PORT_VMEM_PAGE_FLAG_NOT_USED OMRPORT_VMEM_PAGE_FLAG_NOT_USED
#define J9PORT_VMEM_STRICT_PAGE_SIZE OMRPORT_VMEM_STRICT_PAGE_SIZE
Expand Down
2 changes: 2 additions & 0 deletions runtime/oti/jvminit.h
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,8 @@ enum INIT_STAGE {
#define MAPOPT_XXONOUTOFMEMORYERROR_EQUALS "-XX:OnOutOfMemoryError="
#define MAPOPT_XXENABLEEXITONOUTOFMEMORYERROR "-XX:+ExitOnOutOfMemoryError"
#define MAPOPT_XXDISABLEEXITONOUTOFMEMORYERROR "-XX:-ExitOnOutOfMemoryError"
#define MAPOPT_XXLARGEPAGESIZEINBYTES_EQUALS "-XX:LargePageSizeInBytes="
#define MAPOPT_XXUSELARGEPAGES "-XX:+UseLargePages"
Copy link
Contributor

@dmitripivkine dmitripivkine Mar 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be recognition of "-XX:-UseLargePages" for symmetry ? I am neutral about this. Asking for VM Reviewer opinion

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pshipton Should this be added?

In theory, it makes sense to have an option to disable all large page options, including -Xlp*. However this PR is to map Hotspot Options, and Hotspot does not support such an option.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this needs to have the -XX:+UseLargePages to be consistent with our standard processes. If there is a + version, there must be a - version as well. Otherwise, use the non-[+-] -XX:Foo style option

#define MAPOPT_XXPARALLELCMSTHREADS_EQUALS "-XX:ParallelCMSThreads="
#define MAPOPT_XXCONCGCTHREADS_EQUALS "-XX:ConcGCThreads="
#define MAPOPT_XXPARALLELGCTHREADS_EQUALS "-XX:ParallelGCThreads="
Expand Down
Loading