[foreign-memaccess+abi] RFR: 8291639: Improve the ability to visualize a MemorySegment in human readable forms [v17]

Gavin Ray duke at openjdk.org
Mon Sep 5 18:16:58 UTC 2022


On Mon, 5 Sep 2022 14:16:09 GMT, Per Minborg <duke at openjdk.org> wrote:

>> This PR improves the ability to visualize a `MemorySegment` in human-readable forms (`ByteBuffer`, `byte[]` or any other memory abstraction can be viewed by means of wrapping).
>> 
>> It exposes a new method via the new utility class `MemoryInspection`
>> 
>> 
>>     /**
>>      * Returns a human-readable view of the provided {@code memory} abstraction by optionally
>>      * (if not a {@link MemorySession} and {@link Adapter#ofMemorySegment()} already) copying the contents
>>      * to a fresh MemorySegment and then view the resulting MemorySegment through the provided {@code layout}.
>>      * <p>
>>      * Lines are separated with the system-dependent line separator {@link System#lineSeparator() }.
>>      * Otherwise, the exact format of the returned view is unspecified and should not
>>      * be acted upon programmatically.
>>      * <p>
>>      * As an example, a MemorySegment viewed though the following memory layout
>>      * {@snippet lang = java:
>>      * var layout = MemoryLayout.structLayout(
>>      *         ValueLayout.JAVA_INT.withName("x"),
>>      *         ValueLayout.JAVA_INT.withName("y")
>>      * ).withName("Point");
>>      *}
>>      * might be rendered to something like this:
>>      * {@snippet lang = text:
>>      * Point {
>>      *   x=1,
>>      *   y=2
>>      * }
>>      *}
>>      * <p>
>>      * This method is intended to view memory abstractions through small and medium-sized memory layouts.
>>      *
>>      * @param memory   to be viewed
>>      * @param adapter  to apply to the provided memory to determine the size and content of the memory abstraction.
>>      * @param layout   to use as a layout when viewing the memory segment
>>      * @param renderer to apply when rendering value layouts
>>      * @param <M>      the memory abstraction type.
>>      * @return a view of the memory abstraction viewed through the memory layout
>>      * @throws OutOfMemoryError if the view exceeds the array size VM limit
>>      */
>>     public static <M> String toString(M memory,
>>                                       Adapter<M> adapter,
>>                                       MemoryLayout layout,
>>                                       ValueLayoutRenderer renderer) {
>>                                       
>> 
>> 
>> the existing `HexFormat` class will also get a new configurable `MemoryDumper` that can produce dumps of MemorySegments, byte arrays and ByteBuffers:
>> 
>> 
>> 0000000000000000 54 68 65 20 71 75 69 63 6B 20 62 72 6F 77 6E 20 |The quick brown |
>> 0000000000000010 66 6F 78 20 6A 75 6D 70 65 64 20 6F 76 65 72 20 |fox jumped over |
>> 0000000000000020 74 68 65 20 6C 61 7A 79 20 64 6F 67 0A 53 65 63 |the lazy dog.Sec|
>> 0000000000000030 6F 6E 64 20 6C 69 6E 65 09 3A 68 65 72 65 00 00 |ond line.:here..|
>> 0000000000000040 00 00 00 00                                     |....            |
>> 
>> 
>> A MemoryDumper can contain any number of columns (either index or data) which can be formatted in a large number of ways using composable `HexFormat` instances. Even more configuration possibilities can be achieved by providing custom formatting lambdas.
>
> Per Minborg has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Update MemoryInspection JavaDoc

src/java.base/share/classes/java/lang/foreign/MemoryInspection.java line 187:

> 185:          * @return rendered String
> 186:          */
> 187:         default String render(ValueLayout.OfAddress addressLayout, MemorySegment value) {

I think you can make it take `Addressable` so it works for both `MemorySegment` and `MemoryAddress`:


default String render(ValueLayout.OfAddress addressLayout, Addressable value) {
    requireNonNull(addressLayout);
    return String.format("0x%0" + (ValueLayout.ADDRESS.byteSize() * 2) + "X", value.address());
}


In JDK 20 release I get an error:
![image](https://user-images.githubusercontent.com/26604994/188499156-a1c19a0d-cdea-430d-8866-7f99e0fe7f8b.png)


Trying to do `(MemorySegment)` cast fails:

![image](https://user-images.githubusercontent.com/26604994/188499194-0e319c83-ee4d-4ff4-969f-f5ff2ca82587.png)

But if I make it take `Addressable` instead, then it works:
![image](https://user-images.githubusercontent.com/26604994/188499260-2e86662c-d317-43c8-a94d-ea8695de75e3.png)

-------------

PR: https://git.openjdk.org/panama-foreign/pull/695


More information about the panama-dev mailing list