changeset 14071:42bf13af7c8b

Prototype of MemoryRegion and further Pointer/Reference support
author mikael
date Fri, 22 Apr 2016 15:19:32 -0700
parents 1763ab0ccba6
children be659db504e8
files src/demo/share/panama/Panama/NativeIntArray.java src/demo/share/panama/Panama/Printf.java src/demo/share/panama/Panama/Qsort.java src/demo/share/panama/Panama/stdio.java src/demo/share/panama/Panama/stdlib.java src/java.base/share/classes/java/lang/invoke/MethodHandles.java src/java.base/share/classes/java/nicl/NativeLibrary.java src/java.base/share/classes/java/nicl/Scope.java src/java.base/share/classes/java/nicl/types/BoundedPointer.java src/java.base/share/classes/java/nicl/types/LayoutType.java src/java.base/share/classes/java/nicl/types/MemoryRegion.java src/java.base/share/classes/java/nicl/types/Pointer.java src/java.base/share/classes/java/nicl/types/PointerImpl.java src/java.base/share/classes/java/nicl/types/PointerToken.java src/java.base/share/classes/java/nicl/types/Reference.java src/java.base/share/classes/java/nicl/types/Transformer.java src/java.base/share/classes/jdk/internal/nicl/Civilizer.java src/java.base/share/classes/jdk/internal/nicl/FieldGenerator.java src/java.base/share/classes/jdk/internal/nicl/HeaderImplGenerator.java src/java.base/share/classes/jdk/internal/nicl/LdLoader.java src/java.base/share/classes/jdk/internal/nicl/MethodGenerator.java src/java.base/share/classes/jdk/internal/nicl/MethodImplGenerator.java src/java.base/share/classes/jdk/internal/nicl/NativeLibraryImpl.java src/java.base/share/classes/jdk/internal/nicl/StructImplGenerator.java src/java.base/share/classes/jdk/internal/nicl/UnixDynamicLibraries.java src/java.base/share/classes/jdk/internal/nicl/UnixLibrary.java src/java.base/share/classes/jdk/internal/nicl/UnsupportedOperationMethodImpl.java src/java.base/share/classes/jdk/internal/nicl/UpcallHandler.java src/java.base/share/classes/jdk/internal/nicl/Util.java src/java.base/share/classes/jdk/internal/nicl/VarargsInvoker.java src/java.base/share/classes/jdk/internal/nicl/VarargsMethodImplGenerator.java src/java.base/share/classes/jdk/internal/nicl/abi/types/Types.java src/java.base/share/classes/jdk/internal/nicl/types/BoundedMemoryRegion.java src/java.base/share/classes/jdk/internal/nicl/types/BoundedPointer.java src/java.base/share/classes/jdk/internal/nicl/types/LayoutTypeImpl.java src/java.base/share/classes/jdk/internal/nicl/types/PointerTokenImpl.java src/java.base/share/classes/jdk/internal/nicl/types/ReferenceImpl.java src/java.base/share/classes/jdk/internal/nicl/types/UncheckedPointer.java src/java.base/share/classes/jdk/internal/panama/CodeSnippet.java src/jdk.jextract/share/classes/com/sun/tools/jextract/JType.java src/jdk.jextract/share/classes/com/sun/tools/jextract/PointerType.java src/jdk.jextract/share/classes/com/sun/tools/jextract/ReferenceType.java test/java/nicl/System/UnixSystem.java test/java/nicl/Upcall/CallbackSort.java test/java/nicl/Upcall/DoubleUpcall.java test/java/nicl/Upcall/Long4Upcall.java test/java/nicl/Upcall/StructUpcall.java
diffstat 47 files changed, 1409 insertions(+), 705 deletions(-) [+]
line wrap: on
line diff
--- a/src/demo/share/panama/Panama/NativeIntArray.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/demo/share/panama/Panama/NativeIntArray.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,36 +23,26 @@
 
 
 import java.lang.reflect.Field;
-import java.nicl.types.BoundedPointer;
-import java.nicl.types.Pointer.int$ptr;
+import java.nicl.NativeLibrary;
+import java.nicl.Scope;
+import java.nicl.types.Pointer;
+import java.nicl.types.Reference;
 import java.util.Iterator;
-import sun.misc.Unsafe;
 
 public class NativeIntArray implements Iterable<Integer> {
-    private static final Unsafe U;
-    
-    static {
-        try {
-            Field f = Unsafe.class.getDeclaredField("theUnsafe");
-            f.setAccessible(true);
-            U = (Unsafe)f.get(null);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
     private static final int ELEM_SIZE = 4;
 
     private final int nelems;
-    private final long addr;
+    private final Scope scope = new Scope();
+    private final Pointer<Integer> base;
 
     public NativeIntArray(int nelems) {
         this.nelems = nelems;
-        this.addr = U.allocateMemory(nelems * ELEM_SIZE);
+        this.base = scope.allocate(NativeLibrary.createLayout(int.class), nelems * ELEM_SIZE);
     }
 
-    public int$ptr getBasePointer() {
-        return new BoundedPointer.BoundedIntPointer(addr, addr, addr + nelems * ELEM_SIZE);
+    public Pointer<Integer> getBasePointer() {
+        return base;
     }
 
     public int size() {
@@ -63,25 +53,20 @@
         return ELEM_SIZE;
     }
 
-    @Override
-    public void finalize() {
-        U.freeMemory(addr);
-    }
+    private Reference<Integer> refAt(int index) {
+        if (index < 0 || index >= nelems) {
+            throw new IndexOutOfBoundsException();
+        }
 
-    private long addrForIndex(int index) {
-        return addr + index * ELEM_SIZE;
+        return base.offset(index * ELEM_SIZE).deref();
     }
 
     public int getAt(int index) {
-        return U.getInt(addrForIndex(index));
+        return refAt(index).get();
     }
 
     public void setAt(int index, int value) {
-        if (index >= nelems) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        U.putInt(addrForIndex(index), value);
+        refAt(index).set(value);
     }
 
     @Override
--- a/src/demo/share/panama/Panama/Printf.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/demo/share/panama/Panama/Printf.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
 
         // Convert the Java string to a native one
         // Basically uses Unsafe to allocate memory and copy the bytes
-        Pointer<Byte> fmt = Transformer.toCStrPtr("Hello, World!\n", scope);
+        Pointer<Byte> fmt = Transformer.toCString("Hello, World!\n", scope);
 
         // Call printf
         i.printf(fmt);
@@ -65,7 +65,7 @@
         Scope scope = new Scope();
 
         // Convert the Java string to a native one 
-        Pointer<Byte> fmt = Transformer.toCStrPtr("Hello, %d!\n", scope); 
+        Pointer<Byte> fmt = Transformer.toCString("Hello, %d!\n", scope); 
 
         // Call printf
         printf.invoke(i, fmt, 4711);
@@ -87,7 +87,7 @@
         // Create a scope to allocate things in
         Scope scope = new Scope();
 
-        Pointer<Byte> fmt = Transformer.toCStrPtr("Hello, %d!\n", scope); 
+        Pointer<Byte> fmt = Transformer.toCString("Hello, %d!\n", scope); 
         printf.invoke(i, fmt, 4711);
 
         // Make sure output is not stuck in buffer
@@ -105,8 +105,8 @@
         // Lookup a MH for the printf function 
         MethodHandle printf = Util.lookup(Util.Function.PRINTF);
 
-        Pointer<Byte> fmt = Transformer.toCStrPtr("Hello, %s!\n", scope); 
-        Pointer<Byte> arg = Transformer.toCStrPtr("World", scope); 
+        Pointer<Byte> fmt = Transformer.toCString("Hello, %s!\n", scope); 
+        Pointer<Byte> arg = Transformer.toCString("World", scope); 
 
         printf.invoke(i, fmt, arg);
 
--- a/src/demo/share/panama/Panama/Qsort.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/demo/share/panama/Panama/Qsort.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,9 +22,10 @@
  */
 
 
-import java.nicl.types.BoundedPointer.BoundedIntPointer;
+import java.nicl.types.Pointer;
 import java.nicl.NativeLibrary;
 import java.nicl.types.Pointer;
+import java.nicl.types.Reference;
 
 public class Qsort {
     /**
@@ -42,18 +43,15 @@
         @Override
         public int fn(Pointer<Void> e1, Pointer<Void> e2) {
             // Extract the actual integers to be compared
-            int i1 = new BoundedIntPointer(e1.addr()).defref();
-            int i2 = new BoundedIntPointer(e2.addr()).defref();
+            Pointer<Integer> p1 = e1.cast(NativeLibrary.createLayout(int.class));
+            Pointer<Integer> p2 = e2.cast(NativeLibrary.createLayout(int.class));
+
+            int i1 = p1.deref().get();
+            int i2 = p1.deref().get();
 
             System.out.println("sort_function(" + i1 + ", " + i2 + ")");
 
-            if (i1 == i2) {
-                return 0;
-            } else if (i1 < i2) {
-                return -1;
-            } else {
-                return 1;
-            }
+            return i1 - i2;
         }
     }
 
@@ -76,7 +74,7 @@
 
         printElements(arr);
 
-        stdlib.qsort(arr.getBasePointer(), arr.size(), arr.getElemSize(), new comparator());
+        stdlib.qsort(arr.getBasePointer().cast(NativeLibrary.createLayout(void.class)), arr.size(), arr.getElemSize(), new comparator());
 
         printElements(arr);
     }
--- a/src/demo/share/panama/Panama/stdio.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/demo/share/panama/Panama/stdio.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@
 import java.nicl.metadata.Header;
 import java.nicl.metadata.NativeType;
 import java.nicl.types.Pointer;
-import java.nicl.types.Pointer.int$ptr;
 
 @Header(path="/usr/include/stdio.h")
 public interface stdio {
@@ -55,9 +54,4 @@
     @NativeType(layout="(ip:c)p", ctype="FILE* (int fd, const char* mode)", size=1)
     @CallingConvention(value=1)
     Pointer<Void> fdopen(int fd, Pointer<Byte> mode);
-
-    @FunctionalInterface
-    static interface compar {
-        public int fn(Pointer<int$ptr> e1, Pointer<int$ptr> e2);
-    }
 }
--- a/src/demo/share/panama/Panama/stdlib.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/demo/share/panama/Panama/stdlib.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@
 import java.nicl.metadata.Header;
 import java.nicl.metadata.NativeType;
 import java.nicl.types.Pointer;
-import java.nicl.types.Pointer.int$ptr;
 
 @Header(path="stdlib.h")
 public interface stdlib {
@@ -39,5 +38,5 @@
     @C(file="stdlib.h", line=47, column=11, USR="c:@F@qsort")
     @NativeType(layout="(p:VLLp:(p:Vp:V)i)V", ctype="void (void*, size_t, size_t, int(*)(const void*,const void*))", size=1)
     @CallingConvention(value=1)
-    public abstract void qsort(int$ptr base, long nmemb, long size, compar compar);
+    public abstract void qsort(Pointer<Void> base, long nmemb, long size, compar compar);
 }
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1216,6 +1216,7 @@
 
         /** TODO */
         private static MethodHandle INVOKE_NATIVE_MH;
+        private static final java.nicl.types.PointerToken TOKEN = new jdk.internal.nicl.types.PointerTokenImpl();
         static {
             try {
                 INVOKE_NATIVE_MH = Lookup.IMPL_LOOKUP.findStatic(MethodHandleNatives.class, "invokeNative", MethodType.methodType(void.class, long[].class, long[].class, long[].class, NativeEntryPoint.class));
@@ -1224,21 +1225,21 @@
             }
         } 
 
-        public MethodHandle findNative2(Library lib, String name, MethodType type) throws NoSuchMethodException {
+        public MethodHandle findNative2(Library lib, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
             assert(type.equals(INVOKE_NATIVE_MH.type().dropParameterTypes(INVOKE_NATIVE_MH.type().parameterCount() - 1, INVOKE_NATIVE_MH.type().parameterCount())));
             LibrarySymbol sym = lib.lookup(name);
-            NativeEntryPoint nativeFunc = NativeEntryPoint.make(sym.getAddress().addr(), name, type, null);
+            NativeEntryPoint nativeFunc = NativeEntryPoint.make(sym.getAddress().addr(TOKEN), name, type, null);
             return MethodHandles.insertArguments(INVOKE_NATIVE_MH, INVOKE_NATIVE_MH.type().parameterCount() - 1, nativeFunc);
         }
 
-        public MethodHandle findNative(Library lib, String name, MethodType type) throws NoSuchMethodException {
+        public MethodHandle findNative(Library lib, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
             LibrarySymbol sym = lib.lookup(name);
-            NativeEntryPoint nativeFunc = NativeEntryPoint.make(sym.getAddress().addr(), name, type, null);
+            NativeEntryPoint nativeFunc = NativeEntryPoint.make(sym.getAddress().addr(TOKEN), name, type, null);
             MethodHandle mh = NativeMethodHandle.make(type, nativeFunc);
             return mh;
         }
 
-        public MethodHandle findNative(String name, MethodType type) throws NoSuchMethodException {
+        public MethodHandle findNative(String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
             long addr = findNativeAddress(name);
             if (addr == 0) {
                 throw new NoSuchMethodException("Failed to look up " + name);
@@ -1249,7 +1250,7 @@
         }
 
         // FIXME: remove
-        public MethodHandle findNative(String name, long addr, MethodType type, byte[] snippet) {
+        public MethodHandle findNative(String name, long addr, MethodType type, byte[] snippet) throws NoSuchMethodException, IllegalAccessException {
             NativeEntryPoint nativeFunc = NativeEntryPoint.make(addr, name, type, snippet);
             MethodHandle mh = NativeMethodHandle.make(type, nativeFunc);
             return mh;
--- a/src/java.base/share/classes/java/nicl/NativeLibrary.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/java/nicl/NativeLibrary.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,21 +25,43 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.nicl.types.LayoutType;
 import java.nicl.types.Pointer;
-import java.nicl.types.PointerImpl;
+import java.nicl.types.PointerToken;
 import java.nicl.types.Reference;
 import jdk.internal.nicl.NativeLibraryImpl;
 import jdk.internal.nicl.Platform;
+import jdk.internal.nicl.types.BoundedMemoryRegion;
+import jdk.internal.nicl.types.BoundedPointer;
+import jdk.internal.nicl.types.LayoutTypeImpl;
+import jdk.internal.nicl.types.PointerTokenImpl;
 
 public class NativeLibrary {
 
     private static final boolean DEBUG = Boolean.getBoolean("java.nicl.NativeLibrary.DEBUG");
 
-    public static long unpack(Pointer<?> ptr) {
+    // FIXME: Only here for debugging/until all uses of pointer have been updated
+    @Deprecated
+    public static PointerToken debugCreatePointerToken() {
+        return new PointerTokenImpl();
+    }
+
+    // FIXME: Only here for debugging/until all uses of pointer have been updated
+    @Deprecated
+    public static long unpack(Pointer<?> ptr) throws IllegalAccessException {
+        System.err.println("WARNING: long unpack(Pointer) is deprecated");
+        new Exception().printStackTrace();
         if (ptr == null) {
             return 0;
         }
-        return ptr.addr();
+        return ptr.addr(new PointerTokenImpl());
+    }
+
+    public static long unpack(Pointer<?> ptr, PointerToken token) throws IllegalAccessException {
+        if (ptr == null) {
+            return 0;
+        }
+        return ptr.addr(token);
     }
 
     /**
@@ -84,93 +106,54 @@
         return Platform.getInstance().defaultLibrary();
     }
 
-    public static <T> T createStruct(Class<T> c) {
+    public static <T> Class<? extends Reference<T>> getStructImplClass(Class<T> c) {
         if (DEBUG) {
             System.out.println("NativeLibrary: Creating struct of type: " + c.getName());
         }
 
-        Class<? extends Reference<T>> cls = NativeLibraryImpl.getOrCreateStructImpl(c);
-
-        try {
-            @SuppressWarnings("unchecked")
-            T instance = (T) cls.newInstance();
-            return instance;
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
-
-    public static <T> Reference<T> createStruct(Class<T> c, long addr) {
-        if (DEBUG) {
-            System.out.println("NativeLibrary: Creating struct of type: " + c.getName());
-        }
-
-        Class<? extends Reference<T>> cls = NativeLibraryImpl.getOrCreateStructImpl(c);
-
-        try {
-            MethodHandle mh = MethodHandles.publicLookup().findConstructor(cls, MethodType.methodType(void.class, long.class));
-            T t = (T) mh.invoke(addr);
-
-            MethodHandle mh2 = MethodHandles.publicLookup().findVirtual(cls, "get", MethodType.methodType(Reference.class));
-            return (Reference<T>) mh2.invokeExact(t);
-        } catch (Throwable e) {
-            throw new Error(e);
-        }
+        return NativeLibraryImpl.getOrCreateStructImpl(c);
     }
 
     /* =================================================================== */
-    @SuppressWarnings("unchecked")
-    public static <T> Pointer<T> nullPtr() {
-        return (Pointer<T>) PointerImpl.NULL_PTR;
+
+    public static <T> LayoutType<T> createLayout(Class<T> c) {
+        return LayoutTypeImpl.create(c);
     }
 
-    public static <T> Pointer<T> createPtr(long addr, Class<T> cls) {
-        return createPtr(null, addr, cls);
+    @Deprecated
+    public static <T> Pointer<T> createPtr(long addr, Class<T> type) {
+        return createPtr(null, addr, NativeLibrary.createLayout(type));
     }
 
-    public static <T> Pointer<T> createPtr(Object base, long addr, Class<T> cls) {
-        if (base == null && addr == 0) {
-            return nullPtr();
-        }
-        return new PointerImpl<>(base, addr, cls);
+    public static <T> Pointer<T> createPtr(long addr, LayoutType<T> type) {
+        return createPtr(null, addr, type);
     }
 
+    public static <T> Pointer<T> createPtr(Object base, long addr, LayoutType<T> type) {
+        if (base == null && addr == 0) {
+            return Pointer.NULL_PTR.cast(type);
+        }
+        return new BoundedPointer<T>(type, new BoundedMemoryRegion(base, addr, Long.MAX_VALUE), 0);
+    }
+
 
     /*** FIXME: Temporary exports ***/
-
     public static long createUpcallHandler(Object o, Class<?> c) throws Throwable {
         return NativeLibraryImpl.createUpcallHandler(o, c);
     }
 
+    @Deprecated
     public static long allocateMemory(long size) {
         return NativeLibraryImpl.U.allocateMemory(size);
     }
 
+    @Deprecated
     public static long rawStructRead(long address) {
         return NativeLibraryImpl.U.getLong(address);
     }
 
+    @Deprecated
     public static void rawStructWrite(long address, long value) {
         NativeLibraryImpl.U.putLong(address, value);
     }
-
-
-    /*** FIXME: Remove this when vectors are stable ***/
-
-    public static void putLong(jdk.internal.misc.Unsafe unsafe, long addr, long value) {
-        System.err.println("0x" + Long.toHexString(value) + " -> [0x" + Long.toHexString(addr) + "]");
-        unsafe.putLong(addr, value);
-    }
-
-    public static void printLong(Long2 v) {
-        System.err.println("printLong: " + v);
-    }
-
-    public static void printLong(Long4 v) {
-        System.err.println("printLong: " + v);
-    }
-
-    public static void printLong(Long8 v) {
-        System.err.println("printLong: " + v);
-    }
 }
--- a/src/java.base/share/classes/java/nicl/Scope.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/java/nicl/Scope.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,12 +22,16 @@
  */
 package java.nicl;
 
-import java.nicl.types.BoundedPointer;
-import jdk.internal.nicl.Util;
+import java.nicl.types.LayoutType;
 import java.nicl.types.Pointer;
-import java.nicl.types.PointerImpl;
 import java.nicl.types.Reference;
 import jdk.internal.misc.Unsafe;
+import jdk.internal.nicl.Util;
+import jdk.internal.nicl.abi.types.Types;
+import jdk.internal.nicl.types.BoundedMemoryRegion;
+import jdk.internal.nicl.types.BoundedPointer;
+import jdk.internal.nicl.types.LayoutTypeImpl;
+import jdk.internal.nicl.types.ReferenceImpl;
 
 /**
  * A unit of resources allocation that can be released all together.
@@ -39,7 +43,7 @@
     // 64KB block
     private final static long UNIT_SIZE = 64 * 1024;
 
-    // the addres of allocated memory
+    // the address of allocated memory
     long block;
     // the first offset of available memory
     long free_offset;
@@ -72,6 +76,7 @@
         transaction_origin = -1;
     }
 
+    @Deprecated
     public long allocate(long size) {
         if (size <= 0) {
             rollbackAllocation();
@@ -88,41 +93,45 @@
         return rv;
     }
 
-    public <T> Reference<T> allocate(Class<T> cls) {
-        long size = Util.sizeof(cls);
+    public <T> Pointer<T> allocate(LayoutType<T> type, long size) {
+        // Sanity check for now, can be removed/loosened if needed
         if (size > Integer.MAX_VALUE) {
             throw new UnsupportedOperationException("allocate size to large");
         }
-        long addr = allocate((int) size);
-        return NativeLibrary.createStruct(cls, addr);
+
+        return new BoundedPointer<T>(type, new BoundedMemoryRegion(allocate(size), size), 0);
     }
 
-    public Reference.int$ref allocateInt() {
-        // FIXME: Use precise size(alignment or not) of an integer on the target platform
-        long addr = allocate(4);
-        return new Reference.int$ref() {
-            @Override
-            public int get() {
-                return U.getInt(addr);
-            }
+    public <T> Pointer<T> allocate(LayoutType<T> type) {
+        if (type.getCarrierType().isPrimitive()) {
+            return allocate(type, Util.sizeof(type.getCarrierType()));
+        } else if (Pointer.class.isAssignableFrom(type.getCarrierType())) {
+            long size = U.addressSize();
+            long addr = allocate(size);
+            @SuppressWarnings("unchecked")
+            Pointer<T> p = (Pointer<T>) new BoundedPointer<T>(type, new BoundedMemoryRegion(addr, size), 0);
+            return p;
+        } else if (Util.isCStruct(type.getCarrierType())) {
+            return allocateStruct(type).ptr();
+        }
 
-            @Override
-            public void set(int value) {
-                U.putInt(addr, value);
-            }
-
-            @Override
-            public Pointer.int$ptr ptr() {
-                return new BoundedPointer.BoundedIntPointer(addr);
-            }
-        };
+        throw new IllegalArgumentException("Unhandled type: " + type.getCarrierType());
     }
 
-    public <T> Pointer<T> allocatePointer(Class<T> cls) {
-        long addr = allocate(U.addressSize());
-        // FIXME: we probably need a flag to signal the pointer so that we know
-        // how to proper dispose reference when calling deref() on the returned pointer.
-        return new PointerImpl<>(addr, cls);
+    public <T> Reference<T> allocateStruct(LayoutType<T> type) {
+        Class<? extends Reference<T>> implClass = NativeLibrary.getStructImplClass(type.getCarrierType());
+
+        try {
+            Reference<T> r = implClass.newInstance();
+            return r;
+        } catch (InstantiationException | IllegalAccessException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Deprecated
+    public Reference<Integer> allocateInt() {
+        return allocate(new LayoutTypeImpl<Integer>(int.class, Types.Cint32_t), 4).deref();
     }
 
     @Override
--- a/src/java.base/share/classes/java/nicl/types/BoundedPointer.java	Thu Apr 21 15:23:01 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code 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
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package java.nicl.types;
-
-import jdk.internal.misc.Unsafe;
-
-public class BoundedPointer<T> implements Pointer<T> {
-    final long min, max;
-
-    private final long addr;
-
-    public BoundedPointer(long addr, long min, long max) {
-        this.min = min;
-        this.max = max;
-        this.addr = addr;
-    }
-
-    public BoundedPointer(long addr) {
-        this(addr, addr, addr);
-    }
-
-    @Override
-    public Reference<T> deref() {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public long addr() {
-        return addr;
-    }
-
-    @Override
-    public <S> Pointer<S> cast(Class<S> cls) {
-        throw new UnsupportedOperationException();
-    }
-
-    long computeAndCheckAddr(long offset) {
-        long newAddr = addr + offset;
-        if (newAddr > max || newAddr < min) {
-            throw new IndexOutOfBoundsException();
-        }
-
-        return newAddr;
-    }
-
-    @Override
-    public BoundedPointer<T> offset(long offset) {
-        return new BoundedPointer<T>(computeAndCheckAddr(offset), min, max);
-    }
-
-    public static class BoundedIntPointer extends BoundedPointer<Integer> implements int$ptr {
-        private static final Unsafe U = Unsafe.getUnsafe();
-
-        public BoundedIntPointer(long addr, long min, long max) {
-            super(addr, min, max);
-        }
-
-        public BoundedIntPointer(long addr) {
-            this(addr, addr, addr + 4);
-        }
-
-        @Override
-        public int defref() {
-            return U.getInt(addr());
-        }
-
-        public void set(int value) {
-            U.putInt(addr(), value);
-        }
-
-        @Override
-        public BoundedIntPointer offset(long offset) {
-            return new BoundedIntPointer(computeAndCheckAddr(offset), min, max);
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/nicl/types/LayoutType.java	Fri Apr 22 15:19:32 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.nicl.types;
+
+import jdk.internal.nicl.abi.types.AbstractType;
+
+public interface LayoutType<T> {
+    Class<T> getCarrierType();
+    AbstractType getType();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/nicl/types/MemoryRegion.java	Fri Apr 22 15:19:32 2016 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.nicl.types;
+
+public interface MemoryRegion {
+    // Various checking methods which throw exceptions on errors
+    public void checkWritable();
+    public void checkAlive();
+    public void checkBounds(long offset) throws IndexOutOfBoundsException;
+
+    public long addr() throws UnsupportedOperationException;
+
+    // Getters & setters
+    public long getBits(long offset, long size, boolean isSigned);
+    public void putBits(long offset, long size, long value);
+
+    public byte getByte(long offset);
+    public void putByte(long offset, byte value);
+    public short getShort(long offset);
+    public void putShort(long offset, short value);
+    public int getInt(long offset);
+    public void putInt(long offset, int value);
+    public long getLong(long offset);
+    public void putLong(long offset, long value);
+
+    public long getAddress(long offset);
+    public void putAddress(long offset, long value);
+}
--- a/src/java.base/share/classes/java/nicl/types/Pointer.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/java/nicl/types/Pointer.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,28 +22,21 @@
  */
 package java.nicl.types;
 
+import jdk.internal.nicl.abi.types.Types;
+import jdk.internal.nicl.types.BoundedMemoryRegion;
+import jdk.internal.nicl.types.BoundedPointer;
+import jdk.internal.nicl.types.LayoutTypeImpl;
+
 /**
  * @param <T> The type of the pointee
  */
 public interface Pointer<T> {
+    public static final Pointer<Void> NULL_PTR = new BoundedPointer<Void>(new LayoutTypeImpl<Void>(void.class, Types.Cvoid), BoundedMemoryRegion.NOTHING, 0);
+
+    Pointer<T> offset(long diff);
+    <S> Pointer<S> cast(LayoutType<S> type);
+
+    long addr(PointerToken token) throws IllegalAccessException;
+
     Reference<T> deref();
-    long addr();
-    Pointer<T> offset(long diff);
-    <S> Pointer<S> cast(Class<S> cls);
-
-    default <S> Pointer<S> offset(long diff, Class<S> cls) {
-        return offset(diff).cast(cls);
-    }
-
-    public static interface int$ptr extends Pointer<Integer> {
-        int defref();
-        @Override
-        int$ptr offset(long offset);
-    }
-
-    public static interface long$ptr extends Pointer<Long> {
-        long defref();
-        @Override
-        long$ptr offset(long offset);
-    }
 }
--- a/src/java.base/share/classes/java/nicl/types/PointerImpl.java	Thu Apr 21 15:23:01 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code 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
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package java.nicl.types;
-
-import java.nicl.NativeLibrary;
-import jdk.internal.misc.Unsafe;
-
-public class PointerImpl<T> implements Pointer<T> {
-    public static final Pointer<Void> NULL_PTR = new PointerImpl<>(null, 0, null);
-
-    final Object base; // null for off-heap
-
-    private final long addr;   // offset for on-heap,
-    // absolute address for off-heap
-
-    // private Scope scope;
-
-    private final Class<T> type; // TODO: should be type descriptor eventually
-
-    public PointerImpl(Object base, long addr, Class<T> type) {
-        this.base = base;
-        this.addr = addr;
-        this.type = type;
-    }
-
-    public PointerImpl(long addr, Class<T> type) {
-        this.base = null;
-        this.addr = addr;
-        this.type = type;
-    }
-
-
-    @Override
-    public long addr() {
-        return addr;
-    }
-
-    @Override
-    public Pointer<T> offset(long diff) {
-        return new PointerImpl<>(base, addr + diff, type);
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <S> Pointer<S> cast(Class<S> cls) {
-        // TODO: ignore type tag if null
-        if (type == cls)  return (Pointer<S>)this;
-        return new PointerImpl<>(base, addr, cls);
-    }
-
-    @Override
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public Reference<T> deref() {
-        // TODO: need a complete story on object-based pointer
-        if (base != null) {
-            if (addr == 0 && type.equals(base.getClass())) {
-                return new Reference.PojoReference(base);
-            } else {
-                throw new UnsupportedOperationException();
-            }
-        }
-        if (Pointer.class.isAssignableFrom(type)) {
-            final Pointer<T> instance = this;
-            long pointee = Unsafe.getUnsafe().getAddress(addr);
-            return new Reference<T>() {
-                @Override
-                public Pointer<T> ptr() {
-                    return instance;
-                }
-
-                @Override
-                public T get() {
-                    return (T) new PointerImpl<Void>(pointee, Void.class);
-                }
-            };
-        }
-        return NativeLibrary.createStruct(type, addr);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/nicl/types/PointerToken.java	Fri Apr 22 15:19:32 2016 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.nicl.types;
+
+public interface PointerToken {
+}
--- a/src/java.base/share/classes/java/nicl/types/Reference.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/java/nicl/types/Reference.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,36 +23,10 @@
 package java.nicl.types;
 
 import java.nicl.NativeLibrary;
+import jdk.internal.misc.Unsafe;
 
 public interface Reference<T> {
     public Pointer<T> ptr();
     public T get();
-
-    public static interface int$ref {
-        public int get();
-        public void set(int value);
-        public Pointer.int$ptr ptr();
-    }
-
-    public static interface long$ref {
-        public long get();
-        public void set(long value);
-        public Pointer.long$ptr ptr();
-    }
-
-    public static class PojoReference<T> implements Reference<T> {
-        private final T instance;
-
-        public PojoReference(T instance) {
-            this.instance = instance;
-        }
-        @SuppressWarnings("unchecked")
-        public Pointer<T> ptr() {
-            return NativeLibrary.createPtr(instance, 0, (Class<T>) instance.getClass());
-        }
-
-        public T get() {
-            return instance;
-        }
-    }
+    public void set(T value);
 }
--- a/src/java.base/share/classes/java/nicl/types/Transformer.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/java/nicl/types/Transformer.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,66 +25,64 @@
 import java.io.ByteArrayOutputStream;
 import java.nicl.Scope;
 import jdk.internal.misc.Unsafe;
+import jdk.internal.nicl.abi.types.Types;
+import jdk.internal.nicl.types.BoundedMemoryRegion;
+import jdk.internal.nicl.types.BoundedPointer;
+import jdk.internal.nicl.types.LayoutTypeImpl;
+import jdk.internal.nicl.types.PointerTokenImpl;
 
 /**
  * Perform data transformation between members
  */
 public class Transformer {
-    private static final Unsafe unsafe = Unsafe.getUnsafe();
-
-    @SuppressWarnings("unchecked")
-    public static <T> Pointer<T> nullPtr() {
-        return (Pointer<T>) PointerImpl.NULL_PTR;
-    }
+    private static final Unsafe UNSAFE = Unsafe.getUnsafe();
 
     public static String toString(Pointer<Byte> cstr) {
-        long addr = cstr.addr();
         ByteArrayOutputStream os = new ByteArrayOutputStream();
-        for (byte b; (b = unsafe.getByte(addr)) != 0; addr++) {
+
+        byte b;
+        for (int i = 0; (b = cstr.offset(i).deref().get()) != 0; i++) {
             os.write(b);
         }
         return os.toString();
     }
 
-    private static long toCStr(String str, Scope scope) {
-        byte[] ar = str.getBytes();
-        long buf = scope.allocate(ar.length + 1);
-        unsafe.copyMemory(ar, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, buf, ar.length);
-        unsafe.putByte(buf + ar.length, (byte) 0);
+    private static Pointer<Byte> toCString(byte[] ar, Scope scope) {
+        Pointer<Byte> buf = scope.allocate(new LayoutTypeImpl<Byte>(byte.class, Types.Cchar), ar.length + 1);
+        long addr;
+        try {
+            addr = buf.addr(PointerTokenImpl.getToken());
+        } catch (IllegalAccessException e) {
+            throw new Error(e);
+        }
+        // FIXME: Provide a helper copy somewhere which takes pointer arguments
+        UNSAFE.copyMemory(ar, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, addr, ar.length);
+        buf.offset(ar.length).deref().set((byte)0);
+
         return buf;
     }
 
-    public static Pointer<Byte> toCStrPtr(String str, Scope scope) {
-        // FIXME with more efficient impl
-        return new PointerImpl<>(toCStr(str, scope), Byte.class);
+    public static Pointer<Byte> toCString(String str, Scope scope) {
+        return toCString(str.getBytes(), scope);
     }
 
-    @SuppressWarnings("unchecked")
+    private static <T> Pointer<T> createNativePtr(LayoutType<T> type, long base, long length) {
+        return new BoundedPointer<T>(type, new BoundedMemoryRegion(base, length), 0);
+    }
+
     public static Pointer<Pointer<Byte>> toCStrArray(String[] ar, Scope scope) {
-        System.out.println("toCStrArray: " + ar.length + " with address size " + unsafe.addressSize()
-            + ", total: " + unsafe.addressSize() * ar.length);
         if (ar.length == 0) {
             return null;
         }
         scope.startAllocation();
-        long dst = scope.allocate(unsafe.addressSize() * ar.length);
+        long size = UNSAFE.addressSize() * ar.length;
+        @SuppressWarnings("unchecked")
+        Pointer<Pointer<Byte>> ptr = scope.allocate(new LayoutTypeImpl<Pointer<Byte>>((Class)Pointer.class, Types.Cvoid_ptr), size);
         for (int i = 0; i < ar.length; i++) {
-            long ptr = dst + unsafe.addressSize() * i;
-            unsafe.putAddress(ptr, toCStr(ar[i], scope));
+            Pointer<Byte> s = toCString(ar[i], scope);
+            ptr.offset(UNSAFE.addressSize() * i).deref().set(s);
         }
         scope.endAllocation();
-        @SuppressWarnings("rawtypes")
-        Pointer<? extends Pointer<Byte>> rv = (Pointer)new PointerImpl<>(dst, Pointer.class);
-        return (Pointer<Pointer<Byte>>) rv;
-    }
-
-    public static Object derefObject(Pointer<Void> ptr) {
-        PointerImpl<Void> p = (PointerImpl<Void>) ptr;
-
-        return p.base;
-    }
-
-    public static Pointer<Void> rawObject(Object o) {
-        return new PointerImpl<Void>(o, 0, Void.class);
+        return ptr;
     }
 }
--- a/src/java.base/share/classes/jdk/internal/nicl/Civilizer.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/Civilizer.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,7 @@
         if (o == null) {
             return null;
         } else if (o instanceof String) {
-            return Transformer.toCStrPtr((String)o, scope);
+            return Transformer.toCString((String)o, scope);
         } else if (o instanceof Integer) {
             return o;
         } else if (o instanceof Pointer) {
--- a/src/java.base/share/classes/jdk/internal/nicl/FieldGenerator.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/FieldGenerator.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,9 @@
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 
 interface FieldGenerator {
-    void generateClinitCode(MethodVisitor mv);
+    default void generateClinitCode(MethodVisitor mv) {
+        // default to no clinit
+    }
 
     boolean isStatic();
 }
--- a/src/java.base/share/classes/jdk/internal/nicl/HeaderImplGenerator.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/HeaderImplGenerator.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,19 +24,23 @@
 
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 import java.io.PrintWriter;
+import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.nicl.types.PointerToken;
 import java.util.stream.Stream;
+import jdk.internal.misc.Unsafe;
+import jdk.internal.nicl.types.PointerTokenImpl;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Type;
 import jdk.internal.org.objectweb.asm.util.TraceClassVisitor;
-import jdk.internal.misc.Unsafe;
 
 class HeaderImplGenerator implements ImplGenerator {
     private static final boolean DEBUG = Boolean.getBoolean("jdk.internal.nicl.HeaderImplGenerator.DEBUG");
 
     private static final Unsafe U = Unsafe.getUnsafe();
+    private static final PointerToken TOKEN = new PointerTokenImpl();
 
     private final Class<?> hostClass;
     private final Class<?>[] interfaces;
@@ -69,8 +73,10 @@
         String[] interfaceNames = Stream.of(interfaces).map(i -> Type.getInternalName(i)).toArray(String[]::new);
         cw.visit(52, ACC_PUBLIC | ACC_SUPER, implClassName, null, "java/lang/Object", interfaceNames);
 
+        String tokenFieldName = addPointerTokenField(cw);
+
         for (MethodGenerator m : methods) {
-            m.generate(cw, constantPoolPatches, fields);
+            m.generate(cw, constantPoolPatches, fields, tokenFieldName);
         }
 
         processFields(cw);
@@ -103,9 +109,32 @@
             }
         }
 
+        try {
+            Field tokenField = implCls.getDeclaredField(tokenFieldName);
+            long offset = U.staticFieldOffset(tokenField);
+            U.putObject(implCls, offset, TOKEN);
+        } catch (NoSuchFieldException e) {
+            e.printStackTrace();
+        }
+
         return implCls;
     }
 
+    private String addPointerTokenField(ClassWriter cw) {
+        String fieldName = "TOKEN";
+
+        cw.visitField(ACC_PRIVATE | ACC_STATIC | ACC_FINAL, fieldName, Type.getDescriptor(PointerToken.class), null, null);
+
+        fields.add(new FieldGenerator() {
+                @Override
+                public boolean isStatic() {
+                    return true;
+                }
+            });
+
+        return fieldName;
+    }
+
     /**
      * Add static fields for the shuffle recipes and generate the necessary
      * <clinit> code to initialize them.
--- a/src/java.base/share/classes/jdk/internal/nicl/LdLoader.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/LdLoader.java	Fri Apr 22 15:19:32 2016 -0700
@@ -72,7 +72,7 @@
                     System.err.println("Trying " + libPath);
                 }
 
-                Pointer<Byte> cname = Transformer.toCStrPtr(libPath, scope);
+                Pointer<Byte> cname = Transformer.toCString(libPath, scope);
 
                 try {
                     Pointer<Void> handle = UnixDynamicLibraries.getInstance().dlopen(cname, RTLD_LAZY);
--- a/src/java.base/share/classes/jdk/internal/nicl/MethodGenerator.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/MethodGenerator.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,5 +25,5 @@
 import jdk.internal.org.objectweb.asm.ClassWriter;
 
 interface MethodGenerator {
-    void generate(ClassWriter cw, ConstantPoolPatches constantPoolPatches, FieldsBuilder fields);
+    void generate(ClassWriter cw, ConstantPoolPatches constantPoolPatches, FieldsBuilder fields, String tokenFieldName);
 }
--- a/src/java.base/share/classes/jdk/internal/nicl/MethodImplGenerator.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/MethodImplGenerator.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,14 +26,19 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
 import java.nicl.NativeLibrary;
+import java.nicl.Scope;
+import java.nicl.types.LayoutType;
+import java.nicl.types.Pointer;
+import java.nicl.types.PointerToken;
+import java.nicl.types.Reference;
+import java.util.Collections;
 import jdk.internal.nicl.abi.ArgumentBinding;
 import jdk.internal.nicl.abi.CallingSequence;
 import jdk.internal.nicl.abi.ShuffleRecipe;
 import jdk.internal.nicl.abi.Storage;
 import jdk.internal.nicl.abi.StorageClass;
-import java.nicl.types.Pointer;
-import java.util.Collections;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Opcodes;
@@ -58,11 +63,13 @@
 
     private final String className;
     private final String methodName;
+    private final Method method; // the interface method actually being implemented
     private final MethodHandle targetMethod;
     private final MethodType methodType;
     private final int firstUnnamedArg;
 
     private final int returnArrayVarIndex;
+    private final int scopeVarIndex;
     private final int structReturnVarIndex;
 
     private final int[] arg2localVar;
@@ -71,10 +78,12 @@
     private CallingSequence callingSequence;
     private ShuffleRecipe shuffleRecipe;
     private String shuffleRecipeFieldName;
+    private String tokenFieldName;
 
-    MethodImplGenerator(String className, String methodName, MethodHandle targetMethod, MethodType methodType, int firstUnnamedArg) {
+    MethodImplGenerator(String className, String methodName, MethodHandle targetMethod, Method m, MethodType methodType, int firstUnnamedArg) {
         this.className = className;
         this.methodName = methodName;
+        this.method = m;
         this.targetMethod = targetMethod;
         this.methodType = methodType;
         this.firstUnnamedArg = firstUnnamedArg;
@@ -82,6 +91,7 @@
         int firstFreeLocalVarIndex = NativeLibraryImpl.getParamSlots(false, methodType);
 
         this.returnArrayVarIndex = firstFreeLocalVarIndex++;
+        this.scopeVarIndex = firstFreeLocalVarIndex++;
         this.structReturnVarIndex = firstFreeLocalVarIndex++;
 
         this.arg2localVar = computeLocalVarsForArguments(methodType);
@@ -130,13 +140,15 @@
      * @param fields
      */
     @Override
-    public void generate(ClassWriter cw, ConstantPoolPatches patches, FieldsBuilder fields) {
+    public void generate(ClassWriter cw, ConstantPoolPatches patches, FieldsBuilder fields, String tokenFieldName) {
         if (DEBUG) {
             System.err.println("Generating impl for: " + methodName);
         }
         String descriptor = methodType.toMethodDescriptorString();
 
         try {
+            this.tokenFieldName = tokenFieldName;
+
             this.callingSequence = CallingSequence.make(methodType, firstUnnamedArg);
 
             this.shuffleRecipe = ShuffleRecipe.make(callingSequence);
@@ -229,7 +241,9 @@
 
         // If returning a struct, allocate it first
         if (Util.isCStruct(methodType.returnType())) {
-            allocateStruct(methodType.returnType(), structReturnVarIndex);
+            // FIXME: Wrap scope in try-with-resources style handler + call close
+            allocateScope(scopeVarIndex);
+            allocateStruct(methodType.returnType(), scopeVarIndex, structReturnVarIndex);
         }
 
         // Create and push method handle instance
@@ -335,8 +349,7 @@
         } else if (Pointer.class.isAssignableFrom(methodType.returnType())) {
             pushLongArrayValue(returnArrayVarIndex, 0);
 
-            // FIXME: Use correct class here
-            mv.visitInsn(ACONST_NULL);
+            mv.visitLdcInsn(Type.getType(NativeLibraryImpl.getPointerTypeArgument(method.getGenericReturnType())));
             mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeLibrary.class), "createPtr", "(" + Type.getDescriptor(long.class) + Type.getDescriptor(Class.class) + ")" + Type.getDescriptor(Pointer.class), false);
             mv.visitInsn(ARETURN);
         } else if (Util.isCStruct(methodType.returnType())) {
@@ -524,9 +537,9 @@
                 throw new UnsupportedOperationException("NYI: " + c.getName());
             }
         } else if (Pointer.class.isAssignableFrom(c)) {
-            // unpack
             mv.visitIntInsn(ALOAD, localVar);
-            mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeLibrary.class), "unpack", "(" + Type.getDescriptor(Pointer.class) + ")J", true);
+            mv.visitFieldInsn(GETSTATIC, className, tokenFieldName, Type.getDescriptor(PointerToken.class));
+            mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeLibrary.class), "unpack", "(" + Type.getDescriptor(Pointer.class) + Type.getDescriptor(PointerToken.class) + ")J", true);
         } else if (NativeLibraryImpl.isVectorType(c)) {
             int index = (int)(offset / 8);
             mv.visitVarInsn(ALOAD, localVar);
@@ -545,21 +558,36 @@
     }
 
     /**
+     * Allocate a scope, and store it in the local variable
+     *
+     * @param varIndex the index of the local variable where the scope will be stored
+     */
+    private void allocateScope(int scopeVarIndex) {
+        mv.visitTypeInsn(NEW, Type.getInternalName(Scope.class));
+        mv.visitInsn(DUP);
+        mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Scope.class), "<init>", "()V", false);
+        mv.visitVarInsn(ASTORE, scopeVarIndex);
+    }
+
+    /**
      * Allocate a struct, and store it in the local variable
      *
      * @param c the type of the struct
-     * @param varIndex the inedx of the local variable where the struct will be stored
+     * @param varIndex the index of the local variable where the struct will be stored
      */
-    private void allocateStruct(Class<?> c, int varIndex) {
-        if (Util.isCStruct(c)) {
-            // Allocate struct
-            mv.visitLdcInsn(Type.getType(c));
-            mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeLibrary.class), "createStruct", "(" + Type.getDescriptor(Class.class) + ")" + Type.getDescriptor(Object.class), false);
-            mv.visitTypeInsn(CHECKCAST, Type.getInternalName(c));
-            mv.visitVarInsn(ASTORE, varIndex);
-        } else {
+    private void allocateStruct(Class<?> c, int scopeVarIndex, int varIndex) {
+        if (!Util.isCStruct(c)) {
             throw new IllegalArgumentException("Unhandled type: " + c.getName());
         }
+
+        // Allocate struct
+        mv.visitLdcInsn(Type.getType(c));
+        mv.visitVarInsn(ALOAD, scopeVarIndex);
+        mv.visitLdcInsn(Type.getType(c));
+        mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeLibrary.class), "createLayout", "(" + Type.getDescriptor(Class.class) + ")" + Type.getDescriptor(LayoutType.class), false);
+        mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Scope.class), "allocateStruct", "(" + Type.getDescriptor(LayoutType.class) + ")" + Type.getDescriptor(Reference.class), false);
+        mv.visitTypeInsn(CHECKCAST, Type.getInternalName(c));
+        mv.visitVarInsn(ASTORE, varIndex);
     }
 
     private void generateRawStructLoad(Class<?> c, int slot, long offset) {
@@ -585,6 +613,8 @@
         // Push payload address
         mv.visitTypeInsn(CHECKCAST, Type.getInternalName(structClass));
         mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(structClass), "ptr", "()" + Type.getDescriptor(Pointer.class), false);
-        mv.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Pointer.class), "addr", "()J", true);
+
+        mv.visitFieldInsn(GETSTATIC, className, tokenFieldName, Type.getDescriptor(PointerToken.class));
+        mv.visitMethodInsn(INVOKEINTERFACE, Type.getInternalName(Pointer.class), "addr", "(" + Type.getDescriptor(PointerToken.class) + ")J", true);
     }
 }
--- a/src/java.base/share/classes/jdk/internal/nicl/NativeLibraryImpl.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/NativeLibraryImpl.java	Fri Apr 22 15:19:32 2016 -0700
@@ -25,7 +25,9 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
 import java.nicl.Library;
 import jdk.internal.nicl.abi.types.AbstractType;
 import jdk.internal.nicl.abi.types.FunctionType;
@@ -100,16 +102,16 @@
 
         try {
             targetMethod = MethodHandles.publicLookup().findNative2(lib, m.getName(), MethodImplGenerator.INVOKER_METHOD_TYPE);
-        } catch (NoSuchMethodException e) {
+        } catch (NoSuchMethodException|IllegalAccessException e) {
             return new UnsupportedOperationMethodImpl(m.getName(), mt, "Trying to call method " + m.getName() + " for which native lookup failed");
         }
 
         if (m.isAnnotationPresent(C.class)) {
             if (m.isAnnotationPresent(CallingConvention.class)) {
                 if (m.isVarArgs()) {
-                    return new VarargsMethodImplGenerator(implClassName, m.getName(), targetMethod, mt);
+                    return new VarargsMethodImplGenerator(implClassName, m.getName(), targetMethod, m, mt);
                 } else {
-                    return new MethodImplGenerator(implClassName, m.getName(), targetMethod, mt, mt.parameterCount());
+                    return new MethodImplGenerator(implClassName, m.getName(), targetMethod, m, mt, mt.parameterCount());
                 }
             } else {
                 // FIXME: Add support for getter method here
@@ -152,7 +154,7 @@
     public static <T> Class<? extends Reference<T>> getOrCreateStructImpl(Class<T> c)
             throws SecurityException, UnsupportedOperationException {
         if (!c.isAnnotationPresent(NativeType.class)) {
-            throw new IllegalArgumentException("Missing @NativeType annotation on class");
+            throw new IllegalArgumentException("Missing @NativeType annotation on class " + c.getName());
         }
 
         String implClassName = generateImplName(c, ImplType.STRUCT);
@@ -267,7 +269,7 @@
             return type;
         } else if (Pointer.class.isAssignableFrom(carrierType)) {
             // FIXME: Use correct pointer type here?
-            return Types.Cvoidp;
+            return Types.Cvoid_ptr;
         } else if (isVectorType(carrierType)) {
             return getVectorTypeFor(carrierType);
         } else if (Util.isCStruct(carrierType)) {
@@ -313,6 +315,45 @@
         return null;
     }
 
+    public static java.lang.reflect.Type getArrayType(java.lang.reflect.Type type) {
+        if (type instanceof Class) {
+            return ((Class<?>)type).getComponentType();
+        } else if (type instanceof GenericArrayType) {
+            return ((GenericArrayType)type).getGenericComponentType();
+        } else {
+            throw new IllegalArgumentException("Unhandled type: " + type);
+        }
+    }
+
+    public static Class<?> getPointerTypeArgument(java.lang.reflect.Type type) {
+        if (!(type instanceof ParameterizedType)) {
+            throw new IllegalArgumentException("Unhandled type: " + type + " of class " + type.getClass());
+        }
+
+        ParameterizedType pt = (ParameterizedType)type;
+        java.lang.reflect.Type[] ta = pt.getActualTypeArguments();
+        if (ta.length != 1) {
+            throw new IllegalArgumentException("Invalid array length " + ta.length + " for type: " + type);
+        }
+
+        java.lang.reflect.Type typeArg = ta[0];
+        if (typeArg.getClass() != Class.class) {
+            throw new IllegalArgumentException("Invalid generic type: " + typeArg);
+        }
+
+        return (Class<?>)typeArg;
+    }
+
+
+    public static long strlen(long addr) {
+        long i;
+
+        for (i = 0; U.getByte(addr + i) != 0; i++) {
+        }
+
+        return i;
+    }
+
     public static long createUpcallHandler(Object o, Class<?> c) throws Throwable {
         if (!isFunctionalInterface(c)) {
             throw new IllegalArgumentException("Class is not a @FunctionalInterface: " + c.getName());
--- a/src/java.base/share/classes/jdk/internal/nicl/StructImplGenerator.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/StructImplGenerator.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,15 +25,19 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 import java.io.PrintWriter;
 import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.Method;
 import java.nicl.NativeLibrary;
 import java.nicl.metadata.Array;
 import java.nicl.metadata.C;
 import java.nicl.metadata.NativeType;
 import java.nicl.metadata.Offset;
+import java.nicl.types.LayoutType;
 import java.nicl.types.Pointer;
+import java.nicl.types.PointerToken;
 import java.util.Collections;
 import java.util.stream.Stream;
+import jdk.internal.nicl.types.PointerTokenImpl;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Label;
@@ -48,8 +52,12 @@
     private static final boolean DEBUG = Boolean.getBoolean("jdk.internal.nicl.StructImplGenerator.DEBUG");
 
     private static final Unsafe U = Unsafe.getUnsafe();
+    private static final PointerToken TOKEN = new PointerTokenImpl();
     private static final Type UNSAFE = Type.getType(Unsafe.class);
 
+    private static final String UNSAFE_FIELD_NAME = "U";
+    private static final String TOKEN_FIELD_NAME = "TOKEN";
+
     private final Class<?> hostClass;
     private final Class<?> c;
     private final String implClassName;
@@ -68,7 +76,7 @@
         this.interfaces = interfaces;
     }
 
-    private void generateArrayFieldAccessors(Method m, Class<?> javaType, long offset) {
+    private void generateArrayFieldAccessors(Method m, Class<?> javaType, java.lang.reflect.Type type, long offset) {
         Array ar = m.getAnnotation(Array.class);
         if (null == ar) {
             throw new IllegalStateException("Array return type should have Array annotation");
@@ -79,11 +87,14 @@
             throw new IllegalArgumentException("Array size is too large");
         }
 
-        doArrayGetter(m, javaType, offset, (int) length, elementSize);
-        doArraySetter(m, javaType, offset, (int) length, elementSize);
+        // get the component type for the array type
+        type = NativeLibraryImpl.getArrayType(type);
+
+        doArrayGetter(m, javaType, type, offset, (int) length, elementSize);
+        doArraySetter(m, javaType, type, offset, (int) length, elementSize);
     }
 
-    private void doArrayGetter(Method m, Class<?> javaType, long offset, int length, long elementSize) {
+    private void doArrayGetter(Method m, Class<?> javaType, java.lang.reflect.Type type, long offset, int length, long elementSize) {
         final Class<?> componentType = javaType.getComponentType();
         GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC,
                 jdk.internal.org.objectweb.asm.commons.Method.getMethod(m),
@@ -96,7 +107,7 @@
         int local_offset = mg.newLocal(Type.LONG_TYPE);
         int local_unsafe = mg.newLocal(UNSAFE);
 
-        mg.getStatic(Type.getObjectType(implClassName), "U", UNSAFE);
+        mg.getStatic(Type.getObjectType(implClassName), UNSAFE_FIELD_NAME, UNSAFE);
         mg.storeLocal(local_unsafe);
 
         jdk.internal.org.objectweb.asm.commons.Method unsafe_get;
@@ -146,7 +157,7 @@
         if (componentType == Pointer.class) {
             // FIXME? getAddress for pointer?
             mg.invokeVirtual(UNSAFE, unsafe_get);
-            mg.visitInsn(ACONST_NULL);
+            mg.visitLdcInsn(Type.getType(Type.getDescriptor(NativeLibraryImpl.getPointerTypeArgument(type))));
             mg.invokeStatic(Type.getType(NativeLibrary.class),
                     new jdk.internal.org.objectweb.asm.commons.Method("createPtr",
                             "(JLjava/lang/Class;)" + Type.getDescriptor(Pointer.class)
@@ -170,7 +181,7 @@
         mg.endMethod();
     }
 
-    private void doArraySetter(Method m, Class<?> javaType, long offset, int length, long elementSize) {
+    private void doArraySetter(Method m, Class<?> javaType, java.lang.reflect.Type type, long offset, int length, long elementSize) {
         final Class<?> componentType = javaType.getComponentType();
         GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC,
                 new jdk.internal.org.objectweb.asm.commons.Method(
@@ -184,7 +195,7 @@
         int local_offset = mg.newLocal(Type.LONG_TYPE);
         int local_unsafe = mg.newLocal(UNSAFE);
 
-        mg.getStatic(Type.getObjectType(implClassName), "U", UNSAFE);
+        mg.getStatic(Type.getObjectType(implClassName), UNSAFE_FIELD_NAME, UNSAFE);
         mg.storeLocal(local_unsafe);
 
         jdk.internal.org.objectweb.asm.commons.Method unsafe_put;
@@ -230,9 +241,10 @@
         mg.arrayLoad(Type.getType(componentType));
 
         if (componentType == Pointer.class) {
+            mg.getStatic(Type.getObjectType(implClassName), TOKEN_FIELD_NAME, Type.getType(PointerToken.class));
             mg.invokeStatic(Type.getType(NativeLibrary.class),
                     new jdk.internal.org.objectweb.asm.commons.Method("unpack",
-                            "(" + Type.getDescriptor(Pointer.class) + ")J"));
+                            "(" + Type.getDescriptor(Pointer.class) + Type.getDescriptor(PointerToken.class) + ")J"));
         }
         mg.invokeVirtual(UNSAFE, unsafe_put);
 
@@ -262,7 +274,7 @@
         }
         mv.visitVarInsn(LSTORE, addrVar);
 
-        mv.visitFieldInsn(GETSTATIC, implClassName, "U", Type.getDescriptor(Unsafe.class));
+        mv.visitFieldInsn(GETSTATIC, implClassName, UNSAFE_FIELD_NAME, Type.getDescriptor(Unsafe.class));
         mv.visitVarInsn(ASTORE, unsafeVar);
 
         for (int i = 0; i < nLongs; i++) {
@@ -306,7 +318,7 @@
         }
         mv.visitVarInsn(LSTORE, addrVar);
 
-        mv.visitFieldInsn(GETSTATIC, implClassName, "U", Type.getDescriptor(Unsafe.class));
+        mv.visitFieldInsn(GETSTATIC, implClassName, UNSAFE_FIELD_NAME, Type.getDescriptor(Unsafe.class));
         mv.visitVarInsn(ASTORE, unsafeVar);
 
         for (int i = 0; i < nLongs; i++) {
@@ -328,24 +340,19 @@
             mv.visitLdcInsn(i);
             mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(javaType), "extract", "(" + Type.getDescriptor(int.class) + ")" + Type.getDescriptor(long.class), false);
 
-            /*** FIXME: Remove this when vectors are stable ***/
-            if (DEBUG) {
-                mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeLibrary.class), "putLong", "(" + Type.getDescriptor(Unsafe.class) + Type.getDescriptor(long.class) + Type.getDescriptor(long.class) + ")" + Type.getDescriptor(void.class), false);
-            } else {
-                mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Unsafe.class), "putLong", "(" + Type.getDescriptor(long.class) + Type.getDescriptor(long.class) + ")" + Type.getDescriptor(void.class), false);
-            }
+            mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Unsafe.class), "putLong", "(" + Type.getDescriptor(long.class) + Type.getDescriptor(long.class) + ")" + Type.getDescriptor(void.class), false);
         }
 
         mv.visitInsn(RETURN);
     }
 
-    private void generateGetter(MethodVisitor mv, long off, Class<?> javaType, Method m) {
+    private void generateGetter(MethodVisitor mv, long off, Class<?> javaType, java.lang.reflect.Type type, Method m) {
         if (NativeLibraryImpl.isVectorType(javaType)) {
             generateVectorGetter(mv, off, javaType);
             return;
         }
 
-        mv.visitFieldInsn(GETSTATIC, implClassName, "U", Type.getDescriptor(Unsafe.class));
+        mv.visitFieldInsn(GETSTATIC, implClassName, UNSAFE_FIELD_NAME, Type.getDescriptor(Unsafe.class));
 
         mv.visitVarInsn(ALOAD, 0);
         mv.visitFieldInsn(GETFIELD, implClassName, "payload", "J");
@@ -373,8 +380,7 @@
         } else if (javaType == Pointer.class) {
             // FIXME? getAddress for pointer?
             mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Unsafe.class), "getLong", "(J)J", false);
-            // FIXME: Use correct class here
-            mv.visitInsn(ACONST_NULL);
+            mv.visitLdcInsn(Type.getType(Type.getDescriptor(NativeLibraryImpl.getPointerTypeArgument(type))));
             mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeLibrary.class), "createPtr", "(" + Type.getDescriptor(long.class) + Type.getDescriptor(Class.class) + ")" + Type.getDescriptor(Pointer.class), false);
             mv.visitInsn(ARETURN);
         } else if (Util.isCStruct(javaType)) {
@@ -402,7 +408,7 @@
             return;
         }
 
-        mv.visitFieldInsn(GETSTATIC, implClassName, "U", Type.getDescriptor(Unsafe.class));
+        mv.visitFieldInsn(GETSTATIC, implClassName, UNSAFE_FIELD_NAME, Type.getDescriptor(Unsafe.class));
 
         mv.visitVarInsn(ALOAD, 0);
         mv.visitFieldInsn(GETFIELD, implClassName, "payload", "J");
@@ -430,7 +436,8 @@
             }
         } else if (javaType == Pointer.class) {
             mv.visitVarInsn(ALOAD, 1);
-            mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeLibrary.class), "unpack", "(" + Type.getDescriptor(Pointer.class) + ")" + Type.getDescriptor(long.class), false);
+            mv.visitFieldInsn(GETSTATIC, implClassName, TOKEN_FIELD_NAME, Type.getDescriptor(PointerToken.class));
+            mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeLibrary.class), "unpack", "(" + Type.getDescriptor(Pointer.class) + Type.getDescriptor(PointerToken.class) + ")" + Type.getDescriptor(long.class), false);
             // FIXME? Should be putAddress for pointer?
             mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Unsafe.class), "putLong", "(" + Type.getDescriptor(long.class) + Type.getDescriptor(long.class) + ")V", false);
         } else if (Util.isCStruct(javaType)) {
@@ -458,7 +465,7 @@
 
             // FIXME: Don't cheat here
             /*
-            mv.visitFieldInsn(GETSTATIC, implClassName, "U", Type.getDescriptor(Unsafe.class));
+            mv.visitFieldInsn(GETSTATIC, implClassName, UNSAFE_FIELD_NAME, Type.getDescriptor(Unsafe.class));
             mv.visitLdcInsn(size);
             mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(Unsafe.class), "allocateMemory", "(J)J", false);
             */
@@ -493,9 +500,10 @@
 
     private void generateFieldAccessors(Method m, long offset) {
         Class<?> javaType = m.getReturnType();
+        java.lang.reflect.Type type = m.getGenericReturnType();
 
         if (javaType.isArray()) {
-            generateArrayFieldAccessors(m, javaType, offset);
+            generateArrayFieldAccessors(m, javaType, type, offset);
             return;
         }
 
@@ -503,7 +511,7 @@
             MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, m.getName(), "()" + Type.getDescriptor(javaType), null, null);
             mv.visitCode();
 
-            generateGetter(mv, offset, javaType, m);
+            generateGetter(mv, offset, javaType, type, m);
 
             mv.visitMaxs(0, 0);
             mv.visitEnd();
@@ -590,7 +598,7 @@
         mv.visitVarInsn(ALOAD, 0);
         mv.visitFieldInsn(GETFIELD, implClassName, "payload", "J");
         mv.visitLdcInsn(Type.getType(Type.getDescriptor(c)));
-        mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeLibrary.class), "createPtr", "(JLjava/lang/Class;)" + Type.getDescriptor(Pointer.class), false);
+        mv.visitMethodInsn(INVOKESTATIC, Type.getInternalName(NativeLibrary.class), "createPtr", "(" + Type.getDescriptor(long.class) + Type.getDescriptor(Class.class) + ")" + Type.getDescriptor(Pointer.class), false);
         mv.visitInsn(ARETURN);
         mv.visitMaxs(0, 0);
         mv.visitEnd();
@@ -604,7 +612,8 @@
 
         cw.visit(52, ACC_PUBLIC | ACC_SUPER, implClassName, null, "java/lang/Object", interfaceNames);
 
-        cw.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, "U", Type.getDescriptor(Unsafe.class), null, null);
+        cw.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, UNSAFE_FIELD_NAME, Type.getDescriptor(Unsafe.class), null, null);
+        cw.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, TOKEN_FIELD_NAME, Type.getDescriptor(PointerToken.class), null, null);
 
         if (DEBUG) {
             System.out.println("Generating struct implementation class " + implClassName);
@@ -628,9 +637,13 @@
         U.ensureClassInitialized(implCls);
 
         try {
-            Field unsafeField = implCls.getDeclaredField("U");
-            long offset = U.staticFieldOffset(unsafeField);
-            U.putObject(implCls, offset, U);
+            Field unsafeField = implCls.getDeclaredField(UNSAFE_FIELD_NAME);
+            long unsafeOffset = U.staticFieldOffset(unsafeField);
+            U.putObject(implCls, unsafeOffset, U);
+
+            Field tokenField = implCls.getDeclaredField(TOKEN_FIELD_NAME);
+            long tokenOffset = U.staticFieldOffset(tokenField);
+            U.putObject(implCls, tokenOffset, TOKEN);
         } catch (NoSuchFieldException e) {
             e.printStackTrace();
         }
--- a/src/java.base/share/classes/jdk/internal/nicl/UnixDynamicLibraries.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/UnixDynamicLibraries.java	Fri Apr 22 15:19:32 2016 -0700
@@ -25,8 +25,14 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.nicl.NativeLibrary;
 import java.nicl.types.Pointer;
-import java.nicl.NativeLibrary;
+import java.nicl.types.PointerToken;
+import jdk.internal.nicl.abi.types.Types;
+import jdk.internal.nicl.types.BoundedPointer;
+import jdk.internal.nicl.types.BoundedMemoryRegion;
+import jdk.internal.nicl.types.LayoutTypeImpl;
+import jdk.internal.nicl.types.PointerTokenImpl;
 
 // FIXME: Grovel this?
 class UnixDynamicLibraries {
@@ -36,7 +42,7 @@
     static final long RTLD_DEFAULT = 0;
     static final long RTLD_NEXT = -1;
 
-    static final Pointer<Void> RTLD_DEFAULT_PTR = NativeLibrary.createPtr(RTLD_DEFAULT, Void.class);
+    static final Pointer<Void> RTLD_DEFAULT_PTR = BoundedPointer.createNativeVoidPointer(RTLD_DEFAULT);
 
     private static final UnixDynamicLibraries INSTANCE = new UnixDynamicLibraries();
 
@@ -48,6 +54,7 @@
     private final MethodHandle DLCLOSE;
     private final MethodHandle DLERROR;
     private final MethodHandle DLSYM;
+    private final PointerToken TOKEN = new PointerTokenImpl();
 
     private UnixDynamicLibraries() {
         try {
@@ -70,12 +77,12 @@
 
     public Pointer<Void> dlopen(Pointer<Byte> filename, int flag) {
         try {
-            long handle = (long)DLOPEN.invokeExact(filename.addr(), flag);
+            long handle = (long)DLOPEN.invokeExact(filename.addr(TOKEN), flag);
             if (handle == 0) {
                 return null;
             }
 
-            return NativeLibrary.createPtr(handle, Void.class);
+            return BoundedPointer.createNativeVoidPointer(handle);
         } catch (Throwable t) {
             t.printStackTrace();
             throw new RuntimeException("Failed to invoke dlopen");
@@ -84,12 +91,12 @@
 
     public Pointer<Void> dlsym(Pointer<Void> handle, Pointer<Byte> symbol) {
         try {
-            long addr = (long)DLSYM.invokeExact(handle.addr(), symbol.addr());
+            long addr = (long)DLSYM.invokeExact(handle.addr(TOKEN), symbol.addr(TOKEN));
             if (addr == 0) {
                 return null;
             }
 
-            return NativeLibrary.createPtr(addr, Void.class);
+            return BoundedPointer.createNativeVoidPointer(addr);
         } catch (Throwable t) {
             t.printStackTrace();
             throw new RuntimeException("Failed to invoke dlopen");
@@ -98,7 +105,7 @@
 
     public int dlclose(Pointer<Byte> handle) {
         try {
-            return (int)DLCLOSE.invokeExact(handle.addr());
+            return (int)DLCLOSE.invokeExact(handle.addr(TOKEN));
         } catch (Throwable t) {
             t.printStackTrace();
             throw new RuntimeException("Failed to invoke dlopen");
@@ -112,7 +119,7 @@
                 return null;
             }
 
-            return NativeLibrary.createPtr(addr, Byte.class);
+            return new BoundedPointer<Byte>(new LayoutTypeImpl<Byte>(byte.class, Types.Cchar), new BoundedMemoryRegion(addr, NativeLibraryImpl.strlen(addr) + 1));
         } catch (Throwable t) {
             t.printStackTrace();
             throw new RuntimeException("Failed to invoke dlopen");
--- a/src/java.base/share/classes/jdk/internal/nicl/UnixLibrary.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/UnixLibrary.java	Fri Apr 22 15:19:32 2016 -0700
@@ -28,6 +28,7 @@
 import java.nicl.types.Pointer;
 import java.nicl.types.Transformer;
 import static jdk.internal.nicl.UnixDynamicLibraries.*;
+import jdk.internal.misc.Unsafe;
 
 public class UnixLibrary implements Library {
     private static final boolean DEBUG = Boolean.getBoolean("jdk.internal.nicl.UnixLibrary.DEBUG");
@@ -44,7 +45,6 @@
                 System.err.println("Libary.lookupDefault(" + name + ")");
             }
 
-            long cnameAddr = cname.addr();
             Pointer<Void> addr = UnixDynamicLibraries.getInstance().dlsym(RTLD_DEFAULT_PTR, cname);
             if (addr == null) {
                 return null;
@@ -64,7 +64,7 @@
         }
 
         try (Scope scope = new Scope()) {
-            Pointer<Byte> cname = Transformer.toCStrPtr(name, scope);
+            Pointer<Byte> cname = Transformer.toCString(name, scope);
 
             Pointer<Void> h;
             if (handle == null) {
--- a/src/java.base/share/classes/jdk/internal/nicl/UnsupportedOperationMethodImpl.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/UnsupportedOperationMethodImpl.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,7 +57,7 @@
     }
 
     @Override
-    public void generate(ClassWriter cw, ConstantPoolPatches constantPoolPatches, FieldsBuilder fields) {
+    public void generate(ClassWriter cw, ConstantPoolPatches constantPoolPatches, FieldsBuilder fields, String tokenFieldName) {
         MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, methodType.toMethodDescriptorString(), null, null);
 
         generateUnsupportedOperationMethod(mv);
--- a/src/java.base/share/classes/jdk/internal/nicl/UpcallHandler.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/UpcallHandler.java	Fri Apr 22 15:19:32 2016 -0700
@@ -22,23 +22,28 @@
  */
 package jdk.internal.nicl;
 
-import java.nicl.types.PointerImpl;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodType;
-import java.nicl.types.BoundedPointer.BoundedIntPointer;
 import java.nicl.NativeLibrary;
+import java.nicl.Scope;
+import java.nicl.types.LayoutType;
+import java.nicl.types.Pointer;
+import java.nicl.types.PointerToken;
+import java.nicl.types.Reference;
+import java.util.ArrayList;
+import java.util.HashMap;
 import jdk.internal.nicl.abi.ArgumentBinding;
 import jdk.internal.nicl.abi.CallingSequence;
 import jdk.internal.nicl.abi.Storage;
 import jdk.internal.nicl.abi.StorageClass;
-import java.nicl.types.Pointer;
-import java.nicl.types.Pointer.int$ptr;
-import java.nicl.types.Reference;
-import java.util.ArrayList;
-import java.util.HashMap;
+import jdk.internal.nicl.abi.sysv.x64.Constants;
+import jdk.internal.nicl.abi.types.Types;
+import jdk.internal.nicl.types.BoundedMemoryRegion;
+import jdk.internal.nicl.types.BoundedPointer;
+import jdk.internal.nicl.types.LayoutTypeImpl;
+import jdk.internal.nicl.types.PointerTokenImpl;
+import jdk.internal.nicl.types.UncheckedPointer;
 import jdk.internal.org.objectweb.asm.Type;
-import jdk.internal.misc.Unsafe;
-import jdk.internal.nicl.abi.sysv.x64.Constants;
 
 public class UpcallHandler {
 
@@ -47,8 +52,7 @@
     private static final Object HANDLERS_LOCK = new Object();
     private static final HashMap<Long, UpcallHandler> NEP2HANDLER = new HashMap<>();
     private static final ArrayList<UpcallHandler> ID2HANDLER = new ArrayList<>();
-    private static final Unsafe U = Unsafe.getUnsafe();
-
+    private static final PointerToken TOKEN = new PointerTokenImpl();
     private final MethodHandle mh;
 
     private final UpcallStub stub;
@@ -89,7 +93,8 @@
             handler = ID2HANDLER.get(id);
         }
 
-        handler.invoke(integers, vectors, stack, integerReturn, vectorReturn);
+        UpcallContext context = new UpcallContext(integers, vectors, stack, integerReturn, vectorReturn);
+        handler.invoke(context);
     }
 
     private UpcallHandler(MethodHandle mh, int id) throws Throwable {
@@ -103,66 +108,70 @@
 
     static class UpcallContext {
 
-        final long integers;
-        final long vectors;
-        final long stack;
-        final long integerReturn;
-        final long vectorReturn;
+        final Pointer<Long> integers;
+        final Pointer<Long> vectors;
+        final Pointer<Long> stack;
+        final Pointer<Long> integerReturn;
+        final Pointer<Long> vectorReturn;
 
         UpcallContext(long integers, long vectors, long stack, long integerReturn, long vectorReturn) {
-            this.integers = integers;
-            this.vectors = vectors;
-            this.stack = stack;
-            this.integerReturn = integerReturn;
-            this.vectorReturn = vectorReturn;
+            LayoutType<Long> type = new LayoutTypeImpl<Long>(long.class, Types.Cint64_t);
+            this.integers = new BoundedPointer<Long>(type, new BoundedMemoryRegion(integers, Constants.MAX_INTEGER_ARGUMENT_REGISTERS * 8));
+            this.vectors = new BoundedPointer<Long>(type, new BoundedMemoryRegion(vectors, Constants.MAX_VECTOR_ARGUMENT_REGISTERS * Constants.VECTOR_REGISTER_SIZE));
+            this.stack = new UncheckedPointer<Long>(type, stack);
+            this.integerReturn = new BoundedPointer<Long>(type, new BoundedMemoryRegion(integerReturn, Constants.MAX_INTEGER_RETURN_REGISTERS * 8));
+            this.vectorReturn = new BoundedPointer<Long>(type, new BoundedMemoryRegion(vectorReturn, Constants.MAX_VECTOR_RETURN_REGISTERS * Constants.VECTOR_REGISTER_SIZE));
         }
     }
 
-    private long getArgumentAddress(UpcallContext context, Storage storage) {
+    private Pointer<Long> getArgumentAddress(UpcallContext context, Storage storage) {
         switch (storage.getStorageClass()) {
             case INTEGER_ARGUMENT_REGISTER:
-                return context.integers + 8 * storage.getStorageIndex();
+                return context.integers.offset(8 * storage.getStorageIndex());
 
             case VECTOR_ARGUMENT_REGISTER:
-                // FIXME: Don't use hard coded value here - needs to agree with what the VM produces
-                return context.vectors + Constants.VECTOR_REGISTER_SIZE * storage.getStorageIndex();
+                return context.vectors.offset(Constants.VECTOR_REGISTER_SIZE * storage.getStorageIndex());
 
             case STACK_ARGUMENT_SLOT:
-                return context.stack + 8 * storage.getStorageIndex();
+                return context.stack.offset(8 * storage.getStorageIndex());
 
             default:
                 throw new IllegalArgumentException("Unhandle storage class: " + storage.getStorageClass());
         }
     }
 
-    private Object boxArgument(ArgumentBinding binding, UpcallContext context, Reference<?>[] structs) {
+    private Object boxArgument(Scope scope, ArgumentBinding binding, UpcallContext context, Reference<?>[] structs) {
         Class<?> carrierType = binding.getMember().getCarrierType();
 
+        if (DEBUG) {
+            System.err.println("boxArgument carrier type: " + carrierType);
+        }
+
         if (carrierType.isPrimitive()) {
             switch (Type.getDescriptor(carrierType)) {
                 case "Z":
-                    return U.getByte(getArgumentAddress(context, binding.getStorage())) != 0;
+                    return getArgumentAddress(context, binding.getStorage()).cast(new LayoutTypeImpl<Boolean>(boolean.class, Types.Cbool)).deref().get();
 
                 case "B":
-                    return U.getByte(getArgumentAddress(context, binding.getStorage()));
+                    return getArgumentAddress(context, binding.getStorage()).cast(new LayoutTypeImpl<Byte>(byte.class, Types.Cbool)).deref().get();
 
                 case "S":
-                    return U.getShort(getArgumentAddress(context, binding.getStorage()));
+                    return getArgumentAddress(context, binding.getStorage()).cast(new LayoutTypeImpl<Short>(short.class, Types.Cint16_t)).deref().get();
 
                 case "C":
-                    return U.getChar(getArgumentAddress(context, binding.getStorage()));
+                    return getArgumentAddress(context, binding.getStorage()).cast(new LayoutTypeImpl<Character>(char.class, Types.Cuint16_t)).deref().get();
 
                 case "I":
-                    return U.getInt(getArgumentAddress(context, binding.getStorage()));
+                    return getArgumentAddress(context, binding.getStorage()).cast(new LayoutTypeImpl<Integer>(int.class, Types.Cint32_t)).deref().get();
 
                 case "J":
-                    return U.getLong(getArgumentAddress(context, binding.getStorage()));
+                    return getArgumentAddress(context, binding.getStorage()).cast(new LayoutTypeImpl<Long>(long.class, Types.Cint64_t)).deref().get();
 
                 case "F":
-                    return U.getFloat(getArgumentAddress(context, binding.getStorage()));
+                    return getArgumentAddress(context, binding.getStorage()).cast(new LayoutTypeImpl<Float>(float.class, Types.Cfloat)).deref().get();
 
                 case "D":
-                    return U.getDouble(getArgumentAddress(context, binding.getStorage()));
+                    return getArgumentAddress(context, binding.getStorage()).cast(new LayoutTypeImpl<Double>(double.class, Types.Cdouble)).deref().get();
 
                 default:
                     throw new UnsupportedOperationException("Unhandled type: " + carrierType.getName());
@@ -170,28 +179,22 @@
         } else if (Pointer.class.isAssignableFrom(carrierType)) {
             Storage storage = binding.getStorage();
 
-            long addr = U.getLong(getArgumentAddress(context, storage));
-
-            if (carrierType == int$ptr.class) {
-                return new BoundedIntPointer(addr);
-            } else {
-                // FIXME: Create correct pointer here
-                return new PointerImpl<>(addr, null);
-            }
+            long addr = getArgumentAddress(context, storage).deref().get();
+            return BoundedPointer.createNativeVoidPointer(addr);
         } else if (NativeLibraryImpl.isVectorType(carrierType)) {
             Storage storage = binding.getStorage();
             int n = NativeLibraryImpl.getVectorSize(carrierType) / 8;
 
             long[] bits = new long[n];
 
-            long baseAddress = getArgumentAddress(context, storage);
+            Pointer<Long> baseAddress = getArgumentAddress(context, storage);
 
             // FIXME: Work-around for now - the method is called once per stack slot,
             // so we need to return the same vector value all the time
-            baseAddress -= binding.getOffset();
+            baseAddress = baseAddress.offset(-binding.getOffset());
 
             for (int i = 0; i < n; i++) {
-                bits[i] = U.getLong(baseAddress + i * 8);
+                bits[i] = baseAddress.offset(i * 8).deref().get();
             }
 
             switch (n) {
@@ -207,7 +210,9 @@
         } else if (Util.isCStruct(carrierType)) {
             int index = binding.getMember().getArgumentIndex();
             if (structs[index] == null) {
-                structs[index] = createStruct(carrierType);
+                @SuppressWarnings("unchecked")
+                Class<? extends Reference<?>> c = (Class<? extends Reference<?>>)carrierType;
+                structs[index] = createStruct(scope, c);
             }
             if (DEBUG) {
                 System.out.println("Populating struct at arg index " + index + " at offset 0x" + Long.toHexString(binding.getOffset()));
@@ -220,32 +225,37 @@
     }
 
     private long getRawBits(UpcallContext context, Storage storage, long offset) {
+        if (DEBUG) {
+            System.err.println("getRawBits storage class: " + storage.getStorageClass());
+        }
+
         switch (storage.getStorageClass()) {
             case INTEGER_ARGUMENT_REGISTER:
-                return U.getLong(context.integers + 8 * storage.getStorageIndex() + offset);
+                return context.integers.offset(8 * storage.getStorageIndex() + offset).deref().get();
 
             case VECTOR_ARGUMENT_REGISTER:
-                return U.getLong(context.vectors + Constants.VECTOR_REGISTER_SIZE * storage.getStorageIndex() + offset);
+                return context.vectors.offset(Constants.VECTOR_REGISTER_SIZE * storage.getStorageIndex() + offset).deref().get();
 
             case STACK_ARGUMENT_SLOT:
-                return U.getLong(context.stack + 8 * storage.getStorageIndex() + offset);
+                return context.stack.offset(8 * storage.getStorageIndex() + offset).deref().get();
 
             default:
                 throw new IllegalArgumentException("Invalid storage type: " + storage);
         }
     }
 
-    private Reference<?> createStruct(Class<?> c) {
-        @SuppressWarnings("unchecked")
-        Class<? extends Reference<?>> c2 = (Class<? extends Reference<?>>) c;
-        return NativeLibrary.createStruct(c2);
+    private Reference<?> createStruct(Scope scope, Class<? extends Reference<?>> c) {
+        @SuppressWarnings({"rawtypes", "unchecked"})
+        Reference<?> r = scope.allocateStruct(new LayoutTypeImpl(c, Types.TEMPORARY_STRUCT_TYPE));
+        return r;
     }
 
     private void populateStruct(Reference<?> struct, UpcallContext context, ArgumentBinding binding) {
         Storage storage = binding.getStorage();
         int n = (int) (storage.getSize() / 8);
 
-        Pointer<?> p = struct.ptr();
+        // FIXME: needs to handle 32-bit here
+        Pointer<Long> p = struct.ptr().cast(new LayoutTypeImpl<Long>(long.class, Types.Cint64_t));
 
         for (int i = 0; i < n; i++) {
             long offs = i * 8;
@@ -255,11 +265,11 @@
                 System.out.println("getRawBits binding " + binding + " returned 0x" + Long.toHexString(bits));
             }
 
-            U.putLong(p.addr() + binding.getOffset() + offs, bits);
+            p.offset(binding.getOffset() + offs).deref().set(bits);
         }
     }
 
-    private Object[] boxArguments(UpcallContext context, CallingSequence callingSequence) {
+    private Object[] boxArguments(Scope scope, UpcallContext context, CallingSequence callingSequence) {
         Object[] args = new Object[mh.type().parameterCount()];
 
         Reference<?>[] structs = new Reference<?>[mh.type().parameterCount()];
@@ -273,14 +283,14 @@
                 .stream()
                 .filter((binding) -> binding != null)
                 .forEach((binding) -> {
-                    args[binding.getMember().getArgumentIndex()] = boxArgument(binding, context, structs);
+                    args[binding.getMember().getArgumentIndex()] = boxArgument(scope, binding, context, structs);
                 });
 
         callingSequence
                 .getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER)
                 .stream()
                 .forEach((binding) -> {
-                    args[binding.getMember().getArgumentIndex()] = boxArgument(binding, context, structs);
+                    args[binding.getMember().getArgumentIndex()] = boxArgument(scope, binding, context, structs);
                 });
 
         callingSequence
@@ -288,20 +298,20 @@
                 .stream()
                 .skip(callingSequence.returnsInMemory() ? 1 : 0)
                 .forEach((binding) -> {
-                    args[binding.getMember().getArgumentIndex()] = boxArgument(binding, context, structs);
+                    args[binding.getMember().getArgumentIndex()] = boxArgument(scope, binding, context, structs);
                 });
 
         return args;
     }
 
     private void copyReturn(UpcallContext context, Storage storage, long bits) {
-        U.putLong(context.integerReturn + 8 * storage.getStorageIndex(), bits);
+        context.integerReturn.offset(8 * storage.getStorageIndex()).deref().set(bits);
     }
 
     private void copyReturn(UpcallContext context, Storage storage, long[] bits) {
         // FIXME: Remove hard coded value here
         for (int i = 0; i < bits.length; i++) {
-            U.putLong(context.vectorReturn + Constants.VECTOR_REGISTER_SIZE * storage.getStorageIndex() + i * 8, bits[i]);
+            context.vectorReturn.offset(Constants.VECTOR_REGISTER_SIZE * storage.getStorageIndex() + i * 8).deref().set(bits[i]);
         }
     }
 
@@ -313,31 +323,41 @@
             System.out.println(binding);
         }
 
-        long sourceAddr = struct.ptr().addr();
+        // FIXME: handle 32-bit here
+        Pointer<Long> srcPtr = struct.ptr().cast(new LayoutTypeImpl<Long>(long.class, Types.Cint64_t));
+        long bits;
 
         if (returnsInMemory) {
-            long targetAddr = U.getLong(context.integers);
-            long size = Util.sizeof(c);
+            long targetAddr = context.integers.deref().get();
+
+            // first integer register contains pointer to caller allocated struct
+            Pointer<Long> structAddrPtr = context.integers.offset(0);
+
+            // FIXME: 32-bit support goes here
+            long size = Util.alignUp(Util.sizeof(c), 8);
+            Pointer<Long> dstPtr = new BoundedPointer<Long>(new LayoutTypeImpl<Long>(long.class, Types.Cint64_t), new BoundedMemoryRegion(structAddrPtr.deref().get(), size));
 
             for (long offs = 0; offs < size; offs += 8) {
-                U.putLong(targetAddr + offs, U.getLong(sourceAddr + offs));
+                bits = srcPtr.offset(offs).deref().get();
+                dstPtr.offset(offs).deref().set(bits);
             }
 
-            U.putLong(context.integerReturn, targetAddr);
+            context.integerReturn.deref().set(targetAddr);
         } else {
             long baseOffset = binding.getOffset();
             Storage storage = binding.getStorage();
 
             switch (storage.getStorageClass()) {
                 case INTEGER_RETURN_REGISTER:
-                    U.putLong(context.integerReturn + 8 * storage.getStorageIndex(), U.getLong(sourceAddr + baseOffset));
+                    bits = struct.ptr().offset(baseOffset).cast(new LayoutTypeImpl<Long>(long.class, Types.Cint64_t)).deref().get();
+                    context.integerReturn.offset(8 * storage.getStorageIndex()).deref().set(bits);
                     break;
 
                 case VECTOR_RETURN_REGISTER:
                     // FIXME: Candidate for U.copyMemory
                     for (long offset = 0; offset < storage.getSize(); offset += 8) {
-                        long bits = U.getLong(sourceAddr + baseOffset + offset);
-                        U.putLong(context.vectorReturn + Constants.VECTOR_REGISTER_SIZE * storage.getStorageIndex() + offset, bits);
+                        bits = struct.ptr().offset(baseOffset + offset).cast(new LayoutTypeImpl<Long>(long.class, Types.Cint64_t)).deref().get();
+                        context.vectorReturn.offset(Constants.VECTOR_REGISTER_SIZE * storage.getStorageIndex() + offset).deref().set(bits);
                     }
                     break;
 
@@ -392,8 +412,14 @@
             }
         } else if (Pointer.class.isAssignableFrom(c)) {
             Storage storage = binding.getStorage();
-            Pointer<?> p = (Pointer<?>) o;
-            U.putLong(context.integerReturn + 8 * storage.getStorageIndex(), p.addr());
+            long addr;
+            try {
+                addr = NativeLibrary.unpack((Pointer<?>) o, TOKEN);
+            } catch (IllegalAccessException e) {
+                throw new RuntimeException(e);
+            }
+
+            context.integerReturn.offset(8 * storage.getStorageIndex()).deref().set(addr);
         } else if (NativeLibraryImpl.isVectorType(c)) {
             Storage storage = binding.getStorage();
             int n = (int) (storage.getSize() / 8);
@@ -424,25 +450,24 @@
 
             copyReturn(context, storage, bits);
         } else if (Util.isCStruct(c)) {
-            copyStructReturn(context, binding, c, (Reference<?>) o);
+            Reference<?> r = (Reference<?>) o;
+            copyStructReturn(context, binding, c, r);
         } else {
             throw new UnsupportedOperationException("Unhandled type: " + c.getName());
         }
     }
 
-    public void invoke(long integers, long vectors, long stack, long integerReturn, long vectorReturn) {
-        UpcallContext context = new UpcallContext(integers, vectors, stack, integerReturn, vectorReturn);
-
+    private void invoke(UpcallContext context) {
         // FIXME: Handle varargs upcalls here
         CallingSequence callingSequence = CallingSequence.make(mh.type());
 
         if (DEBUG) {
-            System.out.println("=== UpcallHandler.invoke ===");
-            System.out.println(callingSequence.asString());
+            System.err.println("=== UpcallHandler.invoke ===");
+            System.err.println(callingSequence.asString());
         }
 
-        try {
-            Object[] args = boxArguments(context, callingSequence);
+        try (Scope scope = new Scope()) {
+            Object[] args = boxArguments(scope, context, callingSequence);
 
             Object o = mh.asSpreader(Object[].class, args.length).invoke(args);
 
--- a/src/java.base/share/classes/jdk/internal/nicl/Util.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/Util.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 import java.nicl.metadata.C;
 import java.nicl.metadata.CallingConvention;
 import java.nicl.metadata.NativeType;
+import jdk.internal.org.objectweb.asm.Type;
 
 public class Util {
     private Util() {
@@ -55,7 +56,35 @@
         return clz.isAnnotationPresent(CallingConvention.class);
     }
 
+    private static long sizeofPrimitive(Class<?> cls) {
+        switch (Type.getDescriptor(cls)) {
+        case "B":
+        case "Z":
+            return 1;
+
+        case "S":
+        case "C":
+            return 2;
+
+        case "I":
+        case "F":
+            return 4;
+
+        case "J":
+        case "D":
+            return 8;
+
+        default:
+            throw new IllegalArgumentException("Unhandled type: " + cls);
+        }
+    }
+
     public static long sizeof(Class<?> clz) {
+        // FIXME: treat java primitives as corresponding native types
+        if (clz.isPrimitive()) {
+            return sizeofPrimitive(clz);
+        }
+
         if (! isCType(clz)) {
             throw new IllegalArgumentException();
         }
--- a/src/java.base/share/classes/jdk/internal/nicl/VarargsInvoker.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/VarargsInvoker.java	Fri Apr 22 15:19:32 2016 -0700
@@ -25,6 +25,7 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
 import java.nicl.NativeLibrary;
 import java.nicl.types.Pointer;
 import java.util.ArrayList;
@@ -40,6 +41,7 @@
     static {
         BRIDGE_METHOD_TYPE = MethodType.methodType(
                 Object.class,       // <return type>
+                Method.class,       // method
                 MethodHandle.class, // targetMethod
                 int.class,          // nNamedArgs
                 MethodType.class,   // methodType
@@ -66,7 +68,7 @@
         }
     }
 
-    public Object executeVarargsCall(MethodHandle targetMethod, int nNamedArgs, MethodType mt, Object[] args) throws RuntimeException {
+    public Object executeVarargsCall(Method method, MethodHandle targetMethod, int nNamedArgs, MethodType mt, Object[] args) throws RuntimeException {
         ArrayList<Class<?>> types = new ArrayList<>();
 
         for (int i = 0; i < mt.parameterCount() - 1; i++) {
@@ -86,7 +88,7 @@
         MethodType dynamicTypes = MethodType.methodType(mt.returnType(), types.toArray(new Class<?>[0]));
 
         MethodGenerator generators[] = new MethodGenerator[]{
-            new MethodImplGenerator(className, methodName, targetMethod, dynamicTypes, mt.parameterCount())
+            new MethodImplGenerator(className, methodName, targetMethod, method, dynamicTypes, mt.parameterCount())
         };
 
         Class<?> c = new HeaderImplGenerator(NativeLibrary.class, className, generators, new Class<?>[0]).generate();
--- a/src/java.base/share/classes/jdk/internal/nicl/VarargsMethodImplGenerator.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/VarargsMethodImplGenerator.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.*;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.Type;
@@ -34,18 +35,20 @@
     private final String methodName;
     private final MethodHandle targetMethod;
     private final MethodType methodType;
+    private final Method method;
 
     private MethodVisitor mv;
 
-    VarargsMethodImplGenerator(String className, String methodName, MethodHandle targetMethod, MethodType methodType) {
+    VarargsMethodImplGenerator(String className, String methodName, MethodHandle targetMethod, Method method, MethodType methodType) {
         this.className = className;
         this.methodName = methodName;
         this.targetMethod = targetMethod;
+        this.method = method;
         this.methodType = methodType;
     }
 
     @Override
-    public void generate(ClassWriter cw, ConstantPoolPatches patches, FieldsBuilder fields) {
+    public void generate(ClassWriter cw, ConstantPoolPatches patches, FieldsBuilder fields, String tokenFieldName) {
         String descriptor = methodType.toMethodDescriptorString();
 
         this.mv = cw.visitMethod(ACC_PUBLIC | ACC_VARARGS, methodName, descriptor, null, null);
@@ -54,13 +57,14 @@
             mv.visitCode();
 
             VarargsInvoker invoker = new VarargsInvoker();
-            MethodHandle boundTargetMethod = VarargsInvoker.BRIDGE_METHOD_HANDLE.bindTo(invoker);
+            MethodHandle boundTargetMethod = VarargsInvoker.BRIDGE_METHOD_HANDLE.bindTo(invoker).bindTo(method);
 
             // insert placeholder in CP and remember the patch
             String targetMHPlaceholder = patches.make(targetMethod);
             String varargsBridgeMHPlaceholder = patches.make(boundTargetMethod);
 
-            generateMethodBody(varargsBridgeMHPlaceholder, targetMHPlaceholder);
+
+            generateMethodBody(boundTargetMethod.type(), varargsBridgeMHPlaceholder, targetMHPlaceholder);
         } catch (Exception e) {
             System.err.println("WARNING: Failed to generate varargs method impl for method " + methodName + " in class " + className + ": " + e.getMessage());
             e.printStackTrace();
@@ -210,7 +214,7 @@
         mv.visitTypeInsn(CHECKCAST, Type.getInternalName(MethodHandle.class));
     }
 
-    private void generateMethodBody(String varargsBridgeMHPlaceholder, String targetMHPlaceholder) {
+    private void generateMethodBody(MethodType mt, String varargsBridgeMHPlaceholder, String targetMHPlaceholder) {
         pushMethodHandle(varargsBridgeMHPlaceholder);
 
         pushMethodHandle(targetMHPlaceholder);
@@ -222,7 +226,7 @@
 
         collectArguments();
 
-        mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(MethodHandle.class), "invoke", VarargsInvoker.BRIDGE_METHOD_TYPE.toMethodDescriptorString(), false);
+        mv.visitMethodInsn(INVOKEVIRTUAL, Type.getInternalName(MethodHandle.class), "invoke", mt.toMethodDescriptorString(), false);
 
         unboxReturnValue();
     }
--- a/src/java.base/share/classes/jdk/internal/nicl/abi/types/Types.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/nicl/abi/types/Types.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,6 @@
     private static final Map<String,AbstractType> KNOWN_TYPES = new HashMap<>();
 
     public static final AbstractScalarType Cvoid = new IntegerType("void", 0, false);
-    public static final AbstractScalarType Cvoidp = new PointerType(Cvoid);
 
     public static final AbstractScalarType Cconst_char = new IntegerType("const char", 1, true);
 
@@ -78,6 +77,13 @@
     public static final AbstractScalarType C__M256 = new VectorType("__m256", 32);
     public static final AbstractScalarType C__M512 = new VectorType("__m512", 64);
 
+    // Some helpful/common pointer types
+    public static final AbstractScalarType Cvoid_ptr = Cvoid.getPointerType();
+    public static final AbstractScalarType Cchar_ptr = Cchar.getPointerType();
+
+
+    public static final StructType TEMPORARY_STRUCT_TYPE = new StructType("__temp__", new AggregateTypeMember[0]);
+
     public static void add(AbstractType type) {
         KNOWN_TYPES.put(type.getName(), type);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/nicl/types/BoundedMemoryRegion.java	Fri Apr 22 15:19:32 2016 -0700
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.nicl.types;
+
+import java.nicl.types.MemoryRegion;
+import jdk.internal.misc.Unsafe;
+
+public class BoundedMemoryRegion implements MemoryRegion {
+    public static final BoundedMemoryRegion EVERYTHING = new BoundedMemoryRegion(0, Long.MAX_VALUE); // FIXME: Not actually MAX_VALUE
+    public static final BoundedMemoryRegion NOTHING = new BoundedMemoryRegion(0, 0);
+    private static final Unsafe U = Unsafe.getUnsafe();
+
+    private final Object base;
+    private final long min;
+    private final long length;
+
+    public BoundedMemoryRegion(long addr, long length) {
+        this(null, addr, length);
+    }
+
+    public BoundedMemoryRegion(Object base, long min, long length) {
+        this.base = base;
+        this.min = min;
+        this.length = length;
+    }
+
+    @Override
+    public long addr() throws UnsupportedOperationException {
+        if (base != null) {
+            throw new UnsupportedOperationException();
+        }
+
+        return min;
+    }
+
+    @Override
+    public void checkWritable() {
+    }
+
+    @Override
+    public void checkAlive() {
+    }
+
+    @Override
+    public void checkBounds(long offset) {
+        if (offset < 0 || offset >= length) {
+            throw new IndexOutOfBoundsException("offset=0x" + Long.toHexString(offset) + " length=0x" + Long.toHexString(length));
+        }
+    }
+
+    private void checkRange(long offset, long length) {
+        checkBounds(offset);
+        checkBounds(offset + length - 1);
+    }
+
+    @Override
+    public long getBits(long offset, long size, boolean isSigned) {
+        checkRange(offset, size);
+
+        if (size < 0 || size > Integer.MAX_VALUE) {
+            throw new IllegalArgumentException("Invalid size: " + size);
+        }
+
+        long bits;
+
+        switch ((int)size) {
+        case 1:
+            bits = U.getByte(base, this.min + offset);
+            return isSigned ? bits : Byte.toUnsignedLong((byte)bits);
+
+        case 2:
+            bits = U.getShort(base, this.min + offset);
+            return isSigned ? bits : Short.toUnsignedLong((short)bits);
+
+        case 4:
+            bits = U.getInt(base, this.min + offset);
+            return isSigned ? bits : Integer.toUnsignedLong((int)bits);
+
+        case 8:
+            return U.getLong(base, this.min + offset);
+ 
+        default:
+            throw new IllegalArgumentException("Invalid size: " + size);
+        }
+    }
+
+    public long getBits(long offset, long size) {
+        return getBits(offset, size, true);
+    }
+
+    @Override
+    public void putBits(long offset, long size, long value) {
+        checkRange(offset, size);
+
+        if (size < 0 || size > Integer.MAX_VALUE) {
+            throw new IllegalArgumentException("Invalid size: " + size);
+        }
+
+        switch ((int)size) {
+        case 1:
+            U.putByte(base, this.min + offset, (byte)value);
+            break;
+
+        case 2:
+            U.putShort(base, this.min + offset, (short)value);
+            break;
+
+        case 4:
+            U.putInt(base, this.min + offset, (int)value);
+            break;
+
+        case 8:
+            U.putLong(base, this.min + offset, value);
+            break;
+ 
+        default:
+            throw new IllegalArgumentException("Invalid size: " + size);
+        }
+    }
+
+
+    @Override
+    public byte getByte(long offset) {
+        return (byte)getBits(offset, 1);
+    }
+
+    @Override
+    public void putByte(long offset, byte value) {
+        putBits(offset, 1, value);
+    }
+
+    @Override
+    public short getShort(long offset) {
+        return (short)getBits(offset, 2);
+    }
+
+    @Override
+    public void putShort(long offset, short value) {
+        putBits(offset, 2, value);
+    }
+
+    @Override
+    public int getInt(long offset) {
+        return (int)getBits(offset, 4);
+    }
+
+    @Override
+    public void putInt(long offset, int value) {
+        putBits(offset, 4, value);
+    }
+
+    @Override
+    public long getLong(long offset) {
+        return getBits(offset, 8);
+    }
+
+    @Override
+    public void putLong(long offset, long value) {
+        putBits(offset, 8, value);
+    }
+
+    @Override
+    public long getAddress(long offset) {
+        if (base != null) {
+            throw new UnsupportedOperationException();
+        }
+        checkRange(offset, U.addressSize());
+        return U.getAddress(this.min + offset);
+    }
+
+    @Override
+    public void putAddress(long offset, long value) {
+        if (base != null) {
+            throw new UnsupportedOperationException();
+        }
+        checkRange(offset, U.addressSize());
+        U.putAddress(this.min + offset, value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/nicl/types/BoundedPointer.java	Fri Apr 22 15:19:32 2016 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.nicl.types;
+
+import java.nicl.types.LayoutType;
+import java.nicl.types.MemoryRegion;
+import java.nicl.types.Pointer;
+import java.nicl.types.PointerToken;
+import java.nicl.types.Reference;
+import jdk.internal.misc.Unsafe;
+import jdk.internal.nicl.abi.types.Types;
+
+public class BoundedPointer<T> implements Pointer<T> {
+    final MemoryRegion region;
+    final long offset;
+
+    final LayoutType<T> type;
+
+    public BoundedPointer(LayoutType<T> type, MemoryRegion region, long offset) {
+        this.region = region;
+        this.offset = offset;
+        this.type = type;
+    }
+
+    public BoundedPointer(LayoutType<T> type, MemoryRegion region) {
+        this(type, region, 0);
+    }
+
+    public static BoundedPointer<Void> createNativeVoidPointer(long offset) {
+        return new BoundedPointer<Void>(new LayoutTypeImpl<Void>(void.class, Types.Cvoid), BoundedMemoryRegion.EVERYTHING, offset);
+    }
+
+    @Override
+    public Reference<T> deref() {
+        // check bounds here
+        return new ReferenceImpl<T>(type, region, offset);
+    }
+
+    @Override
+    public long addr(PointerToken token) throws UnsupportedOperationException, IllegalAccessException {
+        if (token == null) {
+            throw new IllegalAccessException();
+        }
+        return region.addr() + offset;
+    }
+
+    @Override
+    public <S> Pointer<S> cast(LayoutType<S> type) {
+        return new BoundedPointer<S>(type, region, offset);
+    }
+
+    @Override
+    public BoundedPointer<T> offset(long offset) {
+        long newOffset = this.offset + offset;
+        region.checkBounds(newOffset); // eager check for sanity, at least for now
+        return new BoundedPointer<T>(type, region, newOffset);
+    }
+
+    @Override
+    public String toString() {
+        return "{ BoundedPointer<" + type.getCarrierType() + "> }";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/nicl/types/LayoutTypeImpl.java	Fri Apr 22 15:19:32 2016 -0700
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.nicl.types;
+
+import java.nicl.types.LayoutType;
+import java.nicl.types.Pointer;
+import jdk.internal.nicl.Util;
+import jdk.internal.nicl.abi.types.AbstractType;
+import jdk.internal.nicl.abi.types.Types;
+import jdk.internal.org.objectweb.asm.Type;
+
+public class LayoutTypeImpl<T> implements LayoutType<T> {
+    private final Class<T> carrierType;
+    private final AbstractType type;
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public static <S> LayoutTypeImpl<S> create(Class<S> c) {
+        if (c.isPrimitive()) {
+            switch (Type.getDescriptor(c)) {
+            case "V":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Void>(void.class, Types.Cvoid);
+
+            case "Z":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Boolean>(boolean.class, Types.Cbool);
+
+            case "B":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Byte>(byte.class, Types.Cchar);
+
+            case "S":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Short>(short.class, Types.Cint16_t);
+
+            case "C":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Character>(char.class, Types.Cuint16_t);
+
+            case "I":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Integer>(int.class, Types.Cint32_t);
+
+            case "J":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Long>(long.class, Types.Cint64_t);
+
+            case "F":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Float>(float.class, Types.Cfloat);
+
+            case "D":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Double>(double.class, Types.Cdouble);
+
+            default:
+                throw new UnsupportedOperationException("NYI: " + c.getName());
+            }
+        } else if (Pointer.class.isAssignableFrom(c)) {
+            return (LayoutTypeImpl<S>) new LayoutTypeImpl<Pointer>(Pointer.class, Types.Cvoid_ptr);
+        } else if (Util.isCStruct(c)) {
+            return new LayoutTypeImpl<>(c, Types.TEMPORARY_STRUCT_TYPE);
+        } else {
+            switch (c.getName()) {
+            case "java.lang.Void":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Void>(void.class, Types.Cvoid);
+
+            case "java.lang.Boolean":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Boolean>(boolean.class, Types.Cbool);
+
+            case "java.lang.Byte":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Byte>(byte.class, Types.Cchar);
+
+            case "java.lang.Short":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Short>(short.class, Types.Cint16_t);
+
+            case "java.lang.Character":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Character>(char.class, Types.Cuint16_t);
+
+            case "java.lang.Integer":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Integer>(int.class, Types.Cint32_t);
+
+            case "java.lang.Long":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Long>(long.class, Types.Cint64_t);
+
+            case "java.lang.Float":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Float>(float.class, Types.Cfloat);
+
+            case "java.lang.Double":
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Double>(double.class, Types.Cdouble);
+
+            default:
+                return (LayoutTypeImpl<S>) new LayoutTypeImpl<Void>(void.class, Types.Cvoid);
+            }
+        }
+    }
+
+    public LayoutTypeImpl(Class<T> carrierType, AbstractType type) {
+        this.carrierType = carrierType;
+        this.type = type;
+    }
+
+    public Class<T> getCarrierType() {
+        return carrierType;
+    }
+
+    public AbstractType getType() {
+        return type;
+    }
+
+    @Override
+    public String toString() {
+        return "{ LayoutTypeImpl carrierType=" + carrierType.getName() + " type=" + type + "}";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/nicl/types/PointerTokenImpl.java	Fri Apr 22 15:19:32 2016 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.nicl.types;
+
+import java.nicl.types.PointerToken;
+
+public class PointerTokenImpl implements PointerToken {
+    private static PointerToken TOKEN = new PointerTokenImpl();
+
+    public static PointerToken getToken() {
+        return TOKEN;
+    }
+
+    public PointerTokenImpl() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/nicl/types/ReferenceImpl.java	Fri Apr 22 15:19:32 2016 -0700
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.nicl.types;
+
+import java.nicl.types.LayoutType;
+import java.nicl.types.MemoryRegion;
+import java.nicl.types.Pointer;
+import java.nicl.types.Reference;
+import jdk.internal.nicl.abi.types.AbstractType;
+import jdk.internal.nicl.abi.types.IntegerType;
+import jdk.internal.nicl.abi.types.Types;
+import jdk.internal.org.objectweb.asm.Type;
+
+public class ReferenceImpl<T> implements Reference<T> {
+    final MemoryRegion region;
+    final long offset;
+
+    final LayoutType<T> type;
+
+    ReferenceImpl(LayoutType<T> type, MemoryRegion region, long offset) {
+        this.region = region;
+        this.offset = offset;
+        this.type = type;
+    }
+
+    public Pointer<T> ptr() {
+        return new BoundedPointer<T>(type, region, offset);
+    }
+
+    private long getLongBits() {
+        boolean isSigned = true;
+        AbstractType t = type.getType();
+        if (t instanceof IntegerType) {
+            isSigned = ((IntegerType)t).isSigned();
+        }
+        return region.getBits(offset, t.getSize(), isSigned);
+    }
+
+    private void putLongBits(long value) {
+        AbstractType t = type.getType();
+        region.putBits(offset, t.getSize(), value);
+    }
+
+    @SuppressWarnings("unchecked")
+    public T get() {
+        Class<?> c = type.getCarrierType();
+        if (c.isPrimitive()) {
+            switch (Type.getDescriptor(c)) {
+            case "Z":
+                return (T)new Boolean((byte)getLongBits() != 0);
+            case "B":
+                return (T)new Byte((byte)getLongBits());
+            case "C":
+                return (T)new Character((char)getLongBits());
+            case "S":
+                return (T)new Short((short)getLongBits());
+            case "I":
+                return (T)new Integer((int)getLongBits());
+            case "J":
+                return (T)new Long(getLongBits());
+            case "F":
+                return (T)new Float(Float.intBitsToFloat((int)getLongBits()));
+            case "D":
+                return (T)new Double(Double.longBitsToDouble(getLongBits()));
+            case "V":
+                throw new RuntimeException("void type");
+            default:
+                throw new UnsupportedOperationException("Unhandled type: " + c.getName());
+            }
+        } else if (Pointer.class.isAssignableFrom(type.getCarrierType())) {
+            return (T)new Long(getLongBits());
+        } else  {
+            // FIXME: Handle vectors, structs here
+            throw new UnsupportedOperationException("Unhandled type: " + type.getCarrierType());
+        }
+    }
+
+    public void set(T value) {
+        Class<?> c = type.getCarrierType();
+        if (c.isPrimitive()) {
+            switch (Type.getDescriptor(c)) {
+            case "Z":
+                putLongBits((boolean)value ? 1 : 0);
+                break;
+            case "B":
+                putLongBits((byte)value);
+                break;
+            case "C":
+                putLongBits((char)value);
+                break;
+            case "S":
+                putLongBits((short)value);
+                break;
+            case "I":
+                putLongBits((int)value);
+                break;
+            case "J":
+                putLongBits((long)value);
+                break;
+            case "F":
+                putLongBits(Float.floatToRawIntBits((float)value));
+                break;
+            case "D":
+                putLongBits(Double.doubleToRawLongBits((double)value));
+                break;
+            case "V":
+                throw new RuntimeException("void type");
+            default:
+                throw new UnsupportedOperationException("Unhandled type: " + c.getName());
+            }
+        } else {
+            // FIXME: Handle vectors, structs here
+            throw new UnsupportedOperationException("Unhandled type: " + type.getCarrierType());
+        }
+    }
+
+    public String toString() {
+        return "{ ReferenceImpl type=" + type + " }";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/nicl/types/UncheckedPointer.java	Fri Apr 22 15:19:32 2016 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.nicl.types;
+
+import java.nicl.types.LayoutType;
+import java.nicl.types.MemoryRegion;
+import java.nicl.types.Pointer;
+import java.nicl.types.PointerToken;
+import java.nicl.types.Reference;
+import jdk.internal.misc.Unsafe;
+import jdk.internal.nicl.abi.types.Types;
+
+public class UncheckedPointer<T> extends BoundedPointer<T> {
+    public UncheckedPointer(LayoutType<T> type, long offset) {
+        super(type, BoundedMemoryRegion.EVERYTHING, offset);
+    }
+
+    public UncheckedPointer(LayoutType<T> type) {
+        this(type, 0);
+    }
+
+    @Override
+    public <S> Pointer<S> cast(LayoutType<S> type) {
+        return new UncheckedPointer<S>(type, offset);
+    }
+}
--- a/src/java.base/share/classes/jdk/internal/panama/CodeSnippet.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/java.base/share/classes/jdk/internal/panama/CodeSnippet.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,3 +1,25 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
 package jdk.internal.panama;
 
 import jdk.internal.ref.Cleaner;
@@ -46,7 +68,11 @@
             if (DEBUG) {
                 System.out.printf("%s: Address: 0x%x\n", name, addr);
             }
-            mh = LOOKUP.findNative(name, addr, rawMT, code);
+            try {
+                mh = LOOKUP.findNative(name, addr, rawMT, code);
+            } catch (IllegalAccessException | NoSuchMethodException e) {
+                throw new Error(e);
+            }
 
             if (vectorReturn) {
                 // findConstructor() + collectArguments():
--- a/src/jdk.jextract/share/classes/com/sun/tools/jextract/JType.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/jdk.jextract/share/classes/com/sun/tools/jextract/JType.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -76,8 +76,8 @@
                     return JType.Void;
             }
         }
-		if (cls == Object.class) {
-			return JType.Object;
+        if (cls == Object.class) {
+            return JType.Object;
         } else if (cls == Long2.class) {
             return JType.Long2;
         } else if (cls == Long4.class) {
--- a/src/jdk.jextract/share/classes/com/sun/tools/jextract/PointerType.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/jdk.jextract/share/classes/com/sun/tools/jextract/PointerType.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,20 +33,12 @@
 
     @Override
     public String getDescriptor() {
-        if (referenced == JType.Int) {
-            return JType.of(Pointer.int$ptr.class).getDescriptor();
-        } else if (referenced == JType.Long) {
-            return JType.of(Pointer.long$ptr.class).getDescriptor();
-        }
-
         return JType.of(Pointer.class).getDescriptor();
     }
 
     public String getSignature() {
-        if (referenced == JType.Int) {
-            return JType.of(Pointer.int$ptr.class).getDescriptor();
-        } else if (referenced == JType.Long) {
-            return JType.of(Pointer.long$ptr.class).getDescriptor();
+        if (referenced == JType.Int || referenced == JType.Long) {
+            return JType.of(Pointer.class).getDescriptor();
         }
 
         StringBuilder sb = new StringBuilder();
--- a/src/jdk.jextract/share/classes/com/sun/tools/jextract/ReferenceType.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/src/jdk.jextract/share/classes/com/sun/tools/jextract/ReferenceType.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,21 +33,13 @@
 
     @Override
     public String getDescriptor() {
-        if (referenced == JType.Int) {
-            return JType.of(Reference.int$ref.class).getDescriptor();
-        } else if (referenced == JType.Long) {
-            return JType.of(Reference.long$ref.class).getDescriptor();
-        }
-
         return JType.of(Reference.class).getDescriptor();
     }
 
     @Override
     public String getSignature() {
-        if (referenced == JType.Int) {
-            return JType.of(Reference.int$ref.class).getDescriptor();
-        } else if (referenced == JType.Long) {
-            return JType.of(Reference.long$ref.class).getDescriptor();
+        if (referenced == JType.Int || referenced == JType.Long) {
+            return JType.of(Reference.class).getDescriptor();
         }
 
         StringBuilder sb = new StringBuilder();
--- a/test/java/nicl/System/UnixSystem.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/test/java/nicl/System/UnixSystem.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,8 +58,9 @@
         try (Scope scope = new Scope()) {
             long bufSize = 128;
 
-            Pointer<Byte> buf = NativeLibrary.createPtr(scope.allocate(bufSize), Byte.class);
-            Pointer<Byte> cfmt = Transformer.toCStrPtr(fmt, scope);
+            LayoutType<Byte> t = NativeLibrary.createLayout(byte.class);
+            Pointer<Byte> buf = scope.allocate(t, bufSize);
+            Pointer<Byte> cfmt = Transformer.toCString(fmt, scope);
 
             int n = i.snprintf(buf, bufSize, cfmt, args);
             if (n >= bufSize) {
@@ -78,7 +79,7 @@
         assertEquals("foo", lowerAndSprintf(i, "foo"));
         assertEquals("foo: 4711", lowerAndSprintf(i, "foo: %d", 4711));
         try (Scope scope = new Scope()) {
-            assertEquals("foo: bar", lowerAndSprintf(i, "foo: %s", Transformer.toCStrPtr("bar", scope)));
+            assertEquals("foo: bar", lowerAndSprintf(i, "foo: %s", Transformer.toCString("bar", scope)));
         }
     }
 
--- a/test/java/nicl/Upcall/CallbackSort.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/test/java/nicl/Upcall/CallbackSort.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,40 +30,39 @@
 import java.nicl.metadata.C;
 import java.nicl.metadata.CallingConvention;
 import java.nicl.metadata.Header;
-import java.nicl.types.BoundedPointer.BoundedIntPointer;
 import java.nicl.types.Pointer;
-import java.nicl.types.Pointer.int$ptr;
+import java.nicl.types.Reference;
 import java.util.Iterator;
 
 public class CallbackSort {
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = Boolean.getBoolean("CallbackSort.DEBUG");
     private boolean upcallCalled = false;
 
     @Header(path="dummy")
     public static interface stdlib {
         @FunctionalInterface
         static interface compar {
-            public int fn(Pointer<int$ptr> e1, Pointer<int$ptr> e2);
+            public int fn(Pointer<Void> e1, Pointer<Void> e2);
         }
 
         @C(file="dummy", line=47, column=11, USR="c:@F@slowsort")
         @CallingConvention(value=1)
-        public abstract void slowsort(int$ptr base, long nmemb, long size, compar compar);
+        public abstract void slowsort(Pointer<Void> base, long nmemb, long size, compar compar);
     }
 
     public class comparator implements stdlib.compar {
         @Override
-        public int fn(Pointer<int$ptr> e1, Pointer<int$ptr> e2) {
+        public int fn(Pointer<Void> e1, Pointer<Void> e2) {
             upcallCalled = true;
 
-            BoundedIntPointer bip1 = new BoundedIntPointer(e1.addr());
-            BoundedIntPointer bip2 = new BoundedIntPointer(e2.addr());
+            Pointer<Integer> p1 = e1.cast(NativeLibrary.createLayout(int.class));
+            Pointer<Integer> p2 = e2.cast(NativeLibrary.createLayout(int.class));
 
-            int i1 = bip1.defref();
-            int i2 = bip2.defref();
+            int i1 = p1.deref().get();
+            int i2 = p2.deref().get();
 
             if (DEBUG) {
-                System.out.println("fn(0x" + Long.toHexString(e1.addr()) + " -> " + i1 + ", 0x" + Long.toHexString(e2.addr()) + " -> " + i2 + ")");
+                System.out.println("fn(i1=" + i1 + ", i2=" + i2 + ")");
             }
 
             return i1 - i2;
@@ -72,7 +71,8 @@
 
     private void doSort(NativeIntArray elems) {
         stdlib i = NativeLibrary.bindRaw(stdlib.class, NativeLibrary.load("Upcall"));
-        i.slowsort(elems.getBasePointer(), elems.size(), elems.getElemSize(), new comparator());
+        Pointer<Void> p = elems.getBasePointer().cast(NativeLibrary.createLayout(void.class));
+        i.slowsort(p, elems.size(), elems.getElemSize(), new comparator());
     }
 
     private void printElems(NativeIntArray arr) {
@@ -125,15 +125,14 @@
         private final Scope scope = new Scope();
 
         private final int nelems;
-        private final BoundedIntPointer base;
+        private final Pointer<Integer> base;
 
         public NativeIntArray(int nelems) {
             this.nelems = nelems;
-            long addr = scope.allocate(nelems * ELEM_SIZE);
-            this.base = new BoundedIntPointer(addr, addr, addr + nelems * ELEM_SIZE);
+            this.base = scope.allocate(NativeLibrary.createLayout(int.class), nelems * ELEM_SIZE);
         }
 
-        public int$ptr getBasePointer() {
+        public Pointer<Integer> getBasePointer() {
             return base;
         }
 
@@ -145,20 +144,20 @@
             return ELEM_SIZE;
         }
 
-        private BoundedIntPointer ptrForIndex(int index) {
-            return base.offset(index * ELEM_SIZE);
+        private Reference<Integer> refAt(int index) {
+            if (index < 0 || index >= nelems) {
+                throw new IndexOutOfBoundsException();
+            }
+
+            return base.offset(index * ELEM_SIZE).deref();
         }
 
         public int getAt(int index) {
-            return ptrForIndex(index).defref();
+            return refAt(index).get();
         }
 
         public void setAt(int index, int value) {
-            if (index >= nelems) {
-                throw new IndexOutOfBoundsException();
-            }
-
-            ptrForIndex(index).set(value);
+            refAt(index).set(value);
         }
 
         @Override
--- a/test/java/nicl/Upcall/DoubleUpcall.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/test/java/nicl/Upcall/DoubleUpcall.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,15 +23,12 @@
 
 /*
  * @test
- * @run junit DoubleUpcall
  */
 
-import static org.junit.Assert.*;
 import java.nicl.NativeLibrary;
 import java.nicl.metadata.C;
 import java.nicl.metadata.CallingConvention;
 import java.nicl.metadata.Header;
-import org.junit.Test;
 
 public class DoubleUpcall {
     private static final boolean DEBUG = false;
@@ -62,7 +59,6 @@
         }
     }
 
-    @Test
     public void test() {
         upcall i = NativeLibrary.bindRaw(upcall.class, NativeLibrary.load("Upcall"));
         upcall.cb v = new cbImpl();
@@ -77,6 +73,12 @@
         assertEquals(2.34, d, 0.1);
     }
 
+    private static void assertEquals(double expected, double actual, double maxDiff) {
+        if (Math.abs(expected - actual) > maxDiff) {
+            throw new RuntimeException("actual: " + actual + " does not match expected: " + expected);
+        }
+    }
+
     public static void main(String[] args) {
         new DoubleUpcall().test();
     }
--- a/test/java/nicl/Upcall/Long4Upcall.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/test/java/nicl/Upcall/Long4Upcall.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,15 +23,12 @@
 
 /*
  * @test
- * @run junit Long4Upcall
  */
 
-import static org.junit.Assert.*;
 import java.nicl.NativeLibrary;
 import java.nicl.metadata.C;
 import java.nicl.metadata.CallingConvention;
 import java.nicl.metadata.Header;
-import org.junit.Test;
 
 public class Long4Upcall {
     private static final boolean DEBUG = false;
@@ -73,7 +70,6 @@
         }
     }
 
-    @Test
     public void test() {
         upcall i = NativeLibrary.bindRaw(upcall.class, NativeLibrary.load("Upcall"));
         upcall.cb v = new cbImpl();
@@ -91,6 +87,12 @@
         }
     }
 
+    private static void assertEquals(long expected, long actual) {
+        if (expected != actual) {
+            throw new RuntimeException("actual: " + actual + " does not match expected: " + expected);
+        }
+    }
+
     public static void main(String[] args) {
         new Long4Upcall().test();
     }
--- a/test/java/nicl/Upcall/StructUpcall.java	Thu Apr 21 15:23:01 2016 -0700
+++ b/test/java/nicl/Upcall/StructUpcall.java	Fri Apr 22 15:19:32 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,20 +23,20 @@
 
 /*
  * @test
- * @run junit StructUpcall
+ * @modules java.base/jdk.internal.nicl.types
  */
 
-import static org.junit.Assert.*;
 import java.nicl.NativeLibrary;
+import java.nicl.Scope;
 import java.nicl.metadata.C;
 import java.nicl.metadata.CallingConvention;
 import java.nicl.metadata.Header;
 import java.nicl.metadata.NativeType;
 import java.nicl.metadata.Offset;
 import java.nicl.types.Pointer;
-import java.nicl.types.PointerImpl;
+import java.nicl.types.PointerToken;
 import java.nicl.types.Reference;
-import org.junit.Test;
+import jdk.internal.nicl.types.PointerTokenImpl;
 
 public class StructUpcall {
     private static final boolean DEBUG = false;
@@ -87,46 +87,75 @@
         public abstract void struct_upcall(MyStructVisitor v, MyStruct s);
     }
 
+
     public static class MyStructVisitorImpl implements Index.MyStructVisitor {
+        private static final PointerToken TOKEN = new PointerTokenImpl();
+
+        private Pointer<Void> p1;
+        private Pointer<Void> p2;
+        private Pointer<Void> p3;
+
+        MyStructVisitorImpl(Pointer<Void> p1, Pointer<Void> p2, Pointer<Void> p3) {
+            this.p1 = p1;
+            this.p2 = p2;
+            this.p3 = p3;
+        }
+
         @Override
         public void fn(Index.MyStruct s) {
-            if (DEBUG) {
-                System.err.println("visit(" + s + ")");
-                System.err.println("\ts.field1  = " + s.field1$get());
-                System.err.println("\ts.field2 = " + s.field2$get());
-                System.err.println("\ts.field3 = " + s.field3$get().addr());
-                System.err.println("\ts.field4 = " + s.field4$get().addr());
-                System.err.println("\ts.field5 = " + s.field5$get().addr());
+            try {
+                if (DEBUG) {
+                    System.err.println("visit(" + s + ")");
+                    System.err.println("\ts.field1  = " + s.field1$get());
+                    System.err.println("\ts.field2 = " + s.field2$get());
+                    System.err.println("\ts.field3 = " + s.field3$get().addr(TOKEN));
+                    System.err.println("\ts.field4 = " + s.field4$get().addr(TOKEN));
+                    System.err.println("\ts.field5 = " + s.field5$get().addr(TOKEN));
+                }
+
+                assertEquals(47, s.field1$get());
+                assertEquals(11, s.field2$get());
+                assertEquals(p1.addr(TOKEN), s.field3$get().addr(TOKEN));
+                assertEquals(p2.addr(TOKEN), s.field4$get().addr(TOKEN));
+                assertEquals(p3.addr(TOKEN), s.field5$get().addr(TOKEN));
+            } catch (IllegalAccessException e) {
+                throw new RuntimeException(e);
             }
-
-            assertEquals(47, s.field1$get());
-            assertEquals(11, s.field2$get());
-            assertEquals(101, s.field3$get().addr());
-            assertEquals(102, s.field4$get().addr());
-            assertEquals(103, s.field5$get().addr());
         }
     }
 
-    @Test
     public void test() {
         Index i = NativeLibrary.bindRaw(Index.class, NativeLibrary.load("Upcall"));
-        Index.MyStructVisitor v = new MyStructVisitorImpl();
 
-        Index.MyStruct s = NativeLibrary.createStruct(Index.MyStruct.class);
+        try (Scope scope = new Scope()) {
+                Reference<Index.MyStruct> s = scope.allocateStruct(NativeLibrary.createLayout(Index.MyStruct.class));
 
-        s.field1$set(47);
-        s.field2$set(11);
-        s.field3$set(new PointerImpl<Void>(101, void.class));
-        s.field4$set(new PointerImpl<Void>(102, void.class));
-        s.field5$set(new PointerImpl<Void>(103, void.class));
+            Pointer<Void> p1 = scope.allocate(NativeLibrary.createLayout(byte.class)).cast(NativeLibrary.createLayout(void.class));
+            Pointer<Void> p2 = scope.allocate(NativeLibrary.createLayout(byte.class)).cast(NativeLibrary.createLayout(void.class));
+            Pointer<Void> p3 = scope.allocate(NativeLibrary.createLayout(byte.class)).cast(NativeLibrary.createLayout(void.class));
 
-        i.struct_upcall(v, s);
+            s.get().field1$set(47);
+            s.get().field2$set(11);
+            s.get().field3$set(p1);
+            s.get().field4$set(p2);
+            s.get().field5$set(p3);
+
+            Index.MyStructVisitor v = new MyStructVisitorImpl(p1, p2, p3);
+
+            i.struct_upcall(v, s.get());
+        }
 
         if (DEBUG) {
             System.err.println("back in test()\n");
         }
     }
 
+    static void assertEquals(long expected, long actual) {
+        if (expected != actual) {
+            throw new RuntimeException("expected: " + expected + " does not match actual: " + actual);
+        }
+    }
+
     public static void main(String[] args) {
         new StructUpcall().test();
     }