Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/jcl/common/java_lang_invoke_MethodHandleNatives.cpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2021, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* 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-exception
21
*******************************************************************************/
22
23
#include "j9.h"
24
#include "jclprots.h"
25
#include "j9cp.h"
26
#include "j9protos.h"
27
#include "ut_j9jcl.h"
28
#include "j9port.h"
29
#include "jclglob.h"
30
#include "jcl_internal.h"
31
#include "util_api.h"
32
#include "j9vmconstantpool.h"
33
#include "ObjectAccessBarrierAPI.hpp"
34
#include "objhelp.h"
35
36
#include <string.h>
37
#include <assert.h>
38
39
#include "VMHelpers.hpp"
40
41
extern "C" {
42
43
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
44
45
/* Constants mapped from java.lang.invoke.MethodHandleNatives$Constants
46
* These constants are validated by the MethodHandleNatives$Constants.verifyConstants()
47
* method when Java assertions are enabled
48
*/
49
50
#define MN_REFERENCE_KIND_SHIFT 24
51
#define MN_REFERENCE_KIND_MASK 0xF /* (flag >> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK */
52
53
#define MN_SEARCH_SUPERCLASSES 0x00100000
54
#define MN_SEARCH_INTERFACES 0x00200000
55
56
#if JAVA_SPEC_VERSION >= 16
57
#define MN_MODULE_MODE 0x00000010
58
#define MN_UNCONDITIONAL_MODE 0x00000020
59
#define MN_TRUSTED_MODE -1
60
#endif /* JAVA_SPEC_VERSION >= 16 */
61
62
/* PlaceHolder value used for MN.vmindex that has default method conflict */
63
#define J9VM_RESOLVED_VMINDEX_FOR_DEFAULT_THROW 1
64
65
J9_DECLARE_CONSTANT_UTF8(mutableCallSite, "java/lang/invoke/MutableCallSite");
66
67
static bool
68
isPolymorphicMHMethod(J9JavaVM *vm, J9Class *declaringClass, J9UTF8 *methodName)
69
{
70
if (declaringClass == J9VMJAVALANGINVOKEMETHODHANDLE(vm)) {
71
U_8 *nameData = J9UTF8_DATA(methodName);
72
U_16 nameLength = J9UTF8_LENGTH(methodName);
73
74
if (J9UTF8_LITERAL_EQUALS(nameData, nameLength, "invoke")
75
|| J9UTF8_LITERAL_EQUALS(nameData, nameLength, "invokeBasic")
76
|| J9UTF8_LITERAL_EQUALS(nameData, nameLength, "linkToVirtual")
77
|| J9UTF8_LITERAL_EQUALS(nameData, nameLength, "linkToStatic")
78
|| J9UTF8_LITERAL_EQUALS(nameData, nameLength, "linkToSpecial")
79
|| J9UTF8_LITERAL_EQUALS(nameData, nameLength, "linkToInterface")
80
|| J9UTF8_LITERAL_EQUALS(nameData, nameLength, "linkToNative")
81
) {
82
return true;
83
}
84
}
85
86
return false;
87
}
88
89
/* Private MemberName object init helper
90
*
91
* Set the MemberName fields based on the refObject given:
92
* For j.l.reflect.Field:
93
* find JNIFieldID for refObject, create j.l.String for name and signature and store in MN.name/type fields.
94
* set vmindex to the fieldID pointer and target to the field offset.
95
* set MN.clazz to declaring class in the fieldID struct.
96
* For j.l.reflect.Method or j.l.reflect.Constructor:
97
* find JNIMethodID, set vmindex to the methodID pointer and target to the J9Method struct.
98
* set MN.clazz to the refObject's declaring class.
99
*
100
* Then for both, compute the MN.flags using access flags and invocation type based on the JNI-id.
101
*
102
* Throw an IllegalArgumentException if the refObject is not a Field/Method/Constructor
103
*
104
* Note: caller must have vmaccess before invoking this helper
105
*/
106
static void
107
initImpl(J9VMThread *currentThread, j9object_t membernameObject, j9object_t refObject)
108
{
109
J9JavaVM *vm = currentThread->javaVM;
110
const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
111
112
J9Class* refClass = J9OBJECT_CLAZZ(currentThread, refObject);
113
114
jint flags = 0;
115
jlong vmindex = 0;
116
jlong target = 0;
117
j9object_t clazzObject = NULL;
118
j9object_t nameObject = NULL;
119
j9object_t typeObject = NULL;
120
121
if (refClass == J9VMJAVALANGREFLECTFIELD(vm)) {
122
J9JNIFieldID *fieldID = vm->reflectFunctions.idFromFieldObject(currentThread, NULL, refObject);
123
J9ROMFieldShape *romField = fieldID->field;
124
UDATA offset = fieldID->offset;
125
126
if (J9_ARE_ANY_BITS_SET(romField->modifiers, J9AccStatic)) {
127
offset |= J9_SUN_STATIC_FIELD_OFFSET_TAG;
128
if (J9_ARE_ANY_BITS_SET(romField->modifiers, J9AccFinal)) {
129
offset |= J9_SUN_FINAL_FIELD_OFFSET_TAG;
130
}
131
}
132
vmindex = (jlong)fieldID;
133
target = (jlong)offset;
134
135
flags = fieldID->field->modifiers & CFR_FIELD_ACCESS_MASK;
136
flags |= MN_IS_FIELD;
137
flags |= (J9_ARE_ANY_BITS_SET(flags, J9AccStatic) ? MH_REF_GETSTATIC : MH_REF_GETFIELD) << MN_REFERENCE_KIND_SHIFT;
138
if (VM_VMHelpers::isTrustedFinalField(fieldID->field, fieldID->declaringClass->romClass)) {
139
flags |= MN_TRUSTED_FINAL;
140
}
141
142
nameObject = J9VMJAVALANGREFLECTFIELD_NAME(currentThread, refObject);
143
typeObject = J9VMJAVALANGREFLECTFIELD_TYPE(currentThread, refObject);
144
145
clazzObject = J9VM_J9CLASS_TO_HEAPCLASS(fieldID->declaringClass);
146
} else if (refClass == J9VMJAVALANGREFLECTMETHOD(vm)) {
147
J9JNIMethodID *methodID = vm->reflectFunctions.idFromMethodObject(currentThread, refObject);
148
vmindex = (jlong)methodID;
149
target = (jlong)methodID->method;
150
151
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(methodID->method);
152
153
J9Class *declaringClass = J9_CLASS_FROM_METHOD(methodID->method);
154
J9UTF8 *methodName = J9ROMMETHOD_NAME(romMethod);
155
if (isPolymorphicMHMethod(vm, declaringClass, methodName)
156
#if JAVA_SPEC_VERSION >= 9
157
|| ((declaringClass == J9VMJAVALANGINVOKEVARHANDLE(vm))
158
&& VM_VMHelpers::isPolymorphicVarHandleMethod(J9UTF8_DATA(methodName), J9UTF8_LENGTH(methodName)))
159
#endif
160
) {
161
/* Do not initialize polymorphic MH/VH methods as the Java code handles the "MemberName.clazz == null" case for them. */
162
return;
163
}
164
165
flags = romMethod->modifiers & CFR_METHOD_ACCESS_MASK;
166
if (J9_ARE_ANY_BITS_SET(romMethod->modifiers, J9AccMethodCallerSensitive)) {
167
flags |= MN_CALLER_SENSITIVE;
168
}
169
flags |= MN_IS_METHOD;
170
if (J9_ARE_ANY_BITS_SET(methodID->vTableIndex, J9_JNI_MID_INTERFACE)) {
171
flags |= MH_REF_INVOKEINTERFACE << MN_REFERENCE_KIND_SHIFT;
172
} else if (J9_ARE_ANY_BITS_SET(romMethod->modifiers , J9AccStatic)) {
173
flags |= MH_REF_INVOKESTATIC << MN_REFERENCE_KIND_SHIFT;
174
} else if (J9_ARE_ANY_BITS_SET(romMethod->modifiers , J9AccFinal) || !J9ROMMETHOD_HAS_VTABLE(romMethod)) {
175
flags |= MH_REF_INVOKESPECIAL << MN_REFERENCE_KIND_SHIFT;
176
} else {
177
flags |= MH_REF_INVOKEVIRTUAL << MN_REFERENCE_KIND_SHIFT;
178
}
179
180
nameObject = J9VMJAVALANGREFLECTMETHOD_NAME(currentThread, refObject);
181
clazzObject = J9VMJAVALANGREFLECTMETHOD_CLAZZ(currentThread, refObject);
182
} else if (refClass == J9VMJAVALANGREFLECTCONSTRUCTOR(vm)) {
183
J9JNIMethodID *methodID = vm->reflectFunctions.idFromConstructorObject(currentThread, refObject);
184
vmindex = (jlong)methodID;
185
target = (jlong)methodID->method;
186
187
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(methodID->method);
188
189
flags = romMethod->modifiers & CFR_METHOD_ACCESS_MASK;
190
if (J9_ARE_ANY_BITS_SET(romMethod->modifiers, J9AccMethodCallerSensitive)) {
191
flags |= MN_CALLER_SENSITIVE;
192
}
193
flags |= MN_IS_CONSTRUCTOR | (MH_REF_INVOKESPECIAL << MN_REFERENCE_KIND_SHIFT);
194
195
clazzObject = J9VMJAVALANGREFLECTMETHOD_CLAZZ(currentThread, refObject);
196
} else {
197
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, NULL);
198
}
199
200
if (!VM_VMHelpers::exceptionPending(currentThread)) {
201
J9VMJAVALANGINVOKEMEMBERNAME_SET_FLAGS(currentThread, membernameObject, flags);
202
J9VMJAVALANGINVOKEMEMBERNAME_SET_NAME(currentThread, membernameObject, nameObject);
203
if (NULL != typeObject) {
204
Assert_JCL_true(OMR_ARE_ALL_BITS_SET(flags, MN_IS_FIELD));
205
J9VMJAVALANGINVOKEMEMBERNAME_SET_TYPE(currentThread, membernameObject, typeObject);
206
}
207
J9VMJAVALANGINVOKEMEMBERNAME_SET_CLAZZ(currentThread, membernameObject, clazzObject);
208
J9OBJECT_U64_STORE(currentThread, membernameObject, vm->vmindexOffset, (U_64)vmindex);
209
J9OBJECT_U64_STORE(currentThread, membernameObject, vm->vmtargetOffset, (U_64)target);
210
Trc_JCL_java_lang_invoke_MethodHandleNatives_initImpl_setData(currentThread, flags, nameObject, typeObject, clazzObject, vmindex, target);
211
}
212
}
213
214
static char *
215
sigForPrimitiveOrVoid(J9JavaVM *vm, J9Class *clazz)
216
{
217
PORT_ACCESS_FROM_JAVAVM(vm);
218
char* signature = (char*)j9mem_allocate_memory(2, OMRMEM_CATEGORY_VM);
219
220
if (NULL != signature) {
221
if (clazz == vm->booleanReflectClass) {
222
signature[0] = 'Z';
223
} else if (clazz == vm->byteReflectClass) {
224
signature[0] = 'B';
225
} else if (clazz == vm->charReflectClass) {
226
signature[0] = 'C';
227
} else if (clazz == vm->shortReflectClass) {
228
signature[0] = 'S';
229
} else if (clazz == vm->intReflectClass) {
230
signature[0] = 'I';
231
} else if (clazz == vm->longReflectClass) {
232
signature[0] = 'J';
233
} else if (clazz == vm->floatReflectClass) {
234
signature[0] = 'F';
235
} else if (clazz == vm->doubleReflectClass) {
236
signature[0] = 'D';
237
} else if (clazz == vm->voidReflectClass) {
238
signature[0] = 'V';
239
}
240
241
signature[1] = '\0';
242
}
243
244
return signature;
245
}
246
247
static char *
248
getClassSignature(J9VMThread *currentThread, J9Class * clazz)
249
{
250
J9JavaVM *vm = currentThread->javaVM;
251
PORT_ACCESS_FROM_JAVAVM(vm);
252
char *sig = NULL;
253
254
if (J9ROMCLASS_IS_PRIMITIVE_TYPE(clazz->romClass)) {
255
sig = sigForPrimitiveOrVoid(vm, clazz);
256
} else {
257
j9object_t sigString = J9VMJAVALANGCLASS_CLASSNAMESTRING(currentThread, J9VM_J9CLASS_TO_HEAPCLASS(clazz));
258
if (NULL != sigString) {
259
/* +3 so that we can fit 'L' and ';' around the class name with the null-terminator */
260
UDATA utfLength = vm->internalVMFunctions->getStringUTF8Length(currentThread, sigString) + 3;
261
sig = (char *)j9mem_allocate_memory(utfLength, OMRMEM_CATEGORY_VM);
262
if (NULL != sig) {
263
if (J9ROMCLASS_IS_ARRAY(clazz->romClass)) {
264
vm->internalVMFunctions->copyStringToUTF8Helper(currentThread, sigString, J9_STR_NULL_TERMINATE_RESULT | J9_STR_XLAT, 0, J9VMJAVALANGSTRING_LENGTH(currentThread, sigString), (U_8*)sig, utfLength);
265
} else {
266
sig[0] = 'L';
267
vm->internalVMFunctions->copyStringToUTF8Helper(currentThread, sigString, J9_STR_XLAT, 0, J9VMJAVALANGSTRING_LENGTH(currentThread, sigString), (U_8*)(sig + 1), utfLength - 1);
268
sig[utfLength - 2] = ';';
269
sig[utfLength - 1] = '\0';
270
}
271
}
272
} else {
273
U_32 numDims = 0;
274
275
J9Class *myClass = clazz;
276
while (J9ROMCLASS_IS_ARRAY(myClass->romClass)) {
277
J9Class * componentClass = (J9Class *)(((J9ArrayClass*)myClass)->componentType);
278
if (J9ROMCLASS_IS_PRIMITIVE_TYPE(componentClass->romClass)) {
279
break;
280
}
281
numDims += 1;
282
myClass = componentClass;
283
}
284
285
J9UTF8 *romName = J9ROMCLASS_CLASSNAME(myClass->romClass);
286
U_32 nameLength = J9UTF8_LENGTH(romName);
287
char * name = (char *)J9UTF8_DATA(romName);
288
U_32 sigLength = nameLength + numDims;
289
if (* name != '[') {
290
sigLength += 2;
291
}
292
293
sigLength++; /* for null-termination */
294
sig = (char *)j9mem_allocate_memory(sigLength, OMRMEM_CATEGORY_VM);
295
if (NULL != sig) {
296
U_32 i = 0;
297
for (i = 0; i < numDims; i++) {
298
sig[i] = '[';
299
}
300
301
if (*name != '[') {
302
sig[i++] = 'L';
303
}
304
305
memcpy(sig+i, name, nameLength);
306
i += nameLength;
307
308
if (*name != '[') {
309
sig[i++] = ';';
310
}
311
sig[sigLength-1] = '\0';
312
}
313
}
314
}
315
316
return sig;
317
}
318
319
static J9UTF8 *
320
getJ9UTF8SignatureFromMethodType(J9VMThread *currentThread, j9object_t typeObject)
321
{
322
J9JavaVM *vm = currentThread->javaVM;
323
j9object_t ptypes = J9VMJAVALANGINVOKEMETHODTYPE_PTYPES(currentThread, typeObject);
324
U_32 numArgs = J9INDEXABLEOBJECT_SIZE(currentThread, ptypes);
325
326
J9UTF8* methodDescriptor = NULL;
327
char* cursor = NULL;
328
char* rSignature = NULL;
329
UDATA signatureLength = 2; /* space for '(', ')' */
330
331
PORT_ACCESS_FROM_JAVAVM(vm);
332
333
char** signatures = (char**)j9mem_allocate_memory(numArgs * sizeof(char*), OMRMEM_CATEGORY_VM);
334
if (NULL == signatures) {
335
goto done;
336
}
337
338
memset(signatures, 0, numArgs * sizeof(char*));
339
340
for (U_32 i = 0; i < numArgs; i++) {
341
j9object_t pObject = J9JAVAARRAYOFOBJECT_LOAD(currentThread, ptypes, i);
342
J9Class *pclass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, pObject);
343
signatures[i] = getClassSignature(currentThread, pclass);
344
if (NULL == signatures[i]) {
345
goto done;
346
}
347
348
signatureLength += strlen(signatures[i]);
349
}
350
351
{
352
/* Return type */
353
j9object_t rtype = J9VMJAVALANGINVOKEMETHODTYPE_RTYPE(currentThread, typeObject);
354
J9Class *rclass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, rtype);
355
rSignature = getClassSignature(currentThread, rclass);
356
if (NULL == rSignature) {
357
goto done;
358
}
359
360
signatureLength += strlen(rSignature);
361
}
362
363
methodDescriptor = (J9UTF8*)j9mem_allocate_memory(signatureLength + sizeof(J9UTF8), OMRMEM_CATEGORY_VM);
364
if (NULL == methodDescriptor) {
365
goto done;
366
}
367
J9UTF8_SET_LENGTH(methodDescriptor, (U_16)signatureLength);
368
cursor = (char*)J9UTF8_DATA(methodDescriptor);
369
*cursor++ = '(';
370
371
/* Copy class signatures to descriptor string */
372
for (U_32 i = 0; i < numArgs; i++) {
373
UDATA len = strlen(signatures[i]);
374
memcpy(cursor, signatures[i], len);
375
cursor += len;
376
}
377
378
*cursor++ = ')';
379
/* Copy return type signature to descriptor string */
380
memcpy(cursor, rSignature, strlen(rSignature));
381
382
done:
383
j9mem_free_memory(rSignature);
384
385
if (NULL != signatures) {
386
for (U_32 i = 0; i < numArgs; i++) {
387
j9mem_free_memory(signatures[i]);
388
}
389
j9mem_free_memory(signatures);
390
}
391
return methodDescriptor;
392
}
393
394
j9object_t
395
resolveRefToObject(J9VMThread *currentThread, J9ConstantPool *ramConstantPool, U_16 cpIndex, bool resolve)
396
{
397
J9JavaVM *vm = currentThread->javaVM;
398
const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
399
400
j9object_t result = NULL;
401
402
J9RAMSingleSlotConstantRef *ramCP = (J9RAMSingleSlotConstantRef*)ramConstantPool + cpIndex;
403
U_32 *cpShapeDescription = J9ROMCLASS_CPSHAPEDESCRIPTION(J9_CLASS_FROM_CP(ramConstantPool)->romClass);
404
405
switch (J9_CP_TYPE(cpShapeDescription, cpIndex)) {
406
case J9CPTYPE_CLASS: {
407
J9Class *clazz = (J9Class*)ramCP->value;
408
if ((NULL == clazz) && resolve) {
409
clazz = vmFuncs->resolveClassRef(currentThread, ramConstantPool, cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE);
410
}
411
if (NULL != clazz) {
412
result = J9VM_J9CLASS_TO_HEAPCLASS(clazz);
413
}
414
break;
415
}
416
case J9CPTYPE_STRING: {
417
result = (j9object_t)ramCP->value;
418
if ((NULL == result) && resolve) {
419
result = vmFuncs->resolveStringRef(currentThread, ramConstantPool, cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE);
420
}
421
break;
422
}
423
case J9CPTYPE_INT: {
424
J9ROMSingleSlotConstantRef *romCP = (J9ROMSingleSlotConstantRef*)J9_ROM_CP_FROM_CP(ramConstantPool) + cpIndex;
425
result = vm->memoryManagerFunctions->J9AllocateObject(currentThread, J9VMJAVALANGINTEGER_OR_NULL(vm), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);
426
if (NULL == result) {
427
vmFuncs->setHeapOutOfMemoryError(currentThread);
428
goto done;
429
}
430
J9VMJAVALANGINTEGER_SET_VALUE(currentThread, result, romCP->data);
431
break;
432
}
433
case J9CPTYPE_FLOAT: {
434
J9ROMSingleSlotConstantRef *romCP = (J9ROMSingleSlotConstantRef*)J9_ROM_CP_FROM_CP(ramConstantPool) + cpIndex;
435
result = vm->memoryManagerFunctions->J9AllocateObject(currentThread, J9VMJAVALANGFLOAT_OR_NULL(vm), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);
436
if (NULL == result) {
437
vmFuncs->setHeapOutOfMemoryError(currentThread);
438
goto done;
439
}
440
J9VMJAVALANGFLOAT_SET_VALUE(currentThread, result, romCP->data);
441
break;
442
}
443
case J9CPTYPE_LONG: {
444
J9ROMConstantRef *romCP = (J9ROMConstantRef*)J9_ROM_CP_FROM_CP(ramConstantPool) + cpIndex;
445
#ifdef J9VM_ENV_LITTLE_ENDIAN
446
U_64 value = (((U_64)(romCP->slot2)) << 32) | ((U_64)(romCP->slot1));
447
#else
448
U_64 value = (((U_64)(romCP->slot1)) << 32) | ((U_64)(romCP->slot2));
449
#endif
450
result = vm->memoryManagerFunctions->J9AllocateObject(currentThread, J9VMJAVALANGLONG_OR_NULL(vm), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);
451
if (NULL == result) {
452
vmFuncs->setHeapOutOfMemoryError(currentThread);
453
goto done;
454
}
455
J9VMJAVALANGLONG_SET_VALUE(currentThread, result, value);
456
break;
457
}
458
case J9CPTYPE_DOUBLE: {
459
J9ROMConstantRef *romCP = (J9ROMConstantRef*)J9_ROM_CP_FROM_CP(ramConstantPool) + cpIndex;
460
#ifdef J9VM_ENV_LITTLE_ENDIAN
461
U_64 value = (((U_64)(romCP->slot2)) << 32) | ((U_64)(romCP->slot1));
462
#else
463
U_64 value = (((U_64)(romCP->slot1)) << 32) | ((U_64)(romCP->slot2));
464
#endif
465
result = vm->memoryManagerFunctions->J9AllocateObject(currentThread, J9VMJAVALANGDOUBLE_OR_NULL(vm), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);
466
if (NULL == result) {
467
vmFuncs->setHeapOutOfMemoryError(currentThread);
468
goto done;
469
}
470
J9VMJAVALANGDOUBLE_SET_VALUE(currentThread, result, value);
471
break;
472
}
473
case J9CPTYPE_METHOD_TYPE: {
474
result = (j9object_t)ramCP->value;
475
if ((NULL == result) && resolve) {
476
result = vmFuncs->resolveMethodTypeRef(currentThread, ramConstantPool, cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE);
477
}
478
break;
479
}
480
case J9CPTYPE_METHODHANDLE: {
481
result = (j9object_t)ramCP->value;
482
if ((NULL == result) && resolve) {
483
result = vmFuncs->resolveMethodHandleRef(currentThread, ramConstantPool, cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE | J9_RESOLVE_FLAG_NO_CLASS_INIT);
484
}
485
break;
486
}
487
case J9CPTYPE_CONSTANT_DYNAMIC: {
488
result = (j9object_t)ramCP->value;
489
if ((NULL == result) && resolve) {
490
result = vmFuncs->resolveConstantDynamic(currentThread, ramConstantPool, cpIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE);
491
}
492
break;
493
}
494
} /* switch */
495
done:
496
return result;
497
}
498
499
J9Method *
500
lookupMethod(J9VMThread *currentThread, J9Class *resolvedClass, J9UTF8 *name, J9UTF8 *signature, J9Class *callerClass, UDATA lookupOptions)
501
{
502
J9Method *result = NULL;
503
J9NameAndSignature nas;
504
J9UTF8 nullSignature = {0};
505
506
nas.name = name;
507
nas.signature = signature;
508
lookupOptions |= J9_LOOK_DIRECT_NAS;
509
510
/* If looking for a MethodHandle polymorphic INL method, allow any caller signature. */
511
if (isPolymorphicMHMethod(currentThread->javaVM, resolvedClass, name)) {
512
nas.signature = &nullSignature;
513
/* Set flag for partial signature lookup. Signature length is already initialized to 0. */
514
lookupOptions |= J9_LOOK_PARTIAL_SIGNATURE;
515
}
516
517
result = (J9Method*)currentThread->javaVM->internalVMFunctions->javaLookupMethod(currentThread, resolvedClass, (J9ROMNameAndSignature*)&nas, callerClass, lookupOptions);
518
519
return result;
520
}
521
522
static void
523
setCallSiteTargetImpl(J9VMThread *currentThread, jobject callsite, jobject target, bool isVolatile)
524
{
525
J9JavaVM *javaVM = currentThread->javaVM;
526
const J9InternalVMFunctions *vmFuncs = javaVM->internalVMFunctions;
527
vmFuncs->internalEnterVMFromJNI(currentThread);
528
529
if ((NULL == callsite) || (NULL == target)) {
530
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);
531
} else {
532
j9object_t callsiteObject = J9_JNI_UNWRAP_REFERENCE(callsite);
533
j9object_t targetObject = J9_JNI_UNWRAP_REFERENCE(target);
534
535
J9Class *clazz = J9OBJECT_CLAZZ(currentThread, callsiteObject);
536
UDATA offset = (UDATA)vmFuncs->instanceFieldOffset(
537
currentThread,
538
clazz,
539
(U_8*)"target",
540
LITERAL_STRLEN("target"),
541
(U_8*)"Ljava/lang/invoke/MethodHandle;",
542
LITERAL_STRLEN("Ljava/lang/invoke/MethodHandle;"),
543
NULL, NULL, 0);
544
offset += J9VMTHREAD_OBJECT_HEADER_SIZE(currentThread);
545
MM_ObjectAccessBarrierAPI objectAccessBarrier = MM_ObjectAccessBarrierAPI(currentThread);
546
547
/* Check for MutableCallSite modification. */
548
J9JITConfig* jitConfig = javaVM->jitConfig;
549
J9Class *mcsClass = vmFuncs->peekClassHashTable(
550
currentThread,
551
javaVM->systemClassLoader,
552
J9UTF8_DATA(&mutableCallSite),
553
J9UTF8_LENGTH(&mutableCallSite));
554
555
if (!isVolatile /* MutableCallSite uses setTargetNormal(). */
556
&& (NULL != jitConfig)
557
&& (NULL != mcsClass)
558
&& VM_VMHelpers::inlineCheckCast(clazz, mcsClass)
559
) {
560
jitConfig->jitSetMutableCallSiteTarget(currentThread, callsiteObject, targetObject);
561
} else {
562
/* There are no runtime assumptions to invalidate (either because
563
* the call site is not a MutableCallSite, or because the JIT
564
* compiler is not loaded). */
565
objectAccessBarrier.inlineMixedObjectStoreObject(currentThread, callsiteObject, offset, targetObject, isVolatile);
566
}
567
}
568
vmFuncs->internalExitVMToJNI(currentThread);
569
}
570
571
572
/**
573
* static native void init(MemberName self, Object ref);
574
*
575
* Initializes a MemberName object using the given ref object.
576
* see initImpl for detail
577
* Throw NPE if self or ref is null
578
* Throw IllegalArgumentException if ref is not a field/method/constructor
579
*/
580
void JNICALL
581
Java_java_lang_invoke_MethodHandleNatives_init(JNIEnv *env, jclass clazz, jobject self, jobject ref)
582
{
583
J9VMThread *currentThread = (J9VMThread*)env;
584
J9JavaVM *vm = currentThread->javaVM;
585
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
586
vmFuncs->internalEnterVMFromJNI(currentThread);
587
588
Trc_JCL_java_lang_invoke_MethodHandleNatives_init_Entry(env, self, ref);
589
if ((NULL == self) || (NULL == ref)) {
590
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);
591
} else {
592
j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);
593
j9object_t refObject = J9_JNI_UNWRAP_REFERENCE(ref);
594
595
initImpl(currentThread, membernameObject, refObject);
596
}
597
Trc_JCL_java_lang_invoke_MethodHandleNatives_init_Exit(env);
598
vmFuncs->internalExitVMToJNI(currentThread);
599
}
600
601
/**
602
* static native void expand(MemberName self);
603
*
604
* Given a MemberName object, try to set the uninitialized fields from existing VM metadata.
605
* Uses VM metadata (vmindex & vmtarget) to set symblic data fields (name & type & defc)
606
*
607
* Throws NullPointerException if MemberName object is null.
608
* Throws IllegalArgumentException if MemberName doesn't contain required data to expand.
609
* Throws InternalError if the MemberName object contains invalid data or completely uninitialized.
610
*/
611
void JNICALL
612
Java_java_lang_invoke_MethodHandleNatives_expand(JNIEnv *env, jclass clazz, jobject self)
613
{
614
J9VMThread *currentThread = (J9VMThread*)env;
615
J9JavaVM *vm = currentThread->javaVM;
616
const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
617
vmFuncs->internalEnterVMFromJNI(currentThread);
618
619
Trc_JCL_java_lang_invoke_MethodHandleNatives_expand_Entry(env, self);
620
if (NULL == self) {
621
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);
622
} else {
623
j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);
624
jint flags = J9VMJAVALANGINVOKEMEMBERNAME_FLAGS(currentThread, membernameObject);
625
jlong vmindex = (jlong)J9OBJECT_ADDRESS_LOAD(currentThread, membernameObject, vm->vmindexOffset);
626
627
Trc_JCL_java_lang_invoke_MethodHandleNatives_expand_Data(env, membernameObject, flags, vmindex);
628
if (J9_ARE_ANY_BITS_SET(flags, MN_IS_FIELD)) {
629
/* For Field MemberName, the clazz and vmindex fields must be set. */
630
if ((NULL != J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject)) && (NULL != (void*)vmindex)) {
631
J9JNIFieldID *field = (J9JNIFieldID*)vmindex;
632
633
/* if name/type field is uninitialized, create j.l.String from ROM field name/sig and store in MN fields. */
634
if (NULL == J9VMJAVALANGINVOKEMEMBERNAME_NAME(currentThread, membernameObject)) {
635
J9UTF8 *name = J9ROMFIELDSHAPE_NAME(field->field);
636
j9object_t nameString = vm->memoryManagerFunctions->j9gc_createJavaLangStringWithUTFCache(currentThread, name);
637
if (NULL != nameString) {
638
/* Refetch reference after GC point */
639
membernameObject = J9_JNI_UNWRAP_REFERENCE(self);
640
J9VMJAVALANGINVOKEMEMBERNAME_SET_NAME(currentThread, membernameObject, nameString);
641
}
642
}
643
if (NULL == J9VMJAVALANGINVOKEMEMBERNAME_TYPE(currentThread, membernameObject)) {
644
J9UTF8 *signature = J9ROMFIELDSHAPE_SIGNATURE(field->field);
645
j9object_t signatureString = vm->memoryManagerFunctions->j9gc_createJavaLangStringWithUTFCache(currentThread, signature);
646
if (NULL != signatureString) {
647
/* Refetch reference after GC point */
648
membernameObject = J9_JNI_UNWRAP_REFERENCE(self);
649
J9VMJAVALANGINVOKEMEMBERNAME_SET_TYPE(currentThread, membernameObject, signatureString);
650
}
651
}
652
} else {
653
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, NULL);
654
}
655
} else if (J9_ARE_ANY_BITS_SET(flags, MN_IS_METHOD | MN_IS_CONSTRUCTOR)) {
656
if (NULL != (void*)vmindex) {
657
/* For method/constructor MemberName, the vmindex field is required for expand.*/
658
J9JNIMethodID *methodID = (J9JNIMethodID*)vmindex;
659
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(methodID->method);
660
661
/* Retrieve method info using JNIMethodID, store to MN fields. */
662
if (NULL == J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject)) {
663
j9object_t newClassObject = J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_METHOD(methodID->method));
664
J9VMJAVALANGINVOKEMEMBERNAME_SET_CLAZZ(currentThread, membernameObject, newClassObject);
665
}
666
if (NULL == J9VMJAVALANGINVOKEMEMBERNAME_NAME(currentThread, membernameObject)) {
667
J9UTF8 *name = J9ROMMETHOD_NAME(romMethod);
668
j9object_t nameString = vm->memoryManagerFunctions->j9gc_createJavaLangStringWithUTFCache(currentThread, name);
669
if (NULL != nameString) {
670
/* Refetch reference after GC point */
671
membernameObject = J9_JNI_UNWRAP_REFERENCE(self);
672
J9VMJAVALANGINVOKEMEMBERNAME_SET_NAME(currentThread, membernameObject, nameString);
673
}
674
}
675
if (NULL == J9VMJAVALANGINVOKEMEMBERNAME_TYPE(currentThread, membernameObject)) {
676
J9UTF8 *signature = J9ROMMETHOD_SIGNATURE(romMethod);
677
j9object_t signatureString = vm->memoryManagerFunctions->j9gc_createJavaLangStringWithUTFCache(currentThread, signature);
678
if (NULL != signatureString) {
679
/* Refetch reference after GC point */
680
membernameObject = J9_JNI_UNWRAP_REFERENCE(self);
681
J9VMJAVALANGINVOKEMEMBERNAME_SET_TYPE(currentThread, membernameObject, signatureString);
682
}
683
}
684
} else {
685
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, NULL);
686
}
687
} else {
688
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);
689
}
690
}
691
Trc_JCL_java_lang_invoke_MethodHandleNatives_expand_Exit(env);
692
vmFuncs->internalExitVMToJNI(currentThread);
693
}
694
695
/**
696
* static native MemberName resolve(MemberName self, Class<?> caller,
697
* boolean speculativeResolve) throws LinkageError, ClassNotFoundException;
698
*
699
* Resolve the method/field represented by the MemberName's symbolic data (name & type & defc) with the supplied caller
700
* Store the resolved Method/Field's JNI-id in vmindex, field offset / method pointer in vmtarget
701
*
702
* If the speculativeResolve flag is not set, failed resolution will throw the corresponding exception.
703
* If the resolution failed with no exception:
704
* Throw NoSuchFieldError for field MemberName
705
* Throw NoSuchMethodError for method/constructor MemberName
706
* Throw LinkageError for other
707
*/
708
#if JAVA_SPEC_VERSION >= 16
709
jobject JNICALL
710
Java_java_lang_invoke_MethodHandleNatives_resolve(JNIEnv *env, jclass clazz, jobject self, jclass caller, jint lookupMode, jboolean speculativeResolve)
711
#else /* JAVA_SPEC_VERSION >= 16 */
712
jobject JNICALL
713
Java_java_lang_invoke_MethodHandleNatives_resolve(JNIEnv *env, jclass clazz, jobject self, jclass caller, jboolean speculativeResolve)
714
#endif /* JAVA_SPEC_VERSION >= 16 */
715
{
716
J9VMThread *currentThread = (J9VMThread*)env;
717
J9JavaVM *vm = currentThread->javaVM;
718
const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
719
jobject result = NULL;
720
J9UTF8 *name = NULL;
721
J9UTF8 *signature = NULL;
722
PORT_ACCESS_FROM_JAVAVM(vm);
723
vmFuncs->internalEnterVMFromJNI(currentThread);
724
725
Trc_JCL_java_lang_invoke_MethodHandleNatives_resolve_Entry(env, self, caller, (speculativeResolve ? "true" : "false"));
726
if (NULL == self) {
727
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);
728
} else {
729
j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);
730
jlong vmindex = (jlong)(UDATA)J9OBJECT_U64_LOAD(currentThread, membernameObject, vm->vmindexOffset);
731
jlong target = (jlong)(UDATA)J9OBJECT_U64_LOAD(currentThread, membernameObject, vm->vmtargetOffset);
732
733
jint flags = J9VMJAVALANGINVOKEMEMBERNAME_FLAGS(currentThread, membernameObject);
734
jint new_flags = 0;
735
j9object_t new_clazz = NULL;
736
737
Trc_JCL_java_lang_invoke_MethodHandleNatives_resolve_Data(env, membernameObject, caller, flags, vmindex, target);
738
/* Check if MemberName is already resolved */
739
if (0 != target) {
740
result = self;
741
} else {
742
/* Initialize nameObject after creating typeString which could trigger GC */
743
j9object_t nameObject = NULL;
744
j9object_t typeObject = J9VMJAVALANGINVOKEMEMBERNAME_TYPE(currentThread, membernameObject);
745
j9object_t clazzObject = J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject);
746
J9Class *resolvedClass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, clazzObject);
747
748
jint ref_kind = (flags >> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK;
749
750
J9Class *typeClass = J9OBJECT_CLAZZ(currentThread, typeObject);
751
752
/* The type field of a MemberName could be in:
753
* MethodType: MethodType representing method/constructor MemberName's method signature
754
* String: String representing MemberName's signature (field or method)
755
* Class: Class representing field MemberName's field type
756
*/
757
if (J9VMJAVALANGINVOKEMETHODTYPE(vm) == typeClass) {
758
j9object_t sigString = J9VMJAVALANGINVOKEMETHODTYPE_METHODDESCRIPTOR(currentThread, typeObject);
759
if (NULL != sigString) {
760
signature = vmFuncs->copyStringToJ9UTF8WithMemAlloc(currentThread, sigString, J9_STR_XLAT, "", 0, NULL, 0);
761
} else {
762
signature = getJ9UTF8SignatureFromMethodType(currentThread, typeObject);
763
}
764
} else if (J9VMJAVALANGSTRING_OR_NULL(vm) == typeClass) {
765
signature = vmFuncs->copyStringToJ9UTF8WithMemAlloc(currentThread, typeObject, J9_STR_XLAT, "", 0, NULL, 0);
766
} else if (J9VMJAVALANGCLASS(vm) == typeClass) {
767
J9Class *rclass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, typeObject);
768
char *classSignature = getClassSignature(currentThread, rclass);
769
if (NULL != classSignature) {
770
UDATA signatureLength = strlen(classSignature);
771
PORT_ACCESS_FROM_JAVAVM(vm);
772
signature = (J9UTF8*)j9mem_allocate_memory(signatureLength + sizeof(J9UTF8), OMRMEM_CATEGORY_VM);
773
if (NULL != signature) {
774
J9UTF8_SET_LENGTH(signature, (U_16)signatureLength);
775
memcpy(J9UTF8_DATA(signature), classSignature, signatureLength);
776
}
777
j9mem_free_memory(classSignature);
778
}
779
} else {
780
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);
781
goto done;
782
}
783
784
/* Check if signature string is correctly generated */
785
if (NULL == signature) {
786
if (!VM_VMHelpers::exceptionPending(currentThread)) {
787
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
788
}
789
goto done;
790
}
791
792
/* Refetch reference after GC point */
793
membernameObject = J9_JNI_UNWRAP_REFERENCE(self);
794
nameObject = J9VMJAVALANGINVOKEMEMBERNAME_NAME(currentThread, membernameObject);
795
name = vmFuncs->copyStringToJ9UTF8WithMemAlloc(currentThread, nameObject, 0, "", 0, NULL, 0);
796
if (NULL == name) {
797
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
798
goto done;
799
}
800
801
j9object_t callerObject = (NULL == caller) ? NULL : J9_JNI_UNWRAP_REFERENCE(caller);
802
J9Class *callerClass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, callerObject);
803
804
Trc_JCL_java_lang_invoke_MethodHandleNatives_resolve_NAS(env, J9UTF8_LENGTH(name), J9UTF8_DATA(name), J9UTF8_LENGTH(signature), J9UTF8_DATA(signature));
805
806
if (J9_ARE_ANY_BITS_SET(flags, MN_IS_METHOD | MN_IS_CONSTRUCTOR)) {
807
UDATA lookupOptions = 0;
808
809
if (JNI_TRUE == speculativeResolve) {
810
lookupOptions |= J9_LOOK_NO_THROW;
811
}
812
813
#if JAVA_SPEC_VERSION >= 16
814
/* Check CL constraint only for lookup that is not trusted (with caller) and not public (UNCONDITIONAL mode not set)
815
* Note: UNCONDITIONAL lookupMode can only access unconditionally exported public members which assumes readablity
816
* ie lookup class not used to determine lookup context
817
* See java.lang.invoke.MethodHandles$Lookup.publicLookup()
818
*/
819
if ((NULL != callerClass) && J9_ARE_NO_BITS_SET(lookupMode, MN_UNCONDITIONAL_MODE)) {
820
lookupOptions |= J9_LOOK_CLCONSTRAINTS;
821
}
822
#else
823
if (NULL != callerClass) {
824
lookupOptions |= J9_LOOK_CLCONSTRAINTS;
825
}
826
#endif
827
828
/* Determine the lookup type based on reference kind and resolved class flags */
829
switch (ref_kind)
830
{
831
case MH_REF_INVOKEINTERFACE:
832
lookupOptions |= J9_LOOK_INTERFACE;
833
break;
834
case MH_REF_INVOKESPECIAL:
835
lookupOptions |= (J9_LOOK_VIRTUAL | J9_LOOK_ALLOW_FWD | J9_LOOK_HANDLE_DEFAULT_METHOD_CONFLICTS);
836
break;
837
case MH_REF_INVOKESTATIC:
838
lookupOptions |= J9_LOOK_STATIC;
839
if (J9_ARE_ANY_BITS_SET(resolvedClass->romClass->modifiers, J9AccInterface)) {
840
lookupOptions |= J9_LOOK_INTERFACE;
841
}
842
break;
843
default:
844
lookupOptions |= J9_LOOK_VIRTUAL;
845
break;
846
}
847
848
/* Check if signature polymorphic native calls */
849
J9Method *method = lookupMethod(currentThread, resolvedClass, name, signature, callerClass, lookupOptions);
850
851
/* Check for resolution exception */
852
if (VM_VMHelpers::exceptionPending(currentThread)) {
853
J9Class *exceptionClass = J9OBJECT_CLAZZ(currentThread, currentThread->currentException);
854
if ((ref_kind == MH_REF_INVOKESPECIAL) && (exceptionClass == J9VMJAVALANGINCOMPATIBLECLASSCHANGEERROR(vm))) {
855
/* Special handling for default method conflict, defer the exception throw until invocation. */
856
VM_VMHelpers::clearException(currentThread);
857
/* Attempt to lookup method without checking for conflict.
858
* If this failed with error, then throw that error.
859
* Otherwise exception throw will be defered to the MH.invoke call.
860
*/
861
method = lookupMethod(
862
currentThread, resolvedClass, name, signature, callerClass,
863
(lookupOptions & ~J9_LOOK_HANDLE_DEFAULT_METHOD_CONFLICTS));
864
865
if (!VM_VMHelpers::exceptionPending(currentThread)) {
866
/* Set placeholder values for MemberName fields. */
867
vmindex = (jlong)J9VM_RESOLVED_VMINDEX_FOR_DEFAULT_THROW;
868
new_clazz = J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_METHOD(method));
869
new_flags = flags;
870
871
/* Load special sendTarget to throw the exception during invocation */
872
target = (jlong)(UDATA)vm->initialMethods.throwDefaultConflict;
873
} else {
874
goto done;
875
}
876
} else {
877
goto done;
878
}
879
} else if (NULL != method) {
880
J9JNIMethodID *methodID = vmFuncs->getJNIMethodID(currentThread, method);
881
vmindex = (jlong)(UDATA)methodID;
882
target = (jlong)(UDATA)method;
883
884
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(methodID->method);
885
J9UTF8 *methodName = J9ROMMETHOD_NAME(romMethod);
886
U_32 methodModifiers = romMethod->modifiers;
887
new_clazz = J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_METHOD(method));
888
new_flags = methodModifiers & CFR_METHOD_ACCESS_MASK;
889
890
if (J9_ARE_ANY_BITS_SET(methodModifiers, J9AccMethodCallerSensitive)) {
891
new_flags |= MN_CALLER_SENSITIVE;
892
}
893
894
if (J9_ARE_ALL_BITS_SET(flags, MN_IS_METHOD)) {
895
new_flags |= MN_IS_METHOD;
896
if (MH_REF_INVOKEINTERFACE == ref_kind) {
897
Assert_JCL_true(J9_ARE_NO_BITS_SET(methodModifiers, J9AccStatic));
898
if (J9_ARE_ALL_BITS_SET(methodID->vTableIndex, J9_JNI_MID_INTERFACE)) {
899
new_flags |= MH_REF_INVOKEINTERFACE << MN_REFERENCE_KIND_SHIFT;
900
} else if (!J9ROMMETHOD_HAS_VTABLE(romMethod)) {
901
new_flags |= MH_REF_INVOKESPECIAL << MN_REFERENCE_KIND_SHIFT;
902
} else {
903
new_flags |= MH_REF_INVOKEVIRTUAL << MN_REFERENCE_KIND_SHIFT;
904
}
905
} else if (MH_REF_INVOKESPECIAL == ref_kind) {
906
Assert_JCL_true(J9_ARE_NO_BITS_SET(methodModifiers, J9AccStatic));
907
new_flags |= MH_REF_INVOKESPECIAL << MN_REFERENCE_KIND_SHIFT;
908
} else if (MH_REF_INVOKESTATIC == ref_kind) {
909
Assert_JCL_true(J9_ARE_ALL_BITS_SET(methodModifiers, J9AccStatic));
910
new_flags |= MH_REF_INVOKESTATIC << MN_REFERENCE_KIND_SHIFT;
911
} else if (MH_REF_INVOKEVIRTUAL == ref_kind) {
912
Assert_JCL_true(J9_ARE_NO_BITS_SET(methodModifiers, J9AccStatic));
913
if (!J9ROMMETHOD_HAS_VTABLE(romMethod)) {
914
new_flags |= MH_REF_INVOKESPECIAL << MN_REFERENCE_KIND_SHIFT;
915
} else {
916
if (J9_ARE_ALL_BITS_SET(methodID->vTableIndex, J9_JNI_MID_INTERFACE)) {
917
new_clazz = J9VM_J9CLASS_TO_HEAPCLASS(resolvedClass);
918
}
919
new_flags |= MH_REF_INVOKEVIRTUAL << MN_REFERENCE_KIND_SHIFT;
920
}
921
} else {
922
Assert_JCL_unreachable();
923
}
924
} else if (J9_ARE_NO_BITS_SET(methodModifiers, J9AccStatic) && ('<' == (char)*J9UTF8_DATA(methodName))) {
925
new_flags |= MN_IS_CONSTRUCTOR;
926
new_flags |= MH_REF_INVOKESPECIAL << MN_REFERENCE_KIND_SHIFT;
927
} else {
928
Assert_JCL_unreachable();
929
}
930
}
931
} if (J9_ARE_ANY_BITS_SET(flags, MN_IS_FIELD)) {
932
J9Class *declaringClass;
933
J9ROMFieldShape *romField;
934
UDATA lookupOptions = 0;
935
UDATA offset = 0;
936
if (JNI_TRUE == speculativeResolve) {
937
lookupOptions |= J9_RESOLVE_FLAG_NO_THROW_ON_FAIL;
938
}
939
940
/* MemberName doesn't differentiate if a field is static or not,
941
* the resolve code have to attempt to resolve as instance field first,
942
* then as static field if the first attempt failed.
943
*/
944
offset = vmFuncs->instanceFieldOffset(currentThread,
945
resolvedClass,
946
J9UTF8_DATA(name), J9UTF8_LENGTH(name),
947
J9UTF8_DATA(signature), J9UTF8_LENGTH(signature),
948
&declaringClass, (UDATA*)&romField,
949
lookupOptions);
950
951
if (offset == (UDATA)-1) {
952
declaringClass = NULL;
953
954
if (VM_VMHelpers::exceptionPending(currentThread)) {
955
VM_VMHelpers::clearException(currentThread);
956
}
957
958
void* fieldAddress = vmFuncs->staticFieldAddress(currentThread,
959
resolvedClass,
960
J9UTF8_DATA(name), J9UTF8_LENGTH(name),
961
J9UTF8_DATA(signature), J9UTF8_LENGTH(signature),
962
&declaringClass, (UDATA*)&romField,
963
lookupOptions,
964
NULL);
965
966
if (fieldAddress == NULL) {
967
declaringClass = NULL;
968
} else {
969
offset = (UDATA)fieldAddress - (UDATA)declaringClass->ramStatics;
970
}
971
}
972
973
if (NULL != declaringClass) {
974
if ((NULL != callerClass)
975
#if JAVA_SPEC_VERSION >= 16
976
&& (J9_ARE_NO_BITS_SET(lookupMode, MN_UNCONDITIONAL_MODE))
977
#endif
978
) {
979
if (callerClass->classLoader != declaringClass->classLoader) {
980
J9BytecodeVerificationData *verifyData = vm->bytecodeVerificationData;
981
U_16 sigOffset = 0;
982
983
/* Skip the '[', 'L' prefix */
984
while ('[' == J9UTF8_DATA(signature)[sigOffset]) {
985
sigOffset += 1;
986
}
987
if ('L' == J9UTF8_DATA(signature)[sigOffset]) {
988
sigOffset += 1;
989
omrthread_monitor_enter(vm->classTableMutex);
990
UDATA clConstraintResult = verifyData->checkClassLoadingConstraintForNameFunction(
991
currentThread,
992
declaringClass->classLoader,
993
callerClass->classLoader,
994
J9UTF8_DATA(signature) + sigOffset,
995
J9UTF8_DATA(signature) + sigOffset,
996
J9UTF8_LENGTH(signature) - sigOffset - 1, /* -1 to remove the trailing ;*/
997
true);
998
omrthread_monitor_exit(vm->classTableMutex);
999
if (0 != clConstraintResult) {
1000
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGLINKAGEERROR, NULL);
1001
goto done;
1002
}
1003
}
1004
}
1005
}
1006
1007
UDATA inconsistentData = 0;
1008
J9JNIFieldID *fieldID = vmFuncs->getJNIFieldID(currentThread, declaringClass, romField, offset, &inconsistentData);
1009
vmindex = (jlong)(UDATA)fieldID;
1010
1011
new_clazz = J9VM_J9CLASS_TO_HEAPCLASS(declaringClass);
1012
new_flags = MN_IS_FIELD | (fieldID->field->modifiers & CFR_FIELD_ACCESS_MASK);
1013
if (VM_VMHelpers::isTrustedFinalField(fieldID->field, fieldID->declaringClass->romClass)) {
1014
new_flags |= MN_TRUSTED_FINAL;
1015
}
1016
1017
romField = fieldID->field;
1018
1019
if (J9_ARE_ANY_BITS_SET(romField->modifiers, J9AccStatic)) {
1020
offset = fieldID->offset | J9_SUN_STATIC_FIELD_OFFSET_TAG;
1021
if (J9_ARE_ANY_BITS_SET(romField->modifiers, J9AccFinal)) {
1022
offset |= J9_SUN_FINAL_FIELD_OFFSET_TAG;
1023
}
1024
1025
if ((MH_REF_PUTFIELD == ref_kind) || (MH_REF_PUTSTATIC == ref_kind)) {
1026
new_flags |= (MH_REF_PUTSTATIC << MN_REFERENCE_KIND_SHIFT);
1027
} else {
1028
new_flags |= (MH_REF_GETSTATIC << MN_REFERENCE_KIND_SHIFT);
1029
}
1030
} else {
1031
if ((MH_REF_PUTFIELD == ref_kind) || (MH_REF_PUTSTATIC == ref_kind)) {
1032
new_flags |= (MH_REF_PUTFIELD << MN_REFERENCE_KIND_SHIFT);
1033
} else {
1034
new_flags |= (MH_REF_GETFIELD << MN_REFERENCE_KIND_SHIFT);
1035
}
1036
}
1037
1038
target = (jlong)offset;
1039
}
1040
}
1041
1042
if ((0 != vmindex) && (0 != target)) {
1043
/* Refetch reference after GC point */
1044
membernameObject = J9_JNI_UNWRAP_REFERENCE(self);
1045
J9VMJAVALANGINVOKEMEMBERNAME_SET_FLAGS(currentThread, membernameObject, new_flags);
1046
J9VMJAVALANGINVOKEMEMBERNAME_SET_CLAZZ(currentThread, membernameObject, new_clazz);
1047
J9OBJECT_U64_STORE(currentThread, membernameObject, vm->vmindexOffset, (U_64)vmindex);
1048
J9OBJECT_U64_STORE(currentThread, membernameObject, vm->vmtargetOffset, (U_64)target);
1049
1050
Trc_JCL_java_lang_invoke_MethodHandleNatives_resolve_resolved(env, vmindex, target, new_clazz, new_flags);
1051
1052
result = vmFuncs->j9jni_createLocalRef(env, membernameObject);
1053
}
1054
1055
if ((NULL == result) && (JNI_TRUE != speculativeResolve) && !VM_VMHelpers::exceptionPending(currentThread)) {
1056
if (J9_ARE_ANY_BITS_SET(flags, MN_IS_FIELD)) {
1057
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNOSUCHFIELDERROR, NULL);
1058
} else if (J9_ARE_ANY_BITS_SET(flags, MN_IS_CONSTRUCTOR | MN_IS_METHOD)) {
1059
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNOSUCHMETHODERROR, NULL);
1060
} else {
1061
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGLINKAGEERROR, NULL);
1062
}
1063
}
1064
}
1065
}
1066
1067
done:
1068
j9mem_free_memory(name);
1069
j9mem_free_memory(signature);
1070
1071
if ((JNI_TRUE == speculativeResolve) && VM_VMHelpers::exceptionPending(currentThread)) {
1072
VM_VMHelpers::clearException(currentThread);
1073
}
1074
Trc_JCL_java_lang_invoke_MethodHandleNatives_resolve_Exit(env);
1075
vmFuncs->internalExitVMToJNI(currentThread);
1076
return result;
1077
}
1078
1079
/**
1080
* static native int getMembers(Class<?> defc, String matchName, String matchSig,
1081
* int matchFlags, Class<?> caller, int skip, MemberName[] results);
1082
*
1083
* Search the defc (defining class) chain for field/method that matches the given search parameters,
1084
* for each matching result found, initialize the next MemberName object in results array to reference the found field/method
1085
*
1086
* - defc: the class to start the search
1087
* - matchName: name to match, NULL to match any field/method name
1088
* - matchSig: signature to match, NULL to match any field/method type
1089
* - matchFlags: flags defining search options:
1090
* MN_IS_FIELD - search for fields
1091
* MN_IS_CONSTRUCTOR | MN_IS_METHOD - search for method/constructor
1092
* MN_SEARCH_SUPERCLASSES - search the superclasses of the defining class
1093
* MN_SEARCH_INTERFACES - search the interfaces implemented by the defining class
1094
* - caller: the caller class performing the lookup
1095
* - skip: number of matching results to skip before storing
1096
* - results: an array of MemberName objects to hold the matched field/method
1097
*/
1098
jint JNICALL
1099
Java_java_lang_invoke_MethodHandleNatives_getMembers(JNIEnv *env, jclass clazz, jclass defc, jstring matchName, jstring matchSig, jint matchFlags, jclass caller, jint skip, jobjectArray results)
1100
{
1101
J9VMThread *currentThread = (J9VMThread*)env;
1102
J9JavaVM *vm = currentThread->javaVM;
1103
const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
1104
vmFuncs->internalEnterVMFromJNI(currentThread);
1105
jint result = 0;
1106
J9UTF8 *name = NULL;
1107
J9UTF8 *sig = NULL;
1108
j9object_t callerObject = ((NULL == caller) ? NULL : J9_JNI_UNWRAP_REFERENCE(caller));
1109
1110
PORT_ACCESS_FROM_JAVAVM(vm);
1111
1112
Trc_JCL_java_lang_invoke_MethodHandleNatives_getMembers_Entry(env, defc, matchName, matchSig, matchFlags, caller, skip, results);
1113
1114
if ((NULL == defc) || (NULL == results) || ((NULL != callerObject) && (J9VMJAVALANGCLASS(vm) != J9OBJECT_CLAZZ(currentThread, callerObject)))) {
1115
result = -1;
1116
} else {
1117
j9object_t defcObject = J9_JNI_UNWRAP_REFERENCE(defc);
1118
J9Class *defClass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, defcObject);
1119
1120
if (NULL != matchName) {
1121
name = vmFuncs->copyStringToJ9UTF8WithMemAlloc(currentThread, J9_JNI_UNWRAP_REFERENCE(matchName), J9_STR_NONE, "", 0, NULL, 0);
1122
if (NULL == name) {
1123
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
1124
goto done;
1125
}
1126
}
1127
if (NULL != matchSig) {
1128
sig = vmFuncs->copyStringToJ9UTF8WithMemAlloc(currentThread, J9_JNI_UNWRAP_REFERENCE(matchSig), J9_STR_NONE, "", 0, NULL, 0);
1129
if (NULL == sig) {
1130
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
1131
goto done;
1132
}
1133
}
1134
1135
if (!(((NULL != matchName) && (0 == J9UTF8_LENGTH(name))) || ((NULL != matchSig) && (0 == J9UTF8_LENGTH(sig))))) {
1136
j9array_t resultsArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(results);
1137
UDATA length = J9INDEXABLEOBJECT_SIZE(currentThread, resultsArray);
1138
UDATA index = 0;
1139
1140
if (J9ROMCLASS_IS_INTERFACE(defClass->romClass)) {
1141
result = -1;
1142
} else {
1143
if (J9_ARE_ANY_BITS_SET(matchFlags, MN_IS_FIELD)) {
1144
J9ROMFieldShape *romField = NULL;
1145
J9ROMFieldWalkState walkState;
1146
1147
UDATA classDepth = 0;
1148
if (J9_ARE_ANY_BITS_SET(matchFlags, MN_SEARCH_SUPERCLASSES)) {
1149
/* walk superclasses */
1150
J9CLASS_DEPTH(defClass);
1151
}
1152
J9Class *currentClass = defClass;
1153
1154
while (NULL != currentClass) {
1155
/* walk currentClass */
1156
memset(&walkState, 0, sizeof(walkState));
1157
romField = romFieldsStartDo(currentClass->romClass, &walkState);
1158
1159
while (NULL != romField) {
1160
J9UTF8 *nameUTF = J9ROMFIELDSHAPE_NAME(romField);
1161
J9UTF8 *signatureUTF = J9ROMFIELDSHAPE_SIGNATURE(romField);
1162
1163
if (((NULL == matchName) || J9UTF8_EQUALS(name, nameUTF))
1164
&& ((NULL == matchSig) || J9UTF8_EQUALS(sig, signatureUTF))
1165
) {
1166
if (skip > 0) {
1167
skip -=1;
1168
} else {
1169
if (index < length) {
1170
/* Refetch reference after GC point */
1171
resultsArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(results);
1172
j9object_t memberName = J9JAVAARRAYOFOBJECT_LOAD(currentThread, resultsArray, index);
1173
if (NULL == memberName) {
1174
result = -99;
1175
goto done;
1176
}
1177
PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, memberName);
1178
1179
/* create static field object */
1180
j9object_t fieldObj = vm->reflectFunctions.createFieldObject(currentThread, romField, defClass, (romField->modifiers & J9AccStatic) == J9AccStatic);
1181
memberName = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);
1182
1183
if (NULL != fieldObj) {
1184
initImpl(currentThread, memberName, fieldObj);
1185
}
1186
if (VM_VMHelpers::exceptionPending(currentThread)) {
1187
goto done;
1188
}
1189
}
1190
}
1191
result += 1;
1192
}
1193
romField = romFieldsNextDo(&walkState);
1194
}
1195
1196
/* get the superclass */
1197
if (classDepth >= 1) {
1198
classDepth -= 1;
1199
currentClass = defClass->superclasses[classDepth];
1200
} else {
1201
currentClass = NULL;
1202
}
1203
}
1204
1205
/* walk interfaces */
1206
if (J9_ARE_ANY_BITS_SET(matchFlags, MN_SEARCH_INTERFACES)) {
1207
J9ITable *currentITable = (J9ITable *)defClass->iTable;
1208
1209
while (NULL != currentITable) {
1210
memset(&walkState, 0, sizeof(walkState));
1211
romField = romFieldsStartDo(currentITable->interfaceClass->romClass, &walkState);
1212
while (NULL != romField) {
1213
J9UTF8 *nameUTF = J9ROMFIELDSHAPE_NAME(romField);
1214
J9UTF8 *signatureUTF = J9ROMFIELDSHAPE_SIGNATURE(romField);
1215
1216
if (((NULL == matchName) || J9UTF8_EQUALS(name, nameUTF))
1217
&& ((NULL == matchSig) || J9UTF8_EQUALS(sig, signatureUTF))
1218
) {
1219
if (skip > 0) {
1220
skip -=1;
1221
} else {
1222
if (index < length) {
1223
/* Refetch reference after GC point */
1224
resultsArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(results);
1225
j9object_t memberName = J9JAVAARRAYOFOBJECT_LOAD(currentThread, resultsArray, index);
1226
if (NULL == memberName) {
1227
result = -99;
1228
goto done;
1229
}
1230
PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, memberName);
1231
1232
/* create field object */
1233
j9object_t fieldObj = vm->reflectFunctions.createFieldObject(currentThread, romField, defClass, (romField->modifiers & J9AccStatic) == J9AccStatic);
1234
memberName = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);
1235
1236
if (NULL != fieldObj) {
1237
initImpl(currentThread, memberName, fieldObj);
1238
}
1239
if (VM_VMHelpers::exceptionPending(currentThread)) {
1240
goto done;
1241
}
1242
}
1243
}
1244
result += 1;
1245
}
1246
romField = romFieldsNextDo(&walkState);
1247
}
1248
currentITable = currentITable->next;
1249
}
1250
}
1251
} else if (J9_ARE_ANY_BITS_SET(matchFlags, MN_IS_CONSTRUCTOR | MN_IS_METHOD)) {
1252
UDATA classDepth = 0;
1253
if (J9_ARE_ANY_BITS_SET(matchFlags, MN_SEARCH_SUPERCLASSES)) {
1254
/* walk superclasses */
1255
J9CLASS_DEPTH(defClass);
1256
}
1257
J9Class *currentClass = defClass;
1258
1259
while (NULL != currentClass) {
1260
if (!J9ROMCLASS_IS_PRIMITIVE_OR_ARRAY(currentClass->romClass)) {
1261
J9Method *currentMethod = currentClass->ramMethods;
1262
J9Method *endOfMethods = currentMethod + currentClass->romClass->romMethodCount;
1263
while (currentMethod != endOfMethods) {
1264
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);
1265
J9UTF8 *nameUTF = J9ROMMETHOD_SIGNATURE(romMethod);
1266
J9UTF8 *signatureUTF = J9ROMMETHOD_SIGNATURE(romMethod);
1267
1268
if (((NULL == matchName) || J9UTF8_EQUALS(name, nameUTF))
1269
&& ((NULL == matchSig) || J9UTF8_EQUALS(sig, signatureUTF))
1270
) {
1271
if (skip > 0) {
1272
skip -=1;
1273
} else {
1274
if (index < length) {
1275
/* Refetch reference after GC point */
1276
resultsArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(results);
1277
j9object_t memberName = J9JAVAARRAYOFOBJECT_LOAD(currentThread, resultsArray, index);
1278
if (NULL == memberName) {
1279
result = -99;
1280
goto done;
1281
}
1282
PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, memberName);
1283
1284
j9object_t methodObj = NULL;
1285
if (J9_ARE_NO_BITS_SET(romMethod->modifiers, J9AccStatic) && ('<' == (char)*J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)))) {
1286
/* create constructor object */
1287
methodObj = vm->reflectFunctions.createConstructorObject(currentMethod, currentClass, NULL, currentThread);
1288
} else {
1289
/* create method object */
1290
methodObj = vm->reflectFunctions.createMethodObject(currentMethod, currentClass, NULL, currentThread);
1291
}
1292
memberName = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);
1293
1294
if (NULL != methodObj) {
1295
initImpl(currentThread, memberName, methodObj);
1296
}
1297
if (VM_VMHelpers::exceptionPending(currentThread)) {
1298
goto done;
1299
}
1300
}
1301
}
1302
result += 1;
1303
}
1304
currentMethod += 1;
1305
}
1306
}
1307
1308
/* get the superclass */
1309
if (classDepth >= 1) {
1310
classDepth -= 1;
1311
currentClass = defClass->superclasses[classDepth];
1312
} else {
1313
currentClass = NULL;
1314
}
1315
}
1316
1317
/* walk interfaces */
1318
if (J9_ARE_ANY_BITS_SET(matchFlags, MN_SEARCH_INTERFACES)) {
1319
J9ITable *currentITable = (J9ITable *)defClass->iTable;
1320
1321
while (NULL != currentITable) {
1322
J9Class *currentClass = currentITable->interfaceClass;
1323
J9Method *currentMethod = currentClass->ramMethods;
1324
J9Method *endOfMethods = currentMethod + currentClass->romClass->romMethodCount;
1325
while (currentMethod != endOfMethods) {
1326
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);
1327
J9UTF8 *nameUTF = J9ROMMETHOD_SIGNATURE(romMethod);
1328
J9UTF8 *signatureUTF = J9ROMMETHOD_SIGNATURE(romMethod);
1329
1330
if (((NULL == matchName) || J9UTF8_EQUALS(name, nameUTF))
1331
&& ((NULL == matchSig) || J9UTF8_EQUALS(sig, signatureUTF))
1332
) {
1333
if (skip > 0) {
1334
skip -=1;
1335
} else {
1336
if (index < length) {
1337
/* Refetch reference after GC point */
1338
resultsArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(results);
1339
j9object_t memberName = J9JAVAARRAYOFOBJECT_LOAD(currentThread, resultsArray, index);
1340
if (NULL == memberName) {
1341
result = -99;
1342
goto done;
1343
}
1344
PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, memberName);
1345
1346
j9object_t methodObj = NULL;
1347
if (J9_ARE_NO_BITS_SET(romMethod->modifiers, J9AccStatic) && ('<' == (char)*J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod)))) {
1348
/* create constructor object */
1349
methodObj = vm->reflectFunctions.createConstructorObject(currentMethod, currentClass, NULL, currentThread);
1350
} else {
1351
/* create method object */
1352
methodObj = vm->reflectFunctions.createMethodObject(currentMethod, currentClass, NULL, currentThread);
1353
}
1354
memberName = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);
1355
1356
if (NULL != methodObj) {
1357
initImpl(currentThread, memberName, methodObj);
1358
}
1359
if (VM_VMHelpers::exceptionPending(currentThread)) {
1360
goto done;
1361
}
1362
}
1363
}
1364
result += 1;
1365
}
1366
currentMethod += 1;
1367
}
1368
currentITable = currentITable->next;
1369
}
1370
}
1371
}
1372
}
1373
}
1374
}
1375
done:
1376
j9mem_free_memory(name);
1377
j9mem_free_memory(sig);
1378
1379
Trc_JCL_java_lang_invoke_MethodHandleNatives_getMembers_Exit(env, result);
1380
vmFuncs->internalExitVMToJNI(currentThread);
1381
return result;
1382
}
1383
1384
/**
1385
* static native long objectFieldOffset(MemberName self); // e.g., returns vmindex
1386
*
1387
* Returns the objectFieldOffset of the field represented by the MemberName
1388
* result should be same as if calling Unsafe.objectFieldOffset with the actual field object
1389
*/
1390
jlong JNICALL
1391
Java_java_lang_invoke_MethodHandleNatives_objectFieldOffset(JNIEnv *env, jclass clazz, jobject self)
1392
{
1393
J9VMThread *currentThread = (J9VMThread*)env;
1394
J9JavaVM *vm = currentThread->javaVM;
1395
const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
1396
vmFuncs->internalEnterVMFromJNI(currentThread);
1397
jlong result = 0;
1398
1399
Trc_JCL_java_lang_invoke_MethodHandleNatives_objectFieldOffset_Entry(env, self);
1400
1401
if (NULL == self) {
1402
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);
1403
} else {
1404
j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);
1405
j9object_t clazzObject = J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject);
1406
1407
if (NULL == clazzObject) {
1408
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);
1409
} else {
1410
jint flags = J9VMJAVALANGINVOKEMEMBERNAME_FLAGS(currentThread, membernameObject);
1411
if (J9_ARE_ALL_BITS_SET(flags, MN_IS_FIELD) && J9_ARE_NO_BITS_SET(flags, J9AccStatic)) {
1412
J9JNIFieldID *fieldID = (J9JNIFieldID*)(UDATA)J9OBJECT_U64_LOAD(currentThread, membernameObject, vm->vmindexOffset);
1413
result = (jlong)fieldID->offset + J9VMTHREAD_OBJECT_HEADER_SIZE(currentThread);
1414
} else {
1415
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);
1416
}
1417
}
1418
}
1419
1420
Trc_JCL_java_lang_invoke_MethodHandleNatives_objectFieldOffset_Exit(env, result);
1421
vmFuncs->internalExitVMToJNI(currentThread);
1422
return result;
1423
}
1424
1425
/**
1426
* static native long staticFieldOffset(MemberName self); // e.g., returns vmindex
1427
*
1428
* Returns the staticFieldOffset of the field represented by the MemberName
1429
* result should be same as if calling Unsafe.staticFieldOffset with the actual field object
1430
*/
1431
jlong JNICALL
1432
Java_java_lang_invoke_MethodHandleNatives_staticFieldOffset(JNIEnv *env, jclass clazz, jobject self)
1433
{
1434
J9VMThread *currentThread = (J9VMThread*)env;
1435
J9JavaVM *vm = currentThread->javaVM;
1436
const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
1437
vmFuncs->internalEnterVMFromJNI(currentThread);
1438
jlong result = 0;
1439
1440
Trc_JCL_java_lang_invoke_MethodHandleNatives_staticFieldOffset_Entry(env, self);
1441
1442
if (NULL == self) {
1443
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);
1444
} else {
1445
j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);
1446
j9object_t clazzObject = J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject);
1447
1448
if (NULL == clazzObject) {
1449
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);
1450
} else {
1451
jint flags = J9VMJAVALANGINVOKEMEMBERNAME_FLAGS(currentThread, membernameObject);
1452
if (J9_ARE_ALL_BITS_SET(flags, MN_IS_FIELD & J9AccStatic)) {
1453
result = (jlong)(UDATA)J9OBJECT_U64_LOAD(currentThread, membernameObject, vm->vmtargetOffset);
1454
} else {
1455
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);
1456
}
1457
}
1458
}
1459
Trc_JCL_java_lang_invoke_MethodHandleNatives_staticFieldOffset_Exit(env, result);
1460
vmFuncs->internalExitVMToJNI(currentThread);
1461
return result;
1462
}
1463
1464
/**
1465
* static native Object staticFieldBase(MemberName self); // e.g., returns clazz
1466
*
1467
* Returns the staticFieldBase of the field represented by the MemberName
1468
* result should be same as if calling Unsafe.staticFieldBase with the actual field object
1469
*/
1470
jobject JNICALL
1471
Java_java_lang_invoke_MethodHandleNatives_staticFieldBase(JNIEnv *env, jclass clazz, jobject self)
1472
{
1473
J9VMThread *currentThread = (J9VMThread*)env;
1474
const J9InternalVMFunctions *vmFuncs = currentThread->javaVM->internalVMFunctions;
1475
vmFuncs->internalEnterVMFromJNI(currentThread);
1476
jobject result = NULL;
1477
1478
Trc_JCL_java_lang_invoke_MethodHandleNatives_staticFieldBase_Entry(env, self);
1479
if (NULL == self) {
1480
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);
1481
} else {
1482
j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);
1483
j9object_t clazzObject = J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject);
1484
1485
if (NULL == clazzObject) {
1486
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);
1487
} else {
1488
jint flags = J9VMJAVALANGINVOKEMEMBERNAME_FLAGS(currentThread, membernameObject);
1489
if (J9_ARE_ALL_BITS_SET(flags, MN_IS_FIELD & J9AccStatic)) {
1490
result = vmFuncs->j9jni_createLocalRef(env, clazzObject);
1491
} else {
1492
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);
1493
}
1494
}
1495
}
1496
Trc_JCL_java_lang_invoke_MethodHandleNatives_staticFieldBase_Exit(env, result);
1497
vmFuncs->internalExitVMToJNI(currentThread);
1498
return result;
1499
}
1500
1501
/**
1502
* static native Object getMemberVMInfo(MemberName self); // returns {vmindex,vmtarget}
1503
*
1504
* Return a 2-element java array containing the vm offset/target data
1505
* For a field MemberName, array contains:
1506
* (field offset, declaring class)
1507
* For a method MemberName, array contains:
1508
* (vtable index, MemberName object)
1509
*/
1510
jobject JNICALL
1511
Java_java_lang_invoke_MethodHandleNatives_getMemberVMInfo(JNIEnv *env, jclass clazz, jobject self)
1512
{
1513
J9VMThread *currentThread = (J9VMThread*)env;
1514
J9JavaVM *vm = currentThread->javaVM;
1515
const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
1516
jobject result = NULL;
1517
vmFuncs->internalEnterVMFromJNI(currentThread);
1518
1519
Trc_JCL_java_lang_invoke_MethodHandleNatives_getMemberVMInfo_Entry(env, self);
1520
if (NULL != self) {
1521
J9Class *arrayClass = fetchArrayClass(currentThread, J9VMJAVALANGOBJECT(vm));
1522
j9object_t arrayObject = vm->memoryManagerFunctions->J9AllocateIndexableObject(currentThread, arrayClass, 2, J9_GC_ALLOCATE_OBJECT_INSTRUMENTABLE);
1523
if (NULL == arrayObject) {
1524
vmFuncs->setHeapOutOfMemoryError(currentThread);
1525
} else {
1526
PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, arrayObject);
1527
j9object_t box = vm->memoryManagerFunctions->J9AllocateObject(currentThread, J9VMJAVALANGLONG_OR_NULL(vm), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);
1528
if (NULL == box) {
1529
/* Drop arrayObject */
1530
DROP_OBJECT_IN_SPECIAL_FRAME(currentThread);
1531
vmFuncs->setHeapOutOfMemoryError(currentThread);
1532
} else {
1533
arrayObject = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);
1534
j9object_t membernameObject = J9_JNI_UNWRAP_REFERENCE(self);
1535
jint flags = J9VMJAVALANGINVOKEMEMBERNAME_FLAGS(currentThread, membernameObject);
1536
j9object_t target = NULL;
1537
1538
/* For fields, vmindexOffset (J9JNIFieldID) is initialized using the field offset in
1539
* jnicsup.cpp::getJNIFieldID. For methods, vmindexOffset (J9JNIMethodID) is initialized
1540
* using jnicsup.cpp::initializeMethodID.
1541
*/
1542
jlong vmindex = (jlong)(UDATA)J9OBJECT_U64_LOAD(currentThread, membernameObject, vm->vmindexOffset);
1543
1544
if (J9_ARE_ANY_BITS_SET(flags, MN_IS_FIELD)) {
1545
/* vmindex points to the field offset. */
1546
vmindex = ((J9JNIFieldID*)vmindex)->offset;
1547
target = J9VMJAVALANGINVOKEMEMBERNAME_CLAZZ(currentThread, membernameObject);
1548
} else {
1549
jint refKind = (flags >> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK;
1550
if ((MH_REF_INVOKEVIRTUAL == refKind) || (MH_REF_INVOKEINTERFACE == refKind)) {
1551
J9JNIMethodID *methodID = (J9JNIMethodID*)vmindex;
1552
if (J9_ARE_ANY_BITS_SET(methodID->vTableIndex, J9_JNI_MID_INTERFACE)) {
1553
/* vmindex points to an iTable index. */
1554
vmindex = (jlong)(methodID->vTableIndex & ~J9_JNI_MID_INTERFACE);
1555
} else if (0 == methodID->vTableIndex) {
1556
/* initializeMethodID will set J9JNIMethodID->vTableIndex to 0 for private interface
1557
* methods and j.l.Object methods. Reference implementation (RI) expects vmindex to
1558
* be 0 in such cases.
1559
*/
1560
vmindex = 0;
1561
} else {
1562
/* vmindex points to a vTable index. */
1563
vmindex = (jlong)methodID->vTableIndex;
1564
}
1565
} else {
1566
/* RI expects direct invocation, i.e. !invokevirtual and !invokeinterface ref kinds,
1567
* to have a negative vmindex.
1568
*/
1569
vmindex = -1;
1570
}
1571
target = membernameObject;
1572
}
1573
1574
J9VMJAVALANGLONG_SET_VALUE(currentThread, box, vmindex);
1575
J9JAVAARRAYOFOBJECT_STORE(currentThread, arrayObject, 0, box);
1576
J9JAVAARRAYOFOBJECT_STORE(currentThread, arrayObject, 1, target);
1577
1578
result = vmFuncs->j9jni_createLocalRef(env, arrayObject);
1579
}
1580
}
1581
}
1582
Trc_JCL_java_lang_invoke_MethodHandleNatives_getMemberVMInfo_Exit(env, result);
1583
vmFuncs->internalExitVMToJNI(currentThread);
1584
return result;
1585
1586
}
1587
1588
/**
1589
* static native void setCallSiteTargetNormal(CallSite site, MethodHandle target)
1590
*/
1591
void JNICALL
1592
Java_java_lang_invoke_MethodHandleNatives_setCallSiteTargetNormal(JNIEnv *env, jclass clazz, jobject callsite, jobject target)
1593
{
1594
setCallSiteTargetImpl((J9VMThread*)env, callsite, target, false);
1595
}
1596
1597
/**
1598
* static native void setCallSiteTargetVolatile(CallSite site, MethodHandle target);
1599
*/
1600
void JNICALL
1601
Java_java_lang_invoke_MethodHandleNatives_setCallSiteTargetVolatile(JNIEnv *env, jclass clazz, jobject callsite, jobject target)
1602
{
1603
setCallSiteTargetImpl((J9VMThread*)env, callsite, target, true);
1604
}
1605
1606
/**
1607
* static native void copyOutBootstrapArguments(Class<?> caller, int[] indexInfo,
1608
int start, int end,
1609
Object[] buf, int pos,
1610
boolean resolve,
1611
Object ifNotAvailable);
1612
*/
1613
void JNICALL
1614
Java_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)
1615
{
1616
J9VMThread *currentThread = (J9VMThread*)env;
1617
J9JavaVM *vm = currentThread->javaVM;
1618
const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
1619
vmFuncs->internalEnterVMFromJNI(currentThread);
1620
1621
if ((NULL == caller) || (NULL == indexInfo) || (NULL == buf)) {
1622
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);
1623
} else {
1624
J9Class *callerClass = J9VM_J9CLASS_FROM_JCLASS(currentThread, caller);
1625
j9array_t indexInfoArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(indexInfo);
1626
j9array_t bufferArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(buf);
1627
1628
if ((J9INDEXABLEOBJECT_SIZE(currentThread, indexInfoArray) < 2)) {
1629
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);
1630
} else if (((start < -4) || (start > end) || (pos < 0)) || ((jint)J9INDEXABLEOBJECT_SIZE(currentThread, bufferArray) <= pos) || ((jint)J9INDEXABLEOBJECT_SIZE(currentThread, bufferArray) <= (pos + end - start))) {
1631
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGLINKAGEERROR, NULL);
1632
} else {
1633
U_16 bsmArgCount = (U_16)J9JAVAARRAYOFINT_LOAD(currentThread, indexInfoArray, 0);
1634
U_16 cpIndex = (U_16)J9JAVAARRAYOFINT_LOAD(currentThread, indexInfoArray, 1);
1635
J9ROMClass *romClass = callerClass->romClass;
1636
U_32 * cpShapeDescription = J9ROMCLASS_CPSHAPEDESCRIPTION(romClass);
1637
if (J9_CP_TYPE(cpShapeDescription, cpIndex) == J9CPTYPE_CONSTANT_DYNAMIC) {
1638
J9ROMConstantDynamicRef *romConstantRef = (J9ROMConstantDynamicRef*)(J9_ROM_CP_FROM_ROM_CLASS(romClass) + cpIndex);
1639
J9SRP *callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(romClass);
1640
U_16 *bsmIndices = (U_16 *) (callSiteData + romClass->callSiteCount);
1641
U_16 *bsmData = bsmIndices + romClass->callSiteCount;
1642
1643
/* clear the J9DescriptionCpPrimitiveType flag with mask to get bsmIndex */
1644
U_32 bsmIndex = (romConstantRef->bsmIndexAndCpType >> J9DescriptionCpTypeShift) & J9DescriptionCpBsmIndexMask;
1645
J9ROMNameAndSignature* nameAndSig = SRP_PTR_GET(&romConstantRef->nameAndSignature, J9ROMNameAndSignature*);
1646
1647
/* Walk bsmData - skip all bootstrap methods before bsmIndex */
1648
for (U_32 i = 0; i < bsmIndex; i++) {
1649
/* increment by size of bsm data plus header */
1650
bsmData += (bsmData[1] + 2);
1651
}
1652
1653
U_16 bsmCPIndex = bsmData[0];
1654
U_16 argCount = bsmData[1];
1655
1656
/* Check the argCount from indexInfo array matches actual value */
1657
if (bsmArgCount != argCount) {
1658
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGINTERNALERROR, NULL);
1659
goto done;
1660
}
1661
1662
bsmData += 2;
1663
1664
while (start < end) {
1665
/* Copy the arguments between start and end to the buf array
1666
*
1667
* Negative start index refer to the mandatory arguments for a bootstrap method
1668
* -4 -> Lookup
1669
* -3 -> name (String)
1670
* -2 -> signature (MethodType)
1671
* -1 -> argCount of optional arguments
1672
*/
1673
j9object_t obj = NULL;
1674
if (start >= 0) {
1675
U_16 argIndex = bsmData[start];
1676
J9ConstantPool *ramConstantPool = J9_CP_FROM_CLASS(callerClass);
1677
obj = resolveRefToObject(currentThread, ramConstantPool, argIndex, (JNI_TRUE == resolve));
1678
if ((NULL == obj) && (JNI_TRUE != resolve) && (NULL != ifNotAvailable)) {
1679
obj = J9_JNI_UNWRAP_REFERENCE(ifNotAvailable);
1680
}
1681
} else if (start == -4) {
1682
obj = resolveRefToObject(currentThread, J9_CP_FROM_CLASS(callerClass), bsmCPIndex, true);
1683
} else if (start == -3) {
1684
J9UTF8 *name = J9ROMNAMEANDSIGNATURE_NAME(nameAndSig);
1685
obj = vm->memoryManagerFunctions->j9gc_createJavaLangStringWithUTFCache(currentThread, name);
1686
} else if (start == -2) {
1687
J9UTF8 *signature = J9ROMNAMEANDSIGNATURE_SIGNATURE(nameAndSig);
1688
/* Call VM Entry point to create the MethodType - Result is put into the
1689
* currentThread->returnValue as entry points don't "return" in the expected way
1690
*/
1691
vmFuncs->sendFromMethodDescriptorString(currentThread, signature, callerClass->classLoader, NULL);
1692
obj = (j9object_t)currentThread->returnValue;
1693
} else if (start == -1) {
1694
obj = vm->memoryManagerFunctions->J9AllocateObject(currentThread, J9VMJAVALANGINTEGER_OR_NULL(vm), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);
1695
if (NULL == obj) {
1696
vmFuncs->setHeapOutOfMemoryError(currentThread);
1697
} else {
1698
J9VMJAVALANGINTEGER_SET_VALUE(currentThread, obj, argCount);
1699
}
1700
}
1701
if (VM_VMHelpers::exceptionPending(currentThread)) {
1702
goto done;
1703
}
1704
/* Refetch reference after GC point */
1705
bufferArray = (j9array_t)J9_JNI_UNWRAP_REFERENCE(buf);
1706
J9JAVAARRAYOFOBJECT_STORE(currentThread, bufferArray, pos, obj);
1707
start += 1;
1708
pos += 1;
1709
}
1710
} else {
1711
vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGLINKAGEERROR, NULL);
1712
}
1713
}
1714
}
1715
done:
1716
vmFuncs->internalExitVMToJNI(currentThread);
1717
}
1718
1719
/**
1720
* private static native void clearCallSiteContext(CallSiteContext context);
1721
*/
1722
void JNICALL
1723
Java_java_lang_invoke_MethodHandleNatives_clearCallSiteContext(JNIEnv *env, jclass clazz, jobject context)
1724
{
1725
return;
1726
}
1727
1728
/**
1729
* private static native int getNamedCon(int which, Object[] name);
1730
*/
1731
jint JNICALL
1732
Java_java_lang_invoke_MethodHandleNatives_getNamedCon(JNIEnv *env, jclass clazz, jint which, jobjectArray name)
1733
{
1734
return 0;
1735
}
1736
1737
/**
1738
* private static native void registerNatives();
1739
*/
1740
void JNICALL
1741
Java_java_lang_invoke_MethodHandleNatives_registerNatives(JNIEnv *env, jclass clazz)
1742
{
1743
return;
1744
}
1745
1746
#endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
1747
1748
#if defined (J9VM_OPT_METHOD_HANDLE) || defined(J9VM_OPT_OPENJDK_METHODHANDLE)
1749
jobject JNICALL
1750
Java_java_lang_invoke_MethodHandle_invokeExact(JNIEnv *env, jclass ignored, jobject handle, jobject args)
1751
{
1752
throwNewUnsupportedOperationException(env);
1753
return NULL;
1754
}
1755
1756
jobject JNICALL
1757
Java_java_lang_invoke_MethodHandle_invoke(JNIEnv *env, jclass ignored, jobject handle, jobject args)
1758
{
1759
throwNewUnsupportedOperationException(env);
1760
return NULL;
1761
}
1762
#endif /* defined (J9VM_OPT_METHOD_HANDLE) || defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
1763
} /* extern "C" */
1764
1765