1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.internal.nicl.types; 27 28 import jdk.internal.nicl.LibrariesHelper; 29 import jdk.internal.nicl.Util; 30 31 import java.nicl.Libraries; 32 import java.nicl.metadata.NativeStruct; 33 import java.nicl.layout.Address; 34 import java.nicl.layout.Sequence; 35 import java.nicl.layout.Value; 36 import java.nicl.layout.Value.Kind; 37 import java.nicl.types.*; 38 39 import java.lang.invoke.MethodHandle; 40 import java.lang.invoke.MethodHandles; 41 import java.lang.invoke.MethodType; 42 43 /** 44 * Helper class for references. Defines several reference subclasses, specialized in well-known Java carrier 45 * types (both primitive and reference types). It also provides factories for common reference types. 46 */ 47 public final class References { 48 49 private References() {} 50 51 /** 52 * Reference for primitive carriers. It exposes specialized accessors for getting/setting 53 * the contents of a reference. 54 */ 55 static class OfPrimitive implements Reference { 56 57 static final MethodHandle MH_GET_LONG_BITS; 58 static final MethodHandle MH_SET_LONG_BITS; 59 60 Class<?> carrier; 61 62 static { 63 try { 64 MH_GET_LONG_BITS = MethodHandles.lookup().findStatic(OfPrimitive.class, "getLongBits", MethodType.methodType(long.class, Pointer.class)); 65 MH_SET_LONG_BITS = MethodHandles.lookup().findStatic(OfPrimitive.class, "setLongBits", MethodType.methodType(void.class, Pointer.class, long.class)); 66 } catch (Throwable ex) { 67 throw new IllegalStateException(ex); 68 } 69 } 70 71 static long getLongBits(Pointer<?> p2) { 72 BoundedPointer<?> ptr = (BoundedPointer<?>)p2; 73 boolean signed = ptr.type.layout() instanceof Value && 74 ((Value)ptr.type.layout()).kind() != Kind.INTEGRAL_UNSIGNED; 75 return ptr.region.getBits(ptr.offset, ptr.type.layout().bitsSize() / 8, signed); 76 } 77 78 static void setLongBits(Pointer<?> p2, long value) { 79 BoundedPointer<?> ptr = (BoundedPointer<?>)p2; 80 ptr.region.putBits(ptr.offset, ptr.type.layout().bitsSize() / 8, value); 81 } 82 83 static boolean toBoolean(long value) { 84 return value != 0; 85 } 86 87 static long fromBoolean(boolean value) { 88 return value ? 1 : 0; 89 } 90 91 public OfPrimitive(Class<?> carrier) { 92 super(); 93 this.carrier = carrier; 94 } 95 96 @Override 97 public MethodHandle getter() { 98 return MethodHandles.explicitCastArguments(MH_GET_LONG_BITS, MH_GET_LONG_BITS.type().changeReturnType(carrier)); 99 } 100 101 @Override 102 public MethodHandle setter() { 103 return MethodHandles.explicitCastArguments(MH_SET_LONG_BITS, MH_SET_LONG_BITS.type().changeParameterType(1, carrier)); 104 } 105 } 106 107 /** 108 * A reference for the Java primitive type {@code boolean}. 109 */ 110 public static class OfBoolean extends OfPrimitive { 111 112 static final MethodHandle MH_TO_BOOLEAN; 113 static final MethodHandle MH_FROM_BOOLEAN; 114 115 static { 116 try { 117 MH_TO_BOOLEAN = MethodHandles.lookup().findStatic(OfPrimitive.class, "toBoolean", MethodType.methodType(boolean.class, long.class)); 118 MH_FROM_BOOLEAN = MethodHandles.lookup().findStatic(OfPrimitive.class, "fromBoolean", MethodType.methodType(long.class, boolean.class)); 119 } catch (Throwable ex) { 120 throw new IllegalStateException(ex); 121 } 122 } 123 124 125 OfBoolean() { 126 super(boolean.class); 127 } 128 129 @Override 130 public MethodHandle getter() { 131 return MethodHandles.filterReturnValue(MH_GET_LONG_BITS, MH_TO_BOOLEAN); 132 } 133 134 @Override 135 public MethodHandle setter() { 136 return MethodHandles.filterArguments(MH_SET_LONG_BITS, 1, MH_FROM_BOOLEAN); 137 } 138 139 /** 140 * Read the contents of this reference as a boolean value. 141 * @return the boolean value. 142 */ 143 public boolean get(Pointer<?> pointer) { 144 try { 145 return (boolean)getter().invokeExact(pointer); 146 } catch (Throwable ex) { 147 throw new IllegalStateException(ex); 148 } 149 } 150 151 /** 152 * Store a given boolean value in this reference. 153 * @param value the boolean value. 154 */ 155 public void set(Pointer<?> pointer, boolean value) { 156 try { 157 setter().invokeExact(pointer, value); 158 } catch (Throwable ex) { 159 throw new IllegalStateException(ex); 160 } 161 } 162 } 163 164 /** 165 * A reference for the Java primitive type {@code char}. 166 */ 167 public static class OfChar extends OfPrimitive { 168 169 OfChar() { 170 super(char.class); 171 } 172 173 /** 174 * Read the contents of this reference as a char value. 175 * @return the char value. 176 */ 177 public char get(Pointer<?> pointer) { 178 try { 179 return (char)getter().invokeExact(pointer); 180 } catch (Throwable ex) { 181 throw new IllegalStateException(ex); 182 } 183 } 184 185 /** 186 * Store a given char value in this reference. 187 * @param value the char value. 188 */ 189 public void set(Pointer<?> pointer, char value) { 190 try { 191 setter().invokeExact(pointer, value); 192 } catch (Throwable ex) { 193 throw new IllegalStateException(ex); 194 } 195 } 196 } 197 198 /** 199 * A reference for the Java primitive type {@code byte}. 200 */ 201 public static final class OfByte extends OfPrimitive { 202 203 OfByte() { 204 super(byte.class); 205 } 206 207 /** 208 * Read the contents of this reference as a byte value. 209 * @return the byte value. 210 */ 211 public byte get(Pointer<?> pointer) { 212 try { 213 return (byte)getter().invokeExact(pointer); 214 } catch (Throwable ex) { 215 throw new IllegalStateException(ex); 216 } 217 } 218 219 /** 220 * Store a given byte value in this reference. 221 * @param value the byte value. 222 */ 223 public void set(Pointer<?> pointer, byte value) { 224 try { 225 setter().invokeExact(pointer, value); 226 } catch (Throwable ex) { 227 throw new IllegalStateException(ex); 228 } 229 } 230 } 231 232 /** 233 * A reference for the Java primitive type {@code short}. 234 */ 235 public static class OfShort extends OfPrimitive { 236 237 OfShort() { 238 super(short.class); 239 } 240 241 /** 242 * Read the contents of this reference as a short value. 243 * @return the short value. 244 */ 245 public short get(Pointer<?> pointer) { 246 try { 247 return (short)getter().invokeExact(pointer); 248 } catch (Throwable ex) { 249 throw new IllegalStateException(ex); 250 } 251 } 252 253 /** 254 * Store a given short value in this reference. 255 * @param value the short value. 256 */ 257 public void set(Pointer<?> pointer, short value) { 258 try { 259 setter().invokeExact(pointer, value); 260 } catch (Throwable ex) { 261 throw new IllegalStateException(ex); 262 } 263 } 264 } 265 266 /** 267 * A reference for the Java primitive type {@code int}. 268 */ 269 public static class OfInt extends OfPrimitive { 270 OfInt() { 271 super(int.class); 272 } 273 274 /** 275 * Read the contents of this reference as an int value. 276 * @return the int value. 277 */ 278 public int get(Pointer<?> pointer) { 279 try { 280 return (int)getter().invokeExact(pointer); 281 } catch (Throwable ex) { 282 throw new IllegalStateException(ex); 283 } 284 } 285 286 /** 287 * Store a given int value in this reference. 288 * @param value the int value. 289 */ 290 public void set(Pointer<?> pointer, int value) { 291 try { 292 setter().invokeExact(pointer, value); 293 } catch (Throwable ex) { 294 throw new IllegalStateException(ex); 295 } 296 } 297 } 298 299 /** 300 * A reference for the Java primitive type {@code float}. 301 */ 302 public static class OfFloat extends OfPrimitive { 303 304 static final MethodHandle MH_TO_FLOAT; 305 static final MethodHandle MH_FROM_FLOAT; 306 307 static { 308 try { 309 MH_TO_FLOAT = MethodHandles.explicitCastArguments(MethodHandles.lookup().findStatic(Float.class, "intBitsToFloat", MethodType.methodType(float.class, int.class)), MethodType.methodType(float.class, long.class)); 310 MH_FROM_FLOAT = MethodHandles.explicitCastArguments(MethodHandles.lookup().findStatic(Float.class, "floatToRawIntBits", MethodType.methodType(int.class, float.class)), MethodType.methodType(long.class, float.class)); 311 } catch (Throwable ex) { 312 throw new IllegalStateException(ex); 313 } 314 } 315 316 OfFloat() { 317 super(float.class); 318 } 319 320 @Override 321 public MethodHandle getter() { 322 return MethodHandles.filterReturnValue(MH_GET_LONG_BITS, MH_TO_FLOAT); 323 } 324 325 @Override 326 public MethodHandle setter() { 327 return MethodHandles.filterArguments(MH_SET_LONG_BITS, 1, MH_FROM_FLOAT); 328 } 329 330 /** 331 * Read the contents of this reference as a float value. 332 * @return the float value. 333 */ 334 public float get(Pointer<?> pointer) { 335 try { 336 return (float)getter().invokeExact(pointer); 337 } catch (Throwable ex) { 338 throw new IllegalStateException(ex); 339 } 340 } 341 342 /** 343 * Store a given float value in this reference. 344 * @param value the float value. 345 */ 346 public void set(Pointer<?> pointer, float value) { 347 try { 348 setter().invokeExact(pointer, value); 349 } catch (Throwable ex) { 350 throw new IllegalStateException(ex); 351 } 352 } 353 } 354 355 /** 356 * A reference for the Java primitive type {@code long}. 357 */ 358 public static class OfLong extends OfPrimitive { 359 360 OfLong() { 361 super(long.class); 362 } 363 364 /** 365 * Read the contents of this reference as a long value. 366 * @return the long value. 367 */ 368 public long get(Pointer<?> pointer) { 369 try { 370 return (long)getter().invokeExact(pointer); 371 } catch (Throwable ex) { 372 throw new IllegalStateException(ex); 373 } 374 } 375 376 /** 377 * Store a given long value in this reference. 378 * @param value the long value. 379 */ 380 public void set(Pointer<?> pointer, long value) { 381 try { 382 setter().invokeExact(pointer, value); 383 } catch (Throwable ex) { 384 throw new IllegalStateException(ex); 385 } 386 } 387 } 388 389 /** 390 * A reference for the Java primitive type {@code double}. 391 */ 392 public static class OfDouble extends OfPrimitive { 393 394 static final MethodHandle MH_TO_DOUBLE; 395 static final MethodHandle MH_FROM_DOUBLE; 396 397 static { 398 try { 399 MH_TO_DOUBLE = MethodHandles.lookup().findStatic(Double.class, "longBitsToDouble", MethodType.methodType(double.class, long.class)); 400 MH_FROM_DOUBLE = MethodHandles.lookup().findStatic(Double.class, "doubleToRawLongBits", MethodType.methodType(long.class, double.class)); 401 } catch (Throwable ex) { 402 throw new IllegalStateException(ex); 403 } 404 } 405 406 OfDouble() { 407 super(double.class); 408 } 409 410 @Override 411 public MethodHandle getter() { 412 return MethodHandles.filterReturnValue(MH_GET_LONG_BITS, MH_TO_DOUBLE); 413 } 414 415 @Override 416 public MethodHandle setter() { 417 return MethodHandles.filterArguments(MH_SET_LONG_BITS, 1, MH_FROM_DOUBLE); 418 } 419 420 /** 421 * Read the contents of this reference as a double value. 422 * @return the double value. 423 */ 424 public double get(Pointer<?> pointer) { 425 try { 426 return (double)getter().invokeExact(pointer); 427 } catch (Throwable ex) { 428 throw new IllegalStateException(ex); 429 } 430 } 431 432 /** 433 * Store a given double value in this reference. 434 * @param value the double value. 435 */ 436 public void set(Pointer<?> pointer, double value) { 437 try { 438 setter().invokeExact(pointer, value); 439 } catch (Throwable ex) { 440 throw new IllegalStateException(ex); 441 } 442 } 443 } 444 445 /** 446 * This class models a reference to a Java class type (non-primitive). It provides strongly typed operations 447 * to get/set the contents of the reference. 448 * @param <T> the Java type. 449 */ 450 public static abstract class OfClass<T> implements Reference { 451 452 static final MethodHandle MH_GET; 453 static final MethodHandle MH_SET; 454 455 static { 456 try { 457 MH_GET = MethodHandles.lookup().findVirtual(OfClass.class, "get", MethodType.methodType(Object.class, Pointer.class)); 458 MH_SET = MethodHandles.lookup().findVirtual(OfClass.class, "set", MethodType.methodType(void.class, Pointer.class, Object.class)); 459 } catch (Throwable ex) { 460 throw new IllegalStateException(ex); 461 } 462 } 463 464 protected Class<T> carrier; 465 466 public OfClass(Class<T> carrier) { 467 super(); 468 this.carrier = carrier; 469 } 470 471 @Override 472 public final MethodHandle getter() { 473 return MH_GET.asType(MH_GET.type().changeReturnType(carrier)).bindTo(this); 474 } 475 476 @Override 477 public final MethodHandle setter() { 478 return MH_SET.asType(MH_SET.type().changeParameterType(2, carrier)).bindTo(this); 479 } 480 481 /** 482 * Read the contents of the memory associated with this reference. 483 * @return a value of type {@code T}. 484 */ 485 public abstract T get(Pointer<?> pointer); 486 487 /** 488 * Store a value of type {@code T} in this reference. 489 * @param value a value of type {@code T}. 490 */ 491 public abstract void set(Pointer<?> pointer, T value); 492 } 493 494 /** 495 * Reference for pointers. 496 */ 497 public static class OfPointer<X> extends OfClass<Pointer<X>> { 498 499 private final LayoutType<X> pointeeType; 500 501 @SuppressWarnings({"unchecked", "rawtypes"}) 502 public OfPointer(LayoutType<X> pointeeType) { 503 super((Class) Pointer.class); 504 this.pointeeType = pointeeType; 505 } 506 507 @Override 508 @SuppressWarnings("unchecked") 509 public Pointer<X> get(Pointer<?> pointer) { 510 long addr = ofLong.get(pointer); 511 BoundedPointer<X> rp = addr == 0 ? 512 Pointer.nullPointer() : 513 new BoundedPointer<>(pointeeType, new BoundedMemoryRegion(null, addr, Long.MAX_VALUE), 0); 514 return rp; 515 } 516 517 @Override 518 public void set(Pointer<?> pointer, Pointer<X> pointerValue) { 519 try { 520 ofLong.set(pointer, pointerValue.addr()); 521 } catch (IllegalAccessException iae) { 522 throw new RuntimeException("Access denied", iae); 523 } 524 } 525 } 526 527 /** 528 * Reference for arrays. 529 */ 530 public static class OfArray<X> extends OfClass<Array<X>> { 531 532 private final LayoutType<X> elementType; 533 534 @SuppressWarnings({"unchecked", "rawtypes"}) 535 public OfArray(LayoutType<X> elementType) { 536 super((Class) Array.class); 537 this.elementType = elementType; 538 } 539 540 @Override 541 @SuppressWarnings("unchecked") 542 public Array<X> get(Pointer<?> pointer) { 543 Sequence seq = (Sequence)pointer.type().layout(); 544 return new BoundedArray<>((BoundedPointer<X>)pointer.cast(elementType), seq.elementsSize()); 545 } 546 547 @Override 548 public void set(Pointer<?> pointer, Array<X> arrayValue) { 549 try { 550 MethodHandle elemGetter = elementType.getter(); 551 MethodHandle elemSetter = elementType.setter(); 552 Pointer<?> toElemPointer = ((Array<?>)pointer.get()).elementPointer(); 553 Pointer<X> fromElemPointer = arrayValue.elementPointer(); 554 // @@@ Perform a bulk copy from the array into the pointers 555 // memory region 556 Sequence seq = ((Sequence)pointer.type().layout()); 557 int size = seq.elementsSize(); 558 for (int i = 0 ; i < size ; i++) { 559 Object newVal = elemGetter.invoke(fromElemPointer.offset(i)); 560 elemSetter.invoke(toElemPointer.offset(i), newVal); 561 } 562 } catch (Throwable ex) { 563 throw new IllegalStateException(ex); 564 } 565 } 566 } 567 568 /** 569 * A reference for native structs. 570 * @param <T> The Java type associated with the native struct. 571 */ 572 public static class OfStruct<T extends Struct<T>> extends OfClass<T> { 573 OfStruct(Class<T> carrier) { 574 super(carrier); 575 } 576 577 @Override 578 @SuppressWarnings("unchecked") 579 public T get(Pointer<?> pointer) { 580 Class<?> structClass = LibrariesHelper.getStructImplClass(carrier); 581 try { 582 return (T)structClass.getConstructor(Pointer.class).newInstance(pointer); 583 } catch (ReflectiveOperationException ex) { 584 throw new IllegalStateException(ex); 585 } 586 } 587 588 @Override 589 public void set(Pointer<?> pointer, T t) { 590 try { 591 Util.copy(t.ptr(), pointer, pointer.type().layout().bitsSize() / 8); 592 } catch (IllegalAccessException iae) { 593 throw new RuntimeException("Access denied", iae); 594 } 595 } 596 } 597 598 /** 599 * Reference factory for the {@code char} primitive type. 600 */ 601 public static OfChar ofChar = new OfChar(); 602 603 /** 604 * Reference factory for the {@code boolean} primitive type. 605 */ 606 public static OfBoolean ofBoolean = new OfBoolean(); 607 608 /** 609 * Reference factory for the {@code byte} primitive type. 610 */ 611 public static OfByte ofByte = new OfByte(); 612 613 /** 614 * Reference factory for the {@code short} primitive type. 615 */ 616 public static OfShort ofShort = new OfShort(); 617 618 /** 619 * Reference factory for the {@code int} primitive type. 620 */ 621 public static OfInt ofInt = new OfInt(); 622 623 /** 624 * Reference factory for the {@code float} primitive type. 625 */ 626 public static OfFloat ofFloat = new OfFloat(); 627 628 /** 629 * Reference factory for the {@code long} primitive type. 630 */ 631 public static OfLong ofLong = new OfLong(); 632 633 /** 634 * Reference for the {@code double} primitive type. 635 */ 636 public static OfDouble ofDouble = new OfDouble(); 637 638 public static <X> OfPointer<X> ofPointer(LayoutType<X> pointeeType) { 639 return new OfPointer<>(pointeeType); 640 } 641 642 /** 643 * Create an array reference factory from a given carrier class. 644 * @param elementType the array carrier. 645 * @param <T> the array type. 646 * @return a reference factory for array references. 647 * @throws IllegalArgumentException if the carrier is not an array type. 648 */ 649 public static <T> OfArray<T> ofArray(LayoutType<T> elementType) { return new OfArray<>(elementType); } 650 651 /** 652 * Create a struct reference factory from a given carrier class. 653 * @param clazz the native struct carrier. 654 * @param <T> the native struct type. 655 * @return a reference factory for native struct references. 656 * @throws IllegalArgumentException if the carrier is not annotated with the {@link NativeStruct} annotation. 657 */ 658 public static <T extends Struct<T>> OfStruct<T> ofStruct(Class<T> clazz) throws IllegalArgumentException { 659 if (!clazz.isAnnotationPresent(NativeStruct.class)) { 660 throw new IllegalArgumentException("Not a native struct!"); 661 } 662 return new OfStruct<>(clazz); 663 } 664 }