Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/jcl/src/java.base/share/classes/com/ibm/jit/JITHelpers.java
12628 views
1
/*[INCLUDE-IF Sidecar17]*/
2
3
package com.ibm.jit;
4
5
/*******************************************************************************
6
* Copyright (c) 1998, 2021 IBM Corp. and others
7
*
8
* This program and the accompanying materials are made available under
9
* the terms of the Eclipse Public License 2.0 which accompanies this
10
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
11
* or the Apache License, Version 2.0 which accompanies this distribution and
12
* is available at https://www.apache.org/licenses/LICENSE-2.0.
13
*
14
* This Source Code may also be made available under the following
15
* Secondary Licenses when the conditions for such availability set
16
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
17
* General Public License, version 2 with the GNU Classpath
18
* Exception [1] and GNU General Public License, version 2 with the
19
* OpenJDK Assembly Exception [2].
20
*
21
* [1] https://www.gnu.org/software/classpath/license.html
22
* [2] http://openjdk.java.net/legal/assembly-exception.html
23
*
24
* 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
25
*******************************************************************************/
26
27
import com.ibm.oti.vm.J9UnmodifiableClass;
28
import java.lang.reflect.Field;
29
import java.lang.reflect.Array;
30
import com.ibm.oti.vm.VM;
31
/*[IF Sidecar19-SE]
32
import jdk.internal.misc.Unsafe;
33
import jdk.internal.reflect.Reflection;
34
import jdk.internal.reflect.CallerSensitive;
35
/*[ELSE]*/
36
import sun.misc.Unsafe;
37
import sun.reflect.Reflection;
38
import sun.reflect.CallerSensitive;
39
/*[ENDIF]*/
40
41
/**
42
* The <code>JITHelpers</code> class contains methods used by the JIT to optimize certain primitive operations.
43
*/
44
@SuppressWarnings("javadoc")
45
@J9UnmodifiableClass
46
public final class JITHelpers {
47
48
private static final JITHelpers helpers;
49
private static final Unsafe unsafe;
50
51
private JITHelpers() {
52
}
53
54
@CallerSensitive
55
public static JITHelpers getHelpers() {
56
if (Reflection.getCallerClass().getClassLoader() != null) {
57
throw new SecurityException("JITHelpers"); //$NON-NLS-1$
58
}
59
return helpers;
60
}
61
62
/*
63
* Private method to provide access to the JITHelpers instance from jitted code without the stackwalk.
64
*/
65
private static JITHelpers jitHelpers() {
66
return helpers;
67
}
68
69
public native int transformedEncodeUTF16Big(long src, long dest, int num);
70
71
public native int transformedEncodeUTF16Little(long src, long dest, int num);
72
73
/*
74
* Constants for getSuperclass.
75
*/
76
private static final int CLASS_IS_INTERFACE_OR_PRIMITIVE = classIsInterfaceFlag() | VM.J9_ACC_CLASS_INTERNAL_PRIMITIVE_TYPE;
77
private static final long JLCLASS_J9CLASS_OFFSET = javaLangClassJ9ClassOffset();
78
private static final int POINTER_SIZE = VM.ADDRESS_SIZE;
79
private static final boolean IS_32_BIT = (POINTER_SIZE == 4);
80
81
public static final boolean IS_BIG_ENDIAN = isBigEndian();
82
83
/*
84
* The following natives are used by the static initializer. They do not require special treatment by the JIT.
85
*/
86
private static native int javaLangClassJ9ClassOffset();
87
88
private static int classIsInterfaceFlag() {
89
/* JVMS Table 4.8 ACC_INTERFACE=0x200 */
90
return 0x200;
91
}
92
93
static {
94
helpers = new JITHelpers();
95
unsafe = Unsafe.getUnsafe();
96
}
97
98
/**
99
* Java implementation of the native getSuperclass
100
*
101
* @param clazz
102
* The class to introspect (must not be null).
103
* @return The superclass, or null for primitive types, interfaces and java.lang.Object.
104
*/
105
public Class<?> getSuperclass(Class<?> clazz) {
106
if (IS_32_BIT) {
107
int j9Class = unsafe.getInt(clazz, JLCLASS_J9CLASS_OFFSET);
108
int romClass = unsafe.getInt(j9Class + VM.J9CLASS_ROMCLASS_OFFSET);
109
int modifiers = unsafe.getInt(romClass + VM.J9ROMCLASS_MODIFIERS_OFFSET);
110
if (0 == (modifiers & CLASS_IS_INTERFACE_OR_PRIMITIVE)) {
111
int superclasses = unsafe.getInt(j9Class + VM.J9CLASS_SUPERCLASSES_OFFSET);
112
int depthAndFlags = unsafe.getInt(j9Class + VM.J9CLASS_CLASS_DEPTH_AND_FLAGS_OFFSET);
113
int depth = (depthAndFlags & VM.J9_JAVA_CLASS_DEPTH_MASK);
114
if (depth > 0) {
115
int superclass = unsafe.getInt(superclasses + (POINTER_SIZE * (depth - 1)));
116
return getClassFromJ9Class32(superclass);
117
}
118
}
119
} else {
120
long j9Class = unsafe.getLong(clazz, JLCLASS_J9CLASS_OFFSET);
121
long romClass = unsafe.getLong(j9Class + VM.J9CLASS_ROMCLASS_OFFSET);
122
int modifiers = unsafe.getInt(romClass + VM.J9ROMCLASS_MODIFIERS_OFFSET);
123
if (0 == (modifiers & CLASS_IS_INTERFACE_OR_PRIMITIVE)) {
124
long superclasses = unsafe.getLong(j9Class + VM.J9CLASS_SUPERCLASSES_OFFSET);
125
long depthAndFlags = unsafe.getLong(j9Class + VM.J9CLASS_CLASS_DEPTH_AND_FLAGS_OFFSET);
126
long depth = (depthAndFlags & VM.J9_JAVA_CLASS_DEPTH_MASK);
127
if (depth > 0) {
128
long superclass = unsafe.getLong(superclasses + (POINTER_SIZE * (depth - 1)));
129
return getClassFromJ9Class64(superclass);
130
}
131
}
132
}
133
return null;
134
}
135
136
/*
137
* To be recognized by the JIT and turned into trees that is foldable when obj is known at compile time.
138
*/
139
public boolean isArray(Object obj) {
140
if (is32Bit()) {
141
int j9Class = getJ9ClassFromObject32(obj);
142
int flags = getClassDepthAndFlagsFromJ9Class32(j9Class);
143
return (flags & VM.J9_ACC_CLASS_ARRAY) != 0;
144
}
145
else {
146
long j9Class = getJ9ClassFromObject64(obj);
147
// Cast the flag to int because only the lower 32 bits are valid and VM.J9_ACC_CLASS_ARRAY is int type
148
int flags = (int)getClassDepthAndFlagsFromJ9Class64(j9Class);
149
return (flags & VM.J9_ACC_CLASS_ARRAY) != 0;
150
}
151
}
152
153
/*
154
* To be recognized by the JIT and turned into a load with vft symbol.
155
*/
156
public long getJ9ClassFromObject64(Object obj) {
157
Class<?> clazz = obj.getClass();
158
return getJ9ClassFromClass64(clazz);
159
}
160
161
public int getJ9ClassFromObject32(Object obj) {
162
Class<?> clazz = obj.getClass();
163
return getJ9ClassFromClass32(clazz);
164
}
165
166
167
/*
168
* To be recognized by the JIT and returns true if the hardware supports SIMD case conversion.
169
*/
170
public boolean supportsIntrinsicCaseConversion() {
171
return false;
172
}
173
174
/**
175
* To be used by the JIT when performing SIMD upper case conversion with Latin 1 strings.
176
* @param value the underlying array for the source string.
177
* @param output a new array which will be used for the converted string.
178
* @param length the number of bytes used to represent the string.
179
* @return True if intrinsic conversion was successful, false if fallback conversion must be used.
180
*/
181
public boolean toUpperIntrinsicLatin1(byte[] value, byte[] output, int length) {
182
return false;
183
}
184
185
/**
186
* To be used by the JIT when performing SIMD lower case conversion with Latin 1 strings.
187
* @param value the underlying array for the source string.
188
* @param output a new array which will be used for the converted string.
189
* @param length the number of bytes used to represent the string.
190
* @return True if intrinsic conversion was successful, false if fallback conversion must be used.
191
*/
192
public boolean toLowerIntrinsicLatin1(byte[] value, byte[] output, int length) {
193
return false;
194
}
195
196
/**
197
* To be used by the JIT when performing SIMD upper case conversion with UTF16 strings.
198
* @param value the underlying array for the source string.
199
* @param output a new array which will be used for the converted string.
200
* @param length the number of bytes used to represent the string.
201
* @return True if intrinsic conversion was successful, false if fallback conversion must be used.
202
*/
203
public boolean toUpperIntrinsicUTF16(byte[] value, byte[] output, int length) {
204
return false;
205
}
206
207
/**
208
* To be used by the JIT when performing SIMD lower case conversion with UTF16 strings.
209
* @param value the underlying array for the source string.
210
* @param output a new array which will be used for the converted string.
211
* @param length the number of bytes used to represent the string.
212
* @return True if intrinsic conversion was successful, false if fallback conversion must be used.
213
*/
214
public boolean toLowerIntrinsicUTF16(byte[] value, byte[] output, int length) {
215
return false;
216
}
217
/**
218
* To be used by the JIT when performing SIMD upper case conversion with Latin 1 strings.
219
* @param value the underlying array for the source string.
220
* @param output a new array which will be used for the converted string.
221
* @param length the number of bytes used to represent the string.
222
* @return True if intrinsic conversion was successful, false if fallback conversion must be used.
223
*/
224
public boolean toUpperIntrinsicLatin1(char[] value, char[] output, int length) {
225
return false;
226
}
227
228
/**
229
* To be used by the JIT when performing SIMD lower case conversion with Latin 1 strings.
230
* @param value the underlying array for the source string.
231
* @param output a new array which will be used for the converted string.
232
* @param length the number of bytes used to represent the string.
233
* @return True if intrinsic conversion was successful, false if fallback conversion must be used.
234
*/
235
public boolean toLowerIntrinsicLatin1(char[] value, char[] output, int length) {
236
return false;
237
}
238
239
/**
240
* To be used by the JIT when performing SIMD upper case conversion with UTF16 strings.
241
* @param value the underlying array for the source string.
242
* @param output a new array which will be used for the converted string.
243
* @param length the number of bytes used to represent the string.
244
* @return True if intrinsic conversion was successful, false if fallback conversion must be used.
245
*/
246
public boolean toUpperIntrinsicUTF16(char[] value, char[] output, int length) {
247
return false;
248
}
249
250
/**
251
* To be used by the JIT when performing SIMD lower case conversion with UTF16 strings.
252
* @param value the underlying array for the source string.
253
* @param output a new array which will be used for the converted string.
254
* @param length the number of bytes used to represent the string.
255
* @return True if intrinsic conversion was successful, false if fallback conversion must be used.
256
*/
257
public boolean toLowerIntrinsicUTF16(char[] value, char[] output, int length) {
258
return false;
259
}
260
261
/*
262
* sun.misc.Unsafe.get* and put* have to generate internal control flow for correctness due to different object shapes. The JIT emitted sequences
263
* checks for and handles: 1) standard fields in normal objects 2) static fields from classes 3) entries from arrays This sequence is branchy and
264
* hard for us to optimize. The better solution in cases where we know the type of object is to use case specific accessors which are the methods
265
* below. Be careful that you know the type of the object you are getting from before using these.
266
*
267
* NOTE: JIT assumes that obj is non-null and offset is positive - breaking this assumption is just asking for trouble.
268
*/
269
public int getIntFromObject(Object obj, long offset) {
270
return unsafe.getInt(obj, offset);
271
}
272
273
public int getIntFromObjectVolatile(Object obj, long offset) {
274
return unsafe.getIntVolatile(obj, offset);
275
}
276
277
public long getLongFromObject(Object obj, long offset) {
278
return unsafe.getLong(obj, offset);
279
}
280
281
public long getLongFromObjectVolatile(Object obj, long offset) {
282
return unsafe.getLongVolatile(obj, offset);
283
}
284
285
public Object getObjectFromObject(Object obj, long offset) {
286
return unsafe.getObject(obj, offset);
287
}
288
289
public Object getObjectFromObjectVolatile(Object obj, long offset) {
290
return unsafe.getObjectVolatile(obj, offset);
291
}
292
293
public void putIntInObject(Object obj, long offset, int value) {
294
unsafe.putInt(obj, offset, value);
295
}
296
297
public void putIntInObjectVolatile(Object obj, long offset, int value) {
298
unsafe.putIntVolatile(obj, offset, value);
299
}
300
301
public void putLongInObject(Object obj, long offset, long value) {
302
unsafe.putLong(obj, offset, value);
303
}
304
305
public void putLongInObjectVolatile(Object obj, long offset, long value) {
306
unsafe.putLongVolatile(obj, offset, value);
307
}
308
309
public void putObjectInObject(Object obj, long offset, Object value) {
310
unsafe.putObject(obj, offset, value);
311
}
312
313
public void putObjectInObjectVolatile(Object obj, long offset, Object value) {
314
unsafe.putObjectVolatile(obj, offset, value);
315
}
316
317
public boolean compareAndSwapIntInObject(Object obj, long offset, int expected, int value) {
318
/*[IF Sidecar19-SE-OpenJ9]*/
319
return unsafe.compareAndSetInt(obj, offset, expected, value);
320
/*[ELSE]
321
return unsafe.compareAndSwapInt(obj, offset, expected, value);
322
/*[ENDIF]*/
323
}
324
325
public boolean compareAndSwapLongInObject(Object obj, long offset, long expected, long value) {
326
/*[IF Sidecar19-SE-OpenJ9]*/
327
return unsafe.compareAndSetLong(obj, offset, expected, value);
328
/*[ELSE]
329
return unsafe.compareAndSwapLong(obj, offset, expected, value);
330
/*[ENDIF]*/
331
}
332
333
public boolean compareAndSwapObjectInObject(Object obj, long offset, Object expected, Object value) {
334
/*[IF Sidecar19-SE-OpenJ9]*/
335
return unsafe.compareAndSetObject(obj, offset, expected, value);
336
/*[ELSE]
337
return unsafe.compareAndSwapObject(obj, offset, expected, value);
338
/*[ENDIF]*/
339
}
340
341
public byte getByteFromArray(Object obj, long offset) {
342
return unsafe.getByte(obj, offset);
343
}
344
345
public byte getByteFromArrayVolatile(Object obj, long offset) {
346
return unsafe.getByteVolatile(obj, offset);
347
}
348
349
public char getCharFromArray(Object obj, long offset) {
350
return unsafe.getChar(obj, offset);
351
}
352
353
public char getCharFromArrayVolatile(Object obj, long offset) {
354
return unsafe.getCharVolatile(obj, offset);
355
}
356
357
public int getIntFromArray(Object obj, long offset) {
358
return unsafe.getInt(obj, offset);
359
}
360
361
public int getIntFromArrayVolatile(Object obj, long offset) {
362
return unsafe.getIntVolatile(obj, offset);
363
}
364
365
public long getLongFromArray(Object obj, long offset) {
366
return unsafe.getLong(obj, offset);
367
}
368
369
public long getLongFromArrayVolatile(Object obj, long offset) {
370
return unsafe.getLongVolatile(obj, offset);
371
}
372
373
public Object getObjectFromArray(Object obj, long offset) {
374
return unsafe.getObject(obj, offset);
375
}
376
377
public Object getObjectFromArrayVolatile(Object obj, long offset) {
378
return unsafe.getObjectVolatile(obj, offset);
379
}
380
381
public void putByteInArray(Object obj, long offset, byte value) {
382
unsafe.putByte(obj, offset, value);
383
}
384
385
public void putByteInArrayVolatile(Object obj, long offset, byte value) {
386
unsafe.putByteVolatile(obj, offset, value);
387
}
388
389
public void putCharInArray(Object obj, long offset, char value) {
390
unsafe.putChar(obj, offset, value);
391
}
392
393
public void putCharInArrayVolatile(Object obj, long offset, char value) {
394
unsafe.putCharVolatile(obj, offset, value);
395
}
396
397
public void putIntInArray(Object obj, long offset, int value) {
398
unsafe.putInt(obj, offset, value);
399
}
400
401
public void putIntInArrayVolatile(Object obj, long offset, int value) {
402
unsafe.putIntVolatile(obj, offset, value);
403
}
404
405
public void putLongInArray(Object obj, long offset, long value) {
406
unsafe.putLong(obj, offset, value);
407
}
408
409
public void putLongInArrayVolatile(Object obj, long offset, long value) {
410
unsafe.putLongVolatile(obj, offset, value);
411
}
412
413
public void putObjectInArray(Object obj, long offset, Object value) {
414
unsafe.putObject(obj, offset, value);
415
}
416
417
public void putObjectInArrayVolatile(Object obj, long offset, Object value) {
418
unsafe.putObjectVolatile(obj, offset, value);
419
}
420
421
public boolean compareAndSwapIntInArray(Object obj, long offset, int expected, int value) {
422
/*[IF Sidecar19-SE-OpenJ9]*/
423
return unsafe.compareAndSetInt(obj, offset, expected, value);
424
/*[ELSE]
425
return unsafe.compareAndSwapInt(obj, offset, expected, value);
426
/*[ENDIF]*/
427
}
428
429
public boolean compareAndSwapLongInArray(Object obj, long offset, long expected, long value) {
430
/*[IF Sidecar19-SE-OpenJ9]*/
431
return unsafe.compareAndSetLong(obj, offset, expected, value);
432
/*[ELSE]
433
return unsafe.compareAndSwapLong(obj, offset, expected, value);
434
/*[ENDIF]*/
435
}
436
437
public boolean compareAndSwapObjectInArray(Object obj, long offset, Object expected, Object value) {
438
/*[IF Sidecar19-SE-OpenJ9]*/
439
return unsafe.compareAndSetObject(obj, offset, expected, value);
440
/*[ELSE]
441
return unsafe.compareAndSwapObject(obj, offset, expected, value);
442
/*[ENDIF]*/
443
}
444
445
public char byteToCharUnsigned(byte b) {
446
return (char) ((char) b & (char) 0x00ff);
447
}
448
449
/**
450
* Determine whether {@code lhs} is at a lower address than {@code rhs}.
451
*
452
* Because objects can be moved by the garbage collector, the ordering of
453
* the addresses of distinct objects is not stable over time. As such, the
454
* result of this comparison should be used for heuristic purposes only.
455
*
456
* A null reference is considered less than any non-null reference.
457
*
458
* @param lhs The left hand side of the comparison
459
* @param rhs The right hand side of the comparison
460
* @return true if {@code lhs} is at a lower address, false otherwise
461
*/
462
public native boolean acmplt(Object lhs, Object rhs);
463
464
private static long storeBits(long dest, int width, long value, int vwidth, int offset) {
465
int offsetToModify = IS_BIG_ENDIAN ? ((width - 1) - ((offset * vwidth) % width)) : ((offset * vwidth) % width);
466
467
long vmask = (-1 >>> ((8 - vwidth) * 8));
468
long dmask = ~(vmask << (8 * offsetToModify));
469
470
return (dest & dmask) | ((value & vmask) << (8 * offsetToModify));
471
}
472
473
private static long readBits(long src, int width, int vwidth, int offset) {
474
int offsetToRead = IS_BIG_ENDIAN ? ((width - 1) - ((offset * vwidth) % width)) : ((offset * vwidth) % width);
475
476
long vmask = (-1 >>> ((8 - vwidth) * 8));
477
long smask = vmask << (8 * offsetToRead);
478
479
return (src & smask) >>> (8 * offsetToRead);
480
}
481
482
public void putByteInArrayByIndex(Object obj, int index, byte value) {
483
Class<?> clazz = obj.getClass();
484
485
if (clazz == byte[].class) {
486
((byte[]) obj)[index] = value;
487
} else if (clazz == char[].class) {
488
char[] array = (char[]) obj;
489
int cidx = index >> 1;
490
char c = array[cidx];
491
array[cidx] = (char) storeBits(c, 2, value, 1, index);
492
} else if (clazz == int[].class) {
493
int[] array = (int[]) obj;
494
int iidx = index >> 2;
495
int i = array[iidx];
496
array[iidx] = (int) storeBits(i, 4, value, 1, index);
497
} else if (clazz == long[].class) {
498
long[] array = (long[]) obj;
499
int lidx = index >> 3;
500
long l = array[lidx];
501
array[lidx] = (long) storeBits(l, 8, value, 1, index);
502
}
503
}
504
505
public byte getByteFromArrayByIndex(Object obj, int index) {
506
Class<?> clazz = obj.getClass();
507
508
if (clazz == byte[].class) {
509
return ((byte[]) obj)[index];
510
} else if (clazz == char[].class) {
511
return (byte) readBits(((char[]) obj)[index >> 1], 2, 1, index);
512
} else if (clazz == int[].class) {
513
return (byte) readBits(((int[]) obj)[index >> 2], 4, 1, index);
514
} else if (clazz == long[].class) {
515
return (byte) readBits(((long[]) obj)[index >> 3], 8, 1, index);
516
}
517
throw new RuntimeException("Unknown array type for bit manipulation");
518
}
519
520
public void putCharInArrayByIndex(Object obj, int index, char value) {
521
Class<?> clazz = obj.getClass();
522
523
if (clazz == byte[].class) {
524
index = index << 1;
525
byte[] array = (byte[]) obj;
526
if (!IS_BIG_ENDIAN) {
527
array[index] = (byte) value;
528
array[index + 1] = (byte) (value >>> 8);
529
} else {
530
array[index] = (byte) (value >>> 8);
531
array[index + 1] = (byte) value;
532
}
533
} else if (clazz == char[].class) {
534
((char[]) obj)[index] = value;
535
} else if (clazz == int[].class) {
536
int[] array = (int[]) obj;
537
int iidx = index >> 1;
538
int i = array[iidx];
539
array[iidx] = (int) storeBits(i, 4, value, 2, index);
540
} else if (clazz == long[].class) {
541
long[] array = (long[]) obj;
542
int lidx = index >> 2;
543
long l = array[lidx];
544
array[lidx] = (long) storeBits(l, 8, value, 2, index);
545
}
546
}
547
548
public char getCharFromArrayByIndex(Object obj, int index) {
549
Class<?> clazz = obj.getClass();
550
551
if (clazz == byte[].class) {
552
index = index << 1;
553
byte[] array = (byte[]) obj;
554
if (!IS_BIG_ENDIAN) {
555
return (char) ((byteToCharUnsigned(array[index + 1]) << 8) | byteToCharUnsigned(array[index]));
556
} else {
557
return (char) (byteToCharUnsigned(array[index + 1]) | (byteToCharUnsigned(array[index]) << 8));
558
}
559
} else if (clazz == char[].class) {
560
return ((char[]) obj)[index];
561
} else if (clazz == int[].class) {
562
return (char) readBits(((int[]) obj)[index >> 1], 4, 2, index);
563
} else if (clazz == long[].class) {
564
return (char) readBits(((long[]) obj)[index >> 2], 8, 2, index);
565
} else {
566
throw new RuntimeException("Unknown array type for bit manipulation");
567
}
568
}
569
570
/**
571
* Returns the first index of the target character array within the source character array starting from the specified
572
* offset.
573
*
574
* <p>This API implicitly assumes the following:
575
* <blockquote><pre>
576
* - s1Value != null
577
* - s2Value != null
578
* - 0 <= s1len <= s1Value.length * 2
579
* - 1 <= s2len <= s2Value.length * 2
580
* - 0 <= start < s1len
581
* <blockquote><pre>
582
*
583
* @param s1Value the source character array to search in.
584
* @param s1len the length (in number of characters) of the source array.
585
* @param s2Value the target character array to search for.
586
* @param s2len the length (in number of characters) of the target array.
587
* @param start the starting offset (in number of characters) to search from.
588
* @return the index (in number of characters) of the target array within the source array, or -1 if the
589
* target array is not found within the source array.
590
*/
591
public int intrinsicIndexOfStringLatin1(Object s1Value, int s1len, Object s2Value, int s2len, int start) {
592
char firstChar = byteToCharUnsigned(getByteFromArrayByIndex(s2Value, 0));
593
594
while (true) {
595
int i = intrinsicIndexOfLatin1(s1Value, (byte)firstChar, start, s1len);
596
597
// Handles subCount > count || start >= count
598
if (i == -1 || s2len + i > s1len) {
599
return -1;
600
}
601
602
int o1 = i;
603
int o2 = 0;
604
605
while (++o2 < s2len && getByteFromArrayByIndex(s1Value, ++o1) == getByteFromArrayByIndex(s2Value, o2))
606
;
607
608
if (o2 == s2len) {
609
return i;
610
}
611
612
start = i + 1;
613
}
614
}
615
616
/**
617
* Returns the first index of the target character array within the source character array starting from the specified
618
* offset.
619
*
620
* <p>This API implicitly assumes the following:
621
* <blockquote><pre>
622
* - s1Value != null
623
* - s2Value != null
624
* - 0 <= s1len <= s1Value.length
625
* - 1 <= s2len <= s2Value.length
626
* - 0 <= start < s1len
627
* <blockquote><pre>
628
*
629
* @param s1Value the source character array to search in.
630
* @param s1len the length (in number of characters) of the source array.
631
* @param s2Value the target character array to search for.
632
* @param s2len the length (in number of characters) of the target array.
633
* @param start the starting offset (in number of characters) to search from.
634
* @return the index (in number of characters) of the target array within the source array, or -1 if the
635
* target array is not found within the source array.
636
*/
637
public int intrinsicIndexOfStringUTF16(Object s1Value, int s1len, Object s2Value, int s2len, int start) {
638
char firstChar = getCharFromArrayByIndex(s2Value, 0);
639
640
while (true) {
641
int i = intrinsicIndexOfUTF16(s1Value, firstChar, start, s1len);
642
643
// Handles subCount > count || start >= count
644
if (i == -1 || s2len + i > s1len) {
645
return -1;
646
}
647
648
int o1 = i;
649
int o2 = 0;
650
651
while (++o2 < s2len && getCharFromArrayByIndex(s1Value, ++o1) == getCharFromArrayByIndex(s2Value, o2))
652
;
653
654
if (o2 == s2len) {
655
return i;
656
}
657
658
start = i + 1;
659
}
660
}
661
662
/**
663
* Returns the first index of the character within the source character array starting from the specified offset.
664
*
665
* <p>This API implicitly assumes the following:
666
* <blockquote><pre>
667
* - array != null
668
* - 0 <= offset < length <= array.length * 1 (if array instanceof byte[])
669
* - 0 <= offset < length <= array.length * 2 (if array instanceof char[])
670
* <blockquote><pre>
671
*
672
* @param array the source character array to search in.
673
* @param ch the character to search for.
674
* @param offset the starting offset (in number of characters) to search from.
675
* @param length the length (in number of characters) of the source array.
676
* @return the index (in number of characters) of \p ch within the source array, or -1 if \p ch is not found
677
* within the source array.
678
*/
679
public int intrinsicIndexOfLatin1(Object array, byte ch, int offset, int length) {
680
for (int i = offset; i < length; i++) {
681
if (getByteFromArrayByIndex(array, i) == ch) {
682
return i;
683
}
684
}
685
return -1;
686
}
687
688
/**
689
* Returns the first index of the character within the source character array starting from the specified offset.
690
*
691
* <p>This API implicitly assumes the following:
692
* <blockquote><pre>
693
* - array != null
694
* - 0 <= offset < length <= array.length * 1 (if array instanceof byte[])
695
* - 0 <= offset < length <= array.length * 2 (if array instanceof char[])
696
* <blockquote><pre>
697
*
698
* @param array the source character array to search in.
699
* @param ch the character to search for.
700
* @param offset the starting offset (in number of characters) to search from.
701
* @param length the length (in number of characters) of the source array.
702
* @return the index (in number of characters) of \p ch within the source array, or -1 if \p ch is not found
703
* within the source array.
704
*/
705
public int intrinsicIndexOfUTF16(Object array, char ch, int offset, int length) {
706
for (int i = offset; i < length; i++) {
707
if (getCharFromArrayByIndex(array, i) == ch) {
708
return i;
709
}
710
}
711
return -1;
712
}
713
714
/*
715
* Constants for optimizedClone
716
*/
717
private static final int DESCRIPTION_WORD_SIZE = VM.ADDRESS_SIZE;
718
private static final int DESCRIPTION_WORD_BIT_SIZE = DESCRIPTION_WORD_SIZE * 8;
719
// Depends on the definition of slot and whether it's 32 or 64 bit
720
private static final int SLOT_SIZE = VM.FJ9OBJECT_SIZE;
721
722
private static boolean isDescriptorPointerTagged(int descriptorPtr) {
723
return (descriptorPtr & 1) == 1;
724
}
725
726
private static boolean isDescriptorPointerTagged(long descriptorPtr) {
727
return (descriptorPtr & 1) == 1;
728
}
729
730
/**
731
* Called by the JIT on 32bit platforms to copy a source object's contents to a destination object as part of a clone. This is a shallow copy only.
732
*
733
* @param srcObj
734
* The object whose fields are to be copied
735
* @param destObj
736
* The object whose fields are to be set (may not be initialized)
737
* @param j9clazz
738
* The j9class pointer for the type of the object being copied (usually from a loadaddr)
739
*/
740
public final void unsafeObjectShallowCopy32(Object srcObj, Object destObj, int j9clazz) {
741
int instanceSize = unsafe.getInt(j9clazz + VM.J9CLASS_INSTANCESIZE_OFFSET);
742
int descriptorPtr = unsafe.getInt(j9clazz + VM.J9CLASS_INSTANCE_DESCRIPTION_OFFSET);
743
int numSlotsInObject = instanceSize / SLOT_SIZE;
744
745
int descriptorWord = descriptorPtr;
746
int bitIndex = DESCRIPTION_WORD_BIT_SIZE - 1;
747
if ((descriptorWord & 1) == 1) {
748
descriptorWord = descriptorWord >> 1;
749
} else {
750
descriptorWord = unsafe.getInt(descriptorPtr);
751
descriptorPtr = descriptorPtr + DESCRIPTION_WORD_SIZE;
752
}
753
754
for (int slot = 0; slot < numSlotsInObject; ++slot) {
755
if (((descriptorWord & 1) == 1)) {
756
Object fieldValue = getObjectFromObject(srcObj, VM.OBJECT_HEADER_SIZE + (slot * SLOT_SIZE));
757
putObjectInObject(destObj, VM.OBJECT_HEADER_SIZE + (slot * SLOT_SIZE), fieldValue);
758
} else {
759
int fieldValue = getIntFromObject(srcObj, VM.OBJECT_HEADER_SIZE + (slot * SLOT_SIZE));
760
putIntInObject(destObj, VM.OBJECT_HEADER_SIZE + (slot * SLOT_SIZE), fieldValue);
761
}
762
763
descriptorWord = descriptorWord >> 1;
764
if (bitIndex-- == 0) {
765
descriptorWord = unsafe.getInt(descriptorPtr);
766
descriptorPtr = descriptorPtr + DESCRIPTION_WORD_SIZE;
767
bitIndex = DESCRIPTION_WORD_BIT_SIZE - 1;
768
}
769
}
770
771
/*
772
* If the object has a lockword, it needs to be set to the correct initial value since this method
773
* is effectively the cloned object's initialization.
774
*/
775
int lockOffset = unsafe.getInt(j9clazz + VM.J9CLASS_LOCK_OFFSET_OFFSET);
776
if (lockOffset != 0) {
777
int lwValue = getInitialLockword32(j9clazz);
778
putIntInObject(destObj, lockOffset, lwValue);
779
}
780
unsafe.storeFence();
781
}
782
783
/**
784
* Called by the JIT on 64bit platforms to copy a source object's contents to a destination object as part of a clone. This is a shallow copy only.
785
*
786
* @param srcObj
787
* The object whose fields are to be copied
788
* @param destObj
789
* The object whose fields are to be set (may not be initialized)
790
* @param j9clazz
791
* The j9class pointer for the type of the object being copied (usually from a loadaddr)
792
*/
793
public final void unsafeObjectShallowCopy64(Object srcObj, Object destObj, long j9clazz) {
794
long instanceSize = unsafe.getLong(j9clazz + VM.J9CLASS_INSTANCESIZE_OFFSET);
795
long descriptorPtr = unsafe.getLong(j9clazz + VM.J9CLASS_INSTANCE_DESCRIPTION_OFFSET);
796
int header = VM.OBJECT_HEADER_SIZE;
797
int numSlotsInObject = (int) (instanceSize / SLOT_SIZE);
798
799
long descriptorWord = descriptorPtr;
800
int bitIndex = DESCRIPTION_WORD_BIT_SIZE - 1;
801
if ((descriptorWord & 1) == 1) {
802
descriptorWord = descriptorWord >> 1;
803
} else {
804
descriptorWord = unsafe.getLong(descriptorPtr);
805
descriptorPtr = descriptorPtr + DESCRIPTION_WORD_SIZE;
806
}
807
808
for (int slot = 0; slot < numSlotsInObject; ++slot) {
809
if (((descriptorWord & 1) == 1)) {
810
Object fieldValue = getObjectFromObject(srcObj, (header + (slot * SLOT_SIZE)));
811
putObjectInObject(destObj, header + (slot * SLOT_SIZE), fieldValue);
812
} else {
813
if (SLOT_SIZE == 4) {
814
int fieldValue = getIntFromObject(srcObj, header + (slot * SLOT_SIZE));
815
putIntInObject(destObj, header + (slot * SLOT_SIZE), fieldValue);
816
} else {
817
long fieldValue = getLongFromObject(srcObj, header + (slot * SLOT_SIZE));
818
putLongInObject(destObj, header + (slot * SLOT_SIZE), fieldValue);
819
}
820
}
821
822
descriptorWord = descriptorWord >> 1;
823
if (bitIndex-- == 0) {
824
descriptorWord = unsafe.getLong(descriptorPtr);
825
descriptorPtr = descriptorPtr + DESCRIPTION_WORD_SIZE;
826
bitIndex = DESCRIPTION_WORD_BIT_SIZE - 1;
827
}
828
}
829
830
/*
831
* If the object has a lockword, it needs to be set to the correct initial value since this method
832
* is effectively the cloned object's initialization.
833
*/
834
long lockOffset = unsafe.getLong(j9clazz + VM.J9CLASS_LOCK_OFFSET_OFFSET);
835
if (lockOffset != 0) {
836
int lwValue = getInitialLockword64(j9clazz);
837
if (SLOT_SIZE == 4) {
838
// for compressed reference, the LockWord is 4 bytes
839
putIntInObject(destObj, lockOffset, lwValue);
840
} else {
841
putLongInObject(destObj, lockOffset, lwValue);
842
}
843
}
844
unsafe.storeFence();
845
}
846
847
/**
848
* Java implementation of optimized clone.
849
*
850
* @param srcObj
851
* The source object of the clone.
852
* @return The cloned object.
853
*/
854
public Object optimizedClone(Object srcObj) throws CloneNotSupportedException {
855
Class<?> clnClass = srcObj.getClass();
856
857
if (clnClass.isArray()) {
858
Class<?> eleClass = clnClass.getComponentType();
859
int len = Array.getLength(srcObj);
860
Object clnObj = Array.newInstance(eleClass, len);
861
System.arraycopy(srcObj, 0, clnObj, 0, len);
862
return clnObj;
863
}
864
865
if (!(srcObj instanceof Cloneable)) {
866
throw new CloneNotSupportedException();
867
}
868
869
Object clnObj = null;
870
try {
871
clnObj = (Object) unsafe.allocateInstance(clnClass);
872
} catch (InstantiationException e) {
873
// This can never actually happen as clnClass is clearly instantiable
874
}
875
876
int bitIndex = 0;
877
if (IS_32_BIT) {
878
int j9clazz = unsafe.getInt(clnClass, JLCLASS_J9CLASS_OFFSET);
879
// Get the instance size out of the J9Class
880
int instanceSize = unsafe.getInt(j9clazz + VM.J9CLASS_INSTANCESIZE_OFFSET);
881
// Get the pointer to instance descriptor out of the J9Class. Tells which fields are refs and prims
882
int descriptorPtr = unsafe.getInt(j9clazz + VM.J9CLASS_INSTANCE_DESCRIPTION_OFFSET);
883
int numSlotsInObject = instanceSize / SLOT_SIZE;
884
int descriptorWord = 0;
885
if (isDescriptorPointerTagged(descriptorPtr)) {
886
bitIndex++;
887
descriptorWord = descriptorPtr >>> 1;
888
} else {
889
descriptorWord = unsafe.getInt(descriptorPtr);
890
}
891
892
int countSlots = 0;
893
for (int index = 0; numSlotsInObject != 0; index++) {
894
if (isDescriptorPointerTagged(descriptorWord)) {
895
Object fieldValue = unsafe.getObject(srcObj, VM.OBJECT_HEADER_SIZE + (countSlots * SLOT_SIZE));
896
unsafe.putObject(clnObj, VM.OBJECT_HEADER_SIZE + (index * SLOT_SIZE), fieldValue);
897
} else {
898
int fieldValue = unsafe.getInt(srcObj, VM.OBJECT_HEADER_SIZE + (countSlots * SLOT_SIZE));
899
unsafe.putInt(clnObj, VM.OBJECT_HEADER_SIZE + (index * SLOT_SIZE), fieldValue);
900
}
901
countSlots++;
902
if (countSlots >= numSlotsInObject) {
903
break;
904
}
905
if (bitIndex == (DESCRIPTION_WORD_BIT_SIZE - 1)) {
906
descriptorPtr = descriptorPtr + DESCRIPTION_WORD_SIZE;
907
bitIndex = 0;
908
descriptorWord = unsafe.getInt(descriptorPtr);
909
} else {
910
descriptorWord = descriptorWord >>> 1;
911
bitIndex++;
912
}
913
}
914
/* If the object has a lockword, it needs to be set to the correct initial value. */
915
long lockOffset = unsafe.getInt(j9clazz + VM.J9CLASS_LOCK_OFFSET_OFFSET);
916
if (lockOffset != 0) {
917
int lwValue = getInitialLockword32(j9clazz);
918
unsafe.putInt(clnObj, lockOffset, lwValue);
919
}
920
} else {
921
long j9clazz = unsafe.getLong(clnClass, JLCLASS_J9CLASS_OFFSET);
922
// Get the instance size out of the J9Class
923
long instanceSize = unsafe.getLong(j9clazz + VM.J9CLASS_INSTANCESIZE_OFFSET);
924
// Get the pointer to instance descriptor out of the J9Class. Tells which fields are refs and prims
925
long descriptorPtr = unsafe.getLong(j9clazz + VM.J9CLASS_INSTANCE_DESCRIPTION_OFFSET);
926
int numSlotsInObject = (int) (instanceSize / SLOT_SIZE);
927
long descriptorWord = 0;
928
if (isDescriptorPointerTagged(descriptorPtr)) {
929
bitIndex++;
930
descriptorWord = descriptorPtr >>> 1;
931
} else {
932
descriptorWord = unsafe.getLong(descriptorPtr);
933
}
934
int countSlots = 0;
935
for (int index = 0; numSlotsInObject != 0; index++) {
936
if (isDescriptorPointerTagged(descriptorWord)) {
937
Object fieldValue = unsafe.getObject(srcObj, VM.OBJECT_HEADER_SIZE + (countSlots * SLOT_SIZE));
938
unsafe.putObject(clnObj, VM.OBJECT_HEADER_SIZE + (index * SLOT_SIZE), fieldValue);
939
} else {
940
long fieldValue = unsafe.getLong(srcObj, VM.OBJECT_HEADER_SIZE + (countSlots * SLOT_SIZE));
941
unsafe.putLong(clnObj, VM.OBJECT_HEADER_SIZE + (index * SLOT_SIZE), fieldValue);
942
}
943
countSlots++;
944
if (countSlots >= numSlotsInObject) {
945
break;
946
}
947
if (bitIndex == (DESCRIPTION_WORD_BIT_SIZE - 1)) {
948
descriptorPtr = descriptorPtr + DESCRIPTION_WORD_SIZE;
949
bitIndex = 0;
950
descriptorWord = unsafe.getLong(descriptorPtr);
951
} else {
952
descriptorWord = descriptorWord >>> 1;
953
bitIndex++;
954
}
955
}
956
/* If the object has a lockword, it needs to be set to the correct initial value. */
957
long lockOffset = unsafe.getLong(j9clazz + VM.J9CLASS_LOCK_OFFSET_OFFSET);
958
if (lockOffset != 0) {
959
int lwValue = getInitialLockword64(j9clazz);
960
if (SLOT_SIZE == 4) {
961
// for compressed reference, the LockWord is 4 bytes
962
unsafe.putInt(clnObj, lockOffset, lwValue);
963
} else {
964
unsafe.putLong(clnObj, lockOffset, lwValue);
965
}
966
}
967
}
968
969
unsafe.storeFence();
970
return clnObj;
971
}
972
973
/**
974
* Get class initialize status flag. Calls to this method will be recognized and optimized by the JIT.
975
* @parm defc
976
* The class whose initialize status is desired.
977
* @return
978
* initializeStatus from J9Class.
979
*/
980
public final int getClassInitializeStatus(Class<?> defc) {
981
long defcClass = 0;
982
if (is32Bit()) {
983
defcClass = getJ9ClassFromClass32(defc);
984
} else {
985
defcClass = getJ9ClassFromClass64(defc);
986
}
987
int initStatus = 0;
988
if (4 == VM.ADDRESS_SIZE) {
989
initStatus = unsafe.getInt(defcClass + VM.J9CLASS_INITIALIZE_STATUS_OFFSET);
990
} else {
991
initStatus = (int)unsafe.getLong(defcClass + VM.J9CLASS_INITIALIZE_STATUS_OFFSET);
992
}
993
return initStatus;
994
}
995
996
/**
997
* Determine initial lockword value, 32-bit version. Calls to this method will return what the lockword should start at.
998
*
999
* @parm j9clazz
1000
* The J9Class of the object whose lockword is being initialized.
1001
*
1002
* @return
1003
* The initial lockword to use.
1004
*/
1005
public int getInitialLockword32(int j9clazz) {
1006
int flags = getClassFlagsFromJ9Class32(j9clazz);
1007
1008
/*
1009
* Unsafe calls are used to get the reservedCounter and cancelCounter out of the J9Class.
1010
* reservedCounter and cancelCounter are unsigned 16 bit values so a mask is used to force a zero extend.
1011
*/
1012
int reservedCounter = ((int)(unsafe.getShort(j9clazz + VM.J9CLASS_LOCK_RESERVATION_HISTORY_RESERVED_COUNTER_OFFSET))) & 0xFFFF;
1013
int cancelCounter = ((int)(unsafe.getShort(j9clazz + VM.J9CLASS_LOCK_RESERVATION_HISTORY_CANCEL_COUNTER_OFFSET))) & 0xFFFF;
1014
1015
return getInitialLockword(flags, reservedCounter, cancelCounter);
1016
}
1017
1018
/**
1019
* Determine initial lockword value, 64-bit version. Calls to this method will return what the lockword should start at.
1020
*
1021
* @parm j9clazz
1022
* The J9Class of the object whose lockword is being initialized.
1023
*
1024
* @return
1025
* The initial lockword to use.
1026
*/
1027
public int getInitialLockword64(long j9clazz) {
1028
int flags = getClassFlagsFromJ9Class64(j9clazz);
1029
1030
/*
1031
* Unsafe calls are used to get the reservedCounter and cancelCounter out of the J9Class.
1032
* reservedCounter and cancelCounter are unsigned 16 bit values so a mask is used to force a zero extend.
1033
*/
1034
int reservedCounter = ((int)(unsafe.getShort(j9clazz + VM.J9CLASS_LOCK_RESERVATION_HISTORY_RESERVED_COUNTER_OFFSET))) & 0xFFFF;
1035
int cancelCounter = ((int)(unsafe.getShort(j9clazz + VM.J9CLASS_LOCK_RESERVATION_HISTORY_CANCEL_COUNTER_OFFSET))) & 0xFFFF;
1036
1037
return getInitialLockword(flags, reservedCounter, cancelCounter);
1038
}
1039
1040
/**
1041
* Determine initial lockword value. Calls to this method will return what the lockword should start at.
1042
*
1043
* @parm flags
1044
* Class flags from the J9Class.
1045
*
1046
* @parm reservedCounter
1047
* reservedCounter from the J9Class.
1048
*
1049
* @parm cancelCounter
1050
* cancelCounter from the J9Class.
1051
*
1052
* @return
1053
* The initial lockword to use.
1054
*/
1055
public int getInitialLockword(int flags, int reservedCounter, int cancelCounter) {
1056
int lwValue = 0;
1057
1058
if (1 == VM.GLR_ENABLE_GLOBAL_LOCK_RESERVATION) {
1059
/* This path is taken when Global Lock Reservation is enabled. */
1060
int reservedAbsoluteThreshold = VM.GLR_RESERVED_ABSOLUTE_THRESHOLD;
1061
int minimumReservedRatio = VM.GLR_MINIMUM_RESERVED_RATIO;
1062
1063
int cancelAbsoluteThreshold = VM.GLR_CANCEL_ABSOLUTE_THRESHOLD;
1064
int minimumLearningRatio = VM.GLR_MINIMUM_LEARNING_RATIO;
1065
1066
/*
1067
* Check reservedCounter and cancelCounter against different thresholds to determine what to initialize the lockword to.
1068
* First check if the ratio of resevation to cancellations is high enough to set the lockword to the New-AutoReserve state.
1069
* If so, the initial lockword value is OBJECT_HEADER_LOCK_RESERVED.
1070
* Second check if the ratio is high enough to set the lockword to the New-PreLearning state.
1071
* If so, the initial lockword value is OBJECT_HEADER_LOCK_LEARNING.
1072
* If the ratio is too low, the lockword starts in the Flat-Unlocked state and 0 is returned for the lockword value.
1073
*
1074
* Start as New-AutoReserve -> Initial lockword: OBJECT_HEADER_LOCK_RESERVED
1075
* Start as New-PreLearning -> Initial lockword: OBJECT_HEADER_LOCK_LEARNING
1076
* Start as Flat-Unlocked -> Initial lockword: 0
1077
*
1078
* reservedCounter, cancelCounter, minimumReservedRatio and minimumLearningRatio all have a maximum value of 0xFFFF so casting to long
1079
* is required to guarantee signed overflow does not occur after multiplication.
1080
*/
1081
if ((reservedCounter >= reservedAbsoluteThreshold) && ((long)reservedCounter > ((long)cancelCounter * (long)minimumReservedRatio))) {
1082
lwValue = VM.OBJECT_HEADER_LOCK_RESERVED;
1083
} else if ((cancelCounter < cancelAbsoluteThreshold) || ((long)reservedCounter > ((long)cancelCounter * (long)minimumLearningRatio))) {
1084
lwValue = VM.OBJECT_HEADER_LOCK_LEARNING;
1085
}
1086
} else if ((flags & VM.J9CLASS_RESERVABLE_LOCK_WORD_INIT) != 0) {
1087
/* Initialize lockword to New-ReserveOnce. This path is x86 only. */
1088
lwValue = VM.OBJECT_HEADER_LOCK_RESERVED;
1089
}
1090
1091
return lwValue;
1092
}
1093
1094
/**
1095
* Determines whether the underlying platform's memory model is big-endian.
1096
*
1097
* @return True if the underlying platform's memory model is big-endian, false otherwise.
1098
*/
1099
private native static final boolean isBigEndian();
1100
1101
/* Placeholder for JIT GPU optimizations - this method never actually gets run */
1102
public final native void GPUHelper();
1103
1104
/*
1105
* The following natives are recognized and handled specially by the JIT.
1106
*/
1107
1108
public native boolean is32Bit();
1109
1110
public native int getNumBitsInReferenceField();
1111
1112
public native int getNumBytesInReferenceField();
1113
1114
public native int getNumBitsInDescriptionWord();
1115
1116
public native int getNumBytesInDescriptionWord();
1117
1118
public native int getNumBytesInJ9ObjectHeader();
1119
1120
public native int getJ9ClassFromClass32(Class c);
1121
1122
public native Class getClassFromJ9Class32(int j9clazz);
1123
1124
public native int getTotalInstanceSizeFromJ9Class32(int j9clazz);
1125
1126
public native int getInstanceDescriptionFromJ9Class32(int j9clazz);
1127
1128
public native int getDescriptionWordFromPtr32(int descriptorPtr);
1129
1130
public native long getJ9ClassFromClass64(Class c);
1131
1132
public native Class getClassFromJ9Class64(long j9clazz);
1133
1134
public native long getTotalInstanceSizeFromJ9Class64(long j9clazz);
1135
1136
public native long getInstanceDescriptionFromJ9Class64(long j9clazz);
1137
1138
public native long getDescriptionWordFromPtr64(long descriptorPtr);
1139
1140
public native int getNumSlotsInObject(Class currentClass);
1141
1142
public native int getSlotIndex(Field field);
1143
1144
public native boolean isDescriptorPointerTagged(int descriptorPtr, long descriptorPtr64);
1145
1146
public native int getRomClassFromJ9Class32(int j9clazz);
1147
1148
public native int getSuperClassesFromJ9Class32(int j9clazz);
1149
1150
public native int getClassDepthAndFlagsFromJ9Class32(int j9clazz);
1151
1152
public native int getBackfillOffsetFromJ9Class32(int j9clazz);
1153
1154
public native int getArrayShapeFromRomClass32(int j9romclazz);
1155
1156
public native int getModifiersFromRomClass32(int j9romclazz);
1157
1158
public native long getRomClassFromJ9Class64(long j9clazz);
1159
1160
public native long getSuperClassesFromJ9Class64(long j9clazz);
1161
1162
public native long getClassDepthAndFlagsFromJ9Class64(long j9clazz);
1163
1164
public native long getBackfillOffsetFromJ9Class64(long j9clazz);
1165
1166
public native int getArrayShapeFromRomClass64(long j9romclazz);
1167
1168
public native int getModifiersFromRomClass64(long j9romclazz);
1169
1170
public native int getClassFlagsFromJ9Class32(int j9clazz);
1171
1172
public native int getClassFlagsFromJ9Class64(long j9clazz);
1173
1174
public static native void dispatchComputedStaticCall();
1175
1176
public static native void dispatchVirtual();
1177
}
1178
1179