1 /* 2 * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 /* 26 * @test 27 * @run testng TestDereferencePath 28 */ 29 30 import java.lang.foreign.Arena; 31 import java.lang.foreign.MemoryLayout; 32 import java.lang.foreign.MemoryLayout.PathElement; 33 import java.lang.foreign.MemorySegment; 34 35 import java.lang.foreign.ValueLayout; 36 37 import org.testng.annotations.*; 38 39 import java.lang.invoke.VarHandle; 40 import static org.testng.Assert.*; 41 42 public class TestDereferencePath { 43 44 static final MemoryLayout C = MemoryLayout.structLayout( 45 ValueLayout.JAVA_INT.withName("x") 46 ); 47 48 static final MemoryLayout B = MemoryLayout.structLayout( 49 ValueLayout.ADDRESS.withName("c") 50 .withTargetLayout(C) 51 ); 52 53 static final MemoryLayout A = MemoryLayout.structLayout( 54 ValueLayout.ADDRESS.withName("b") 55 .withTargetLayout(B) 56 ); 57 58 static final VarHandle abcx = A.varHandle( 59 PathElement.groupElement("b"), PathElement.dereferenceElement(), 60 PathElement.groupElement("c"), PathElement.dereferenceElement(), 61 PathElement.groupElement("x")); 62 63 @Test 64 public void testSingle() { 65 try (Arena arena = Arena.ofConfined()) { 66 // init structs 67 MemorySegment a = arena.allocate(A); 68 MemorySegment b = arena.allocate(B); 69 MemorySegment c = arena.allocate(C); 70 // init struct fields 71 a.set(ValueLayout.ADDRESS, 0, b); 72 b.set(ValueLayout.ADDRESS, 0, c); 73 c.set(ValueLayout.JAVA_INT, 0, 42); 74 // dereference 75 int val = (int) abcx.get(a, 0L); 76 assertEquals(val, 42); 77 } 78 } 79 80 static final MemoryLayout B_MULTI = MemoryLayout.structLayout( 81 ValueLayout.ADDRESS.withName("cs") 82 .withTargetLayout(MemoryLayout.sequenceLayout(2, C)) 83 ); 84 85 static final MemoryLayout A_MULTI = MemoryLayout.structLayout( 86 ValueLayout.ADDRESS.withName("bs") 87 .withTargetLayout(MemoryLayout.sequenceLayout(2, B_MULTI)) 88 ); 89 90 static final VarHandle abcx_multi = A_MULTI.varHandle( 91 PathElement.groupElement("bs"), PathElement.dereferenceElement(), PathElement.sequenceElement(), 92 PathElement.groupElement("cs"), PathElement.dereferenceElement(), PathElement.sequenceElement(), 93 PathElement.groupElement("x")); 94 95 @Test 96 public void testMulti() { 97 try (Arena arena = Arena.ofConfined()) { 98 // init structs 99 MemorySegment a = arena.allocate(A); 100 MemorySegment b = arena.allocate(B, 2); 101 MemorySegment c = arena.allocate(C, 4); 102 // init struct fields 103 a.set(ValueLayout.ADDRESS, 0, b); 104 b.set(ValueLayout.ADDRESS, 0, c); 105 b.setAtIndex(ValueLayout.ADDRESS, 1, c.asSlice(C.byteSize() * 2)); 106 c.setAtIndex(ValueLayout.JAVA_INT, 0, 1); 107 c.setAtIndex(ValueLayout.JAVA_INT, 1, 2); 108 c.setAtIndex(ValueLayout.JAVA_INT, 2, 3); 109 c.setAtIndex(ValueLayout.JAVA_INT, 3, 4); 110 // dereference 111 int val00 = (int) abcx_multi.get(a, 0L, 0, 0); // a->b[0]->c[0] = 1 112 assertEquals(val00, 1); 113 int val10 = (int) abcx_multi.get(a, 0L, 1, 0); // a->b[1]->c[0] = 3 114 assertEquals(val10, 3); 115 int val01 = (int) abcx_multi.get(a, 0L, 0, 1); // a->b[0]->c[1] = 2 116 assertEquals(val01, 2); 117 int val11 = (int) abcx_multi.get(a, 0L, 1, 1); // a->b[1]->c[1] = 4 118 assertEquals(val11, 4); 119 } 120 } 121 122 @Test(expectedExceptions = IllegalArgumentException.class) 123 void testBadDerefInSelect() { 124 A.select(PathElement.groupElement("b"), PathElement.dereferenceElement()); 125 } 126 127 @Test(expectedExceptions = IllegalArgumentException.class) 128 void testBadDerefInOffset() { 129 A.byteOffset(PathElement.groupElement("b"), PathElement.dereferenceElement()); 130 } 131 132 @Test(expectedExceptions = IllegalArgumentException.class) 133 void testBadDerefInSlice() { 134 A.sliceHandle(PathElement.groupElement("b"), PathElement.dereferenceElement()); 135 } 136 137 static final MemoryLayout A_MULTI_NO_TARGET = MemoryLayout.structLayout( 138 ValueLayout.ADDRESS.withName("bs") 139 ); 140 141 @Test(expectedExceptions = IllegalArgumentException.class) 142 void badDerefAddressNoTarget() { 143 A_MULTI_NO_TARGET.varHandle(PathElement.groupElement("bs"), PathElement.dereferenceElement()); 144 } 145 146 @Test(expectedExceptions = IllegalArgumentException.class) 147 void badDerefMisAligned() { 148 MemoryLayout struct = MemoryLayout.structLayout( 149 ValueLayout.ADDRESS.withTargetLayout(ValueLayout.JAVA_INT).withName("x")); 150 151 try (Arena arena = Arena.ofConfined()) { 152 MemorySegment segment = arena.allocate(struct.byteSize() + 1).asSlice(1); 153 VarHandle vhX = struct.varHandle(PathElement.groupElement("x"), PathElement.dereferenceElement()); 154 vhX.set(segment, 0L, 42); // should throw 155 } 156 } 157 }