From 4fd2402611905480ba87792fbddae28be37ae78d Mon Sep 17 00:00:00 2001 From: Not Zed Date: Thu, 9 Dec 2021 08:26:36 +1030 Subject: [PATCH] Checkpoint panama work --- src/notzed.zcl/classes/api/Frame.java | 69 ++++++ .../tests/au/notzed/zcl/MemoryTest.java | 197 ++++++++++++++++++ 2 files changed, 266 insertions(+) create mode 100644 src/notzed.zcl/classes/api/Frame.java create mode 100644 src/notzed.zcl/tests/au/notzed/zcl/MemoryTest.java diff --git a/src/notzed.zcl/classes/api/Frame.java b/src/notzed.zcl/classes/api/Frame.java new file mode 100644 index 0000000..b5ca8c9 --- /dev/null +++ b/src/notzed.zcl/classes/api/Frame.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2021 Michael Zucchi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package api; + +import jdk.incubator.foreign.MemoryAccess; +import jdk.incubator.foreign.MemorySegment; + +public interface Frame extends AutoCloseable { + + MemorySegment allocate(long size, long alignment); + + @Override + public void close(); + + default MemorySegment allocate(long size) { + return allocate(size, 1); + } + + default MemorySegment copy(byte value) { + MemorySegment mem = allocate(1); + MemoryAccess.setByte(mem, value); + return mem; + } + + default MemorySegment copy(int value) { + MemorySegment mem = allocate(4, 4); + MemoryAccess.setInt(mem, value); + return mem; + } + + default MemorySegment copy(long value) { + MemorySegment mem = allocate(8, 8); + MemoryAccess.setLong(mem, value); + return mem; + } + + default MemorySegment copy(byte[] value, int alignment) { + MemorySegment mem = allocate(value.length, alignment); + mem.copyFrom(MemorySegment.ofArray(value)); + return mem; + } + + default MemorySegment copy(int[] value, int alignment) { + MemorySegment mem = allocate(value.length * 4, alignment); + mem.copyFrom(MemorySegment.ofArray(value)); + return mem; + } + + default MemorySegment copy(long[] value, int alignment) { + MemorySegment mem = allocate(value.length * 8, alignment); + mem.copyFrom(MemorySegment.ofArray(value)); + return mem; + } + +} diff --git a/src/notzed.zcl/tests/au/notzed/zcl/MemoryTest.java b/src/notzed.zcl/tests/au/notzed/zcl/MemoryTest.java new file mode 100644 index 0000000..bcbac8f --- /dev/null +++ b/src/notzed.zcl/tests/au/notzed/zcl/MemoryTest.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2021 Michael Zucchi + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package au.notzed.zcl; + +import api.Frame; +import api.Memory; +import jdk.incubator.foreign.MemorySegment; +import static org.junit.Assert.*; +import org.junit.Before; +import org.junit.Test; + +public class MemoryTest { + + @Before + public void setup() { + } + + @Test + public void testFrameAlignment() throws Exception { + System.out.println("testFrame Alignment"); + + try (Frame frame = Memory.createFrame()) { + MemorySegment a = frame.allocate(1, 1); + MemorySegment b = frame.allocate(16, 16); + MemorySegment c = frame.allocate(2, 2); + MemorySegment d = frame.allocate(8, 8); + + assertEquals(b.address().toRawLongValue() & 15, 0); + assertEquals(d.address().toRawLongValue() & 7, 0); + } + } + + /* + @Test + public void testFrameExhaustion() throws Exception { + Throwable x = null; + + System.out.println("testFrame Exhaustion"); + + try (Frame frame = Memory.createFrame()) { + while (true) + frame.allocate(8); + } catch (OutOfMemoryError e) { + x = e; + } + + assertNotNull(x); + assertEquals(x.getClass(), OutOfMemoryError.class); + }*/ + @Test + public void testFrameLarge() throws Exception { + System.out.println("testFrame Large"); + + try (Frame frame = Memory.createFrame()) { + MemorySegment a = frame.allocate(1024 * 1024); + MemorySegment b = frame.allocate(1024 * 1024); + MemorySegment c = frame.allocate(1024 * 1024); + assertNotNull(a); + assertNotNull(b); + assertNotNull(c); + } + } + + @Test + public void testBadAlignment() throws Exception { + Throwable x = null; + + System.out.println("testFrame Bad alignment"); + + try (Frame frame = Memory.createFrame()) { + MemorySegment a = frame.allocate(1, 3); + } catch (IllegalArgumentException e) { + x = e; + } + + assertNotNull(x); + assertEquals(x.getClass(), IllegalArgumentException.class); + } + + @Test + public void testAfterClose() throws Exception { + Throwable x = null; + + System.out.println("testFrame use after close"); + + Frame frame = Memory.createFrame(); + frame.close(); + try { + MemorySegment a = frame.allocate(1, 3); + } catch (IllegalStateException e) { + x = e; + } + + assertNotNull(x); + assertEquals(x.getClass(), IllegalStateException.class); + } + + static void assertSeparate(MemorySegment a, MemorySegment b) { + long ap = a.address().toRawLongValue(); + long as = a.byteSize(); + long bp = b.address().toRawLongValue(); + long bs = b.byteSize(); + + assertNotEquals(ap, bp); + if (ap < bp) { + assertTrue(String.format("memory overlap %016x - %016x, %016x - %016x", ap, ap + as, bp, bp + bs), ap + as <= bp); + } else { + assertTrue(String.format("memory overlap %016x - %016x, %016x - %016x", bp, bp + bs, ap, ap + as), bp + bs <= ap); + } + + } + + @Test + public void testFrameAlloc() throws Exception { + System.out.println("testFrame Alloc"); + + try (Frame frame = Memory.createFrame()) { + MemorySegment a = frame.allocate(1, 1); + MemorySegment b = frame.allocate(16, 16); + MemorySegment c = frame.allocate(2, 2); + MemorySegment d = frame.allocate(8, 8); + + assertEquals(a.byteSize(), 1); + assertEquals(b.byteSize(), 16); + assertEquals(c.byteSize(), 2); + assertEquals(d.byteSize(), 8); + + assertSeparate(a, b); + assertSeparate(a, c); + assertSeparate(a, d); + + assertSeparate(b, c); + assertSeparate(b, d); + + assertSeparate(c, d); + } + } + + @Test + public void testFrameNested() throws Exception { + System.out.println("testFrame Nested"); + + try (Frame framea = Memory.createFrame()) { + MemorySegment a = framea.allocate(1, 1); + MemorySegment b = framea.allocate(16, 16); + + try (Frame frameb = Memory.createFrame()) { + MemorySegment c = frameb.allocate(2, 2); + MemorySegment d = frameb.allocate(8, 8); + + assertEquals(a.byteSize(), 1); + assertEquals(b.byteSize(), 16); + assertEquals(c.byteSize(), 2); + assertEquals(d.byteSize(), 8); + + assertSeparate(a, b); + assertSeparate(a, c); + assertSeparate(a, d); + + assertSeparate(b, c); + assertSeparate(b, d); + + assertSeparate(c, d); + } + + MemorySegment c = framea.allocate(2, 2); + MemorySegment d = framea.allocate(8, 8); + + assertEquals(c.byteSize(), 2); + assertEquals(d.byteSize(), 8); + + assertSeparate(a, b); + assertSeparate(a, c); + assertSeparate(a, d); + + assertSeparate(b, c); + assertSeparate(b, d); + + assertSeparate(c, d); + } + } + +} -- 2.39.5