|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  |  | 
|  | package jdk.internal.access.foreign; | 
|  |  | 
|  | import jdk.internal.misc.ScopedMemoryAccess; | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  | public abstract class MemorySegmentProxy { | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public abstract void checkAccess(long offset, long length, boolean readOnly); | 
|  |     public abstract long unsafeGetOffset(); | 
|  |     public abstract Object unsafeGetBase(); | 
|  |     public abstract boolean isSmall(); | 
|  |     public abstract ScopedMemoryAccess.Scope scope(); | 
|  |  | 
|  |     /* Helper functions for offset computations. These are required so that we can avoid issuing long opcodes | 
|  |      * (e.g. LMUL, LADD) when we're operating on 'small' segments (segments whose length can be expressed with an int). | 
|  |      * C2 BCE code is very sensitive to the kind of opcode being emitted, and this workaround allows us to rescue | 
|  |      * BCE when working with small segments. This workaround should be dropped when JDK-8223051 is resolved. | 
|  |      */ | 
|  |  | 
|  |     public static long addOffsets(long op1, long op2, MemorySegmentProxy segmentProxy) { | 
|  |         if (segmentProxy.isSmall()) { | 
|  |              | 
|  |             if (op1 > Integer.MAX_VALUE || op2 > Integer.MAX_VALUE | 
|  |                     || op1 < Integer.MIN_VALUE || op2 < Integer.MIN_VALUE) { | 
|  |                 throw overflowException(Integer.MIN_VALUE, Integer.MAX_VALUE); | 
|  |             } | 
|  |             int i1 = (int)op1; | 
|  |             int i2 = (int)op2; | 
|  |             try { | 
|  |                 return Math.addExact(i1, i2); | 
|  |             } catch (ArithmeticException ex) { | 
|  |                 throw overflowException(Integer.MIN_VALUE, Integer.MAX_VALUE); | 
|  |             } | 
|  |         } else { | 
|  |             try { | 
|  |                 return Math.addExact(op1, op2); | 
|  |             } catch (ArithmeticException ex) { | 
|  |                 throw overflowException(Long.MIN_VALUE, Long.MAX_VALUE); | 
|  |             } | 
|  |         } | 
|  |     } | 
|  |  | 
|  |     public static long multiplyOffsets(long op1, long op2, MemorySegmentProxy segmentProxy) { | 
|  |         if (segmentProxy.isSmall()) { | 
|  |             if (op1 > Integer.MAX_VALUE || op2 > Integer.MAX_VALUE | 
|  |                     || op1 < Integer.MIN_VALUE || op2 < Integer.MIN_VALUE) { | 
|  |                 throw overflowException(Integer.MIN_VALUE, Integer.MAX_VALUE); | 
|  |             } | 
|  |              | 
|  |             int i1 = (int)op1; | 
|  |             int i2 = (int)op2; | 
|  |             try { | 
|  |                 return Math.multiplyExact(i1, i2); | 
|  |             } catch (ArithmeticException ex) { | 
|  |                 throw overflowException(Integer.MIN_VALUE, Integer.MAX_VALUE); | 
|  |             } | 
|  |         } else { | 
|  |             try { | 
|  |                 return Math.multiplyExact(op1, op2); | 
|  |             } catch (ArithmeticException ex) { | 
|  |                 throw overflowException(Long.MIN_VALUE, Long.MAX_VALUE); | 
|  |             } | 
|  |         } | 
|  |     } | 
|  |  | 
|  |     private static IndexOutOfBoundsException overflowException(long min, long max) { | 
|  |         return new IndexOutOfBoundsException(String.format("Overflow occurred during offset computation ; offset exceeded range { %d .. %d }", min, max)); | 
|  |     } | 
|  | } |