MemoryLayout::varHandle Problems with structuring via mutable arrays

118 views Asked by At

When constructing a varHandle using MemoryLayout::varHandle, I passed in a self-assembled Object array to implement the public method for constructing the MemorySegment. However, I find that it seems to prevent me from using Object arrays instead of mutable arrays.

The code snippet is as follows.

public static MemorySegment buildMemorySegment(Object object, MemorySegment memorySegment, MemoryLayout originMemoryLayout, MemoryLayout memoryLayout, List<PathElement> pathElements, List<Object> indexParams) throws NoSuchFieldException, IllegalAccessException {
    Class<?> aClass = object.getClass();
    if (memoryLayout instanceof SequenceLayout sequenceLayout) {
        pathElements.add(PathElement.sequenceElement());
        for (int i = 0; i < sequenceLayout.elementCount(); i++) {
            Object[] array;
            if (Collection.class.isAssignableFrom(aClass)) {
                assert object instanceof Collection<?>;
                Collection<?> collection = (Collection<?>) object;
                array = collection.toArray();
            } else {
                assert object instanceof Object[];
                array = ((Object[]) object);
            }
            Object o = array[i];
            indexParams.add((long) i);
            buildMemorySegment(o, memorySegment, originMemoryLayout, sequenceLayout.elementLayout(), pathElements, indexParams);
            indexParams.removeLast();
        }
        pathElements.removeLast();
    } else if (memoryLayout instanceof StructLayout structLayout) {
        List<MemoryLayout> memoryLayouts = structLayout.memberLayouts();
        for (MemoryLayout layout : memoryLayouts) {
            String layoutName = layout.name().orElseThrow();
            pathElements.add(PathElement.groupElement(layoutName));
            Field declaredField = aClass.getDeclaredField(layoutName);
            Object fieldValue = getFieldValue(object, declaredField);
            buildMemorySegment(fieldValue, memorySegment, originMemoryLayout, layout, pathElements, indexParams);
            pathElements.removeLast();
        }
    } else if (memoryLayout instanceof ValueLayout) {
        Object[] varParams = new Object[indexParams.size() + 2];
        varParams[0] = memorySegment;
        for (int i = 0; i < indexParams.size(); i++) {
            varParams[i + 1] = indexParams.get(i);
        }
        varParams[varParams.length - 1] = object;
        VarHandle varHandle = originMemoryLayout.varHandle(pathElements.toArray(new PathElement[0]));
        varHandle.set(varParams);
    }
    return MemorySegment.NULL;
}

The key problem is that I successfully built MemoryLayout and constructed varHandle by parsing MemoryLayout to control varHandle parameters. The following problems occur.

enter image description here

connot convert MethodHandle(VarHandle,MemorySegment,long,int)void to (VarHandle,Object[])void

This is what my debug says, and what i want to implement is varHandler.set(segment, (long)i, i);

Can I implement my idea? How do I do it?

1

There are 1 answers

0
Jorn Vernee On BEST ANSWER

You can not pass an Object[] holding the coordinates, directly to VarHandle::set (because it is a signature polymorphic method).

However, you can convert the var handle to a method handle using toMethodHandle and then use invokeWithArguments:

MethodHandle setter = varHandle.toMethodHandle(VarHandle.AccessMode.SET);
setter.invokeWithArguments(varParams);