|
26 | 26 |
|
27 | 27 | import static com.oracle.svm.core.util.VMError.shouldNotReachHere;
|
28 | 28 |
|
29 |
| -import com.oracle.svm.core.heap.ReferenceMapIndex; |
| 29 | +// Checkstyle: stop |
| 30 | +import java.lang.reflect.Executable; |
| 31 | +// Checkstyle: resume |
| 32 | +import java.util.Arrays; |
| 33 | +import java.util.ArrayList; |
| 34 | +import java.util.List; |
| 35 | + |
30 | 36 | import org.graalvm.compiler.api.replacements.Fold;
|
31 | 37 | import org.graalvm.compiler.core.common.util.TypeConversion;
|
| 38 | +import org.graalvm.compiler.core.common.util.UnsafeArrayTypeReader; |
32 | 39 | import org.graalvm.compiler.options.Option;
|
33 | 40 | import org.graalvm.nativeimage.ImageSingletons;
|
34 | 41 |
|
35 | 42 | import com.oracle.svm.core.annotate.AlwaysInline;
|
36 | 43 | import com.oracle.svm.core.annotate.Uninterruptible;
|
| 44 | +import com.oracle.svm.core.c.NonmovableArrays; |
| 45 | +import com.oracle.svm.core.heap.ReferenceMapIndex; |
| 46 | +import com.oracle.svm.core.hub.DynamicHub; |
| 47 | +import com.oracle.svm.core.jdk.Target_jdk_internal_reflect_ConstantPool; |
37 | 48 | import com.oracle.svm.core.option.HostedOptionKey;
|
| 49 | +import com.oracle.svm.core.reflect.RuntimeReflectionConstructors; |
38 | 50 | import com.oracle.svm.core.util.ByteArrayReader;
|
39 | 51 | import com.oracle.svm.core.util.Counter;
|
40 | 52 | import com.oracle.svm.core.util.NonmovableByteArrayReader;
|
@@ -491,6 +503,138 @@ private static long advanceOffset(long entryOffset, int entryFlags) {
|
491 | 503 | static CodeInfoDecoderCounters counters() {
|
492 | 504 | return ImageSingletons.lookup(CodeInfoDecoderCounters.class);
|
493 | 505 | }
|
| 506 | + |
| 507 | + public static Executable[] getMethodMetadata(DynamicHub declaringType) { |
| 508 | + return getMethodMetadata(declaringType.getTypeID()); |
| 509 | + } |
| 510 | + |
| 511 | + public static Executable[] getAllMethodMetadata() { |
| 512 | + List<Executable> allMethods = new ArrayList<>(); |
| 513 | + for (int i = 0; i < ImageSingletons.lookup(MethodMetadataEncoding.class).getIndexEncoding().length / Integer.BYTES; ++i) { |
| 514 | + allMethods.addAll(Arrays.asList(getMethodMetadata(i))); |
| 515 | + } |
| 516 | + return allMethods.toArray(new Executable[0]); |
| 517 | + } |
| 518 | + |
| 519 | + /** |
| 520 | + * The metadata for methods in the image is split into two arrays: one for the index and the |
| 521 | + * other for data. The index contains an array of integers pointing to offsets in the data, and |
| 522 | + * indexed by type ID. The data array contains arrays of method metadata, ordered by type ID, |
| 523 | + * such that all methods declared by a class are stored consecutively. The data for a method is |
| 524 | + * stored in the following format: |
| 525 | + * |
| 526 | + * <pre> |
| 527 | + * { |
| 528 | + * int methodNameIndex; // index in frameInfoSourceMethodNames ("<init>" for constructors) |
| 529 | + * int modifiers; |
| 530 | + * int paramCount; |
| 531 | + * { |
| 532 | + * int paramTypeIndex; // index in frameInfoSourceClasses |
| 533 | + * } paramTypes[paramCount]; |
| 534 | + * int returnTypeIndex; // index in frameInfoSourceClasses (void for constructors) |
| 535 | + * int exceptionTypeCount; |
| 536 | + * { |
| 537 | + * int exceptionTypeIndex; // index in frameInfoSourceClasses |
| 538 | + * } exceptionTypes[exceptionTypeCount]; |
| 539 | + * // Annotation encodings (see {@link CodeInfoEncoder}) |
| 540 | + * int annotationsLength; |
| 541 | + * byte[] annotationsEncoding[annotationsLength]; |
| 542 | + * int parameterAnnotationsLength; |
| 543 | + * byte[] parameterAnnotationsEncoding[parameterAnnotationsLength]; |
| 544 | + * } |
| 545 | + * </pre> |
| 546 | + */ |
| 547 | + public static Executable[] getMethodMetadata(int typeID) { |
| 548 | + CodeInfo info = CodeInfoTable.getImageCodeInfo(); |
| 549 | + MethodMetadataEncoding encoding = ImageSingletons.lookup(MethodMetadataEncoding.class); |
| 550 | + byte[] index = encoding.getIndexEncoding(); |
| 551 | + UnsafeArrayTypeReader indexReader = UnsafeArrayTypeReader.create(index, Integer.BYTES * typeID, ByteArrayReader.supportsUnalignedMemoryAccess()); |
| 552 | + int offset = indexReader.getS4(); |
| 553 | + if (offset == MethodMetadataEncoder.NO_METHOD_METADATA) { |
| 554 | + return new Executable[0]; |
| 555 | + } |
| 556 | + byte[] data = ImageSingletons.lookup(MethodMetadataEncoding.class).getMethodsEncoding(); |
| 557 | + UnsafeArrayTypeReader dataReader = UnsafeArrayTypeReader.create(data, offset, ByteArrayReader.supportsUnalignedMemoryAccess()); |
| 558 | + |
| 559 | + int methodCount = dataReader.getUVInt(); |
| 560 | + Executable[] methods = new Executable[methodCount]; |
| 561 | + for (int i = 0; i < methodCount; ++i) { |
| 562 | + int classIndex = dataReader.getSVInt(); |
| 563 | + Class<?> declaringClass = NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceClasses(info), classIndex); |
| 564 | + |
| 565 | + int nameIndex = dataReader.getSVInt(); |
| 566 | + /* Interning the string to ensure JDK8 method search succeeds */ |
| 567 | + String name = NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceMethodNames(info), nameIndex).intern(); |
| 568 | + |
| 569 | + int modifiers = dataReader.getUVInt(); |
| 570 | + |
| 571 | + int paramCount = dataReader.getUVInt(); |
| 572 | + Class<?>[] paramTypes = new Class<?>[paramCount]; |
| 573 | + for (int j = 0; j < paramCount; ++j) { |
| 574 | + int paramTypeIndex = dataReader.getSVInt(); |
| 575 | + paramTypes[j] = NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceClasses(info), paramTypeIndex); |
| 576 | + } |
| 577 | + |
| 578 | + int returnTypeIndex = dataReader.getSVInt(); |
| 579 | + Class<?> returnType = NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceClasses(info), returnTypeIndex); |
| 580 | + |
| 581 | + int exceptionCount = dataReader.getUVInt(); |
| 582 | + Class<?>[] exceptionTypes = new Class<?>[exceptionCount]; |
| 583 | + for (int j = 0; j < exceptionCount; ++j) { |
| 584 | + int exceptionTypeIndex = dataReader.getSVInt(); |
| 585 | + exceptionTypes[j] = NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceClasses(info), exceptionTypeIndex); |
| 586 | + } |
| 587 | + |
| 588 | + int signatureIndex = dataReader.getSVInt(); |
| 589 | + String signature = NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceMethodNames(info), signatureIndex); |
| 590 | + |
| 591 | + int annotationsLength = dataReader.getUVInt(); |
| 592 | + byte[] annotations = new byte[annotationsLength]; |
| 593 | + for (int j = 0; j < annotationsLength; ++j) { |
| 594 | + annotations[j] = (byte) dataReader.getS1(); |
| 595 | + } |
| 596 | + |
| 597 | + int parameterAnnotationsLength = dataReader.getUVInt(); |
| 598 | + byte[] parameterAnnotations = new byte[parameterAnnotationsLength]; |
| 599 | + for (int j = 0; j < parameterAnnotationsLength; ++j) { |
| 600 | + parameterAnnotations[j] = (byte) dataReader.getS1(); |
| 601 | + } |
| 602 | + |
| 603 | + int typeAnnotationsLength = dataReader.getUVInt(); |
| 604 | + byte[] typeAnnotations = new byte[typeAnnotationsLength]; |
| 605 | + for (int j = 0; j < typeAnnotationsLength; ++j) { |
| 606 | + typeAnnotations[j] = (byte) dataReader.getS1(); |
| 607 | + } |
| 608 | + |
| 609 | + boolean parameterDataPresent = dataReader.getU1() == 1; |
| 610 | + String[] parameterNames = null; |
| 611 | + int[] parameterModifiers = null; |
| 612 | + if (parameterDataPresent) { |
| 613 | + int parameterCount = dataReader.getUVInt(); |
| 614 | + parameterNames = new String[parameterCount]; |
| 615 | + parameterModifiers = new int[parameterCount]; |
| 616 | + for (int j = 0; j < paramCount; ++j) { |
| 617 | + int parameterNameIndex = dataReader.getSVInt(); |
| 618 | + parameterNames[j] = NonmovableArrays.getObject(CodeInfoAccess.getFrameInfoSourceMethodNames(info), parameterNameIndex); |
| 619 | + parameterModifiers[j] = dataReader.getS4(); |
| 620 | + } |
| 621 | + } |
| 622 | + |
| 623 | + if (name.equals("<init>")) { |
| 624 | + assert returnType == void.class; |
| 625 | + methods[i] = ImageSingletons.lookup(RuntimeReflectionConstructors.class).newConstructor(declaringClass, paramTypes, exceptionTypes, modifiers, signature, |
| 626 | + annotations, parameterAnnotations, typeAnnotations, parameterNames, parameterModifiers); |
| 627 | + } else { |
| 628 | + methods[i] = ImageSingletons.lookup(RuntimeReflectionConstructors.class).newMethod(declaringClass, name, paramTypes, returnType, exceptionTypes, modifiers, signature, |
| 629 | + annotations, parameterAnnotations, null, typeAnnotations, parameterNames, parameterModifiers); |
| 630 | + } |
| 631 | + } |
| 632 | + return methods; |
| 633 | + } |
| 634 | + |
| 635 | + public static Target_jdk_internal_reflect_ConstantPool getMetadataPseudoConstantPool() { |
| 636 | + return new Target_jdk_internal_reflect_ConstantPool(); |
| 637 | + } |
494 | 638 | }
|
495 | 639 |
|
496 | 640 | class CodeInfoDecoderCounters {
|
|
0 commit comments