/*
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package java.lang.invoke;

import jdk.internal.access.foreign.MemoryAddressProxy;
import jdk.internal.vm.annotation.ForceInline;

import java.util.Objects;

import static java.lang.invoke.MethodHandleStatics.UNSAFE;

// -- This file was mechanically generated: Do not edit! -- //

final class VarHandleMemoryAddressAsInts {

    static final boolean BE = UNSAFE.isBigEndian();

    static final int VM_ALIGN = Integer.BYTES - 1;

    @ForceInline
    static int convEndian(boolean big, int n) {
        return big == BE ? n : Integer.reverseBytes(n);
    }

    @ForceInline
    static MemoryAddressProxy checkAddress(Object obb, long offset, long length, boolean ro) {
        MemoryAddressProxy oo = (MemoryAddressProxy)Objects.requireNonNull(obb);
        oo.checkAccess(offset, length, ro);
        return oo;
    }
    
    @ForceInline
    static long offset(MemoryAddressProxy bb, long offset, long alignmentMask) {
        long address = offsetNoVMAlignCheck(bb, offset, alignmentMask);
        if ((address & VM_ALIGN) != 0) {
            throw VarHandleMemoryAddressBase.newIllegalStateExceptionForMisalignedAccess(address);
        }
        return address;
    }

    @ForceInline
    static long offsetNoVMAlignCheck(MemoryAddressProxy bb, long offset, long alignmentMask) {
        long base = bb.unsafeGetOffset();
        long address = base + offset;
        //note: the offset portion has already been aligned-checked, by construction
        if ((base & alignmentMask) != 0) {
            throw VarHandleMemoryAddressBase.newIllegalStateExceptionForMisalignedAccess(address);
        }
        return address;
    }
    
    @ForceInline
    static int get0(VarHandleMemoryAddressBase handle, Object obb, long base) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, true);
        return UNSAFE.getIntUnaligned(
                bb.unsafeGetBase(),
                offsetNoVMAlignCheck(bb, base, handle.alignmentMask),
                handle.be);
    }

    @ForceInline
    static void set0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        UNSAFE.putIntUnaligned(
                bb.unsafeGetBase(),
                offsetNoVMAlignCheck(bb, base, handle.alignmentMask),
                value,
                handle.be);
    }

    @ForceInline
    static int getVolatile0(VarHandleMemoryAddressBase handle, Object obb, long base) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, true);
        return convEndian(handle.be,
                          UNSAFE.getIntVolatile(
                                  bb.unsafeGetBase(),
                                  offset(bb, base, handle.alignmentMask)));
    }

    @ForceInline
    static void setVolatile0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        UNSAFE.putIntVolatile(
                bb.unsafeGetBase(),
                offset(bb, base, handle.alignmentMask),
                convEndian(handle.be, value));
    }

    @ForceInline
    static int getAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, true);
        return convEndian(handle.be,
                          UNSAFE.getIntAcquire(
                                  bb.unsafeGetBase(),
                                  offset(bb, base, handle.alignmentMask)));
    }

    @ForceInline
    static void setRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        UNSAFE.putIntRelease(
                bb.unsafeGetBase(),
                offset(bb, base, handle.alignmentMask),
                convEndian(handle.be, value));
    }

    @ForceInline
    static int getOpaque0(VarHandleMemoryAddressBase handle, Object obb, long base) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, true);
        return convEndian(handle.be,
                          UNSAFE.getIntOpaque(
                                  bb.unsafeGetBase(),
                                  offset(bb, base, handle.alignmentMask)));
    }

    @ForceInline
    static void setOpaque0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        UNSAFE.putIntOpaque(
                bb.unsafeGetBase(),
                offset(bb, base, handle.alignmentMask),
                convEndian(handle.be, value));
    }

    @ForceInline
    static boolean compareAndSet0(VarHandleMemoryAddressBase handle, Object obb, long base, int expected, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        return UNSAFE.compareAndSetInt(
                bb.unsafeGetBase(),
                offset(bb, base, handle.alignmentMask),
                convEndian(handle.be, expected), convEndian(handle.be, value));
    }

    @ForceInline
    static int compareAndExchange0(VarHandleMemoryAddressBase handle, Object obb, long base, int expected, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        return convEndian(handle.be,
                          UNSAFE.compareAndExchangeInt(
                                  bb.unsafeGetBase(),
                                  offset(bb, base, handle.alignmentMask),
                                  convEndian(handle.be, expected), convEndian(handle.be, value)));
    }

    @ForceInline
    static int compareAndExchangeAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, int expected, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        return convEndian(handle.be,
                          UNSAFE.compareAndExchangeIntAcquire(
                                  bb.unsafeGetBase(),
                                  offset(bb, base, handle.alignmentMask),
                                  convEndian(handle.be, expected), convEndian(handle.be, value)));
    }

    @ForceInline
    static int compareAndExchangeRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, int expected, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        return convEndian(handle.be,
                          UNSAFE.compareAndExchangeIntRelease(
                                  bb.unsafeGetBase(),
                                  offset(bb, base, handle.alignmentMask),
                                  convEndian(handle.be, expected), convEndian(handle.be, value)));
    }

    @ForceInline
    static boolean weakCompareAndSetPlain0(VarHandleMemoryAddressBase handle, Object obb, long base, int expected, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        return UNSAFE.weakCompareAndSetIntPlain(
                bb.unsafeGetBase(),
                offset(bb, base, handle.alignmentMask),
                convEndian(handle.be, expected), convEndian(handle.be, value));
    }

    @ForceInline
    static boolean weakCompareAndSet0(VarHandleMemoryAddressBase handle, Object obb, long base, int expected, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        return UNSAFE.weakCompareAndSetInt(
                bb.unsafeGetBase(),
                offset(bb, base, handle.alignmentMask),
                convEndian(handle.be, expected), convEndian(handle.be, value));
    }

    @ForceInline
    static boolean weakCompareAndSetAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, int expected, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        return UNSAFE.weakCompareAndSetIntAcquire(
                bb.unsafeGetBase(),
                offset(bb, base, handle.alignmentMask),
                convEndian(handle.be, expected), convEndian(handle.be, value));
    }

    @ForceInline
    static boolean weakCompareAndSetRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, int expected, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        return UNSAFE.weakCompareAndSetIntRelease(
                bb.unsafeGetBase(),
                offset(bb, base, handle.alignmentMask),
                convEndian(handle.be, expected), convEndian(handle.be, value));
    }

    @ForceInline
    static int getAndSet0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        return convEndian(handle.be,
                          UNSAFE.getAndSetInt(
                                  bb.unsafeGetBase(),
                                  offset(bb, base, handle.alignmentMask),
                                  convEndian(handle.be, value)));
    }

    @ForceInline
    static int getAndSetAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        return convEndian(handle.be,
                          UNSAFE.getAndSetIntAcquire(
                                  bb.unsafeGetBase(),
                                  offset(bb, base, handle.alignmentMask),
                                  convEndian(handle.be, value)));
    }

    @ForceInline
    static int getAndSetRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        return convEndian(handle.be,
                          UNSAFE.getAndSetIntRelease(
                                  bb.unsafeGetBase(),
                                  offset(bb, base, handle.alignmentMask),
                                  convEndian(handle.be, value)));
    }

    @ForceInline
    static int getAndAdd0(VarHandleMemoryAddressBase handle, Object obb, long base, int delta) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        if (handle.be == BE) {
            return UNSAFE.getAndAddInt(
                    bb.unsafeGetBase(),
                    offset(bb, base, handle.alignmentMask),
                    delta);
        } else {
            return getAndAddConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), delta);
        }
    }

    @ForceInline
    static int getAndAddAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, int delta) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        if (handle.be == BE) {
            return UNSAFE.getAndAddIntAcquire(
                    bb.unsafeGetBase(),
                    offset(bb, base, handle.alignmentMask),
                    delta);
        } else {
            return getAndAddConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), delta);
        }
    }

    @ForceInline
    static int getAndAddRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, int delta) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        if (handle.be == BE) {
            return UNSAFE.getAndAddIntRelease(
                    bb.unsafeGetBase(),
                    offset(bb, base, handle.alignmentMask),
                    delta);
        } else {
            return getAndAddConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), delta);
        }
    }

    @ForceInline
    static int getAndAddConvEndianWithCAS(MemoryAddressProxy bb, long offset, int delta) {
        int nativeExpectedValue, expectedValue;
        Object base = bb.unsafeGetBase();
        do {
            nativeExpectedValue = UNSAFE.getIntVolatile(base, offset);
            expectedValue = Integer.reverseBytes(nativeExpectedValue);
        } while (!UNSAFE.weakCompareAndSetInt(base, offset,
                nativeExpectedValue, Integer.reverseBytes(expectedValue + delta)));
        return expectedValue;
    }

    @ForceInline
    static int getAndBitwiseOr0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        if (handle.be == BE) {
            return UNSAFE.getAndBitwiseOrInt(
                    bb.unsafeGetBase(),
                    offset(bb, base, handle.alignmentMask),
                    value);
        } else {
            return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value);
        }
    }

    @ForceInline
    static int getAndBitwiseOrRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        if (handle.be == BE) {
            return UNSAFE.getAndBitwiseOrIntRelease(
                    bb.unsafeGetBase(),
                    offset(bb, base, handle.alignmentMask),
                    value);
        } else {
            return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value);
        }
    }

    @ForceInline
    static int getAndBitwiseOrAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        if (handle.be == BE) {
            return UNSAFE.getAndBitwiseOrIntAcquire(
                    bb.unsafeGetBase(),
                    offset(bb, base, handle.alignmentMask),
                    value);
        } else {
            return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value);
        }
    }

    @ForceInline
    static int getAndBitwiseOrConvEndianWithCAS(MemoryAddressProxy bb, long offset, int value) {
        int nativeExpectedValue, expectedValue;
        Object base = bb.unsafeGetBase();
        do {
            nativeExpectedValue = UNSAFE.getIntVolatile(base, offset);
            expectedValue = Integer.reverseBytes(nativeExpectedValue);
        } while (!UNSAFE.weakCompareAndSetInt(base, offset,
                nativeExpectedValue, Integer.reverseBytes(expectedValue | value)));
        return expectedValue;
    }

    @ForceInline
    static int getAndBitwiseAnd0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        if (handle.be == BE) {
            return UNSAFE.getAndBitwiseAndInt(
                    bb.unsafeGetBase(),
                    offset(bb, base, handle.alignmentMask),
                    value);
        } else {
            return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value);
        }
    }

    @ForceInline
    static int getAndBitwiseAndRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        if (handle.be == BE) {
            return UNSAFE.getAndBitwiseAndIntRelease(
                    bb.unsafeGetBase(),
                    offset(bb, base, handle.alignmentMask),
                    value);
        } else {
            return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value);
        }
    }

    @ForceInline
    static int getAndBitwiseAndAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        if (handle.be == BE) {
            return UNSAFE.getAndBitwiseAndIntAcquire(
                    bb.unsafeGetBase(),
                    offset(bb, base, handle.alignmentMask),
                    value);
        } else {
            return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value);
        }
    }

    @ForceInline
    static int getAndBitwiseAndConvEndianWithCAS(MemoryAddressProxy bb, long offset, int value) {
        int nativeExpectedValue, expectedValue;
        Object base = bb.unsafeGetBase();
        do {
            nativeExpectedValue = UNSAFE.getIntVolatile(base, offset);
            expectedValue = Integer.reverseBytes(nativeExpectedValue);
        } while (!UNSAFE.weakCompareAndSetInt(base, offset,
                nativeExpectedValue, Integer.reverseBytes(expectedValue & value)));
        return expectedValue;
    }


    @ForceInline
    static int getAndBitwiseXor0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        if (handle.be == BE) {
            return UNSAFE.getAndBitwiseXorInt(
                    bb.unsafeGetBase(),
                    offset(bb, base, handle.alignmentMask),
                    value);
        } else {
            return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value);
        }
    }

    @ForceInline
    static int getAndBitwiseXorRelease0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        if (handle.be == BE) {
            return UNSAFE.getAndBitwiseXorIntRelease(
                    bb.unsafeGetBase(),
                    offset(bb, base, handle.alignmentMask),
                    value);
        } else {
            return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value);
        }
    }

    @ForceInline
    static int getAndBitwiseXorAcquire0(VarHandleMemoryAddressBase handle, Object obb, long base, int value) {
        MemoryAddressProxy bb = checkAddress(obb, base, handle.length, false);
        if (handle.be == BE) {
            return UNSAFE.getAndBitwiseXorIntAcquire(
                    bb.unsafeGetBase(),
                    offset(bb, base, handle.alignmentMask),
                    value);
        } else {
            return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, handle.alignmentMask), value);
        }
    }

    @ForceInline
    static int getAndBitwiseXorConvEndianWithCAS(MemoryAddressProxy bb, long offset, int value) {
        int nativeExpectedValue, expectedValue;
        Object base = bb.unsafeGetBase();
        do {
            nativeExpectedValue = UNSAFE.getIntVolatile(base, offset);
            expectedValue = Integer.reverseBytes(nativeExpectedValue);
        } while (!UNSAFE.weakCompareAndSetInt(base, offset,
                nativeExpectedValue, Integer.reverseBytes(expectedValue ^ value)));
        return expectedValue;
    }
}
