Skip to content

Commit

Permalink
Merge pull request #10324 from ChengJin01/share_memory_from_copyStrin…
Browse files Browse the repository at this point in the history
…gToUTF8WithMemAlloc

Share the memory allocated by copyStringToUTF8WithMemAlloc
  • Loading branch information
gacholio committed Aug 4, 2020
2 parents ecd7afc + f149fbc commit 5f01dc2
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 74 deletions.
4 changes: 2 additions & 2 deletions runtime/j9vm/j7vmi.c
Expand Up @@ -2556,13 +2556,13 @@ jvmDefineClassHelper(JNIEnv *env, jobject classLoaderObject,

if (NULL != className) {
j9object_t classNameObject = J9_JNI_UNWRAP_REFERENCE(className);
utf8Name = (U_8*)vmFuncs->copyStringToUTF8WithMemAlloc(currentThread, classNameObject, J9_STR_NULL_TERMINATE_RESULT | J9_STR_XLAT, "", 0, utf8NameStackBuffer, J9VM_PACKAGE_NAME_BUFFER_LENGTH, &utf8Length);
utf8Name = (U_8*)vmFuncs->copyStringToUTF8WithMemAlloc(currentThread, classNameObject, J9_STR_NULL_TERMINATE_RESULT, "", 0, utf8NameStackBuffer, J9VM_PACKAGE_NAME_BUFFER_LENGTH, &utf8Length);
if (NULL == utf8Name) {
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
goto done;
}

if (CLASSNAME_INVALID == vmFuncs->verifyQualifiedName(currentThread, classNameObject, CLASSNAME_VALID_NON_ARRARY)) {
if (CLASSNAME_INVALID == vmFuncs->verifyQualifiedName(currentThread, utf8Name, utf8Length, CLASSNAME_VALID_NON_ARRARY)) {
vmFuncs->setCurrentException(currentThread, J9VMCONSTANTPOOL_JAVALANGNOCLASSDEFFOUNDERROR, (UDATA *)*(j9object_t*)className);
goto done;
}
Expand Down
10 changes: 8 additions & 2 deletions runtime/jcl/common/jcldefine.c
Expand Up @@ -95,14 +95,20 @@ defineClassCommon(JNIEnv *env, jobject classLoaderObject,
/* Allocate and initialize a UTF8 copy of the Unicode class-name */
if (NULL != className) {
j9object_t classNameObject = J9_JNI_UNWRAP_REFERENCE(className);
utf8Name = (U_8*)vmFuncs->copyStringToUTF8WithMemAlloc(currentThread, classNameObject, J9_STR_NULL_TERMINATE_RESULT | J9_STR_XLAT, "", 0, utf8NameStackBuffer, J9VM_PACKAGE_NAME_BUFFER_LENGTH, &utf8Length);
UDATA stringFlags = J9_STR_NULL_TERMINATE_RESULT;

if (!validateName) {
stringFlags |= J9_STR_XLAT;
}

utf8Name = (U_8*)vmFuncs->copyStringToUTF8WithMemAlloc(currentThread, classNameObject, stringFlags, "", 0, utf8NameStackBuffer, J9VM_PACKAGE_NAME_BUFFER_LENGTH, &utf8Length);

if (NULL == utf8Name) {
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
goto done;
}

if (validateName && (CLASSNAME_INVALID == vmFuncs->verifyQualifiedName(currentThread, classNameObject, CLASSNAME_VALID_NON_ARRARY))) {
if (validateName && (CLASSNAME_INVALID == vmFuncs->verifyQualifiedName(currentThread, utf8Name, utf8Length, CLASSNAME_VALID_NON_ARRARY))) {
/* We don't yet know if the class being defined is exempt. Setting this option tells
* defineClassCommon() to fail if it discovers that the class is not exempt. That failure
* is distinguished by returning NULL with no exception pending.
Expand Down
11 changes: 1 addition & 10 deletions runtime/oti/bcverify_api.h
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1991, 2019 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 @@ -127,15 +127,6 @@ j9bcv_J9VMDllMain (J9JavaVM* vm, IDATA stage, void* reserved);
I_32
bcvCheckClassName (J9CfrConstantPoolInfo * info);

/**
* Check the validity of a class name during class loading.
*
* @param info A pointer to J9CfrConstantPoolInfo
* @returns The arity of the class if valid, -1 otherwise
*/
I_32
bcvCheckClassNameInLoading (J9CfrConstantPoolInfo * info);

/**
* @brief
* @param info
Expand Down
2 changes: 1 addition & 1 deletion runtime/oti/j9nonbuilder.h
Expand Up @@ -4427,7 +4427,7 @@ typedef struct J9InternalVMFunctions {
UDATA ( *compareStrings)(struct J9VMThread * vmThread, j9object_t string1, j9object_t string2) ;
UDATA ( *compareStringToUTF8)(struct J9VMThread * vmThread, j9object_t stringObject, UDATA stringFlags, const U_8 * utfData, UDATA utfLength) ;
void ( *prepareForExceptionThrow)(struct J9VMThread * currentThread) ;
UDATA ( *verifyQualifiedName)(struct J9VMThread *vmThread, j9object_t string, UDATA allowedBitsForClassName) ;
UDATA ( *verifyQualifiedName)(struct J9VMThread *vmThread, U_8 *className, UDATA classNameLength, UDATA allowedBitsForClassName) ;
UDATA ( *copyStringToUTF8Helper)(struct J9VMThread *vmThread, j9object_t string, UDATA stringFlags, UDATA stringOffset, UDATA stringLength, U_8 *utf8Data, UDATA utf8DataLength);
void (JNICALL *sendCompleteInitialization)(struct J9VMThread *vmContext) ;
IDATA ( *J9RegisterAsyncEvent)(struct J9JavaVM * vm, J9AsyncEventHandler eventHandler, void * userData) ;
Expand Down
5 changes: 3 additions & 2 deletions runtime/oti/vm_api.h
Expand Up @@ -3116,14 +3116,15 @@ getStringUTF8Length(J9VMThread *vmThread,j9object_t string);
* CLASSNAME_VALID_ARRARY - if it is valid and there is a '[' at beginning of class name string.
*
* @param[in] *vmThread current thread
* @param[in] string the class name string
* @param[in] className the class name string
* @param[in] classNameLength the length of the class name string
* @param[in] allowedBitsForClassName the allowed bits for a valid class name,
* including CLASSNAME_VALID_NON_ARRARY, CLASSNAME_VALID_ARRARY, or CLASSNAME_VALID.
*
* @return a UDATA to indicate the nature of incoming class name string, see descriptions above.
*/
UDATA
verifyQualifiedName(J9VMThread *vmThread, j9object_t string, UDATA allowedBitsForClassName);
verifyQualifiedName(J9VMThread *vmThread, U_8 *className, UDATA classNameLength, UDATA allowedBitsForClassName);


/* ---------------- swalk.c ---------------- */
Expand Down
15 changes: 1 addition & 14 deletions runtime/verutil/chverify.c
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1991, 2019 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 @@ -173,19 +173,6 @@ bcvCheckClassName (J9CfrConstantPoolInfo * info)
return checkNameImpl(info, TRUE, FALSE, FALSE);
}

/**
* Determine if this a valid name for Classes during class loading.
*
* @param info A pointer to J9CfrConstantPoolInfo
* @returns The arity of the class if valid, -1 otherwise
*/
I_32
bcvCheckClassNameInLoading (J9CfrConstantPoolInfo * info)
{
/* Class checks, not method checks */
return checkNameImpl(info, TRUE, FALSE, TRUE);
}

/**
* Determine if this a valid name for fields, local variables, etc. Can be used
* to check anything except method names and class names.
Expand Down
26 changes: 16 additions & 10 deletions runtime/vm/classsupport.c
Expand Up @@ -304,14 +304,26 @@ internalFindClassString(J9VMThread* currentThread, j9object_t moduleName, j9obje
if (NULL == result) {
J9Module **findResult = NULL;
J9Module *j9module = NULL;
char localBuf[J9VM_PACKAGE_NAME_BUFFER_LENGTH];
char *utf8Name = NULL;
U_8 localBuf[J9VM_PACKAGE_NAME_BUFFER_LENGTH];
U_8 *utf8Name = NULL;
UDATA utf8Length = 0;
UDATA stringFlags = J9_STR_NULL_TERMINATE_RESULT;
PORT_ACCESS_FROM_JAVAVM(vm);

if (CLASSNAME_INVALID == allowedBitsForClassName) {
stringFlags |= J9_STR_XLAT;
}

utf8Name = (U_8*)copyStringToUTF8WithMemAlloc(currentThread, className, stringFlags, "", 0, (char *)localBuf, J9VM_PACKAGE_NAME_BUFFER_LENGTH, &utf8Length);
if (NULL == utf8Name) {
/* Throw out-of-memory */
setNativeOutOfMemoryError(currentThread, 0, 0);
return NULL;
}

/* Make sure the name is legal */
if ((CLASSNAME_INVALID == allowedBitsForClassName)
|| (CLASSNAME_INVALID != verifyQualifiedName(currentThread, className, allowedBitsForClassName))
|| (CLASSNAME_INVALID != verifyQualifiedName(currentThread, utf8Name, utf8Length, allowedBitsForClassName))
) {
if (NULL != moduleName) {
J9Module module = {0};
Expand All @@ -324,13 +336,7 @@ internalFindClassString(J9VMThread* currentThread, j9object_t moduleName, j9obje
}
}

utf8Name = copyStringToUTF8WithMemAlloc(currentThread, className, J9_STR_NULL_TERMINATE_RESULT | J9_STR_XLAT, "", 0, localBuf, J9VM_PACKAGE_NAME_BUFFER_LENGTH, &utf8Length);
if (NULL == utf8Name) {
/* Throw out-of-memory */
setNativeOutOfMemoryError(currentThread, 0, 0);
return NULL;
}
result = internalFindClassInModule(currentThread, j9module, (U_8 *)utf8Name, utf8Length, classLoader, options);
result = internalFindClassInModule(currentThread, j9module, utf8Name, utf8Length, classLoader, options);
if (utf8Name != localBuf) {
j9mem_free_memory(utf8Name);
}
Expand Down
49 changes: 16 additions & 33 deletions runtime/vm/stringhelpers.cpp
Expand Up @@ -371,26 +371,19 @@ getStringUTF8Length(J9VMThread *vmThread, j9object_t string)
}

UDATA
verifyQualifiedName(J9VMThread *vmThread, j9object_t string, UDATA allowedBitsForClassName)
verifyQualifiedName(J9VMThread *vmThread, U_8 *className, UDATA classNameLength, UDATA allowedBitsForClassName)
{
UDATA unicodeLength = J9VMJAVALANGSTRING_LENGTH(vmThread, string);
j9object_t unicodeBytes = J9VMJAVALANGSTRING_VALUE(vmThread, string);
BOOLEAN isStringCompressed = IS_STRING_COMPRESSED(vmThread, string);
UDATA remainingLength = unicodeLength;
UDATA result = CLASSNAME_INVALID;
UDATA remainingLength = classNameLength;
BOOLEAN separator = FALSE;
BOOLEAN unCheckedChar = FALSE;
U_8 currentChar = 0;
IDATA arity = 0;
UDATA arity = 0;
UDATA i = 0;
UDATA result = CLASSNAME_INVALID;

/* strip leading ['s for array classes */
for (i = 0; i < unicodeLength; i++) {
currentChar = isStringCompressed ? J9JAVAARRAYOFBYTE_LOAD(vmThread, unicodeBytes, i) : (U_8)J9JAVAARRAYOFCHAR_LOAD(vmThread, unicodeBytes, i);
if ('[' == currentChar) {
for (i = 0; i < classNameLength; i++) {
if ('[' == className[i]) {
arity += 1;
} else {
unCheckedChar = TRUE;
break;
}
}
Expand All @@ -402,23 +395,19 @@ verifyQualifiedName(J9VMThread *vmThread, j9object_t string, UDATA allowedBitsFo
}

/* check invalid characters in the class name */
for (; i < unicodeLength; i++) {
if (unCheckedChar) {
unCheckedChar = FALSE;
} else {
currentChar = isStringCompressed ? J9JAVAARRAYOFBYTE_LOAD(vmThread, unicodeBytes, i) : (U_8)J9JAVAARRAYOFCHAR_LOAD(vmThread, unicodeBytes, i);
}

for (; i < classNameLength; i++) {
/* check for illegal characters: 46(.) 47(/) 59(;) 60(<) 70(>) 91([) */
switch (currentChar) {
case '.': /* Fall through */
case '/':
/* Only valid between identifiers and not at end if not in loading classes */
if (('/' == currentChar) || separator) {
switch (className[i]) {
case '.':
if (separator) {
return CLASSNAME_INVALID;
}
/* convert the characters from '.' to '/' in the case of J9_STR_XLAT for later use in the caller */
className[i] = '/';
separator = TRUE;
break;
case '/':
return CLASSNAME_INVALID;
case ';':
/* Valid at the end of array classes */
if (arity && (1 == remainingLength)) {
Expand All @@ -444,15 +433,9 @@ verifyQualifiedName(J9VMThread *vmThread, j9object_t string, UDATA allowedBitsFo
return CLASSNAME_INVALID;
}

/* map the return code against the arity value from checkNameImpl (called by bcvCheckClassName):
* 1) if arity = -1, then rc = CLASSNAME_INVALID(0)
* 2) if arity = 0, then rc = CLASSNAME_VALID_NON_ARRARY(1)
* 3) if arity > 0, then rc = CLASSNAME_VALID_ARRARY(2)
/* check the arity of the class name to see whether it is an array or not
* and check whether the results are the allowed values by the caller.
*/
if (arity < 0) {
return CLASSNAME_INVALID;
}

result = (0 == arity) ? CLASSNAME_VALID_NON_ARRARY : CLASSNAME_VALID_ARRARY;
if (J9_ARE_ANY_BITS_SET(result, allowedBitsForClassName)) {
return result;
Expand Down

0 comments on commit 5f01dc2

Please sign in to comment.