Path: blob/master/runtime/jcl/common/java_lang_invoke_MethodHandleNatives.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2021, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#include "j9.h"23#include "jclprots.h"24#include "j9cp.h"25#include "j9protos.h"26#include "ut_j9jcl.h"27#include "j9port.h"28#include "jclglob.h"29#include "jcl_internal.h"30#include "util_api.h"31#include "j9vmconstantpool.h"32#include "ObjectAccessBarrierAPI.hpp"33#include "objhelp.h"3435#include <string.h>36#include <assert.h>3738#include "VMHelpers.hpp"3940extern "C" {4142#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)4344/* Constants mapped from java.lang.invoke.MethodHandleNatives$Constants45* These constants are validated by the MethodHandleNatives$Constants.verifyConstants()46* method when Java assertions are enabled47*/4849#define MN_REFERENCE_KIND_SHIFT 2450#define MN_REFERENCE_KIND_MASK 0xF /* (flag >> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK */5152#define MN_SEARCH_SUPERCLASSES 0x0010000053#define MN_SEARCH_INTERFACES 0x002000005455#if JAVA_SPEC_VERSION >= 1656#define MN_MODULE_MODE 0x0000001057#define MN_UNCONDITIONAL_MODE 0x0000002058#define MN_TRUSTED_MODE -159#endif /* JAVA_SPEC_VERSION >= 16 */6061/* PlaceHolder value used for MN.vmindex that has default method conflict */62#define J9VM_RESOLVED_VMINDEX_FOR_DEFAULT_THROW 16364J9_DECLARE_CONSTANT_UTF8(mutableCallSite, "java/lang/invoke/MutableCallSite");6566static bool67isPolymorphicMHMethod(J9JavaVM *vm, J9Class *declaringClass, J9UTF8 *methodName)68{69if (declaringClass == J9VMJAVALANGINVOKEMETHODHANDLE(vm)) {70U_8 *nameData = J9UTF8_DATA(methodName);71U_16 nameLength = J9UTF8_LENGTH(methodName);7273if (J9UTF8_LITERAL_EQUALS(nameData, nameLength, "invoke")74|| J9UTF8_LITERAL_EQUALS(nameData, nameLength, "invokeBasic")75|| J9UTF8_LITERAL_EQUALS(nameData, nameLength, "linkToVirtual")76|| J9UTF8_LITERAL_EQUALS(nameData, nameLength, "linkToStatic")77|| J9UTF8_LITERAL_EQUALS(nameData, nameLength, "linkToSpecial")78|| J9UTF8_LITERAL_EQUALS(nameData, nameLength, "linkToInterface")79|| J9UTF8_LITERAL_EQUALS(nameData, nameLength, "linkToNative")80) {81return true;82}83}8485return false;86}8788/* Private MemberName object init helper89*90* Set the MemberName fields based on the refObject given:91* For j.l.reflect.Field:92* find JNIFieldID for refObject, create j.l.String for name and signature and store in MN.name/type fields.93* set vmindex to the fieldID pointer and target to the field offset.94* set MN.clazz to declaring class in the fieldID struct.95* For j.l.reflect.Method or j.l.reflect.Constructor:96* find JNIMethodID, set vmindex to the methodID pointer and target to the J9Method struct.97* set MN.clazz to the refObject's declaring class.98*99* Then for both, compute the MN.flags using access flags and invocation type based on the JNI-id.100*101* Throw an IllegalArgumentException if the refObject is not a Field/Method/Constructor102*103* Note: caller must have vmaccess before invoking this helper104*/105static void106initImpl(J9VMThread *currentThread, j9object_t membernameObject, j9object_t refObject)107{108J9JavaVM *vm = currentThread->javaVM;109const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;110111J9Class* refClass = J9OBJECT_CLAZZ(currentThread, refObject);112113jint flags = 0;114jlong vmindex = 0;115jlong target = 0;116j9object_t clazzObject = NULL;117j9object_t nameObject = NULL;118j9object_t typeObject = NULL;119120if (refClass == J9VMJAVALANGREFLECTFIELD(vm)) {121J9JNIFieldID *fieldID = vm->reflectFunctions.idFromFieldObject(currentThread, NULL, refObject);122J9ROMFieldShape *romField = fieldID->field;123UDATA offset = fieldID->offset;124125if (J9_ARE_ANY_BITS_SET(romField->modifiers, J9AccStatic)) {126offset |= J9_SUN_STATIC_FIELD_OFFSET_TAG;127if (J9_ARE_ANY_BITS_SET(romField->modifiers, J9AccFinal)) {128offset |= J9_SUN_FINAL_FIELD_OFFSET_TAG;129}130}131vmindex = (jlong)fieldID;132target = (jlong)offset;133134flags = fieldID->field->modifiers & CFR_FIELD_ACCESS_MASK;135flags |= MN_IS_FIELD;136flags |= (J9_ARE_ANY_BITS_SET(flags, J9AccStatic) ? MH_REF_GETSTATIC : MH_REF_GETFIELD) << MN_REFERENCE_KIND_SHIFT;137if (VM_VMHelpers::isTrustedFinalField(fieldID->field, fieldID->declaringClass->romClass)) {138flags |= MN_TRUSTED_FINAL;139}140141nameObject = J9VMJAVALANGREFLECTFIELD_NAME(currentThread, refObject);142typeObject = J9VMJAVALANGREFLECTFIELD_TYPE(currentThread, refObject);143144clazzObject = J9VM_J9CLASS_TO_HEAPCLASS(fieldID->declaringClass);145} else if (refClass == J9VMJAVALANGREFLECTMETHOD(vm)) {146J9JNIMethodID *methodID = vm->reflectFunctions.idFromMethodObject(currentThread, refObject);147vmindex = (jlong)methodID;148target = (jlong)methodID->method;149150J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(methodID->method);151152J9Class *declaringClass = J9_CLASS_FROM_METHOD(methodID->method);153J9UTF8 *methodName = J9ROMMETHOD_NAME(romMethod);154if (isPolymorphicMHMethod(vm, declaringClass, methodName)155#if JAVA_SPEC_VERSION >= 9156|| ((declaringClass == J9VMJAVALANGINVOKEVARHANDLE(vm))157&& VM_VMHelpers::isPolymorphicVarHandleMethod(J9UTF8_DATA(methodName), J9UTF8_LENGTH(methodName)))158#endif159) {160/* Do not initialize polymorphic MH/VH methods as the Java code handles the "MemberName.clazz == null" case for them. */161return;162}163164flags = romMethod->modifiers & CFR_METHOD_ACCESS_MASK;165if (J9_ARE_ANY_BITS_SET(romMethod->modifiers, J9AccMethodCallerSensitive)) {166flags |= MN_CALLER_SENSITIVE;167}168flags |= MN_IS_METHOD;169if (J9_ARE_ANY_BITS_SET(methodID->vTableIndex, J9_JNI_MID_INTERFACE)) {170flags |= MH_REF_INVOKEINTERFACE << MN_REFERENCE_KIND_SHIFT;171} else if (J9_ARE_ANY_BITS_SET(romMethod->modifiers , J9AccStatic)) {172flags |= MH_REF_INVOKESTATIC << MN_REFERENCE_KIND_SHIFT;173} else if (J9_ARE_ANY_BITS_SET(romMethod->modifiers , J9AccFinal) || !J9ROMMETHOD_HAS_VTABLE(romMethod)) {174flags |= MH_REF_INVOKESPECIAL << MN_REFERENCE_KIND_SHIFT;175} else {176flags |= MH_REF_INVOKEVIRTUAL << MN_REFERENCE_KIND_SHIFT;177}178179nameObject = J9VMJAVALANGREFLECTMETHOD_NAME(currentThread, refObject);180clazzObject = J9VMJAVALANGREFLECTMETHOD_CLAZZ(currentThread, refObject);181} else if (refClass == J9VMJAVALANGREFLECTCONSTRUCTOR(vm)) {182J9JNIMethodID *methodID = vm->reflectFunctions.idFromConstructorObject(currentThread, refObject);183vmindex = (jlong)methodID;184target = (jlong)methodID->method;185186J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(methodID->method);187188flags = romMethod->modifiers & CFR_METHOD_ACCESS_MASK;189if (J9_ARE_ANY_BITS_SET(romMethod->modifiers, J9AccMethodCallerSensitive)) {190flags |= MN_CALLER_SENSITIVE;191}192flags |= MN_IS_CONSTRUCTOR | (MH_REF_INVOKESPECIAL << MN_REFERENCE_KIND_SHIFT);193194clazzObject = J9VMJAVALANGREFLECTMETHOD_CLAZZ(currentThread, refObject);195} else {196vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, NULL);197}198199if (!VM_VMHelpers::exceptionPending(currentThread)) {200J9VMJAVALANGINVOKEMEMBERNAME_SET_FLAGS(currentThread, membernameObject, flags);201J9VMJAVALANGINVOKEMEMBERNAME_SET_NAME(currentThread, membernameObject, nameObject);202if (NULL != typeObject) {203Assert_JCL_true(OMR_ARE_ALL_BITS_SET(flags, MN_IS_FIELD));204J9VMJAVALANGINVOKEMEMBERNAME_SET_TYPE(currentThread, membernameObject, typeObject);205}206J9VMJAVALANGINVOKEMEMBERNAME_SET_CLAZZ(currentThread, membernameObject, clazzObject);207J9OBJECT_U64_STORE(currentThread, membernameObject, vm->vmindexOffset, (U_64)vmindex);208J9OBJECT_U64_STORE(currentThread, membernameObject, vm->vmtargetOffset, (U_64)target);209Trc_JCL_java_lang_invoke_MethodHandleNatives_initImpl_setData(currentThread, flags, nameObject, typeObject, clazzObject, vmindex, target);210}211}212213static char *214sigForPrimitiveOrVoid(J9JavaVM *vm, J9Class *clazz)215{216PORT_ACCESS_FROM_JAVAVM(vm);217char* signature = (char*)j9mem_allocate_memory(2, OMRMEM_CATEGORY_VM);218219if (NULL != signature) {220if (clazz == vm->booleanReflectClass) {221signature[0] = 'Z';222} else if (clazz == vm->byteReflectClass) {223signature[0] = 'B';224} else if (clazz == vm->charReflectClass) {225signature[0] = 'C';226} else if (clazz == vm->shortReflectClass) {227signature[0] = 'S';228} else if (clazz == vm->intReflectClass) {229signature[0] = 'I';230} else if (clazz == vm->longReflectClass) {231signature[0] = 'J';232} else if (clazz == vm->floatReflectClass) {233signature[0] = 'F';234} else if (clazz == vm->doubleReflectClass) {235signature[0] = 'D';236} else if (clazz == vm->voidReflectClass) {237signature[0] = 'V';238}239240signature[1] = '\0';241}242243return signature;244}245246static char *247getClassSignature(J9VMThread *currentThread, J9Class * clazz)248{249J9JavaVM *vm = currentThread->javaVM;250PORT_ACCESS_FROM_JAVAVM(vm);251char *sig = NULL;252253if (J9ROMCLASS_IS_PRIMITIVE_TYPE(clazz->romClass)) {254sig = sigForPrimitiveOrVoid(vm, clazz);255} else {256j9object_t sigString = J9VMJAVALANGCLASS_CLASSNAMESTRING(currentThread, J9VM_J9CLASS_TO_HEAPCLASS(clazz));257if (NULL != sigString) {258/* +3 so that we can fit 'L' and ';' around the class name with the null-terminator */259UDATA utfLength = vm->internalVMFunctions->getStringUTF8Length(currentThread, sigString) + 3;260sig = (char *)j9mem_allocate_memory(utfLength, OMRMEM_CATEGORY_VM);261if (NULL != sig) {262if (J9ROMCLASS_IS_ARRAY(clazz->romClass)) {263vm->internalVMFunctions->copyStringToUTF8Helper(currentThread, sigString, J9_STR_NULL_TERMINATE_RESULT | J9_STR_XLAT, 0, J9VMJAVALANGSTRING_LENGTH(currentThread, sigString), (U_8*)sig, utfLength);264} else {265sig[0] = 'L';266vm->internalVMFunctions->copyStringToUTF8Helper(currentThread, sigString, J9_STR_XLAT, 0, J9VMJAVALANGSTRING_LENGTH(currentThread, sigString), (U_8*)(sig + 1), utfLength - 1);267sig[utfLength - 2] = ';';268sig[utfLength - 1] = '\0';269}270}271} else {272U_32 numDims = 0;273274J9Class *myClass = clazz;275while (J9ROMCLASS_IS_ARRAY(myClass->romClass)) {276J9Class * componentClass = (J9Class *)(((J9ArrayClass*)myClass)->componentType);277if (J9ROMCLASS_IS_PRIMITIVE_TYPE(componentClass->romClass)) {278break;279}280numDims += 1;281myClass = componentClass;282}283284J9UTF8 *romName = J9ROMCLASS_CLASSNAME(myClass->romClass);285U_32 nameLength = J9UTF8_LENGTH(romName);286char * name = (char *)J9UTF8_DATA(romName);287U_32 sigLength = nameLength + numDims;288if (* name != '[') {289sigLength += 2;290}291292sigLength++; /* for null-termination */293sig = (char *)j9mem_allocate_memory(sigLength, OMRMEM_CATEGORY_VM);294if (NULL != sig) {295U_32 i = 0;296for (i = 0; i < numDims; i++) {297sig[i] = '[';298}299300if (*name != '[') {301sig[i++] = 'L';302}303304memcpy(sig+i, name, nameLength);305i += nameLength;306307if (*name != '[') {308sig[i++] = ';';309}310sig[sigLength-1] = '\0';311}312}313}314315return sig;316}317318static J9UTF8 *319getJ9UTF8SignatureFromMethodType(J9VMThread *currentThread, j9object_t typeObject)320{321J9JavaVM *vm = currentThread->javaVM;322j9object_t ptypes = J9VMJAVALANGINVOKEMETHODTYPE_PTYPES(currentThread, typeObject);323U_32 numArgs = J9INDEXABLEOBJECT_SIZE(currentThread, ptypes);324325J9UTF8* methodDescriptor = NULL;326char* cursor = NULL;327char* rSignature = NULL;328UDATA signatureLength = 2; /* space for '(', ')' */329330PORT_ACCESS_FROM_JAVAVM(vm);331332char** signatures = (char**)j9mem_allocate_memory(numArgs * sizeof(char*), OMRMEM_CATEGORY_VM);333if (NULL == signatures) {334goto done;335}336337memset(signatures, 0, numArgs * sizeof(char*));338339for (U_32 i = 0; i < numArgs; i++) {340j9object_t pObject = J9JAVAARRAYOFOBJECT_LOAD(currentThread, ptypes, i);341J9Class *pclass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, pObject);342signatures[i] = getClassSignature(currentThread, pclass);343if (NULL == signatures[i]) {344goto done;345}346347signatureLength += strlen(signatures[i]);348}349350{351/* Return type */352j9object_t rtype = J9VMJAVALANGINVOKEMETHODTYPE_RTYPE(currentThread, typeObject);353J9Class *rclass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, rtype);354rSignature = getClassSignature(currentThread, rclass);355if (NULL == rSignature) {356goto done;357}358359signatureLength += strlen(rSignature);360}361362methodDescriptor = (J9UTF8*)j9mem_allocate_memory(signatureLength + sizeof(J9UTF8), OMRMEM_CATEGORY_VM);363if (NULL == methodDescriptor) {364goto done;365}366J9UTF8_SET_LENGTH(methodDescriptor, (U_16)signatureLength);367cursor = (char*)J9UTF8_DATA(methodDescriptor);368*cursor++ = '(';369370/* Copy class signatures to descriptor string */371for (U_32 i = 0; i < numArgs; i++) {372UDATA len = strlen(signatures[i]);373memcpy(cursor, signatures[i], len);374cursor += len;375}376377*cursor++ = ')';378/* Copy return type signature to descriptor string */379memcpy(cursor, rSignature, strlen(rSignature));380381done:382j9mem_free_memory(rSignature);383384if (NULL != signatures) {385for (U_32 i = 0; i < numArgs; i++) {386j9mem_free_memory(signatures[i]);387}388j9mem_free_memory(signatures);389}390return methodDescriptor;391}392393j9object_t394resolveRefToObject(J9VMThread *currentThread, J9ConstantPool *ramConstantPool, U_16 cpIndex, bool resolve)395{396J9JavaVM *vm = currentThread->javaVM;397const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;398399j9object_t result = NULL;400401J9RAMSingleSlotConstantRef *ramCP = (J9RAMSingleSlotConstantRef*)ramConstantPool + cpIndex;402U_32 *cpShapeDescription = J9ROMCLASS_CPSHAPEDESCRIPTION(J9_CLASS_FROM_CP(ramConstantPool)->romClass);403404switch (J9_CP_TYPE(cpShapeDescription, cpIndex)) {405case J9CPTYPE_CLASS: {406J9Class *clazz = (J9Class*)ramCP->value;407if ((NULL == clazz) && resolve) {408clazz = vmFuncs->resolveClassRef(currentThread, ramConstantPool, cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE);409}410if (NULL != clazz) {411result = J9VM_J9CLASS_TO_HEAPCLASS(clazz);412}413break;414}415case J9CPTYPE_STRING: {416result = (j9object_t)ramCP->value;417if ((NULL == result) && resolve) {418result = vmFuncs->resolveStringRef(currentThread, ramConstantPool, cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE);419}420break;421}422case J9CPTYPE_INT: {423J9ROMSingleSlotConstantRef *romCP = (J9ROMSingleSlotConstantRef*)J9_ROM_CP_FROM_CP(ramConstantPool) + cpIndex;424result = vm->memoryManagerFunctions->J9AllocateObject(currentThread, J9VMJAVALANGINTEGER_OR_NULL(vm), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);425if (NULL == result) {426vmFuncs->setHeapOutOfMemoryError(currentThread);427goto done;428}429J9VMJAVALANGINTEGER_SET_VALUE(currentThread, result, romCP->data);430break;431}432case J9CPTYPE_FLOAT: {433J9ROMSingleSlotConstantRef *romCP = (J9ROMSingleSlotConstantRef*)J9_ROM_CP_FROM_CP(ramConstantPool) + cpIndex;434result = vm->memoryManagerFunctions->J9AllocateObject(currentThread, J9VMJAVALANGFLOAT_OR_NULL(vm), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);435if (NULL == result) {436vmFuncs->setHeapOutOfMemoryError(currentThread);437goto done;438}439J9VMJAVALANGFLOAT_SET_VALUE(currentThread, result, romCP->data);440break;441}442case J9CPTYPE_LONG: {443J9ROMConstantRef *romCP = (J9ROMConstantRef*)J9_ROM_CP_FROM_CP(ramConstantPool) + cpIndex;444#ifdef J9VM_ENV_LITTLE_ENDIAN445U_64 value = (((U_64)(romCP->slot2)) << 32) | ((U_64)(romCP->slot1));446#else447U_64 value = (((U_64)(romCP->slot1)) << 32) | ((U_64)(romCP->slot2));448#endif449result = vm->memoryManagerFunctions->J9AllocateObject(currentThread, J9VMJAVALANGLONG_OR_NULL(vm), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);450if (NULL == result) {451vmFuncs->setHeapOutOfMemoryError(currentThread);452goto done;453}454J9VMJAVALANGLONG_SET_VALUE(currentThread, result, value);455break;456}457case J9CPTYPE_DOUBLE: {458J9ROMConstantRef *romCP = (J9ROMConstantRef*)J9_ROM_CP_FROM_CP(ramConstantPool) + cpIndex;459#ifdef J9VM_ENV_LITTLE_ENDIAN460U_64 value = (((U_64)(romCP->slot2)) << 32) | ((U_64)(romCP->slot1));461#else462U_64 value = (((U_64)(romCP->slot1)) << 32) | ((U_64)(romCP->slot2));463#endif464result = vm->memoryManagerFunctions->J9AllocateObject(currentThread, J9VMJAVALANGDOUBLE_OR_NULL(vm), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);465if (NULL == result) {466vmFuncs->setHeapOutOfMemoryError(currentThread);467goto done;468}469J9VMJAVALANGDOUBLE_SET_VALUE(currentThread, result, value);470break;471}472case J9CPTYPE_METHOD_TYPE: {473result = (j9object_t)ramCP->value;474if ((NULL == result) && resolve) {475result = vmFuncs->resolveMethodTypeRef(currentThread, ramConstantPool, cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE);476}477break;478}479case J9CPTYPE_METHODHANDLE: {480result = (j9object_t)ramCP->value;481if ((NULL == result) && resolve) {482result = vmFuncs->resolveMethodHandleRef(currentThread, ramConstantPool, cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE | J9_RESOLVE_FLAG_NO_CLASS_INIT);483}484break;485}486case J9CPTYPE_CONSTANT_DYNAMIC: {487result = (j9object_t)ramCP->value;488if ((NULL == result) && resolve) {489result = vmFuncs->resolveConstantDynamic(currentThread, ramConstantPool, cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE);490}491break;492}493} /* switch */494done:495return result;496}497498J9Method *499lookupMethod(J9VMThread *currentThread, J9Class *resolvedClass, J9UTF8 *name, J9UTF8 *signature, J9Class *callerClass, UDATA lookupOptions)500{501J9Method *result = NULL;502J9NameAndSignature nas;503J9UTF8 nullSignature = {0};504505nas.name = name;506nas.signature = signature;507lookupOptions |= J9_LOOK_DIRECT_NAS;508509/* If looking for a MethodHandle polymorphic INL method, allow any caller signature. */510if (isPolymorphicMHMethod(currentThread->javaVM, resolvedClass, name)) {511nas.signature = &nullSignature;512/* Set flag for partial signature lookup. Signature length is already initialized to 0. */513lookupOptions |= J9_LOOK_PARTIAL_SIGNATURE;514}515516result = (J9Method*)currentThread->javaVM->internalVMFunctions->javaLookupMethod(currentThread, resolvedClass, (J9ROMNameAndSignature*)&nas, callerClass, lookupOptions);517518return result;519}520521static void522setCallSiteTargetImpl(J9VMThread *currentThread, jobject callsite, jobject target, bool isVolatile)523{524J9JavaVM *javaVM = currentThread->javaVM;525const J9InternalVMFunctions *vmFuncs = javaVM->internalVMFunctions;526vmFuncs->internalEnterVMFromJNI(currentThread);527528if ((NULL == callsite) || (NULL == target)) {529vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);530} else {531j9object_t callsiteObject = J9_JNI_UNWRAP_REFERENCE(callsite);532j9object_t targetObject = J9_JNI_UNWRAP_REFERENCE(target);533534J9Class *clazz = J9OBJECT_CLAZZ(currentThread, callsiteObject);535UDATA offset = (UDATA)vmFuncs->instanceFieldOffset(536currentThread,537clazz,538(U_8*)"target",539LITERAL_STRLEN("target"),540(U_8*)"Ljava/lang/invoke/MethodHandle;",541LITERAL_STRLEN("Ljava/lang/invoke/MethodHandle;"),542NULL, NULL, 0);543offset += J9VMTHREAD_OBJECT_HEADER_SIZE(currentThread);544MM_ObjectAccessBarrierAPI objectAccessBarrier = MM_ObjectAccessBarrierAPI(currentThread);545546/* Check for MutableCallSite modification. */547J9JITConfig* jitConfig = javaVM->jitConfig;548J9Class *mcsClass = vmFuncs->peekClassHashTable(549currentThread,550javaVM->systemClassLoader,551J9UTF8_DATA(&mutableCallSite),552J9UTF8_LENGTH(&mutableCallSite));553554if (!isVolatile /* MutableCallSite uses setTargetNormal(). */555&& (NULL != jitConfig)556&& (NULL != mcsClass)557&& VM_VMHelpers::inlineCheckCast(clazz, mcsClass)558) {559jitConfig->jitSetMutableCallSiteTarget(currentThread, callsiteObject, targetObject);560} else {561/* There are no runtime assumptions to invalidate (either because562* the call site is not a MutableCallSite, or because the JIT563* compiler is not loaded). */564objectAccessBarrier.inlineMixedObjectStoreObject(currentThread, callsiteObject, offset, targetObject, isVolatile);565}566}567vmFuncs->internalExitVMToJNI(currentThread);568}569570571/**572* static native void init(MemberName self, Object ref);573*574* Initializes a MemberName object using the given ref object.575* see initImpl for detail576* Throw NPE if self or ref is null577* Throw IllegalArgumentException if ref is not a field/method/constructor578*/579void JNICALL580Java_java_lang_invoke_MethodHandleNatives_init(JNIEnv *env, jclass clazz, jobject self, jobject ref)581{582J9VMThread *currentThread = (J9VMThread*)env;583J9JavaVM *vm = currentThread->javaVM;584J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;585vmFuncs->internalEnterVMFromJNI(currentThread);586587Trc_JCL_java_lang_invoke_MethodHandleNatives_init_Entry(env, self, ref);588if ((NULL == self) || (NULL == ref)) {589vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);590} else {591j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);592j9object_t refObject = J9_JNI_UNWRAP_REFERENCE(ref);593594initImpl(currentThread, membernameObject, refObject);595}596Trc_JCL_java_lang_invoke_MethodHandleNatives_init_Exit(env);597vmFuncs->internalExitVMToJNI(currentThread);598}599600/**601* static native void expand(MemberName self);602*603* Given a MemberName object, try to set the uninitialized fields from existing VM metadata.604* Uses VM metadata (vmindex & vmtarget) to set symblic data fields (name & type & defc)605*606* Throws NullPointerException if MemberName object is null.607* Throws IllegalArgumentException if MemberName doesn't contain required data to expand.608* Throws InternalError if the MemberName object contains invalid data or completely uninitialized.609*/610void JNICALL611Java_java_lang_invoke_MethodHandleNatives_expand(JNIEnv *env, jclass clazz, jobject self)612{613J9VMThread *currentThread = (J9VMThread*)env;614J9JavaVM *vm = currentThread->javaVM;615const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;616vmFuncs->internalEnterVMFromJNI(currentThread);617618Trc_JCL_java_lang_invoke_MethodHandleNatives_expand_Entry(env, self);619if (NULL == self) {620vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);621} else {622j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);623jint flags = J9VMJAVALANGINVOKEMEMBERNAME_FLAGS(currentThread, membernameObject);624jlong vmindex = (jlong)J9OBJECT_ADDRESS_LOAD(currentThread, membernameObject, vm->vmindexOffset);625626Trc_JCL_java_lang_invoke_MethodHandleNatives_expand_Data(env, membernameObject, flags, vmindex);627if (J9_ARE_ANY_BITS_SET(flags, MN_IS_FIELD)) {628/* For Field MemberName, the clazz and vmindex fields must be set. */629if ((NULL != J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject)) && (NULL != (void*)vmindex)) {630J9JNIFieldID *field = (J9JNIFieldID*)vmindex;631632/* if name/type field is uninitialized, create j.l.String from ROM field name/sig and store in MN fields. */633if (NULL == J9VMJAVALANGINVOKEMEMBERNAME_NAME(currentThread, membernameObject)) {634J9UTF8 *name = J9ROMFIELDSHAPE_NAME(field->field);635j9object_t nameString = vm->memoryManagerFunctions->j9gc_createJavaLangStringWithUTFCache(currentThread, name);636if (NULL != nameString) {637/* Refetch reference after GC point */638membernameObject = J9_JNI_UNWRAP_REFERENCE(self);639J9VMJAVALANGINVOKEMEMBERNAME_SET_NAME(currentThread, membernameObject, nameString);640}641}642if (NULL == J9VMJAVALANGINVOKEMEMBERNAME_TYPE(currentThread, membernameObject)) {643J9UTF8 *signature = J9ROMFIELDSHAPE_SIGNATURE(field->field);644j9object_t signatureString = vm->memoryManagerFunctions->j9gc_createJavaLangStringWithUTFCache(currentThread, signature);645if (NULL != signatureString) {646/* Refetch reference after GC point */647membernameObject = J9_JNI_UNWRAP_REFERENCE(self);648J9VMJAVALANGINVOKEMEMBERNAME_SET_TYPE(currentThread, membernameObject, signatureString);649}650}651} else {652vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, NULL);653}654} else if (J9_ARE_ANY_BITS_SET(flags, MN_IS_METHOD | MN_IS_CONSTRUCTOR)) {655if (NULL != (void*)vmindex) {656/* For method/constructor MemberName, the vmindex field is required for expand.*/657J9JNIMethodID *methodID = (J9JNIMethodID*)vmindex;658J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(methodID->method);659660/* Retrieve method info using JNIMethodID, store to MN fields. */661if (NULL == J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject)) {662j9object_t newClassObject = J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_METHOD(methodID->method));663J9VMJAVALANGINVOKEMEMBERNAME_SET_CLAZZ(currentThread, membernameObject, newClassObject);664}665if (NULL == J9VMJAVALANGINVOKEMEMBERNAME_NAME(currentThread, membernameObject)) {666J9UTF8 *name = J9ROMMETHOD_NAME(romMethod);667j9object_t nameString = vm->memoryManagerFunctions->j9gc_createJavaLangStringWithUTFCache(currentThread, name);668if (NULL != nameString) {669/* Refetch reference after GC point */670membernameObject = J9_JNI_UNWRAP_REFERENCE(self);671J9VMJAVALANGINVOKEMEMBERNAME_SET_NAME(currentThread, membernameObject, nameString);672}673}674if (NULL == J9VMJAVALANGINVOKEMEMBERNAME_TYPE(currentThread, membernameObject)) {675J9UTF8 *signature = J9ROMMETHOD_SIGNATURE(romMethod);676j9object_t signatureString = vm->memoryManagerFunctions->j9gc_createJavaLangStringWithUTFCache(currentThread, signature);677if (NULL != signatureString) {678/* Refetch reference after GC point */679membernameObject = J9_JNI_UNWRAP_REFERENCE(self);680J9VMJAVALANGINVOKEMEMBERNAME_SET_TYPE(currentThread, membernameObject, signatureString);681}682}683} else {684vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, NULL);685}686} else {687vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);688}689}690Trc_JCL_java_lang_invoke_MethodHandleNatives_expand_Exit(env);691vmFuncs->internalExitVMToJNI(currentThread);692}693694/**695* static native MemberName resolve(MemberName self, Class<?> caller,696* boolean speculativeResolve) throws LinkageError, ClassNotFoundException;697*698* Resolve the method/field represented by the MemberName's symbolic data (name & type & defc) with the supplied caller699* Store the resolved Method/Field's JNI-id in vmindex, field offset / method pointer in vmtarget700*701* If the speculativeResolve flag is not set, failed resolution will throw the corresponding exception.702* If the resolution failed with no exception:703* Throw NoSuchFieldError for field MemberName704* Throw NoSuchMethodError for method/constructor MemberName705* Throw LinkageError for other706*/707#if JAVA_SPEC_VERSION >= 16708jobject JNICALL709Java_java_lang_invoke_MethodHandleNatives_resolve(JNIEnv *env, jclass clazz, jobject self, jclass caller, jint lookupMode, jboolean speculativeResolve)710#else /* JAVA_SPEC_VERSION >= 16 */711jobject JNICALL712Java_java_lang_invoke_MethodHandleNatives_resolve(JNIEnv *env, jclass clazz, jobject self, jclass caller, jboolean speculativeResolve)713#endif /* JAVA_SPEC_VERSION >= 16 */714{715J9VMThread *currentThread = (J9VMThread*)env;716J9JavaVM *vm = currentThread->javaVM;717const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;718jobject result = NULL;719J9UTF8 *name = NULL;720J9UTF8 *signature = NULL;721PORT_ACCESS_FROM_JAVAVM(vm);722vmFuncs->internalEnterVMFromJNI(currentThread);723724Trc_JCL_java_lang_invoke_MethodHandleNatives_resolve_Entry(env, self, caller, (speculativeResolve ? "true" : "false"));725if (NULL == self) {726vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);727} else {728j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);729jlong vmindex = (jlong)(UDATA)J9OBJECT_U64_LOAD(currentThread, membernameObject, vm->vmindexOffset);730jlong target = (jlong)(UDATA)J9OBJECT_U64_LOAD(currentThread, membernameObject, vm->vmtargetOffset);731732jint flags = J9VMJAVALANGINVOKEMEMBERNAME_FLAGS(currentThread, membernameObject);733jint new_flags = 0;734j9object_t new_clazz = NULL;735736Trc_JCL_java_lang_invoke_MethodHandleNatives_resolve_Data(env, membernameObject, caller, flags, vmindex, target);737/* Check if MemberName is already resolved */738if (0 != target) {739result = self;740} else {741/* Initialize nameObject after creating typeString which could trigger GC */742j9object_t nameObject = NULL;743j9object_t typeObject = J9VMJAVALANGINVOKEMEMBERNAME_TYPE(currentThread, membernameObject);744j9object_t clazzObject = J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject);745J9Class *resolvedClass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, clazzObject);746747jint ref_kind = (flags >> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK;748749J9Class *typeClass = J9OBJECT_CLAZZ(currentThread, typeObject);750751/* The type field of a MemberName could be in:752* MethodType: MethodType representing method/constructor MemberName's method signature753* String: String representing MemberName's signature (field or method)754* Class: Class representing field MemberName's field type755*/756if (J9VMJAVALANGINVOKEMETHODTYPE(vm) == typeClass) {757j9object_t sigString = J9VMJAVALANGINVOKEMETHODTYPE_METHODDESCRIPTOR(currentThread, typeObject);758if (NULL != sigString) {759signature = vmFuncs->copyStringToJ9UTF8WithMemAlloc(currentThread, sigString, J9_STR_XLAT, "", 0, NULL, 0);760} else {761signature = getJ9UTF8SignatureFromMethodType(currentThread, typeObject);762}763} else if (J9VMJAVALANGSTRING_OR_NULL(vm) == typeClass) {764signature = vmFuncs->copyStringToJ9UTF8WithMemAlloc(currentThread, typeObject, J9_STR_XLAT, "", 0, NULL, 0);765} else if (J9VMJAVALANGCLASS(vm) == typeClass) {766J9Class *rclass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, typeObject);767char *classSignature = getClassSignature(currentThread, rclass);768if (NULL != classSignature) {769UDATA signatureLength = strlen(classSignature);770PORT_ACCESS_FROM_JAVAVM(vm);771signature = (J9UTF8*)j9mem_allocate_memory(signatureLength + sizeof(J9UTF8), OMRMEM_CATEGORY_VM);772if (NULL != signature) {773J9UTF8_SET_LENGTH(signature, (U_16)signatureLength);774memcpy(J9UTF8_DATA(signature), classSignature, signatureLength);775}776j9mem_free_memory(classSignature);777}778} else {779vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);780goto done;781}782783/* Check if signature string is correctly generated */784if (NULL == signature) {785if (!VM_VMHelpers::exceptionPending(currentThread)) {786vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);787}788goto done;789}790791/* Refetch reference after GC point */792membernameObject = J9_JNI_UNWRAP_REFERENCE(self);793nameObject = J9VMJAVALANGINVOKEMEMBERNAME_NAME(currentThread, membernameObject);794name = vmFuncs->copyStringToJ9UTF8WithMemAlloc(currentThread, nameObject, 0, "", 0, NULL, 0);795if (NULL == name) {796vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);797goto done;798}799800j9object_t callerObject = (NULL == caller) ? NULL : J9_JNI_UNWRAP_REFERENCE(caller);801J9Class *callerClass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, callerObject);802803Trc_JCL_java_lang_invoke_MethodHandleNatives_resolve_NAS(env, J9UTF8_LENGTH(name), J9UTF8_DATA(name), J9UTF8_LENGTH(signature), J9UTF8_DATA(signature));804805if (J9_ARE_ANY_BITS_SET(flags, MN_IS_METHOD | MN_IS_CONSTRUCTOR)) {806UDATA lookupOptions = 0;807808if (JNI_TRUE == speculativeResolve) {809lookupOptions |= J9_LOOK_NO_THROW;810}811812#if JAVA_SPEC_VERSION >= 16813/* Check CL constraint only for lookup that is not trusted (with caller) and not public (UNCONDITIONAL mode not set)814* Note: UNCONDITIONAL lookupMode can only access unconditionally exported public members which assumes readablity815* ie lookup class not used to determine lookup context816* See java.lang.invoke.MethodHandles$Lookup.publicLookup()817*/818if ((NULL != callerClass) && J9_ARE_NO_BITS_SET(lookupMode, MN_UNCONDITIONAL_MODE)) {819lookupOptions |= J9_LOOK_CLCONSTRAINTS;820}821#else822if (NULL != callerClass) {823lookupOptions |= J9_LOOK_CLCONSTRAINTS;824}825#endif826827/* Determine the lookup type based on reference kind and resolved class flags */828switch (ref_kind)829{830case MH_REF_INVOKEINTERFACE:831lookupOptions |= J9_LOOK_INTERFACE;832break;833case MH_REF_INVOKESPECIAL:834lookupOptions |= (J9_LOOK_VIRTUAL | J9_LOOK_ALLOW_FWD | J9_LOOK_HANDLE_DEFAULT_METHOD_CONFLICTS);835break;836case MH_REF_INVOKESTATIC:837lookupOptions |= J9_LOOK_STATIC;838if (J9_ARE_ANY_BITS_SET(resolvedClass->romClass->modifiers, J9AccInterface)) {839lookupOptions |= J9_LOOK_INTERFACE;840}841break;842default:843lookupOptions |= J9_LOOK_VIRTUAL;844break;845}846847/* Check if signature polymorphic native calls */848J9Method *method = lookupMethod(currentThread, resolvedClass, name, signature, callerClass, lookupOptions);849850/* Check for resolution exception */851if (VM_VMHelpers::exceptionPending(currentThread)) {852J9Class *exceptionClass = J9OBJECT_CLAZZ(currentThread, currentThread->currentException);853if ((ref_kind == MH_REF_INVOKESPECIAL) && (exceptionClass == J9VMJAVALANGINCOMPATIBLECLASSCHANGEERROR(vm))) {854/* Special handling for default method conflict, defer the exception throw until invocation. */855VM_VMHelpers::clearException(currentThread);856/* Attempt to lookup method without checking for conflict.857* If this failed with error, then throw that error.858* Otherwise exception throw will be defered to the MH.invoke call.859*/860method = lookupMethod(861currentThread, resolvedClass, name, signature, callerClass,862(lookupOptions & ~J9_LOOK_HANDLE_DEFAULT_METHOD_CONFLICTS));863864if (!VM_VMHelpers::exceptionPending(currentThread)) {865/* Set placeholder values for MemberName fields. */866vmindex = (jlong)J9VM_RESOLVED_VMINDEX_FOR_DEFAULT_THROW;867new_clazz = J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_METHOD(method));868new_flags = flags;869870/* Load special sendTarget to throw the exception during invocation */871target = (jlong)(UDATA)vm->initialMethods.throwDefaultConflict;872} else {873goto done;874}875} else {876goto done;877}878} else if (NULL != method) {879J9JNIMethodID *methodID = vmFuncs->getJNIMethodID(currentThread, method);880vmindex = (jlong)(UDATA)methodID;881target = (jlong)(UDATA)method;882883J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(methodID->method);884J9UTF8 *methodName = J9ROMMETHOD_NAME(romMethod);885U_32 methodModifiers = romMethod->modifiers;886new_clazz = J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_METHOD(method));887new_flags = methodModifiers & CFR_METHOD_ACCESS_MASK;888889if (J9_ARE_ANY_BITS_SET(methodModifiers, J9AccMethodCallerSensitive)) {890new_flags |= MN_CALLER_SENSITIVE;891}892893if (J9_ARE_ALL_BITS_SET(flags, MN_IS_METHOD)) {894new_flags |= MN_IS_METHOD;895if (MH_REF_INVOKEINTERFACE == ref_kind) {896Assert_JCL_true(J9_ARE_NO_BITS_SET(methodModifiers, J9AccStatic));897if (J9_ARE_ALL_BITS_SET(methodID->vTableIndex, J9_JNI_MID_INTERFACE)) {898new_flags |= MH_REF_INVOKEINTERFACE << MN_REFERENCE_KIND_SHIFT;899} else if (!J9ROMMETHOD_HAS_VTABLE(romMethod)) {900new_flags |= MH_REF_INVOKESPECIAL << MN_REFERENCE_KIND_SHIFT;901} else {902new_flags |= MH_REF_INVOKEVIRTUAL << MN_REFERENCE_KIND_SHIFT;903}904} else if (MH_REF_INVOKESPECIAL == ref_kind) {905Assert_JCL_true(J9_ARE_NO_BITS_SET(methodModifiers, J9AccStatic));906new_flags |= MH_REF_INVOKESPECIAL << MN_REFERENCE_KIND_SHIFT;907} else if (MH_REF_INVOKESTATIC == ref_kind) {908Assert_JCL_true(J9_ARE_ALL_BITS_SET(methodModifiers, J9AccStatic));909new_flags |= MH_REF_INVOKESTATIC << MN_REFERENCE_KIND_SHIFT;910} else if (MH_REF_INVOKEVIRTUAL == ref_kind) {911Assert_JCL_true(J9_ARE_NO_BITS_SET(methodModifiers, J9AccStatic));912if (!J9ROMMETHOD_HAS_VTABLE(romMethod)) {913new_flags |= MH_REF_INVOKESPECIAL << MN_REFERENCE_KIND_SHIFT;914} else {915if (J9_ARE_ALL_BITS_SET(methodID->vTableIndex, J9_JNI_MID_INTERFACE)) {916new_clazz = J9VM_J9CLASS_TO_HEAPCLASS(resolvedClass);917}918new_flags |= MH_REF_INVOKEVIRTUAL << MN_REFERENCE_KIND_SHIFT;919}920} else {921Assert_JCL_unreachable();922}923} else if (J9_ARE_NO_BITS_SET(methodModifiers, J9AccStatic) && ('<' == (char)*J9UTF8_DATA(methodName))) {924new_flags |= MN_IS_CONSTRUCTOR;925new_flags |= MH_REF_INVOKESPECIAL << MN_REFERENCE_KIND_SHIFT;926} else {927Assert_JCL_unreachable();928}929}930} if (J9_ARE_ANY_BITS_SET(flags, MN_IS_FIELD)) {931J9Class *declaringClass;932J9ROMFieldShape *romField;933UDATA lookupOptions = 0;934UDATA offset = 0;935if (JNI_TRUE == speculativeResolve) {936lookupOptions |= J9_RESOLVE_FLAG_NO_THROW_ON_FAIL;937}938939/* MemberName doesn't differentiate if a field is static or not,940* the resolve code have to attempt to resolve as instance field first,941* then as static field if the first attempt failed.942*/943offset = vmFuncs->instanceFieldOffset(currentThread,944resolvedClass,945J9UTF8_DATA(name), J9UTF8_LENGTH(name),946J9UTF8_DATA(signature), J9UTF8_LENGTH(signature),947&declaringClass, (UDATA*)&romField,948lookupOptions);949950if (offset == (UDATA)-1) {951declaringClass = NULL;952953if (VM_VMHelpers::exceptionPending(currentThread)) {954VM_VMHelpers::clearException(currentThread);955}956957void* fieldAddress = vmFuncs->staticFieldAddress(currentThread,958resolvedClass,959J9UTF8_DATA(name), J9UTF8_LENGTH(name),960J9UTF8_DATA(signature), J9UTF8_LENGTH(signature),961&declaringClass, (UDATA*)&romField,962lookupOptions,963NULL);964965if (fieldAddress == NULL) {966declaringClass = NULL;967} else {968offset = (UDATA)fieldAddress - (UDATA)declaringClass->ramStatics;969}970}971972if (NULL != declaringClass) {973if ((NULL != callerClass)974#if JAVA_SPEC_VERSION >= 16975&& (J9_ARE_NO_BITS_SET(lookupMode, MN_UNCONDITIONAL_MODE))976#endif977) {978if (callerClass->classLoader != declaringClass->classLoader) {979J9BytecodeVerificationData *verifyData = vm->bytecodeVerificationData;980U_16 sigOffset = 0;981982/* Skip the '[', 'L' prefix */983while ('[' == J9UTF8_DATA(signature)[sigOffset]) {984sigOffset += 1;985}986if ('L' == J9UTF8_DATA(signature)[sigOffset]) {987sigOffset += 1;988omrthread_monitor_enter(vm->classTableMutex);989UDATA clConstraintResult = verifyData->checkClassLoadingConstraintForNameFunction(990currentThread,991declaringClass->classLoader,992callerClass->classLoader,993J9UTF8_DATA(signature) + sigOffset,994J9UTF8_DATA(signature) + sigOffset,995J9UTF8_LENGTH(signature) - sigOffset - 1, /* -1 to remove the trailing ;*/996true);997omrthread_monitor_exit(vm->classTableMutex);998if (0 != clConstraintResult) {999vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGLINKAGEERROR, NULL);1000goto done;1001}1002}1003}1004}10051006UDATA inconsistentData = 0;1007J9JNIFieldID *fieldID = vmFuncs->getJNIFieldID(currentThread, declaringClass, romField, offset, &inconsistentData);1008vmindex = (jlong)(UDATA)fieldID;10091010new_clazz = J9VM_J9CLASS_TO_HEAPCLASS(declaringClass);1011new_flags = MN_IS_FIELD | (fieldID->field->modifiers & CFR_FIELD_ACCESS_MASK);1012if (VM_VMHelpers::isTrustedFinalField(fieldID->field, fieldID->declaringClass->romClass)) {1013new_flags |= MN_TRUSTED_FINAL;1014}10151016romField = fieldID->field;10171018if (J9_ARE_ANY_BITS_SET(romField->modifiers, J9AccStatic)) {1019offset = fieldID->offset | J9_SUN_STATIC_FIELD_OFFSET_TAG;1020if (J9_ARE_ANY_BITS_SET(romField->modifiers, J9AccFinal)) {1021offset |= J9_SUN_FINAL_FIELD_OFFSET_TAG;1022}10231024if ((MH_REF_PUTFIELD == ref_kind) || (MH_REF_PUTSTATIC == ref_kind)) {1025new_flags |= (MH_REF_PUTSTATIC << MN_REFERENCE_KIND_SHIFT);1026} else {1027new_flags |= (MH_REF_GETSTATIC << MN_REFERENCE_KIND_SHIFT);1028}1029} else {1030if ((MH_REF_PUTFIELD == ref_kind) || (MH_REF_PUTSTATIC == ref_kind)) {1031new_flags |= (MH_REF_PUTFIELD << MN_REFERENCE_KIND_SHIFT);1032} else {1033new_flags |= (MH_REF_GETFIELD << MN_REFERENCE_KIND_SHIFT);1034}1035}10361037target = (jlong)offset;1038}1039}10401041if ((0 != vmindex) && (0 != target)) {1042/* Refetch reference after GC point */1043membernameObject = J9_JNI_UNWRAP_REFERENCE(self);1044J9VMJAVALANGINVOKEMEMBERNAME_SET_FLAGS(currentThread, membernameObject, new_flags);1045J9VMJAVALANGINVOKEMEMBERNAME_SET_CLAZZ(currentThread, membernameObject, new_clazz);1046J9OBJECT_U64_STORE(currentThread, membernameObject, vm->vmindexOffset, (U_64)vmindex);1047J9OBJECT_U64_STORE(currentThread, membernameObject, vm->vmtargetOffset, (U_64)target);10481049Trc_JCL_java_lang_invoke_MethodHandleNatives_resolve_resolved(env, vmindex, target, new_clazz, new_flags);10501051result = vmFuncs->j9jni_createLocalRef(env, membernameObject);1052}10531054if ((NULL == result) && (JNI_TRUE != speculativeResolve) && !VM_VMHelpers::exceptionPending(currentThread)) {1055if (J9_ARE_ANY_BITS_SET(flags, MN_IS_FIELD)) {1056vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNOSUCHFIELDERROR, NULL);1057} else if (J9_ARE_ANY_BITS_SET(flags, MN_IS_CONSTRUCTOR | MN_IS_METHOD)) {1058vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNOSUCHMETHODERROR, NULL);1059} else {1060vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGLINKAGEERROR, NULL);1061}1062}1063}1064}10651066done:1067j9mem_free_memory(name);1068j9mem_free_memory(signature);10691070if ((JNI_TRUE == speculativeResolve) && VM_VMHelpers::exceptionPending(currentThread)) {1071VM_VMHelpers::clearException(currentThread);1072}1073Trc_JCL_java_lang_invoke_MethodHandleNatives_resolve_Exit(env);1074vmFuncs->internalExitVMToJNI(currentThread);1075return result;1076}10771078/**1079* static native int getMembers(Class<?> defc, String matchName, String matchSig,1080* int matchFlags, Class<?> caller, int skip, MemberName[] results);1081*1082* Search the defc (defining class) chain for field/method that matches the given search parameters,1083* for each matching result found, initialize the next MemberName object in results array to reference the found field/method1084*1085* - defc: the class to start the search1086* - matchName: name to match, NULL to match any field/method name1087* - matchSig: signature to match, NULL to match any field/method type1088* - matchFlags: flags defining search options:1089* MN_IS_FIELD - search for fields1090* MN_IS_CONSTRUCTOR | MN_IS_METHOD - search for method/constructor1091* MN_SEARCH_SUPERCLASSES - search the superclasses of the defining class1092* MN_SEARCH_INTERFACES - search the interfaces implemented by the defining class1093* - caller: the caller class performing the lookup1094* - skip: number of matching results to skip before storing1095* - results: an array of MemberName objects to hold the matched field/method1096*/1097jint JNICALL1098Java_java_lang_invoke_MethodHandleNatives_getMembers(JNIEnv *env, jclass clazz, jclass defc, jstring matchName, jstring matchSig, jint matchFlags, jclass caller, jint skip, jobjectArray results)1099{1100J9VMThread *currentThread = (J9VMThread*)env;1101J9JavaVM *vm = currentThread->javaVM;1102const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;1103vmFuncs->internalEnterVMFromJNI(currentThread);1104jint result = 0;1105J9UTF8 *name = NULL;1106J9UTF8 *sig = NULL;1107j9object_t callerObject = ((NULL == caller) ? NULL : J9_JNI_UNWRAP_REFERENCE(caller));11081109PORT_ACCESS_FROM_JAVAVM(vm);11101111Trc_JCL_java_lang_invoke_MethodHandleNatives_getMembers_Entry(env, defc, matchName, matchSig, matchFlags, caller, skip, results);11121113if ((NULL == defc) || (NULL == results) || ((NULL != callerObject) && (J9VMJAVALANGCLASS(vm) != J9OBJECT_CLAZZ(currentThread, callerObject)))) {1114result = -1;1115} else {1116j9object_t defcObject = J9_JNI_UNWRAP_REFERENCE(defc);1117J9Class *defClass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, defcObject);11181119if (NULL != matchName) {1120name = vmFuncs->copyStringToJ9UTF8WithMemAlloc(currentThread, J9_JNI_UNWRAP_REFERENCE(matchName), J9_STR_NONE, "", 0, NULL, 0);1121if (NULL == name) {1122vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);1123goto done;1124}1125}1126if (NULL != matchSig) {1127sig = vmFuncs->copyStringToJ9UTF8WithMemAlloc(currentThread, J9_JNI_UNWRAP_REFERENCE(matchSig), J9_STR_NONE, "", 0, NULL, 0);1128if (NULL == sig) {1129vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);1130goto done;1131}1132}11331134if (!(((NULL != matchName) && (0 == J9UTF8_LENGTH(name))) || ((NULL != matchSig) && (0 == J9UTF8_LENGTH(sig))))) {1135j9array_t resultsArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(results);1136UDATA length = J9INDEXABLEOBJECT_SIZE(currentThread, resultsArray);1137UDATA index = 0;11381139if (J9ROMCLASS_IS_INTERFACE(defClass->romClass)) {1140result = -1;1141} else {1142if (J9_ARE_ANY_BITS_SET(matchFlags, MN_IS_FIELD)) {1143J9ROMFieldShape *romField = NULL;1144J9ROMFieldWalkState walkState;11451146UDATA classDepth = 0;1147if (J9_ARE_ANY_BITS_SET(matchFlags, MN_SEARCH_SUPERCLASSES)) {1148/* walk superclasses */1149J9CLASS_DEPTH(defClass);1150}1151J9Class *currentClass = defClass;11521153while (NULL != currentClass) {1154/* walk currentClass */1155memset(&walkState, 0, sizeof(walkState));1156romField = romFieldsStartDo(currentClass->romClass, &walkState);11571158while (NULL != romField) {1159J9UTF8 *nameUTF = J9ROMFIELDSHAPE_NAME(romField);1160J9UTF8 *signatureUTF = J9ROMFIELDSHAPE_SIGNATURE(romField);11611162if (((NULL == matchName) || J9UTF8_EQUALS(name, nameUTF))1163&& ((NULL == matchSig) || J9UTF8_EQUALS(sig, signatureUTF))1164) {1165if (skip > 0) {1166skip -=1;1167} else {1168if (index < length) {1169/* Refetch reference after GC point */1170resultsArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(results);1171j9object_t memberName = J9JAVAARRAYOFOBJECT_LOAD(currentThread, resultsArray, index);1172if (NULL == memberName) {1173result = -99;1174goto done;1175}1176PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, memberName);11771178/* create static field object */1179j9object_t fieldObj = vm->reflectFunctions.createFieldObject(currentThread, romField, defClass, (romField->modifiers & J9AccStatic) == J9AccStatic);1180memberName = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);11811182if (NULL != fieldObj) {1183initImpl(currentThread, memberName, fieldObj);1184}1185if (VM_VMHelpers::exceptionPending(currentThread)) {1186goto done;1187}1188}1189}1190result += 1;1191}1192romField = romFieldsNextDo(&walkState);1193}11941195/* get the superclass */1196if (classDepth >= 1) {1197classDepth -= 1;1198currentClass = defClass->superclasses[classDepth];1199} else {1200currentClass = NULL;1201}1202}12031204/* walk interfaces */1205if (J9_ARE_ANY_BITS_SET(matchFlags, MN_SEARCH_INTERFACES)) {1206J9ITable *currentITable = (J9ITable *)defClass->iTable;12071208while (NULL != currentITable) {1209memset(&walkState, 0, sizeof(walkState));1210romField = romFieldsStartDo(currentITable->interfaceClass->romClass, &walkState);1211while (NULL != romField) {1212J9UTF8 *nameUTF = J9ROMFIELDSHAPE_NAME(romField);1213J9UTF8 *signatureUTF = J9ROMFIELDSHAPE_SIGNATURE(romField);12141215if (((NULL == matchName) || J9UTF8_EQUALS(name, nameUTF))1216&& ((NULL == matchSig) || J9UTF8_EQUALS(sig, signatureUTF))1217) {1218if (skip > 0) {1219skip -=1;1220} else {1221if (index < length) {1222/* Refetch reference after GC point */1223resultsArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(results);1224j9object_t memberName = J9JAVAARRAYOFOBJECT_LOAD(currentThread, resultsArray, index);1225if (NULL == memberName) {1226result = -99;1227goto done;1228}1229PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, memberName);12301231/* create field object */1232j9object_t fieldObj = vm->reflectFunctions.createFieldObject(currentThread, romField, defClass, (romField->modifiers & J9AccStatic) == J9AccStatic);1233memberName = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);12341235if (NULL != fieldObj) {1236initImpl(currentThread, memberName, fieldObj);1237}1238if (VM_VMHelpers::exceptionPending(currentThread)) {1239goto done;1240}1241}1242}1243result += 1;1244}1245romField = romFieldsNextDo(&walkState);1246}1247currentITable = currentITable->next;1248}1249}1250} else if (J9_ARE_ANY_BITS_SET(matchFlags, MN_IS_CONSTRUCTOR | MN_IS_METHOD)) {1251UDATA classDepth = 0;1252if (J9_ARE_ANY_BITS_SET(matchFlags, MN_SEARCH_SUPERCLASSES)) {1253/* walk superclasses */1254J9CLASS_DEPTH(defClass);1255}1256J9Class *currentClass = defClass;12571258while (NULL != currentClass) {1259if (!J9ROMCLASS_IS_PRIMITIVE_OR_ARRAY(currentClass->romClass)) {1260J9Method *currentMethod = currentClass->ramMethods;1261J9Method *endOfMethods = currentMethod + currentClass->romClass->romMethodCount;1262while (currentMethod != endOfMethods) {1263J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);1264J9UTF8 *nameUTF = J9ROMMETHOD_SIGNATURE(romMethod);1265J9UTF8 *signatureUTF = J9ROMMETHOD_SIGNATURE(romMethod);12661267if (((NULL == matchName) || J9UTF8_EQUALS(name, nameUTF))1268&& ((NULL == matchSig) || J9UTF8_EQUALS(sig, signatureUTF))1269) {1270if (skip > 0) {1271skip -=1;1272} else {1273if (index < length) {1274/* Refetch reference after GC point */1275resultsArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(results);1276j9object_t memberName = J9JAVAARRAYOFOBJECT_LOAD(currentThread, resultsArray, index);1277if (NULL == memberName) {1278result = -99;1279goto done;1280}1281PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, memberName);12821283j9object_t methodObj = NULL;1284if (J9_ARE_NO_BITS_SET(romMethod->modifiers, J9AccStatic) && ('<' == (char)*J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)))) {1285/* create constructor object */1286methodObj = vm->reflectFunctions.createConstructorObject(currentMethod, currentClass, NULL, currentThread);1287} else {1288/* create method object */1289methodObj = vm->reflectFunctions.createMethodObject(currentMethod, currentClass, NULL, currentThread);1290}1291memberName = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);12921293if (NULL != methodObj) {1294initImpl(currentThread, memberName, methodObj);1295}1296if (VM_VMHelpers::exceptionPending(currentThread)) {1297goto done;1298}1299}1300}1301result += 1;1302}1303currentMethod += 1;1304}1305}13061307/* get the superclass */1308if (classDepth >= 1) {1309classDepth -= 1;1310currentClass = defClass->superclasses[classDepth];1311} else {1312currentClass = NULL;1313}1314}13151316/* walk interfaces */1317if (J9_ARE_ANY_BITS_SET(matchFlags, MN_SEARCH_INTERFACES)) {1318J9ITable *currentITable = (J9ITable *)defClass->iTable;13191320while (NULL != currentITable) {1321J9Class *currentClass = currentITable->interfaceClass;1322J9Method *currentMethod = currentClass->ramMethods;1323J9Method *endOfMethods = currentMethod + currentClass->romClass->romMethodCount;1324while (currentMethod != endOfMethods) {1325J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);1326J9UTF8 *nameUTF = J9ROMMETHOD_SIGNATURE(romMethod);1327J9UTF8 *signatureUTF = J9ROMMETHOD_SIGNATURE(romMethod);13281329if (((NULL == matchName) || J9UTF8_EQUALS(name, nameUTF))1330&& ((NULL == matchSig) || J9UTF8_EQUALS(sig, signatureUTF))1331) {1332if (skip > 0) {1333skip -=1;1334} else {1335if (index < length) {1336/* Refetch reference after GC point */1337resultsArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(results);1338j9object_t memberName = J9JAVAARRAYOFOBJECT_LOAD(currentThread, resultsArray, index);1339if (NULL == memberName) {1340result = -99;1341goto done;1342}1343PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, memberName);13441345j9object_t methodObj = NULL;1346if (J9_ARE_NO_BITS_SET(romMethod->modifiers, J9AccStatic) && ('<' == (char)*J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)))) {1347/* create constructor object */1348methodObj = vm->reflectFunctions.createConstructorObject(currentMethod, currentClass, NULL, currentThread);1349} else {1350/* create method object */1351methodObj = vm->reflectFunctions.createMethodObject(currentMethod, currentClass, NULL, currentThread);1352}1353memberName = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);13541355if (NULL != methodObj) {1356initImpl(currentThread, memberName, methodObj);1357}1358if (VM_VMHelpers::exceptionPending(currentThread)) {1359goto done;1360}1361}1362}1363result += 1;1364}1365currentMethod += 1;1366}1367currentITable = currentITable->next;1368}1369}1370}1371}1372}1373}1374done:1375j9mem_free_memory(name);1376j9mem_free_memory(sig);13771378Trc_JCL_java_lang_invoke_MethodHandleNatives_getMembers_Exit(env, result);1379vmFuncs->internalExitVMToJNI(currentThread);1380return result;1381}13821383/**1384* static native long objectFieldOffset(MemberName self); // e.g., returns vmindex1385*1386* Returns the objectFieldOffset of the field represented by the MemberName1387* result should be same as if calling Unsafe.objectFieldOffset with the actual field object1388*/1389jlong JNICALL1390Java_java_lang_invoke_MethodHandleNatives_objectFieldOffset(JNIEnv *env, jclass clazz, jobject self)1391{1392J9VMThread *currentThread = (J9VMThread*)env;1393J9JavaVM *vm = currentThread->javaVM;1394const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;1395vmFuncs->internalEnterVMFromJNI(currentThread);1396jlong result = 0;13971398Trc_JCL_java_lang_invoke_MethodHandleNatives_objectFieldOffset_Entry(env, self);13991400if (NULL == self) {1401vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);1402} else {1403j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);1404j9object_t clazzObject = J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject);14051406if (NULL == clazzObject) {1407vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);1408} else {1409jint flags = J9VMJAVALANGINVOKEMEMBERNAME_FLAGS(currentThread, membernameObject);1410if (J9_ARE_ALL_BITS_SET(flags, MN_IS_FIELD) && J9_ARE_NO_BITS_SET(flags, J9AccStatic)) {1411J9JNIFieldID *fieldID = (J9JNIFieldID*)(UDATA)J9OBJECT_U64_LOAD(currentThread, membernameObject, vm->vmindexOffset);1412result = (jlong)fieldID->offset + J9VMTHREAD_OBJECT_HEADER_SIZE(currentThread);1413} else {1414vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);1415}1416}1417}14181419Trc_JCL_java_lang_invoke_MethodHandleNatives_objectFieldOffset_Exit(env, result);1420vmFuncs->internalExitVMToJNI(currentThread);1421return result;1422}14231424/**1425* static native long staticFieldOffset(MemberName self); // e.g., returns vmindex1426*1427* Returns the staticFieldOffset of the field represented by the MemberName1428* result should be same as if calling Unsafe.staticFieldOffset with the actual field object1429*/1430jlong JNICALL1431Java_java_lang_invoke_MethodHandleNatives_staticFieldOffset(JNIEnv *env, jclass clazz, jobject self)1432{1433J9VMThread *currentThread = (J9VMThread*)env;1434J9JavaVM *vm = currentThread->javaVM;1435const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;1436vmFuncs->internalEnterVMFromJNI(currentThread);1437jlong result = 0;14381439Trc_JCL_java_lang_invoke_MethodHandleNatives_staticFieldOffset_Entry(env, self);14401441if (NULL == self) {1442vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);1443} else {1444j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);1445j9object_t clazzObject = J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject);14461447if (NULL == clazzObject) {1448vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);1449} else {1450jint flags = J9VMJAVALANGINVOKEMEMBERNAME_FLAGS(currentThread, membernameObject);1451if (J9_ARE_ALL_BITS_SET(flags, MN_IS_FIELD & J9AccStatic)) {1452result = (jlong)(UDATA)J9OBJECT_U64_LOAD(currentThread, membernameObject, vm->vmtargetOffset);1453} else {1454vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);1455}1456}1457}1458Trc_JCL_java_lang_invoke_MethodHandleNatives_staticFieldOffset_Exit(env, result);1459vmFuncs->internalExitVMToJNI(currentThread);1460return result;1461}14621463/**1464* static native Object staticFieldBase(MemberName self); // e.g., returns clazz1465*1466* Returns the staticFieldBase of the field represented by the MemberName1467* result should be same as if calling Unsafe.staticFieldBase with the actual field object1468*/1469jobject JNICALL1470Java_java_lang_invoke_MethodHandleNatives_staticFieldBase(JNIEnv *env, jclass clazz, jobject self)1471{1472J9VMThread *currentThread = (J9VMThread*)env;1473const J9InternalVMFunctions *vmFuncs = currentThread->javaVM->internalVMFunctions;1474vmFuncs->internalEnterVMFromJNI(currentThread);1475jobject result = NULL;14761477Trc_JCL_java_lang_invoke_MethodHandleNatives_staticFieldBase_Entry(env, self);1478if (NULL == self) {1479vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);1480} else {1481j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);1482j9object_t clazzObject = J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject);14831484if (NULL == clazzObject) {1485vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);1486} else {1487jint flags = J9VMJAVALANGINVOKEMEMBERNAME_FLAGS(currentThread, membernameObject);1488if (J9_ARE_ALL_BITS_SET(flags, MN_IS_FIELD & J9AccStatic)) {1489result = vmFuncs->j9jni_createLocalRef(env, clazzObject);1490} else {1491vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);1492}1493}1494}1495Trc_JCL_java_lang_invoke_MethodHandleNatives_staticFieldBase_Exit(env, result);1496vmFuncs->internalExitVMToJNI(currentThread);1497return result;1498}14991500/**1501* static native Object getMemberVMInfo(MemberName self); // returns {vmindex,vmtarget}1502*1503* Return a 2-element java array containing the vm offset/target data1504* For a field MemberName, array contains:1505* (field offset, declaring class)1506* For a method MemberName, array contains:1507* (vtable index, MemberName object)1508*/1509jobject JNICALL1510Java_java_lang_invoke_MethodHandleNatives_getMemberVMInfo(JNIEnv *env, jclass clazz, jobject self)1511{1512J9VMThread *currentThread = (J9VMThread*)env;1513J9JavaVM *vm = currentThread->javaVM;1514const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;1515jobject result = NULL;1516vmFuncs->internalEnterVMFromJNI(currentThread);15171518Trc_JCL_java_lang_invoke_MethodHandleNatives_getMemberVMInfo_Entry(env, self);1519if (NULL != self) {1520J9Class *arrayClass = fetchArrayClass(currentThread, J9VMJAVALANGOBJECT(vm));1521j9object_t arrayObject = vm->memoryManagerFunctions->J9AllocateIndexableObject(currentThread, arrayClass, 2, J9_GC_ALLOCATE_OBJECT_INSTRUMENTABLE);1522if (NULL == arrayObject) {1523vmFuncs->setHeapOutOfMemoryError(currentThread);1524} else {1525PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, arrayObject);1526j9object_t box = vm->memoryManagerFunctions->J9AllocateObject(currentThread, J9VMJAVALANGLONG_OR_NULL(vm), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);1527if (NULL == box) {1528/* Drop arrayObject */1529DROP_OBJECT_IN_SPECIAL_FRAME(currentThread);1530vmFuncs->setHeapOutOfMemoryError(currentThread);1531} else {1532arrayObject = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);1533j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);1534jint flags = J9VMJAVALANGINVOKEMEMBERNAME_FLAGS(currentThread, membernameObject);1535j9object_t target = NULL;15361537/* For fields, vmindexOffset (J9JNIFieldID) is initialized using the field offset in1538* jnicsup.cpp::getJNIFieldID. For methods, vmindexOffset (J9JNIMethodID) is initialized1539* using jnicsup.cpp::initializeMethodID.1540*/1541jlong vmindex = (jlong)(UDATA)J9OBJECT_U64_LOAD(currentThread, membernameObject, vm->vmindexOffset);15421543if (J9_ARE_ANY_BITS_SET(flags, MN_IS_FIELD)) {1544/* vmindex points to the field offset. */1545vmindex = ((J9JNIFieldID*)vmindex)->offset;1546target = J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject);1547} else {1548jint refKind = (flags >> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK;1549if ((MH_REF_INVOKEVIRTUAL == refKind) || (MH_REF_INVOKEINTERFACE == refKind)) {1550J9JNIMethodID *methodID = (J9JNIMethodID*)vmindex;1551if (J9_ARE_ANY_BITS_SET(methodID->vTableIndex, J9_JNI_MID_INTERFACE)) {1552/* vmindex points to an iTable index. */1553vmindex = (jlong)(methodID->vTableIndex & ~J9_JNI_MID_INTERFACE);1554} else if (0 == methodID->vTableIndex) {1555/* initializeMethodID will set J9JNIMethodID->vTableIndex to 0 for private interface1556* methods and j.l.Object methods. Reference implementation (RI) expects vmindex to1557* be 0 in such cases.1558*/1559vmindex = 0;1560} else {1561/* vmindex points to a vTable index. */1562vmindex = (jlong)methodID->vTableIndex;1563}1564} else {1565/* RI expects direct invocation, i.e. !invokevirtual and !invokeinterface ref kinds,1566* to have a negative vmindex.1567*/1568vmindex = -1;1569}1570target = membernameObject;1571}15721573J9VMJAVALANGLONG_SET_VALUE(currentThread, box, vmindex);1574J9JAVAARRAYOFOBJECT_STORE(currentThread, arrayObject, 0, box);1575J9JAVAARRAYOFOBJECT_STORE(currentThread, arrayObject, 1, target);15761577result = vmFuncs->j9jni_createLocalRef(env, arrayObject);1578}1579}1580}1581Trc_JCL_java_lang_invoke_MethodHandleNatives_getMemberVMInfo_Exit(env, result);1582vmFuncs->internalExitVMToJNI(currentThread);1583return result;15841585}15861587/**1588* static native void setCallSiteTargetNormal(CallSite site, MethodHandle target)1589*/1590void JNICALL1591Java_java_lang_invoke_MethodHandleNatives_setCallSiteTargetNormal(JNIEnv *env, jclass clazz, jobject callsite, jobject target)1592{1593setCallSiteTargetImpl((J9VMThread*)env, callsite, target, false);1594}15951596/**1597* static native void setCallSiteTargetVolatile(CallSite site, MethodHandle target);1598*/1599void JNICALL1600Java_java_lang_invoke_MethodHandleNatives_setCallSiteTargetVolatile(JNIEnv *env, jclass clazz, jobject callsite, jobject target)1601{1602setCallSiteTargetImpl((J9VMThread*)env, callsite, target, true);1603}16041605/**1606* static native void copyOutBootstrapArguments(Class<?> caller, int[] indexInfo,1607int start, int end,1608Object[] buf, int pos,1609boolean resolve,1610Object ifNotAvailable);1611*/1612void JNICALL1613Java_java_lang_invoke_MethodHandleNatives_copyOutBootstrapArguments(JNIEnv *env, jclass clazz, jclass caller, jintArray indexInfo, jint start, jint end, jobjectArray buf, jint pos, jboolean resolve, jobject ifNotAvailable)1614{1615J9VMThread *currentThread = (J9VMThread*)env;1616J9JavaVM *vm = currentThread->javaVM;1617const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;1618vmFuncs->internalEnterVMFromJNI(currentThread);16191620if ((NULL == caller) || (NULL == indexInfo) || (NULL == buf)) {1621vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);1622} else {1623J9Class *callerClass = J9VM_J9CLASS_FROM_JCLASS(currentThread, caller);1624j9array_t indexInfoArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(indexInfo);1625j9array_t bufferArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(buf);16261627if ((J9INDEXABLEOBJECT_SIZE(currentThread, indexInfoArray) < 2)) {1628vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);1629} else if (((start < -4) || (start > end) || (pos < 0)) || ((jint)J9INDEXABLEOBJECT_SIZE(currentThread, bufferArray) <= pos) || ((jint)J9INDEXABLEOBJECT_SIZE(currentThread, bufferArray) <= (pos + end - start))) {1630vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGLINKAGEERROR, NULL);1631} else {1632U_16 bsmArgCount = (U_16)J9JAVAARRAYOFINT_LOAD(currentThread, indexInfoArray, 0);1633U_16 cpIndex = (U_16)J9JAVAARRAYOFINT_LOAD(currentThread, indexInfoArray, 1);1634J9ROMClass *romClass = callerClass->romClass;1635U_32 * cpShapeDescription = J9ROMCLASS_CPSHAPEDESCRIPTION(romClass);1636if (J9_CP_TYPE(cpShapeDescription, cpIndex) == J9CPTYPE_CONSTANT_DYNAMIC) {1637J9ROMConstantDynamicRef *romConstantRef = (J9ROMConstantDynamicRef*)(J9_ROM_CP_FROM_ROM_CLASS(romClass) + cpIndex);1638J9SRP *callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(romClass);1639U_16 *bsmIndices = (U_16 *) (callSiteData + romClass->callSiteCount);1640U_16 *bsmData = bsmIndices + romClass->callSiteCount;16411642/* clear the J9DescriptionCpPrimitiveType flag with mask to get bsmIndex */1643U_32 bsmIndex = (romConstantRef->bsmIndexAndCpType >> J9DescriptionCpTypeShift) & J9DescriptionCpBsmIndexMask;1644J9ROMNameAndSignature* nameAndSig = SRP_PTR_GET(&romConstantRef->nameAndSignature, J9ROMNameAndSignature*);16451646/* Walk bsmData - skip all bootstrap methods before bsmIndex */1647for (U_32 i = 0; i < bsmIndex; i++) {1648/* increment by size of bsm data plus header */1649bsmData += (bsmData[1] + 2);1650}16511652U_16 bsmCPIndex = bsmData[0];1653U_16 argCount = bsmData[1];16541655/* Check the argCount from indexInfo array matches actual value */1656if (bsmArgCount != argCount) {1657vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);1658goto done;1659}16601661bsmData += 2;16621663while (start < end) {1664/* Copy the arguments between start and end to the buf array1665*1666* Negative start index refer to the mandatory arguments for a bootstrap method1667* -4 -> Lookup1668* -3 -> name (String)1669* -2 -> signature (MethodType)1670* -1 -> argCount of optional arguments1671*/1672j9object_t obj = NULL;1673if (start >= 0) {1674U_16 argIndex = bsmData[start];1675J9ConstantPool *ramConstantPool = J9_CP_FROM_CLASS(callerClass);1676obj = resolveRefToObject(currentThread, ramConstantPool, argIndex, (JNI_TRUE == resolve));1677if ((NULL == obj) && (JNI_TRUE != resolve) && (NULL != ifNotAvailable)) {1678obj = J9_JNI_UNWRAP_REFERENCE(ifNotAvailable);1679}1680} else if (start == -4) {1681obj = resolveRefToObject(currentThread, J9_CP_FROM_CLASS(callerClass), bsmCPIndex, true);1682} else if (start == -3) {1683J9UTF8 *name = J9ROMNAMEANDSIGNATURE_NAME(nameAndSig);1684obj = vm->memoryManagerFunctions->j9gc_createJavaLangStringWithUTFCache(currentThread, name);1685} else if (start == -2) {1686J9UTF8 *signature = J9ROMNAMEANDSIGNATURE_SIGNATURE(nameAndSig);1687/* Call VM Entry point to create the MethodType - Result is put into the1688* currentThread->returnValue as entry points don't "return" in the expected way1689*/1690vmFuncs->sendFromMethodDescriptorString(currentThread, signature, callerClass->classLoader, NULL);1691obj = (j9object_t)currentThread->returnValue;1692} else if (start == -1) {1693obj = vm->memoryManagerFunctions->J9AllocateObject(currentThread, J9VMJAVALANGINTEGER_OR_NULL(vm), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);1694if (NULL == obj) {1695vmFuncs->setHeapOutOfMemoryError(currentThread);1696} else {1697J9VMJAVALANGINTEGER_SET_VALUE(currentThread, obj, argCount);1698}1699}1700if (VM_VMHelpers::exceptionPending(currentThread)) {1701goto done;1702}1703/* Refetch reference after GC point */1704bufferArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(buf);1705J9JAVAARRAYOFOBJECT_STORE(currentThread, bufferArray, pos, obj);1706start += 1;1707pos += 1;1708}1709} else {1710vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGLINKAGEERROR, NULL);1711}1712}1713}1714done:1715vmFuncs->internalExitVMToJNI(currentThread);1716}17171718/**1719* private static native void clearCallSiteContext(CallSiteContext context);1720*/1721void JNICALL1722Java_java_lang_invoke_MethodHandleNatives_clearCallSiteContext(JNIEnv *env, jclass clazz, jobject context)1723{1724return;1725}17261727/**1728* private static native int getNamedCon(int which, Object[] name);1729*/1730jint JNICALL1731Java_java_lang_invoke_MethodHandleNatives_getNamedCon(JNIEnv *env, jclass clazz, jint which, jobjectArray name)1732{1733return 0;1734}17351736/**1737* private static native void registerNatives();1738*/1739void JNICALL1740Java_java_lang_invoke_MethodHandleNatives_registerNatives(JNIEnv *env, jclass clazz)1741{1742return;1743}17441745#endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */17461747#if defined (J9VM_OPT_METHOD_HANDLE) || defined(J9VM_OPT_OPENJDK_METHODHANDLE)1748jobject JNICALL1749Java_java_lang_invoke_MethodHandle_invokeExact(JNIEnv *env, jclass ignored, jobject handle, jobject args)1750{1751throwNewUnsupportedOperationException(env);1752return NULL;1753}17541755jobject JNICALL1756Java_java_lang_invoke_MethodHandle_invoke(JNIEnv *env, jclass ignored, jobject handle, jobject args)1757{1758throwNewUnsupportedOperationException(env);1759return NULL;1760}1761#endif /* defined (J9VM_OPT_METHOD_HANDLE) || defined(J9VM_OPT_OPENJDK_METHODHANDLE) */1762} /* extern "C" */176317641765