Skip to content

Commit

Permalink
Merge pull request #8460 from fengxue-IS/cpPatching2
Browse files Browse the repository at this point in the history
Support for CP String patching
  • Loading branch information
DanHeidinga authored Feb 8, 2020
2 parents 961dc66 + 99754a9 commit 71b7b69
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 17 deletions.
16 changes: 15 additions & 1 deletion runtime/bcutil/ConstantPoolMap.cpp
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 @@ -302,6 +302,20 @@ ConstantPoolMap::computeConstantPoolMapAndSizes()
}
}
}

J9ClassPatchMap *map = _context->patchMap();

/**
* If a valid patchMap structure is passed, this class requires ConstantPool patching.
* Record the index mapping from Classfile to J9Class constantpool to allow patching
* the RAM CP after it is created by VM.
*/
if (map != NULL) {
Trc_BCU_Assert_Equals(map->size, cfrCPCount);
for (U_16 cfrCPIndex = 0; cfrCPIndex < cfrCPCount; cfrCPIndex++) {
map->indexMap[cfrCPIndex] = _constantPoolEntries[cfrCPIndex].romCPIndex;
}
}
}

bool
Expand Down
8 changes: 6 additions & 2 deletions runtime/bcutil/ROMClassCreationContext.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2001, 2019 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 @@ -150,13 +150,15 @@ class ROMClassCreationContext
_doDebugCompare(false),
_existingRomMethod(NULL),
_reusingIntermediateClassData(false),
_creatingIntermediateROMClass(creatingIntermediateROMClass)
_creatingIntermediateROMClass(creatingIntermediateROMClass),
_patchMap(NULL)
{
if ((NULL != _javaVM) && (NULL != _javaVM->dynamicLoadBuffers)) {
/* localBuffer should not be NULL */
Trc_BCU_Assert_True(NULL != localBuffer);
_cpIndex = localBuffer->entryIndex;
_loadLocation = localBuffer->loadLocationType;
_patchMap = localBuffer->patchMap;
_sharedStringInternTable = _javaVM->sharedInvariantInternTable;
_interningEnabled = J9_ARE_ALL_BITS_SET(_bcuFlags, BCU_ENABLE_INVARIANT_INTERNING) && J9_ARE_NO_BITS_SET(_findClassFlags, J9_FINDCLASS_FLAG_ANON);
if (0 != (bcuFlags & BCU_VERBOSE)) {
Expand Down Expand Up @@ -189,6 +191,7 @@ class ROMClassCreationContext
J9PortLibrary *portLibrary() const { return _portLibrary; }
UDATA cpIndex() const { return _cpIndex; }
UDATA loadLocation() const {return _loadLocation; }
J9ClassPatchMap *patchMap() const { return _patchMap; }
J9SharedInvariantInternTable *sharedStringInternTable() const { return _sharedStringInternTable; }

U_8 *intermediateClassData() const { return _intermediateClassData; }
Expand Down Expand Up @@ -741,6 +744,7 @@ class ROMClassCreationContext
J9ROMMethod * _existingRomMethod;
bool _reusingIntermediateClassData;
bool _creatingIntermediateROMClass;
J9ClassPatchMap *_patchMap;

J9ROMMethod * romMethodFromOffset(IDATA offset);
};
Expand Down
4 changes: 2 additions & 2 deletions runtime/jcl/common/clsldr.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1998, 2019 IBM Corp. and others
* Copyright (c) 1998, 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 @@ -70,7 +70,7 @@ Java_java_lang_ClassLoader_defineClassImpl(JNIEnv *env, jobject receiver, jstrin
options |= J9_FINDCLASS_FLAG_UNSAFE;
}

jclass result = defineClassCommon(env, receiver, className, classRep, offset, length, protectionDomain, options, NULL);
jclass result = defineClassCommon(env, receiver, className, classRep, offset, length, protectionDomain, options, NULL, NULL);

if (J9_ARE_ANY_BITS_SET(options, J9_FINDCLASS_FLAG_NAME_IS_INVALID) && (NULL == result) && (NULL == currentThread->currentException)) {
/*
Expand Down
8 changes: 6 additions & 2 deletions runtime/jcl/common/jcldefine.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1998, 2019 IBM Corp. and others
* Copyright (c) 1998, 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 @@ -29,7 +29,7 @@

jclass
defineClassCommon(JNIEnv *env, jobject classLoaderObject,
jstring className, jbyteArray classRep, jint offset, jint length, jobject protectionDomain, UDATA options, J9Class *hostClass)
jstring className, jbyteArray classRep, jint offset, jint length, jobject protectionDomain, UDATA options, J9Class *hostClass, J9ClassPatchMap *patchMap)
{
#ifdef J9VM_OPT_DYNAMIC_LOAD_SUPPORT

Expand Down Expand Up @@ -70,6 +70,10 @@ defineClassCommon(JNIEnv *env, jobject classLoaderObject,
goto done;
}

if ((patchMap != NULL) && (patchMap->size != 0)) {
localBuffer.patchMap = patchMap;
}

vmFuncs->internalEnterVMFromJNI(currentThread);
isContiguousClassBytes = J9ISCONTIGUOUSARRAY(currentThread, *(J9IndexableObject **)classRep);
if (!isContiguousClassBytes) {
Expand Down
6 changes: 3 additions & 3 deletions runtime/jcl/common/proxy.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1998, 2019 IBM Corp. and others
* Copyright (c) 1998, 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 @@ -88,7 +88,7 @@ static jclass proxyDefineClass(
defineClassOptions |= J9_FINDCLASS_FLAG_UNSAFE;
}
#endif /* JAVA_SPEC_VERSION == 8 */
return defineClassCommon(env, classLoader, className, classBytes, offset, length, pd, defineClassOptions, NULL);
return defineClassCommon(env, classLoader, className, classBytes, offset, length, pd, defineClassOptions, NULL, NULL);
}

jclass JNICALL Java_java_lang_reflect_Proxy_defineClassImpl(JNIEnv * env, jclass recvClass, jobject classLoader, jstring className, jbyteArray classBytes)
Expand Down Expand Up @@ -119,7 +119,7 @@ Java_java_lang_reflect_Proxy_defineClass0__Ljava_lang_ClassLoader_2Ljava_lang_St
defineClassOptions |= J9_FINDCLASS_FLAG_UNSAFE;
}
#endif /* JAVA_SPEC_VERSION == 8 */
return defineClassCommon(env, classLoader, className, classBytes, offset, length, pd, defineClassOptions, NULL);
return defineClassCommon(env, classLoader, className, classBytes, offset, length, pd, defineClassOptions, NULL, NULL);
}
}

71 changes: 65 additions & 6 deletions runtime/jcl/common/sun_misc_Unsafe.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1998, 2019 IBM Corp. and others
* Copyright (c) 1998, 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 @@ -41,6 +41,8 @@

extern "C" {

#define BUFFER_SIZE 128

jclass JNICALL
Java_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2(
JNIEnv *env, jobject receiver, jstring className, jbyteArray classRep, jint offset, jint length, jobject classLoader, jobject protectionDomain)
Expand All @@ -59,7 +61,7 @@ Java_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader
vmFuncs->internalExitVMToJNI(currentThread);
}

return defineClassCommon(env, classLoader, className, classRep, offset, length, protectionDomain, J9_FINDCLASS_FLAG_UNSAFE, NULL);
return defineClassCommon(env, classLoader, className, classRep, offset, length, protectionDomain, J9_FINDCLASS_FLAG_UNSAFE, NULL, NULL);
}

jclass JNICALL
Expand All @@ -69,9 +71,6 @@ Java_sun_misc_Unsafe_defineAnonymousClass(JNIEnv *env, jobject receiver, jclass
J9JavaVM *vm = currentThread->javaVM;
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;

/* For JSR335 this should be NULL */
Assert_JCL_true(constPatches == NULL);

vmFuncs->internalEnterVMFromJNI(currentThread);
if (NULL == bytecodes) {
vmFuncs->setCurrentException(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);
Expand All @@ -96,19 +95,79 @@ Java_sun_misc_Unsafe_defineAnonymousClass(JNIEnv *env, jobject receiver, jclass
hostClassLoader = vm->systemClassLoader->classLoaderObject;
}
jobject hostClassLoaderLocalRef = vmFuncs->j9jni_createLocalRef(env, hostClassLoader);

J9ClassPatchMap cpPatchMap = {0, NULL};
j9array_t patchArray = NULL;
PORT_ACCESS_FROM_ENV(env);

U_16 indexMap[BUFFER_SIZE];
if (constPatches != NULL) {
patchArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(constPatches);
cpPatchMap.size = (U_16)J9INDEXABLEOBJECT_SIZE(currentThread, patchArray);
if (cpPatchMap.size <= BUFFER_SIZE) {
cpPatchMap.indexMap = indexMap;
} else {
cpPatchMap.indexMap = (U_16 *)j9mem_allocate_memory(cpPatchMap.size * sizeof(U_16), J9MEM_CATEGORY_VM);

if (cpPatchMap.indexMap == NULL) {
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
vmFuncs->internalExitVMToJNI(currentThread);
return NULL;
}
}
}

vmFuncs->internalExitVMToJNI(currentThread);

jsize length = env->GetArrayLength(bytecodes);

/* acquires access internally */
jclass anonClass = defineClassCommon(env, hostClassLoaderLocalRef, NULL,bytecodes, 0, length, protectionDomainLocalRef, J9_FINDCLASS_FLAG_UNSAFE | J9_FINDCLASS_FLAG_ANON, hostClazz);
jclass anonClass = defineClassCommon(env, hostClassLoaderLocalRef, NULL,bytecodes, 0, length, protectionDomainLocalRef, J9_FINDCLASS_FLAG_UNSAFE | J9_FINDCLASS_FLAG_ANON, hostClazz, &cpPatchMap);
if (env->ExceptionCheck()) {
return NULL;
} else if (NULL == anonClass) {
throwNewInternalError(env, NULL);
return NULL;
}

if (constPatches != NULL) {
vmFuncs->internalEnterVMFromJNI(currentThread);
J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(anonClass));
U_32 *cpShapeDescription = J9ROMCLASS_CPSHAPEDESCRIPTION(clazz->romClass);
J9ConstantPool *ramCP = J9_CP_FROM_CLASS(clazz);
J9ROMConstantPoolItem *romCP = ramCP->romConstantPool;

/* Get J9 constantpool mapped item for patch item, only support patching STRING entries has been added */
for (U_16 i = 0; i < cpPatchMap.size; i++) {
j9object_t item = J9JAVAARRAYOFOBJECT_LOAD(currentThread, patchArray, i);
if (item != NULL) {
if (J9_CP_TYPE(cpShapeDescription, cpPatchMap.indexMap[i]) == J9CPTYPE_STRING) {

J9UTF8 *romString = J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *)&romCP[cpPatchMap.indexMap[i]]);

/* For each patch object, search the RAM constantpool for identical string entries */
for (U_16 j = 1; j < clazz->romClass->ramConstantPoolCount; j++) {
if ((J9_CP_TYPE(cpShapeDescription, j) == J9CPTYPE_STRING)
&& J9UTF8_EQUALS(romString, J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *)&romCP[j]))
) {
J9RAMStringRef *ramStringRef = ((J9RAMStringRef *)ramCP) + j;
J9STATIC_OBJECT_STORE(currentThread, clazz, &ramStringRef->stringObject, item);
}
}
} else {
/* Only J9CPTYPE_STRING is patched, other CP types are not supported */
Assert_JCL_unreachable();
}
}
}

if (cpPatchMap.size > BUFFER_SIZE) {
j9mem_free_memory(cpPatchMap.indexMap);
cpPatchMap.indexMap = NULL;
}
vmFuncs->internalExitVMToJNI(currentThread);
}

return anonClass;
}

Expand Down
6 changes: 6 additions & 0 deletions runtime/oti/j9nonbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1825,6 +1825,7 @@ typedef struct J9TranslationLocalBuffer {
IDATA entryIndex;
I_32 loadLocationType;
struct J9ClassPathEntry* cpEntryUsed;
struct J9ClassPatchMap* patchMap;
} J9TranslationLocalBuffer;

typedef struct J9TranslationBufferSet {
Expand Down Expand Up @@ -1958,6 +1959,11 @@ typedef struct J9ClassPathEntry {
#endif
} J9ClassPathEntry;

typedef struct J9ClassPatchMap {
U_16 size;
U_16* indexMap;
} J9ClassPatchMap;

#define CPE_STATUS_ASSUME_JXE 0x1
#define CPE_STATUS_JXE_MISSING_ROM_CLASSES 0x2
#define CPE_STATUS_JXE_CORRUPT_IMAGE_HEADER 0x4
Expand Down
2 changes: 1 addition & 1 deletion runtime/oti/jclprots.h
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ UDATA initializeRequiredClasses(J9VMThread *vmThread, char* libName);
/* J9SourceJclDefineClass*/
extern J9_CFUNC jclass
defineClassCommon (JNIEnv *env, jobject classLoaderObject,
jstring className, jbyteArray classRep, jint offset, jint length, jobject protectionDomain, UDATA options, J9Class *hostClass);
jstring className, jbyteArray classRep, jint offset, jint length, jobject protectionDomain, UDATA options, J9Class *hostClass, J9ClassPatchMap *patchMap);

/* BBjclNativesCommonAccessController*/
jboolean JNICALL Java_java_security_AccessController_initializeInternal (JNIEnv *env, jclass thisClz);
Expand Down

0 comments on commit 71b7b69

Please sign in to comment.