mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-24 21:34:52 +02:00
8350118: Simplify the layout access VarHandle
Reviewed-by: mcimadamore, jvernee, erikj
This commit is contained in:
parent
fb659eba02
commit
c7fa499bf5
18 changed files with 1977 additions and 1140 deletions
|
@ -42,6 +42,17 @@ define GenerateScopedOp
|
||||||
|
|
||||||
$1_Type := $2
|
$1_Type := $2
|
||||||
|
|
||||||
|
ifeq ($$($1_Type), Boolean)
|
||||||
|
$1_type := boolean
|
||||||
|
$1_BoxType := $$($1_Type)
|
||||||
|
|
||||||
|
$1_rawType := $$($1_type)
|
||||||
|
$1_RawType := $$($1_Type)
|
||||||
|
$1_RawBoxType := $$($1_BoxType)
|
||||||
|
|
||||||
|
$1_ARGS += -KCAS
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($$($1_Type), Byte)
|
ifeq ($$($1_Type), Byte)
|
||||||
$1_type := byte
|
$1_type := byte
|
||||||
$1_BoxType := $$($1_Type)
|
$1_BoxType := $$($1_Type)
|
||||||
|
@ -50,6 +61,7 @@ define GenerateScopedOp
|
||||||
$1_RawType := $$($1_Type)
|
$1_RawType := $$($1_Type)
|
||||||
$1_RawBoxType := $$($1_BoxType)
|
$1_RawBoxType := $$($1_BoxType)
|
||||||
|
|
||||||
|
$1_ARGS += -KCAS
|
||||||
$1_ARGS += -Kbyte
|
$1_ARGS += -Kbyte
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -60,6 +72,8 @@ define GenerateScopedOp
|
||||||
$1_rawType := $$($1_type)
|
$1_rawType := $$($1_type)
|
||||||
$1_RawType := $$($1_Type)
|
$1_RawType := $$($1_Type)
|
||||||
$1_RawBoxType := $$($1_BoxType)
|
$1_RawBoxType := $$($1_BoxType)
|
||||||
|
|
||||||
|
$1_ARGS += -KCAS
|
||||||
$1_ARGS += -KUnaligned
|
$1_ARGS += -KUnaligned
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -70,6 +84,8 @@ define GenerateScopedOp
|
||||||
$1_rawType := $$($1_type)
|
$1_rawType := $$($1_type)
|
||||||
$1_RawType := $$($1_Type)
|
$1_RawType := $$($1_Type)
|
||||||
$1_RawBoxType := $$($1_BoxType)
|
$1_RawBoxType := $$($1_BoxType)
|
||||||
|
|
||||||
|
$1_ARGS += -KCAS
|
||||||
$1_ARGS += -KUnaligned
|
$1_ARGS += -KUnaligned
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -82,8 +98,6 @@ define GenerateScopedOp
|
||||||
$1_RawBoxType := $$($1_BoxType)
|
$1_RawBoxType := $$($1_BoxType)
|
||||||
|
|
||||||
$1_ARGS += -KCAS
|
$1_ARGS += -KCAS
|
||||||
$1_ARGS += -KAtomicAdd
|
|
||||||
$1_ARGS += -KBitwise
|
|
||||||
$1_ARGS += -KUnaligned
|
$1_ARGS += -KUnaligned
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -96,8 +110,6 @@ define GenerateScopedOp
|
||||||
$1_RawBoxType := $$($1_BoxType)
|
$1_RawBoxType := $$($1_BoxType)
|
||||||
|
|
||||||
$1_ARGS += -KCAS
|
$1_ARGS += -KCAS
|
||||||
$1_ARGS += -KAtomicAdd
|
|
||||||
$1_ARGS += -KBitwise
|
|
||||||
$1_ARGS += -KUnaligned
|
$1_ARGS += -KUnaligned
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -133,7 +145,7 @@ define GenerateScopedOp
|
||||||
$1_ARGS += -KBitwise
|
$1_ARGS += -KBitwise
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($$(findstring $$($1_Type), Byte Short Char), )
|
ifneq ($$(findstring $$($1_Type), Boolean Byte Short Char), )
|
||||||
$1_ARGS += -KShorterThanInt
|
$1_ARGS += -KShorterThanInt
|
||||||
endif
|
endif
|
||||||
endef
|
endef
|
||||||
|
@ -141,7 +153,7 @@ endef
|
||||||
################################################################################
|
################################################################################
|
||||||
# Setup a rule for generating the ScopedMemoryAccess java class
|
# Setup a rule for generating the ScopedMemoryAccess java class
|
||||||
|
|
||||||
SCOPE_MEMORY_ACCESS_TYPES := Byte Short Char Int Long Float Double
|
SCOPE_MEMORY_ACCESS_TYPES := Boolean Byte Short Char Int Long Float Double
|
||||||
$(foreach t, $(SCOPE_MEMORY_ACCESS_TYPES), \
|
$(foreach t, $(SCOPE_MEMORY_ACCESS_TYPES), \
|
||||||
$(eval $(call GenerateScopedOp,BIN_$t,$t)))
|
$(eval $(call GenerateScopedOp,BIN_$t,$t)))
|
||||||
|
|
||||||
|
|
|
@ -174,6 +174,18 @@ define GenerateVarHandleMemorySegment
|
||||||
|
|
||||||
$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandleSegmentAs$$($1_Type)s.java
|
$1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandleSegmentAs$$($1_Type)s.java
|
||||||
|
|
||||||
|
ifeq ($$($1_Type), Boolean)
|
||||||
|
$1_type := boolean
|
||||||
|
$1_BoxType := $$($1_Type)
|
||||||
|
|
||||||
|
$1_rawType := $$($1_type)
|
||||||
|
$1_RawType := $$($1_Type)
|
||||||
|
$1_RawBoxType := $$($1_BoxType)
|
||||||
|
|
||||||
|
$1_ARGS += -Kbyte
|
||||||
|
$1_ARGS += -KShorterThanInt
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($$($1_Type), Byte)
|
ifeq ($$($1_Type), Byte)
|
||||||
$1_type := byte
|
$1_type := byte
|
||||||
$1_BoxType := $$($1_Type)
|
$1_BoxType := $$($1_Type)
|
||||||
|
@ -183,6 +195,7 @@ define GenerateVarHandleMemorySegment
|
||||||
$1_RawBoxType := $$($1_BoxType)
|
$1_RawBoxType := $$($1_BoxType)
|
||||||
|
|
||||||
$1_ARGS += -Kbyte
|
$1_ARGS += -Kbyte
|
||||||
|
$1_ARGS += -KShorterThanInt
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($$($1_Type), Short)
|
ifeq ($$($1_Type), Short)
|
||||||
|
@ -192,6 +205,8 @@ define GenerateVarHandleMemorySegment
|
||||||
$1_rawType := $$($1_type)
|
$1_rawType := $$($1_type)
|
||||||
$1_RawType := $$($1_Type)
|
$1_RawType := $$($1_Type)
|
||||||
$1_RawBoxType := $$($1_BoxType)
|
$1_RawBoxType := $$($1_BoxType)
|
||||||
|
|
||||||
|
$1_ARGS += -KShorterThanInt
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($$($1_Type), Char)
|
ifeq ($$($1_Type), Char)
|
||||||
|
@ -201,6 +216,8 @@ define GenerateVarHandleMemorySegment
|
||||||
$1_rawType := $$($1_type)
|
$1_rawType := $$($1_type)
|
||||||
$1_RawType := $$($1_Type)
|
$1_RawType := $$($1_Type)
|
||||||
$1_RawBoxType := $$($1_BoxType)
|
$1_RawBoxType := $$($1_BoxType)
|
||||||
|
|
||||||
|
$1_ARGS += -KShorterThanInt
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($$($1_Type), Int)
|
ifeq ($$($1_Type), Int)
|
||||||
|
@ -277,7 +294,7 @@ $(foreach t, $(VARHANDLES_BYTE_ARRAY_TYPES), \
|
||||||
$(eval $(call GenerateVarHandleByteArray,VAR_HANDLE_BYTE_ARRAY_$t,$t)))
|
$(eval $(call GenerateVarHandleByteArray,VAR_HANDLE_BYTE_ARRAY_$t,$t)))
|
||||||
|
|
||||||
# List the types to generate source for, with capitalized first letter
|
# List the types to generate source for, with capitalized first letter
|
||||||
VARHANDLES_MEMORY_SEGMENT_TYPES := Byte Short Char Int Long Float Double
|
VARHANDLES_MEMORY_SEGMENT_TYPES := Boolean Byte Short Char Int Long Float Double
|
||||||
$(foreach t, $(VARHANDLES_MEMORY_SEGMENT_TYPES), \
|
$(foreach t, $(VARHANDLES_MEMORY_SEGMENT_TYPES), \
|
||||||
$(eval $(call GenerateVarHandleMemorySegment,VAR_HANDLE_MEMORY_SEGMENT_$t,$t)))
|
$(eval $(call GenerateVarHandleMemorySegment,VAR_HANDLE_MEMORY_SEGMENT_$t,$t)))
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -43,6 +43,7 @@ import sun.invoke.util.Wrapper;
|
||||||
|
|
||||||
import java.lang.classfile.ClassFile;
|
import java.lang.classfile.ClassFile;
|
||||||
import java.lang.constant.ClassDesc;
|
import java.lang.constant.ClassDesc;
|
||||||
|
import java.lang.foreign.MemoryLayout;
|
||||||
import java.lang.invoke.MethodHandles.Lookup;
|
import java.lang.invoke.MethodHandles.Lookup;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
@ -1552,8 +1553,8 @@ abstract class MethodHandleImpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VarHandle memorySegmentViewHandle(Class<?> carrier, long alignmentMask, ByteOrder order) {
|
public VarHandle memorySegmentViewHandle(Class<?> carrier, MemoryLayout enclosing, long alignmentMask, ByteOrder order, boolean constantOffset, long offset) {
|
||||||
return VarHandles.memorySegmentViewHandle(carrier, alignmentMask, order);
|
return VarHandles.memorySegmentViewHandle(carrier, enclosing, alignmentMask, constantOffset, offset, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019, 2025, 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. Oracle designates this
|
||||||
|
* particular file as subject to the "Classpath" exception as provided
|
||||||
|
* by Oracle in the LICENSE file that accompanied this code.
|
||||||
|
*
|
||||||
|
* 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.lang.invoke;
|
||||||
|
|
||||||
|
import java.lang.foreign.MemoryLayout;
|
||||||
|
import java.lang.foreign.MemorySegment;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import jdk.internal.foreign.AbstractMemorySegmentImpl;
|
||||||
|
import jdk.internal.misc.ScopedMemoryAccess;
|
||||||
|
import jdk.internal.vm.annotation.ForceInline;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A var handle that accesses primitive values in a memory segment.
|
||||||
|
*/
|
||||||
|
final class SegmentVarHandle extends VarHandle {
|
||||||
|
|
||||||
|
// Common implementation fields for the VarForms
|
||||||
|
static final boolean BE = MethodHandleStatics.UNSAFE.isBigEndian();
|
||||||
|
static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
|
||||||
|
|
||||||
|
/** endianness **/
|
||||||
|
final boolean be;
|
||||||
|
/** The layout the accessed segment must be compatible with. */
|
||||||
|
final MemoryLayout enclosing;
|
||||||
|
/** The offset value, if is constant. vform decides if offset is constant or variable. */
|
||||||
|
final long offset;
|
||||||
|
|
||||||
|
SegmentVarHandle(VarForm form, boolean be, MemoryLayout enclosing, long offset, boolean exact) {
|
||||||
|
super(form, exact);
|
||||||
|
this.be = be;
|
||||||
|
this.enclosing = enclosing;
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
final MethodType accessModeTypeUncached(VarHandle.AccessType accessType) {
|
||||||
|
var getType = vform.methodType_table[0]; // erased, but our value type is erase-compatible
|
||||||
|
return getType.parameterCount() == 2
|
||||||
|
? accessType.accessModeType(MemorySegment.class, getType.returnType(), long.class)
|
||||||
|
: accessType.accessModeType(MemorySegment.class, getType.returnType(), long.class, long.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SegmentVarHandle withInvokeExactBehavior() {
|
||||||
|
return hasInvokeExactBehavior() ?
|
||||||
|
this :
|
||||||
|
new SegmentVarHandle(vform, be, enclosing, offset, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SegmentVarHandle withInvokeBehavior() {
|
||||||
|
return !hasInvokeExactBehavior() ?
|
||||||
|
this :
|
||||||
|
new SegmentVarHandle(vform, be, enclosing, offset, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common implementation methods for the VarForms
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static long offset(AbstractMemorySegmentImpl bb, long base, long offset) {
|
||||||
|
long segment_base = bb.unsafeGetOffset();
|
||||||
|
return segment_base + base + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
AbstractMemorySegmentImpl checkSegment(Object obb, long base, boolean ro) {
|
||||||
|
AbstractMemorySegmentImpl oo = (AbstractMemorySegmentImpl) Objects.requireNonNull(obb);
|
||||||
|
oo.checkEnclosingLayout(base, this.enclosing, ro);
|
||||||
|
return oo;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -36,6 +36,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
|
import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
|
||||||
|
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A var handle form containing a set of member name, one for each operation.
|
* A var handle form containing a set of member name, one for each operation.
|
||||||
|
@ -43,6 +44,7 @@ import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
|
||||||
*/
|
*/
|
||||||
final class VarForm {
|
final class VarForm {
|
||||||
|
|
||||||
|
// implClass must be initialized when the member names are accessed!
|
||||||
final Class<?> implClass;
|
final Class<?> implClass;
|
||||||
|
|
||||||
final @Stable MethodType[] methodType_table;
|
final @Stable MethodType[] methodType_table;
|
||||||
|
@ -63,6 +65,15 @@ final class VarForm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VarForm(Class<?> implClass, VarForm methodTypeSource) {
|
||||||
|
this.implClass = implClass;
|
||||||
|
// reuse initMethodTypes result from methodTypeSource
|
||||||
|
this.methodType_table = methodTypeSource.methodType_table;
|
||||||
|
this.methodType_V_table = methodTypeSource.methodType_V_table;
|
||||||
|
this.memberName_table = new MemberName[VarHandle.AccessMode.COUNT];
|
||||||
|
assert assertMethodTypeTableInitialized() : implClass;
|
||||||
|
}
|
||||||
|
|
||||||
// Used by IndirectVarHandle
|
// Used by IndirectVarHandle
|
||||||
VarForm(Class<?> value, Class<?>[] coordinates) {
|
VarForm(Class<?> value, Class<?>[] coordinates) {
|
||||||
this.methodType_table = new MethodType[VarHandle.AccessType.COUNT];
|
this.methodType_table = new MethodType[VarHandle.AccessType.COUNT];
|
||||||
|
@ -103,6 +114,15 @@ final class VarForm {
|
||||||
type.changeReturnType(boolean.class);
|
type.changeReturnType(boolean.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean assertMethodTypeTableInitialized() {
|
||||||
|
if (methodType_table == null)
|
||||||
|
return false;
|
||||||
|
for (int i = 0; i < VarHandle.AccessType.COUNT; i++) {
|
||||||
|
assert methodType_table[i] != null : implClass + " " + VarHandle.AccessType.values()[i];
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
final MethodType getMethodType(int type) {
|
final MethodType getMethodType(int type) {
|
||||||
return methodType_table[type];
|
return methodType_table[type];
|
||||||
|
@ -137,6 +157,7 @@ final class VarForm {
|
||||||
AccessMode value = AccessMode.valueFromOrdinal(mode);
|
AccessMode value = AccessMode.valueFromOrdinal(mode);
|
||||||
String methodName = value.methodName();
|
String methodName = value.methodName();
|
||||||
MethodType type = methodType_table[value.at.ordinal()].insertParameterTypes(0, VarHandle.class);
|
MethodType type = methodType_table[value.at.ordinal()].insertParameterTypes(0, VarHandle.class);
|
||||||
|
assert !UNSAFE.shouldBeInitialized(implClass) : implClass;
|
||||||
return memberName_table[mode] = MethodHandles.Lookup.IMPL_LOOKUP
|
return memberName_table[mode] = MethodHandles.Lookup.IMPL_LOOKUP
|
||||||
.resolveOrNull(REF_invokeStatic, implClass, methodName, type);
|
.resolveOrNull(REF_invokeStatic, implClass, methodName, type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -472,8 +472,7 @@ import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
||||||
* @since 9
|
* @since 9
|
||||||
*/
|
*/
|
||||||
public abstract sealed class VarHandle implements Constable
|
public abstract sealed class VarHandle implements Constable
|
||||||
permits IndirectVarHandle, LazyInitializingVarHandle,
|
permits IndirectVarHandle, LazyInitializingVarHandle, SegmentVarHandle,
|
||||||
VarHandleSegmentViewBase,
|
|
||||||
VarHandleByteArrayAsChars.ByteArrayViewVarHandle,
|
VarHandleByteArrayAsChars.ByteArrayViewVarHandle,
|
||||||
VarHandleByteArrayAsDoubles.ByteArrayViewVarHandle,
|
VarHandleByteArrayAsDoubles.ByteArrayViewVarHandle,
|
||||||
VarHandleByteArrayAsFloats.ByteArrayViewVarHandle,
|
VarHandleByteArrayAsFloats.ByteArrayViewVarHandle,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019, 2024, 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. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* 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.lang.invoke;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for memory segment var handle view implementations.
|
|
||||||
*/
|
|
||||||
abstract sealed class VarHandleSegmentViewBase extends VarHandle permits
|
|
||||||
VarHandleSegmentAsBytes,
|
|
||||||
VarHandleSegmentAsChars,
|
|
||||||
VarHandleSegmentAsDoubles,
|
|
||||||
VarHandleSegmentAsFloats,
|
|
||||||
VarHandleSegmentAsInts,
|
|
||||||
VarHandleSegmentAsLongs,
|
|
||||||
VarHandleSegmentAsShorts {
|
|
||||||
|
|
||||||
/** endianness **/
|
|
||||||
final boolean be;
|
|
||||||
|
|
||||||
/** alignment constraint (in bytes, expressed as a bit mask) **/
|
|
||||||
final long alignmentMask;
|
|
||||||
|
|
||||||
VarHandleSegmentViewBase(VarForm form, boolean be, long alignmentMask, boolean exact) {
|
|
||||||
super(form, exact);
|
|
||||||
this.be = be;
|
|
||||||
this.alignmentMask = alignmentMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
static UnsupportedOperationException newUnsupportedAccessModeForAlignment(long alignment) {
|
|
||||||
return new UnsupportedOperationException("Unsupported access mode for alignment: " + alignment);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,6 +27,7 @@ package java.lang.invoke;
|
||||||
|
|
||||||
import sun.invoke.util.Wrapper;
|
import sun.invoke.util.Wrapper;
|
||||||
|
|
||||||
|
import java.lang.foreign.MemoryLayout;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
@ -291,44 +292,55 @@ final class VarHandles {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a memory segment view var handle.
|
* Creates a memory segment view var handle accessing a {@code carrier} element. It has access coordinates
|
||||||
*
|
* {@code (MS, long)} if {@code constantOffset}, {@code (MS, long, (validated) long)} otherwise.
|
||||||
|
* <p>
|
||||||
* The resulting var handle will take a memory segment as first argument (the segment to be dereferenced),
|
* The resulting var handle will take a memory segment as first argument (the segment to be dereferenced),
|
||||||
* and a {@code long} as second argument (the offset into the segment).
|
* and a {@code long} as second argument (the offset into the segment). Both arguments are checked.
|
||||||
|
* <p>
|
||||||
|
* If {@code constantOffset == false}, the resulting var handle will take a third pre-validated additional
|
||||||
|
* offset instead of the given fixed {@code offset}, and caller must ensure that passed additional offset,
|
||||||
|
* either to the handle (such as computing through method handles) or as fixed {@code offset} here, is valid.
|
||||||
*
|
*
|
||||||
* Note: the returned var handle does not perform any size or alignment check. It is up to clients
|
* @param carrier the Java carrier type of the element
|
||||||
* to adapt the returned var handle and insert the appropriate checks.
|
* @param enclosing the enclosing layout to perform bound and alignment checks against
|
||||||
*
|
* @param alignmentMask alignment of this accessed element in the enclosing layout
|
||||||
* @param carrier the Java carrier type.
|
* @param constantOffset if access path has a constant offset value, i.e. it has no strides
|
||||||
* @param alignmentMask alignment requirement to be checked upon access. In bytes. Expressed as a mask.
|
* @param offset the offset value, if the offset is constant
|
||||||
* @param byteOrder the byte order.
|
* @param byteOrder the byte order
|
||||||
* @return the created VarHandle.
|
* @return the created var handle
|
||||||
*/
|
*/
|
||||||
static VarHandle memorySegmentViewHandle(Class<?> carrier, long alignmentMask,
|
static VarHandle memorySegmentViewHandle(Class<?> carrier, MemoryLayout enclosing, long alignmentMask,
|
||||||
ByteOrder byteOrder) {
|
boolean constantOffset, long offset, ByteOrder byteOrder) {
|
||||||
if (!carrier.isPrimitive() || carrier == void.class || carrier == boolean.class) {
|
if (!carrier.isPrimitive() || carrier == void.class) {
|
||||||
throw new IllegalArgumentException("Invalid carrier: " + carrier.getName());
|
throw new IllegalArgumentException("Invalid carrier: " + carrier.getName());
|
||||||
}
|
}
|
||||||
boolean be = byteOrder == ByteOrder.BIG_ENDIAN;
|
boolean be = byteOrder == ByteOrder.BIG_ENDIAN;
|
||||||
boolean exact = VAR_HANDLE_SEGMENT_FORCE_EXACT;
|
boolean exact = VAR_HANDLE_SEGMENT_FORCE_EXACT;
|
||||||
|
|
||||||
|
// All carrier types must persist across MethodType erasure
|
||||||
|
VarForm form;
|
||||||
if (carrier == byte.class) {
|
if (carrier == byte.class) {
|
||||||
return maybeAdapt(new VarHandleSegmentAsBytes(be, alignmentMask, exact));
|
form = VarHandleSegmentAsBytes.selectForm(alignmentMask, constantOffset);
|
||||||
} else if (carrier == char.class) {
|
} else if (carrier == char.class) {
|
||||||
return maybeAdapt(new VarHandleSegmentAsChars(be, alignmentMask, exact));
|
form = VarHandleSegmentAsChars.selectForm(alignmentMask, constantOffset);
|
||||||
} else if (carrier == short.class) {
|
} else if (carrier == short.class) {
|
||||||
return maybeAdapt(new VarHandleSegmentAsShorts(be, alignmentMask, exact));
|
form = VarHandleSegmentAsShorts.selectForm(alignmentMask, constantOffset);
|
||||||
} else if (carrier == int.class) {
|
} else if (carrier == int.class) {
|
||||||
return maybeAdapt(new VarHandleSegmentAsInts(be, alignmentMask, exact));
|
form = VarHandleSegmentAsInts.selectForm(alignmentMask, constantOffset);
|
||||||
} else if (carrier == float.class) {
|
} else if (carrier == float.class) {
|
||||||
return maybeAdapt(new VarHandleSegmentAsFloats(be, alignmentMask, exact));
|
form = VarHandleSegmentAsFloats.selectForm(alignmentMask, constantOffset);
|
||||||
} else if (carrier == long.class) {
|
} else if (carrier == long.class) {
|
||||||
return maybeAdapt(new VarHandleSegmentAsLongs(be, alignmentMask, exact));
|
form = VarHandleSegmentAsLongs.selectForm(alignmentMask, constantOffset);
|
||||||
} else if (carrier == double.class) {
|
} else if (carrier == double.class) {
|
||||||
return maybeAdapt(new VarHandleSegmentAsDoubles(be, alignmentMask, exact));
|
form = VarHandleSegmentAsDoubles.selectForm(alignmentMask, constantOffset);
|
||||||
|
} else if (carrier == boolean.class) {
|
||||||
|
form = VarHandleSegmentAsBooleans.selectForm(alignmentMask, constantOffset);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("Cannot get here");
|
throw new IllegalStateException("Cannot get here");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return maybeAdapt(new SegmentVarHandle(form, be, enclosing, offset, exact));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static VarHandle maybeAdapt(VarHandle target) {
|
private static VarHandle maybeAdapt(VarHandle target) {
|
||||||
|
@ -724,7 +736,7 @@ final class VarHandles {
|
||||||
// Object getAndUpdate(Object value);
|
// Object getAndUpdate(Object value);
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// record HandleType(Class<?> receiver, Class<?> value, Class<?>... intermediates) {
|
// record HandleType(Class<?> receiver, Class<?>... intermediates) {
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// /**
|
// /**
|
||||||
|
@ -744,48 +756,31 @@ final class VarHandles {
|
||||||
// System.out.println();
|
// System.out.println();
|
||||||
//
|
//
|
||||||
// // Declare the stream of shapes
|
// // Declare the stream of shapes
|
||||||
// Stream<HandleType> hts = Stream.of(
|
// List<HandleType> hts = List.of(
|
||||||
// // Object->Object
|
// // Object->T
|
||||||
// new HandleType(Object.class, Object.class),
|
// new HandleType(Object.class),
|
||||||
// // Object->int
|
//
|
||||||
|
// // <static>->T
|
||||||
|
// new HandleType(null),
|
||||||
|
//
|
||||||
|
// // Array[index]->T
|
||||||
// new HandleType(Object.class, int.class),
|
// new HandleType(Object.class, int.class),
|
||||||
// // Object->long
|
//
|
||||||
|
// // MS[base]->T
|
||||||
// new HandleType(Object.class, long.class),
|
// new HandleType(Object.class, long.class),
|
||||||
// // Object->float
|
|
||||||
// new HandleType(Object.class, float.class),
|
|
||||||
// // Object->double
|
|
||||||
// new HandleType(Object.class, double.class),
|
|
||||||
//
|
//
|
||||||
// // <static>->Object
|
// // MS[base][offset]->T
|
||||||
// new HandleType(null, Object.class),
|
|
||||||
// // <static>->int
|
|
||||||
// new HandleType(null, int.class),
|
|
||||||
// // <static>->long
|
|
||||||
// new HandleType(null, long.class),
|
|
||||||
// // <static>->float
|
|
||||||
// new HandleType(null, float.class),
|
|
||||||
// // <static>->double
|
|
||||||
// new HandleType(null, double.class),
|
|
||||||
//
|
|
||||||
// // Array[int]->Object
|
|
||||||
// new HandleType(Object.class, Object.class, int.class),
|
|
||||||
// // Array[int]->int
|
|
||||||
// new HandleType(Object.class, int.class, int.class),
|
|
||||||
// // Array[int]->long
|
|
||||||
// new HandleType(Object.class, long.class, int.class),
|
|
||||||
// // Array[int]->float
|
|
||||||
// new HandleType(Object.class, float.class, int.class),
|
|
||||||
// // Array[int]->double
|
|
||||||
// new HandleType(Object.class, double.class, int.class),
|
|
||||||
//
|
|
||||||
// // Array[long]->int
|
|
||||||
// new HandleType(Object.class, int.class, long.class),
|
|
||||||
// // Array[long]->long
|
|
||||||
// new HandleType(Object.class, long.class, long.class)
|
// new HandleType(Object.class, long.class, long.class)
|
||||||
// );
|
// );
|
||||||
//
|
//
|
||||||
// hts.flatMap(ht -> Stream.of(VarHandleTemplate.class.getMethods()).
|
// Stream.of(VarHandleTemplate.class.getMethods()).<MethodType>
|
||||||
// map(m -> generateMethodType(m, ht.receiver, ht.value, ht.intermediates))).
|
// mapMulti((m, sink) -> {
|
||||||
|
// for (var ht : hts) {
|
||||||
|
// for (var bt : LambdaForm.BasicType.ARG_TYPES) {
|
||||||
|
// sink.accept(generateMethodType(m, ht.receiver, bt.btClass, ht.intermediates));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }).
|
||||||
// distinct().
|
// distinct().
|
||||||
// map(GuardMethodGenerator::generateMethod).
|
// map(GuardMethodGenerator::generateMethod).
|
||||||
// forEach(System.out::println);
|
// forEach(System.out::println);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,53 +25,106 @@
|
||||||
package java.lang.invoke;
|
package java.lang.invoke;
|
||||||
|
|
||||||
import jdk.internal.foreign.AbstractMemorySegmentImpl;
|
import jdk.internal.foreign.AbstractMemorySegmentImpl;
|
||||||
import jdk.internal.foreign.Utils;
|
|
||||||
import jdk.internal.misc.ScopedMemoryAccess;
|
|
||||||
import jdk.internal.vm.annotation.ForceInline;
|
import jdk.internal.vm.annotation.ForceInline;
|
||||||
|
|
||||||
import java.lang.foreign.MemoryLayout;
|
|
||||||
import java.lang.foreign.MemorySegment;
|
import java.lang.foreign.MemorySegment;
|
||||||
import java.lang.ref.Reference;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
import static java.lang.invoke.SegmentVarHandle.*;
|
||||||
|
|
||||||
import static java.lang.invoke.MethodHandleStatics.UNSAFE;
|
|
||||||
|
|
||||||
#warn
|
#warn
|
||||||
|
|
||||||
final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase {
|
{#if[byte]?final:sealed} class VarHandleSegmentAs$Type$s {
|
||||||
|
|
||||||
static final boolean BE = UNSAFE.isBigEndian();
|
|
||||||
|
|
||||||
static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess();
|
|
||||||
|
|
||||||
|
#if[!byte]
|
||||||
static final int NON_PLAIN_ACCESS_MIN_ALIGN_MASK = $BoxType$.BYTES - 1;
|
static final int NON_PLAIN_ACCESS_MIN_ALIGN_MASK = $BoxType$.BYTES - 1;
|
||||||
|
|
||||||
static final VarForm FORM = new VarForm(VarHandleSegmentAs$Type$s.class, MemorySegment.class, $type$.class, MemoryLayout.class, long.class, long.class);
|
#end[byte]
|
||||||
|
static VarForm selectForm(long alignmentMask, boolean constantOffset) {
|
||||||
VarHandleSegmentAs$Type$s(boolean be, long alignmentMask, boolean exact) {
|
#if[byte]
|
||||||
super(FORM, be, alignmentMask, exact);
|
return constantOffset ? CONSTANT_OFFSET_FORM : VARIABLE_OFFSET_FORM;
|
||||||
|
#else[byte]
|
||||||
|
return (alignmentMask & NON_PLAIN_ACCESS_MIN_ALIGN_MASK) != NON_PLAIN_ACCESS_MIN_ALIGN_MASK ?
|
||||||
|
(constantOffset ? CONSTANT_OFFSET_FORM : VARIABLE_OFFSET_FORM) :
|
||||||
|
(constantOffset ? VarHandleSegmentAs$Type$sAligned.CONSTANT_OFFSET_FORM : VarHandleSegmentAs$Type$sAligned.VARIABLE_OFFSET_FORM);
|
||||||
|
#end[byte]
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
static final VarForm CONSTANT_OFFSET_FORM = new VarForm(VarHandleSegmentAs$Type$s.class, MemorySegment.class, $type$.class, long.class);
|
||||||
final MethodType accessModeTypeUncached(VarHandle.AccessType accessType) {
|
static final VarForm VARIABLE_OFFSET_FORM = new VarForm(VarHandleSegmentAs$Type$s.class, MemorySegment.class, $type$.class, long.class, long.class);
|
||||||
return accessType.accessModeType(MemorySegment.class, $type$.class, MemoryLayout.class, long.class, long.class);
|
|
||||||
|
VarHandleSegmentAs$Type$s() { throw new AssertionError(); }
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ get(VarHandle ob, Object obb, long base) {
|
||||||
|
return get(ob, obb, base, ((SegmentVarHandle) ob).offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ForceInline
|
||||||
public VarHandleSegmentAs$Type$s withInvokeExactBehavior() {
|
static $type$ get(VarHandle ob, Object obb, long base, long offset) {
|
||||||
return hasInvokeExactBehavior() ?
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
this :
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, true);
|
||||||
new VarHandleSegmentAs$Type$s(be, alignmentMask, true);
|
#if[floatingPoint]
|
||||||
|
$rawType$ rawValue = SCOPED_MEMORY_ACCESS.get$RawType$Unaligned(bb.sessionImpl(),
|
||||||
|
bb.unsafeGetBase(),
|
||||||
|
offset(bb, base, offset),
|
||||||
|
handle.be);
|
||||||
|
return $Type$.$rawType$BitsTo$Type$(rawValue);
|
||||||
|
#else[floatingPoint]
|
||||||
|
#if[byte]
|
||||||
|
return SCOPED_MEMORY_ACCESS.get$Type$(bb.sessionImpl(),
|
||||||
|
bb.unsafeGetBase(),
|
||||||
|
offset(bb, base, offset));
|
||||||
|
#else[byte]
|
||||||
|
return SCOPED_MEMORY_ACCESS.get$Type$Unaligned(bb.sessionImpl(),
|
||||||
|
bb.unsafeGetBase(),
|
||||||
|
offset(bb, base, offset),
|
||||||
|
handle.be);
|
||||||
|
#end[byte]
|
||||||
|
#end[floatingPoint]
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ForceInline
|
||||||
public VarHandleSegmentAs$Type$s withInvokeBehavior() {
|
static void set(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
return !hasInvokeExactBehavior() ?
|
set(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
this :
|
|
||||||
new VarHandleSegmentAs$Type$s(be, alignmentMask, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static void set(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
|
#if[floatingPoint]
|
||||||
|
SCOPED_MEMORY_ACCESS.put$RawType$Unaligned(bb.sessionImpl(),
|
||||||
|
bb.unsafeGetBase(),
|
||||||
|
offset(bb, base, offset),
|
||||||
|
$Type$.$type$ToRaw$RawType$Bits(value),
|
||||||
|
handle.be);
|
||||||
|
#else[floatingPoint]
|
||||||
|
#if[byte]
|
||||||
|
SCOPED_MEMORY_ACCESS.put$Type$(bb.sessionImpl(),
|
||||||
|
bb.unsafeGetBase(),
|
||||||
|
offset(bb, base, offset),
|
||||||
|
value);
|
||||||
|
#else[byte]
|
||||||
|
SCOPED_MEMORY_ACCESS.put$Type$Unaligned(bb.sessionImpl(),
|
||||||
|
bb.unsafeGetBase(),
|
||||||
|
offset(bb, base, offset),
|
||||||
|
value,
|
||||||
|
handle.be);
|
||||||
|
#end[byte]
|
||||||
|
#end[floatingPoint]
|
||||||
|
}
|
||||||
|
#if[!byte]
|
||||||
|
}
|
||||||
|
|
||||||
|
// This class must be accessed through non-aligned VarHandleSegmentAs$Type$s
|
||||||
|
final class VarHandleSegmentAs$Type$sAligned extends VarHandleSegmentAs$Type$s {
|
||||||
|
|
||||||
|
static final VarForm CONSTANT_OFFSET_FORM = new VarForm(VarHandleSegmentAs$Type$sAligned.class, VarHandleSegmentAs$Type$s.CONSTANT_OFFSET_FORM);
|
||||||
|
static final VarForm VARIABLE_OFFSET_FORM = new VarForm(VarHandleSegmentAs$Type$sAligned.class, VarHandleSegmentAs$Type$s.VARIABLE_OFFSET_FORM);
|
||||||
|
|
||||||
|
VarHandleSegmentAs$Type$sAligned() { throw new AssertionError(); }
|
||||||
|
#end[byte]
|
||||||
|
|
||||||
#if[floatingPoint]
|
#if[floatingPoint]
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $rawType$ convEndian(boolean big, $type$ v) {
|
static $rawType$ convEndian(boolean big, $type$ v) {
|
||||||
|
@ -99,296 +152,338 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase {
|
||||||
#end[floatingPoint]
|
#end[floatingPoint]
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static AbstractMemorySegmentImpl checkSegment(Object obb, Object encl, long base, boolean ro) {
|
static $type$ getVolatile(VarHandle ob, Object obb, long base) {
|
||||||
AbstractMemorySegmentImpl oo = (AbstractMemorySegmentImpl)Objects.requireNonNull(obb);
|
return getVolatile(ob, obb, base, ((SegmentVarHandle) ob).offset);
|
||||||
oo.checkEnclosingLayout(base, (MemoryLayout)encl, ro);
|
|
||||||
return oo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static long offsetNonPlain(AbstractMemorySegmentImpl bb, long base, long offset, long alignmentMask) {
|
static $type$ getVolatile(VarHandle ob, Object obb, long base, long offset) {
|
||||||
if ((alignmentMask & NON_PLAIN_ACCESS_MIN_ALIGN_MASK) != NON_PLAIN_ACCESS_MIN_ALIGN_MASK) {
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
throw VarHandleSegmentViewBase.newUnsupportedAccessModeForAlignment(alignmentMask + 1);
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, true);
|
||||||
}
|
|
||||||
return offsetPlain(bb, base, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ForceInline
|
|
||||||
static long offsetPlain(AbstractMemorySegmentImpl bb, long base, long offset) {
|
|
||||||
long segment_base = bb.unsafeGetOffset();
|
|
||||||
return segment_base + base + offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ForceInline
|
|
||||||
static $type$ get(VarHandle ob, Object obb, Object encl, long base, long offset) {
|
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, true);
|
|
||||||
#if[floatingPoint]
|
|
||||||
$rawType$ rawValue = SCOPED_MEMORY_ACCESS.get$RawType$Unaligned(bb.sessionImpl(),
|
|
||||||
bb.unsafeGetBase(),
|
|
||||||
offsetPlain(bb, base, offset),
|
|
||||||
handle.be);
|
|
||||||
return $Type$.$rawType$BitsTo$Type$(rawValue);
|
|
||||||
#else[floatingPoint]
|
|
||||||
#if[byte]
|
|
||||||
return SCOPED_MEMORY_ACCESS.get$Type$(bb.sessionImpl(),
|
|
||||||
bb.unsafeGetBase(),
|
|
||||||
offsetPlain(bb, base, offset));
|
|
||||||
#else[byte]
|
|
||||||
return SCOPED_MEMORY_ACCESS.get$Type$Unaligned(bb.sessionImpl(),
|
|
||||||
bb.unsafeGetBase(),
|
|
||||||
offsetPlain(bb, base, offset),
|
|
||||||
handle.be);
|
|
||||||
#end[byte]
|
|
||||||
#end[floatingPoint]
|
|
||||||
}
|
|
||||||
|
|
||||||
@ForceInline
|
|
||||||
static void set(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
|
||||||
#if[floatingPoint]
|
|
||||||
SCOPED_MEMORY_ACCESS.put$RawType$Unaligned(bb.sessionImpl(),
|
|
||||||
bb.unsafeGetBase(),
|
|
||||||
offsetPlain(bb, base, offset),
|
|
||||||
$Type$.$type$ToRaw$RawType$Bits(value),
|
|
||||||
handle.be);
|
|
||||||
#else[floatingPoint]
|
|
||||||
#if[byte]
|
|
||||||
SCOPED_MEMORY_ACCESS.put$Type$(bb.sessionImpl(),
|
|
||||||
bb.unsafeGetBase(),
|
|
||||||
offsetPlain(bb, base, offset),
|
|
||||||
value);
|
|
||||||
#else[byte]
|
|
||||||
SCOPED_MEMORY_ACCESS.put$Type$Unaligned(bb.sessionImpl(),
|
|
||||||
bb.unsafeGetBase(),
|
|
||||||
offsetPlain(bb, base, offset),
|
|
||||||
value,
|
|
||||||
handle.be);
|
|
||||||
#end[byte]
|
|
||||||
#end[floatingPoint]
|
|
||||||
}
|
|
||||||
|
|
||||||
@ForceInline
|
|
||||||
static $type$ getVolatile(VarHandle ob, Object obb, Object encl, long base, long offset) {
|
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, true);
|
|
||||||
return convEndian(handle.be,
|
return convEndian(handle.be,
|
||||||
SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),
|
SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask)));
|
offset(bb, base, offset)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static void setVolatile(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static void setVolatile(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
setVolatile(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static void setVolatile(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
SCOPED_MEMORY_ACCESS.put$RawType$Volatile(bb.sessionImpl(),
|
SCOPED_MEMORY_ACCESS.put$RawType$Volatile(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, value));
|
convEndian(handle.be, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAcquire(VarHandle ob, Object obb, Object encl, long base, long offset) {
|
static $type$ getAcquire(VarHandle ob, Object obb, long base) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, true);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAcquire(VarHandle ob, Object obb, long base, long offset) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, true);
|
||||||
return convEndian(handle.be,
|
return convEndian(handle.be,
|
||||||
SCOPED_MEMORY_ACCESS.get$RawType$Acquire(bb.sessionImpl(),
|
SCOPED_MEMORY_ACCESS.get$RawType$Acquire(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask)));
|
offset(bb, base, offset)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static void setRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static void setRelease(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
setRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static void setRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
SCOPED_MEMORY_ACCESS.put$RawType$Release(bb.sessionImpl(),
|
SCOPED_MEMORY_ACCESS.put$RawType$Release(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, value));
|
convEndian(handle.be, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getOpaque(VarHandle ob, Object obb, Object encl, long base, long offset) {
|
static $type$ getOpaque(VarHandle ob, Object obb, long base) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getOpaque(ob, obb, base, ((SegmentVarHandle) ob).offset);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, true);
|
|
||||||
return convEndian(handle.be,
|
|
||||||
SCOPED_MEMORY_ACCESS.get$RawType$Opaque(bb.sessionImpl(),
|
|
||||||
bb.unsafeGetBase(),
|
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static void setOpaque(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static $type$ getOpaque(VarHandle ob, Object obb, long base, long offset) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, true);
|
||||||
|
return convEndian(handle.be,
|
||||||
|
SCOPED_MEMORY_ACCESS.get$RawType$Opaque(bb.sessionImpl(),
|
||||||
|
bb.unsafeGetBase(),
|
||||||
|
offset(bb, base, offset)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static void setOpaque(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
|
setOpaque(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static void setOpaque(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
SCOPED_MEMORY_ACCESS.put$RawType$Opaque(bb.sessionImpl(),
|
SCOPED_MEMORY_ACCESS.put$RawType$Opaque(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, value));
|
convEndian(handle.be, value));
|
||||||
}
|
}
|
||||||
#if[CAS]
|
#if[CAS]
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static boolean compareAndSet(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
static boolean compareAndSet(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return compareAndSet(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static boolean compareAndSet(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
return SCOPED_MEMORY_ACCESS.compareAndSet$RawType$(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.compareAndSet$RawType$(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ compareAndExchange(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
static $type$ compareAndExchange(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return compareAndExchange(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ compareAndExchange(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
return convEndian(handle.be,
|
return convEndian(handle.be,
|
||||||
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$(bb.sessionImpl(),
|
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ compareAndExchangeAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
static $type$ compareAndExchangeAcquire(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return compareAndExchangeAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ compareAndExchangeAcquire(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
return convEndian(handle.be,
|
return convEndian(handle.be,
|
||||||
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Acquire(bb.sessionImpl(),
|
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Acquire(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ compareAndExchangeRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
static $type$ compareAndExchangeRelease(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return compareAndExchangeRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ compareAndExchangeRelease(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
return convEndian(handle.be,
|
return convEndian(handle.be,
|
||||||
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Release(bb.sessionImpl(),
|
SCOPED_MEMORY_ACCESS.compareAndExchange$RawType$Release(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
convEndian(handle.be, expected), convEndian(handle.be, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static boolean weakCompareAndSetPlain(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
static boolean weakCompareAndSetPlain(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return weakCompareAndSetPlain(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static boolean weakCompareAndSetPlain(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Plain(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Plain(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static boolean weakCompareAndSet(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
static boolean weakCompareAndSet(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return weakCompareAndSet(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static boolean weakCompareAndSet(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static boolean weakCompareAndSetAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
static boolean weakCompareAndSetAcquire(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return weakCompareAndSetAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static boolean weakCompareAndSetAcquire(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Acquire(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Acquire(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static boolean weakCompareAndSetRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ expected, $type$ value) {
|
static boolean weakCompareAndSetRelease(VarHandle ob, Object obb, long base, $type$ expected, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return weakCompareAndSetRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, expected, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static boolean weakCompareAndSetRelease(VarHandle ob, Object obb, long base, long offset, $type$ expected, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Release(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$Release(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, expected), convEndian(handle.be, value));
|
convEndian(handle.be, expected), convEndian(handle.be, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndSet(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static $type$ getAndSet(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndSet(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndSet(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
return convEndian(handle.be,
|
return convEndian(handle.be,
|
||||||
SCOPED_MEMORY_ACCESS.getAndSet$RawType$(bb.sessionImpl(),
|
SCOPED_MEMORY_ACCESS.getAndSet$RawType$(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, value)));
|
convEndian(handle.be, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndSetAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static $type$ getAndSetAcquire(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndSetAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndSetAcquire(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
return convEndian(handle.be,
|
return convEndian(handle.be,
|
||||||
SCOPED_MEMORY_ACCESS.getAndSet$RawType$Acquire(bb.sessionImpl(),
|
SCOPED_MEMORY_ACCESS.getAndSet$RawType$Acquire(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, value)));
|
convEndian(handle.be, value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndSetRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static $type$ getAndSetRelease(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndSetRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndSetRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
return convEndian(handle.be,
|
return convEndian(handle.be,
|
||||||
SCOPED_MEMORY_ACCESS.getAndSet$RawType$Release(bb.sessionImpl(),
|
SCOPED_MEMORY_ACCESS.getAndSet$RawType$Release(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
convEndian(handle.be, value)));
|
convEndian(handle.be, value)));
|
||||||
}
|
}
|
||||||
#end[CAS]
|
#end[CAS]
|
||||||
#if[AtomicAdd]
|
#if[AtomicAdd]
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndAdd(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ delta) {
|
static $type$ getAndAdd(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndAdd(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndAdd(VarHandle ob, Object obb, long base, long offset, $type$ delta) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
|
#if[!byte]
|
||||||
if (handle.be == BE) {
|
if (handle.be == BE) {
|
||||||
|
#end[byte]
|
||||||
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
delta);
|
delta);
|
||||||
|
#if[!byte]
|
||||||
} else {
|
} else {
|
||||||
return getAndAddConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), delta);
|
return getAndAddConvEndianWithCAS(bb, offset(bb, base, offset), delta);
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndAddAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ delta) {
|
static $type$ getAndAddAcquire(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndAddAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndAddAcquire(VarHandle ob, Object obb, long base, long offset, $type$ delta) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
|
#if[!byte]
|
||||||
if (handle.be == BE) {
|
if (handle.be == BE) {
|
||||||
|
#end[byte]
|
||||||
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Acquire(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Acquire(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
delta);
|
delta);
|
||||||
|
#if[!byte]
|
||||||
} else {
|
} else {
|
||||||
return getAndAddConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), delta);
|
return getAndAddConvEndianWithCAS(bb, offset(bb, base, offset), delta);
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndAddRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ delta) {
|
static $type$ getAndAddRelease(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndAddRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndAddRelease(VarHandle ob, Object obb, long base, long offset, $type$ delta) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
|
#if[!byte]
|
||||||
if (handle.be == BE) {
|
if (handle.be == BE) {
|
||||||
|
#end[byte]
|
||||||
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Release(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.getAndAdd$RawType$Release(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
delta);
|
delta);
|
||||||
|
#if[!byte]
|
||||||
} else {
|
} else {
|
||||||
return getAndAddConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), delta);
|
return getAndAddConvEndianWithCAS(bb, offset(bb, base, offset), delta);
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
}
|
}
|
||||||
|
#if[!byte]
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndAddConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ delta) {
|
static $type$ getAndAddConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ delta) {
|
||||||
|
@ -398,53 +493,82 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase {
|
||||||
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset);
|
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset);
|
||||||
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
|
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
|
||||||
} while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset,
|
} while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset,
|
||||||
nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue + delta)));
|
nativeExpectedValue, $RawBoxType$.reverseBytes({#if[ShorterThanInt]?($type$) }(expectedValue + delta))));
|
||||||
return expectedValue;
|
return expectedValue;
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
#end[AtomicAdd]
|
#end[AtomicAdd]
|
||||||
#if[Bitwise]
|
#if[Bitwise]
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndBitwiseOr(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static $type$ getAndBitwiseOr(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndBitwiseOr(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndBitwiseOr(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
|
#if[!byte]
|
||||||
if (handle.be == BE) {
|
if (handle.be == BE) {
|
||||||
|
#end[byte]
|
||||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
value);
|
value);
|
||||||
|
#if[!byte]
|
||||||
} else {
|
} else {
|
||||||
return getAndBitwiseOrConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndBitwiseOrRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static $type$ getAndBitwiseOrRelease(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndBitwiseOrRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndBitwiseOrRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
|
#if[!byte]
|
||||||
if (handle.be == BE) {
|
if (handle.be == BE) {
|
||||||
|
#end[byte]
|
||||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Release(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Release(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
value);
|
value);
|
||||||
|
#if[!byte]
|
||||||
} else {
|
} else {
|
||||||
return getAndBitwiseOrConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndBitwiseOrAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static $type$ getAndBitwiseOrAcquire(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndBitwiseOrAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndBitwiseOrAcquire(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
|
#if[!byte]
|
||||||
if (handle.be == BE) {
|
if (handle.be == BE) {
|
||||||
|
#end[byte]
|
||||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Acquire(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.getAndBitwiseOr$RawType$Acquire(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
value);
|
value);
|
||||||
|
#if[!byte]
|
||||||
} else {
|
} else {
|
||||||
return getAndBitwiseOrConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
return getAndBitwiseOrConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
}
|
}
|
||||||
|
#if[!byte]
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndBitwiseOrConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ value) {
|
static $type$ getAndBitwiseOrConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ value) {
|
||||||
|
@ -454,51 +578,81 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase {
|
||||||
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset);
|
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset);
|
||||||
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
|
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
|
||||||
} while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset,
|
} while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset,
|
||||||
nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue | value)));
|
nativeExpectedValue, $RawBoxType$.reverseBytes({#if[ShorterThanInt]?($type$) }(expectedValue | value))));
|
||||||
return expectedValue;
|
return expectedValue;
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndBitwiseAnd(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static $type$ getAndBitwiseAnd(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndBitwiseAnd(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndBitwiseAnd(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
|
#if[!byte]
|
||||||
if (handle.be == BE) {
|
if (handle.be == BE) {
|
||||||
|
#end[byte]
|
||||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
value);
|
value);
|
||||||
|
#if[!byte]
|
||||||
} else {
|
} else {
|
||||||
return getAndBitwiseAndConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndBitwiseAndRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static $type$ getAndBitwiseAndRelease(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndBitwiseAndRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndBitwiseAndRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
|
#if[!byte]
|
||||||
if (handle.be == BE) {
|
if (handle.be == BE) {
|
||||||
|
#end[byte]
|
||||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Release(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Release(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
value);
|
value);
|
||||||
|
#if[!byte]
|
||||||
} else {
|
} else {
|
||||||
return getAndBitwiseAndConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndBitwiseAndAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static $type$ getAndBitwiseAndAcquire(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndBitwiseAndAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndBitwiseAndAcquire(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
|
#if[!byte]
|
||||||
if (handle.be == BE) {
|
if (handle.be == BE) {
|
||||||
|
#end[byte]
|
||||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Acquire(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.getAndBitwiseAnd$RawType$Acquire(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
value);
|
value);
|
||||||
|
#if[!byte]
|
||||||
} else {
|
} else {
|
||||||
return getAndBitwiseAndConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
return getAndBitwiseAndConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
}
|
}
|
||||||
|
#if[!byte]
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndBitwiseAndConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ value) {
|
static $type$ getAndBitwiseAndConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ value) {
|
||||||
|
@ -508,52 +662,80 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase {
|
||||||
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset);
|
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset);
|
||||||
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
|
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
|
||||||
} while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset,
|
} while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset,
|
||||||
nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue & value)));
|
nativeExpectedValue, $RawBoxType$.reverseBytes({#if[ShorterThanInt]?($type$) }(expectedValue & value))));
|
||||||
return expectedValue;
|
return expectedValue;
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndBitwiseXor(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static $type$ getAndBitwiseXor(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndBitwiseXor(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndBitwiseXor(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
|
#if[!byte]
|
||||||
if (handle.be == BE) {
|
if (handle.be == BE) {
|
||||||
|
#end[byte]
|
||||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
value);
|
value);
|
||||||
|
#if[!byte]
|
||||||
} else {
|
} else {
|
||||||
return getAndBitwiseXorConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndBitwiseXorRelease(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static $type$ getAndBitwiseXorRelease(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndBitwiseXorRelease(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndBitwiseXorRelease(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
|
#if[!byte]
|
||||||
if (handle.be == BE) {
|
if (handle.be == BE) {
|
||||||
|
#end[byte]
|
||||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Release(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Release(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
value);
|
value);
|
||||||
|
#if[!byte]
|
||||||
} else {
|
} else {
|
||||||
return getAndBitwiseXorConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndBitwiseXorAcquire(VarHandle ob, Object obb, Object encl, long base, long offset, $type$ value) {
|
static $type$ getAndBitwiseXorAcquire(VarHandle ob, Object obb, long base, $type$ value) {
|
||||||
VarHandleSegmentViewBase handle = (VarHandleSegmentViewBase)ob;
|
return getAndBitwiseXorAcquire(ob, obb, base, ((SegmentVarHandle) ob).offset, value);
|
||||||
AbstractMemorySegmentImpl bb = checkSegment(obb, encl, base, false);
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
static $type$ getAndBitwiseXorAcquire(VarHandle ob, Object obb, long base, long offset, $type$ value) {
|
||||||
|
SegmentVarHandle handle = (SegmentVarHandle)ob;
|
||||||
|
AbstractMemorySegmentImpl bb = handle.checkSegment(obb, base, false);
|
||||||
|
#if[!byte]
|
||||||
if (handle.be == BE) {
|
if (handle.be == BE) {
|
||||||
|
#end[byte]
|
||||||
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Acquire(bb.sessionImpl(),
|
return SCOPED_MEMORY_ACCESS.getAndBitwiseXor$RawType$Acquire(bb.sessionImpl(),
|
||||||
bb.unsafeGetBase(),
|
bb.unsafeGetBase(),
|
||||||
offsetNonPlain(bb, base, offset, handle.alignmentMask),
|
offset(bb, base, offset),
|
||||||
value);
|
value);
|
||||||
|
#if[!byte]
|
||||||
} else {
|
} else {
|
||||||
return getAndBitwiseXorConvEndianWithCAS(bb, offsetNonPlain(bb, base, offset, handle.alignmentMask), value);
|
return getAndBitwiseXorConvEndianWithCAS(bb, offset(bb, base, offset), value);
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
}
|
}
|
||||||
|
#if[!byte]
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
static $type$ getAndBitwiseXorConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ value) {
|
static $type$ getAndBitwiseXorConvEndianWithCAS(AbstractMemorySegmentImpl bb, long offset, $type$ value) {
|
||||||
|
@ -563,8 +745,9 @@ final class VarHandleSegmentAs$Type$s extends VarHandleSegmentViewBase {
|
||||||
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset);
|
nativeExpectedValue = SCOPED_MEMORY_ACCESS.get$RawType$Volatile(bb.sessionImpl(),base, offset);
|
||||||
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
|
expectedValue = $RawBoxType$.reverseBytes(nativeExpectedValue);
|
||||||
} while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset,
|
} while (!SCOPED_MEMORY_ACCESS.weakCompareAndSet$RawType$(bb.sessionImpl(),base, offset,
|
||||||
nativeExpectedValue, $RawBoxType$.reverseBytes(expectedValue ^ value)));
|
nativeExpectedValue, $RawBoxType$.reverseBytes({#if[ShorterThanInt]?($type$) }(expectedValue ^ value))));
|
||||||
return expectedValue;
|
return expectedValue;
|
||||||
}
|
}
|
||||||
|
#end[byte]
|
||||||
#end[Bitwise]
|
#end[Bitwise]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -27,8 +27,8 @@ package jdk.internal.access;
|
||||||
|
|
||||||
import jdk.internal.foreign.abi.NativeEntryPoint;
|
import jdk.internal.foreign.abi.NativeEntryPoint;
|
||||||
|
|
||||||
|
import java.lang.foreign.MemoryLayout;
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles.Lookup;
|
|
||||||
import java.lang.invoke.MethodType;
|
import java.lang.invoke.MethodType;
|
||||||
import java.lang.invoke.VarHandle;
|
import java.lang.invoke.VarHandle;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
@ -75,7 +75,7 @@ public interface JavaLangInvokeAccess {
|
||||||
* Used by {@code jdk.internal.foreign.LayoutPath} and
|
* Used by {@code jdk.internal.foreign.LayoutPath} and
|
||||||
* {@code java.lang.invoke.MethodHandles}.
|
* {@code java.lang.invoke.MethodHandles}.
|
||||||
*/
|
*/
|
||||||
VarHandle memorySegmentViewHandle(Class<?> carrier, long alignmentMask, ByteOrder order);
|
VarHandle memorySegmentViewHandle(Class<?> carrier, MemoryLayout enclosing, long alignmentMask, ByteOrder order, boolean constantOffset, long offset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Var handle carrier combinator.
|
* Var handle carrier combinator.
|
||||||
|
|
|
@ -59,6 +59,7 @@ public class LayoutPath {
|
||||||
private static final long[] EMPTY_STRIDES = new long[0];
|
private static final long[] EMPTY_STRIDES = new long[0];
|
||||||
private static final long[] EMPTY_BOUNDS = new long[0];
|
private static final long[] EMPTY_BOUNDS = new long[0];
|
||||||
private static final MethodHandle[] EMPTY_DEREF_HANDLES = new MethodHandle[0];
|
private static final MethodHandle[] EMPTY_DEREF_HANDLES = new MethodHandle[0];
|
||||||
|
public static final MemoryLayout.PathElement[] EMPTY_PATH_ELEMENTS = new MemoryLayout.PathElement[0];
|
||||||
|
|
||||||
private static final MethodHandle MH_ADD_SCALED_OFFSET;
|
private static final MethodHandle MH_ADD_SCALED_OFFSET;
|
||||||
private static final MethodHandle MH_SLICE;
|
private static final MethodHandle MH_SLICE;
|
||||||
|
@ -205,15 +206,13 @@ public class LayoutPath {
|
||||||
String.format("Path does not select a value layout: %s", breadcrumbs()));
|
String.format("Path does not select a value layout: %s", breadcrumbs()));
|
||||||
}
|
}
|
||||||
|
|
||||||
VarHandle handle = Utils.makeRawSegmentViewVarHandle(valueLayout); // (MS, ML, long, long)
|
boolean constantOffset = strides.length == 0;
|
||||||
handle = MethodHandles.insertCoordinates(handle, 1, rootLayout()); // (MS, long, long)
|
// (MS, long, long) if variable offset, (MS, long) if constant offset
|
||||||
if (strides.length > 0) {
|
VarHandle handle = Utils.makeRawSegmentViewVarHandle(rootLayout(), valueLayout, constantOffset, offset);
|
||||||
MethodHandle offsetAdapter = offsetHandle();
|
if (!constantOffset) {
|
||||||
|
MethodHandle offsetAdapter = offsetHandle(); // Adapter performs the bound checks
|
||||||
offsetAdapter = MethodHandles.insertArguments(offsetAdapter, 0, 0L);
|
offsetAdapter = MethodHandles.insertArguments(offsetAdapter, 0, 0L);
|
||||||
handle = MethodHandles.collectCoordinates(handle, 2, offsetAdapter); // (MS, long)
|
handle = MethodHandles.collectCoordinates(handle, 2, offsetAdapter); // (MS, long)
|
||||||
} else {
|
|
||||||
// simpler adaptation
|
|
||||||
handle = MethodHandles.insertCoordinates(handle, 2, offset); // (MS, long)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adapt) {
|
if (adapt) {
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 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
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
* questions.
|
* questions.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package jdk.internal.foreign;
|
package jdk.internal.foreign;
|
||||||
|
@ -34,7 +33,6 @@ import sun.invoke.util.Wrapper;
|
||||||
|
|
||||||
import java.lang.foreign.AddressLayout;
|
import java.lang.foreign.AddressLayout;
|
||||||
import java.lang.foreign.MemoryLayout;
|
import java.lang.foreign.MemoryLayout;
|
||||||
import java.lang.foreign.MemoryLayout.PathElement;
|
|
||||||
import java.lang.foreign.MemorySegment;
|
import java.lang.foreign.MemorySegment;
|
||||||
import java.lang.foreign.StructLayout;
|
import java.lang.foreign.StructLayout;
|
||||||
import java.lang.foreign.ValueLayout;
|
import java.lang.foreign.ValueLayout;
|
||||||
|
@ -46,6 +44,7 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,25 +55,31 @@ public final class Utils {
|
||||||
// Suppresses default constructor, ensuring non-instantiability.
|
// Suppresses default constructor, ensuring non-instantiability.
|
||||||
private Utils() {}
|
private Utils() {}
|
||||||
|
|
||||||
private static final MethodHandle BYTE_TO_BOOL;
|
private static final Class<?> ADDRESS_CARRIER_TYPE;
|
||||||
private static final MethodHandle BOOL_TO_BYTE;
|
private static final MethodHandle LONG_TO_CARRIER;
|
||||||
private static final MethodHandle ADDRESS_TO_LONG;
|
|
||||||
private static final MethodHandle LONG_TO_ADDRESS_TARGET;
|
private static final MethodHandle LONG_TO_ADDRESS_TARGET;
|
||||||
private static final MethodHandle LONG_TO_ADDRESS_NO_TARGET;
|
private static final MethodHandle LONG_TO_ADDRESS_NO_TARGET;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
try {
|
|
||||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||||
BYTE_TO_BOOL = lookup.findStatic(Utils.class, "byteToBoolean",
|
String unboxSegmentName;
|
||||||
MethodType.methodType(boolean.class, byte.class));
|
Class<?> rawAddressType;
|
||||||
BOOL_TO_BYTE = lookup.findStatic(Utils.class, "booleanToByte",
|
if (Unsafe.getUnsafe().addressSize() == 8) {
|
||||||
MethodType.methodType(byte.class, boolean.class));
|
unboxSegmentName = "unboxSegment";
|
||||||
ADDRESS_TO_LONG = lookup.findStatic(SharedUtils.class, "unboxSegment",
|
rawAddressType = long.class;
|
||||||
MethodType.methodType(long.class, MemorySegment.class));
|
} else {
|
||||||
|
assert Unsafe.getUnsafe().addressSize() == 4 : Unsafe.getUnsafe().addressSize();
|
||||||
|
unboxSegmentName = "unboxSegment32";
|
||||||
|
rawAddressType = int.class;
|
||||||
|
}
|
||||||
|
ADDRESS_CARRIER_TYPE = rawAddressType;
|
||||||
|
try {
|
||||||
|
LONG_TO_CARRIER = lookup.findStatic(SharedUtils.class, unboxSegmentName,
|
||||||
|
MethodType.methodType(rawAddressType, MemorySegment.class));
|
||||||
LONG_TO_ADDRESS_TARGET = lookup.findStatic(Utils.class, "longToAddress",
|
LONG_TO_ADDRESS_TARGET = lookup.findStatic(Utils.class, "longToAddress",
|
||||||
MethodType.methodType(MemorySegment.class, long.class, AddressLayout.class));
|
MethodType.methodType(MemorySegment.class, rawAddressType, AddressLayout.class));
|
||||||
LONG_TO_ADDRESS_NO_TARGET = lookup.findStatic(Utils.class, "longToAddress",
|
LONG_TO_ADDRESS_NO_TARGET = lookup.findStatic(Utils.class, "longToAddress",
|
||||||
MethodType.methodType(MemorySegment.class, long.class));
|
MethodType.methodType(MemorySegment.class, rawAddressType));
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
throw new ExceptionInInitializerError(ex);
|
throw new ExceptionInInitializerError(ex);
|
||||||
}
|
}
|
||||||
|
@ -90,48 +95,57 @@ public final class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns a <em>raw var handle</em>, that is, a var handle that does not perform any size
|
* This method returns a var handle that accesses a target layout in an enclosing layout, taking the memory offset
|
||||||
* or alignment checks. Such checks are added (using adaptation) by {@link LayoutPath#dereferenceHandle()}.
|
* and the base offset of the enclosing layout in the segment.
|
||||||
|
* <p>
|
||||||
|
* If the offset of the target layout in the enclosing layout is constant, the coordinates are (MS, long).
|
||||||
|
* If the offset of the target layout in the enclosing layout is variable, the coordinates are (MS, long, long).
|
||||||
|
* The trailing long is a pre-validated, variable extra offset, which the var handle does not perform any size or
|
||||||
|
* alignment checks against. Such checks are added (using adaptation) by {@link LayoutPath#dereferenceHandle()}.
|
||||||
* <p>
|
* <p>
|
||||||
* We provide two level of caching of the generated var handles. First, the var handle associated
|
* We provide two level of caching of the generated var handles. First, the var handle associated
|
||||||
* with a {@link ValueLayout#varHandle()} call is cached inside a stable field of the value layout implementation.
|
* with a {@link ValueLayout#varHandle()} call is cached inside a stable field of the value layout implementation.
|
||||||
* This optimizes common code idioms like {@code JAVA_INT.varHandle().getInt(...)}. A second layer of caching
|
* This optimizes common code idioms like {@code JAVA_INT.varHandle().getInt(...)}. A second layer of caching
|
||||||
* is then provided by this method: after all, var handles constructed by {@link MemoryLayout#varHandle(PathElement...)}
|
* is then provided by this method, so different value layouts with same effects can reuse var handle instances.
|
||||||
* will be obtained by adapting some raw var handle generated by this method.
|
* (The 2nd layer may be redundant in the long run)
|
||||||
*
|
*
|
||||||
* @param layout the value layout for which a raw memory segment var handle is to be created.
|
* @param enclosing the enclosing context of the value layout
|
||||||
* @return a raw memory segment var handle.
|
* @param layout the value layout for which a raw memory segment var handle is to be created
|
||||||
|
* @param constantOffset if the VH carries a constant offset instead of taking a variable offset
|
||||||
|
* @param offset the offset if it is a constant
|
||||||
|
* @return a raw memory segment var handle
|
||||||
*/
|
*/
|
||||||
public static VarHandle makeRawSegmentViewVarHandle(ValueLayout layout) {
|
public static VarHandle makeRawSegmentViewVarHandle(MemoryLayout enclosing, ValueLayout layout, boolean constantOffset, long offset) {
|
||||||
final class VarHandleCache {
|
if (enclosing instanceof ValueLayout direct) {
|
||||||
|
assert direct.equals(layout) && constantOffset && offset == 0;
|
||||||
|
record VarHandleCache() implements Function<ValueLayout, VarHandle> {
|
||||||
private static final Map<ValueLayout, VarHandle> HANDLE_MAP = new ConcurrentHashMap<>();
|
private static final Map<ValueLayout, VarHandle> HANDLE_MAP = new ConcurrentHashMap<>();
|
||||||
|
private static final VarHandleCache INSTANCE = new VarHandleCache();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VarHandle apply(ValueLayout valueLayout) {
|
||||||
|
return Utils.makeRawSegmentViewVarHandleInternal(valueLayout, valueLayout, true, 0);
|
||||||
}
|
}
|
||||||
return VarHandleCache.HANDLE_MAP
|
}
|
||||||
.computeIfAbsent(layout.withoutName(), Utils::makeRawSegmentViewVarHandleInternal);
|
return VarHandleCache.HANDLE_MAP.computeIfAbsent(direct.withoutName(), VarHandleCache.INSTANCE);
|
||||||
|
}
|
||||||
|
return makeRawSegmentViewVarHandleInternal(enclosing, layout, constantOffset, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static VarHandle makeRawSegmentViewVarHandleInternal(ValueLayout layout) {
|
private static VarHandle makeRawSegmentViewVarHandleInternal(MemoryLayout enclosing, ValueLayout layout, boolean constantOffset, long offset) {
|
||||||
Class<?> baseCarrier = layout.carrier();
|
Class<?> baseCarrier = layout.carrier();
|
||||||
if (layout.carrier() == MemorySegment.class) {
|
if (layout.carrier() == MemorySegment.class) {
|
||||||
baseCarrier = switch ((int) ValueLayout.ADDRESS.byteSize()) {
|
baseCarrier = ADDRESS_CARRIER_TYPE;
|
||||||
case Long.BYTES -> long.class;
|
|
||||||
case Integer.BYTES -> int.class;
|
|
||||||
default -> throw new UnsupportedOperationException("Unsupported address layout");
|
|
||||||
};
|
|
||||||
} else if (layout.carrier() == boolean.class) {
|
|
||||||
baseCarrier = byte.class;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VarHandle handle = SharedSecrets.getJavaLangInvokeAccess().memorySegmentViewHandle(baseCarrier,
|
VarHandle handle = SharedSecrets.getJavaLangInvokeAccess().memorySegmentViewHandle(baseCarrier,
|
||||||
layout.byteAlignment() - 1, layout.order());
|
enclosing, layout.byteAlignment() - 1, layout.order(), constantOffset, offset);
|
||||||
|
|
||||||
if (layout.carrier() == boolean.class) {
|
if (layout instanceof AddressLayout addressLayout) {
|
||||||
handle = MethodHandles.filterValue(handle, BOOL_TO_BYTE, BYTE_TO_BOOL);
|
|
||||||
} else if (layout instanceof AddressLayout addressLayout) {
|
|
||||||
MethodHandle longToAddressAdapter = addressLayout.targetLayout().isPresent() ?
|
MethodHandle longToAddressAdapter = addressLayout.targetLayout().isPresent() ?
|
||||||
MethodHandles.insertArguments(LONG_TO_ADDRESS_TARGET, 1, addressLayout) :
|
MethodHandles.insertArguments(LONG_TO_ADDRESS_TARGET, 1, addressLayout) :
|
||||||
LONG_TO_ADDRESS_NO_TARGET;
|
LONG_TO_ADDRESS_NO_TARGET;
|
||||||
handle = MethodHandles.filterValue(handle, ADDRESS_TO_LONG, longToAddressAdapter);
|
handle = MethodHandles.filterValue(handle, LONG_TO_CARRIER, longToAddressAdapter);
|
||||||
}
|
}
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
@ -149,11 +163,23 @@ public final class Utils {
|
||||||
return longToAddress(addr, 0, 1);
|
return longToAddress(addr, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 32 bit
|
||||||
|
@ForceInline
|
||||||
|
public static MemorySegment longToAddress(int addr) {
|
||||||
|
return longToAddress(addr, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
public static MemorySegment longToAddress(long addr, AddressLayout layout) {
|
public static MemorySegment longToAddress(long addr, AddressLayout layout) {
|
||||||
return longToAddress(addr, pointeeByteSize(layout), pointeeByteAlign(layout));
|
return longToAddress(addr, pointeeByteSize(layout), pointeeByteAlign(layout));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 32 bit
|
||||||
|
@ForceInline
|
||||||
|
public static MemorySegment longToAddress(int addr, AddressLayout layout) {
|
||||||
|
return longToAddress(addr, pointeeByteSize(layout), pointeeByteAlign(layout));
|
||||||
|
}
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
public static MemorySegment longToAddress(long addr, long size, long align) {
|
public static MemorySegment longToAddress(long addr, long size, long align) {
|
||||||
if (!isAligned(addr, align)) {
|
if (!isAligned(addr, align)) {
|
||||||
|
|
|
@ -321,11 +321,20 @@ public final class SharedUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
public static long unboxSegment(MemorySegment segment) {
|
public static long unboxSegment(MemorySegment segment) {
|
||||||
checkNative(segment);
|
checkNative(segment);
|
||||||
return segment.address();
|
return segment.address();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ForceInline
|
||||||
|
public static int unboxSegment32(MemorySegment segment) {
|
||||||
|
// This cast to 'int' is safe, because we only call this method on 32-bit
|
||||||
|
// platforms, where we know the address of a segment is truncated to 32-bits.
|
||||||
|
// There's a similar cast for 4-byte addresses in Unsafe.putAddress.
|
||||||
|
return (int) unboxSegment(segment);
|
||||||
|
}
|
||||||
|
|
||||||
public static void checkExceptions(MethodHandle target) {
|
public static void checkExceptions(MethodHandle target) {
|
||||||
Class<?>[] exceptions = JLIA.exceptionTypes(target);
|
Class<?>[] exceptions = JLIA.exceptionTypes(target);
|
||||||
if (exceptions != null && exceptions.length != 0) {
|
if (exceptions != null && exceptions.length != 0) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
*/
|
*/
|
||||||
package jdk.internal.foreign.layout;
|
package jdk.internal.foreign.layout;
|
||||||
|
|
||||||
|
import jdk.internal.foreign.LayoutPath;
|
||||||
import jdk.internal.foreign.Utils;
|
import jdk.internal.foreign.Utils;
|
||||||
import jdk.internal.misc.Unsafe;
|
import jdk.internal.misc.Unsafe;
|
||||||
import jdk.internal.reflect.CallerSensitive;
|
import jdk.internal.reflect.CallerSensitive;
|
||||||
|
@ -38,10 +39,8 @@ import java.lang.foreign.MemorySegment;
|
||||||
import java.lang.foreign.ValueLayout;
|
import java.lang.foreign.ValueLayout;
|
||||||
import java.lang.invoke.VarHandle;
|
import java.lang.invoke.VarHandle;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A value layout. A value layout is used to model the memory layout associated with values of basic data types, such as <em>integral</em> types
|
* A value layout. A value layout is used to model the memory layout associated with values of basic data types, such as <em>integral</em> types
|
||||||
|
@ -159,19 +158,13 @@ public final class ValueLayouts {
|
||||||
|
|
||||||
@ForceInline
|
@ForceInline
|
||||||
public final VarHandle varHandle() {
|
public final VarHandle varHandle() {
|
||||||
final class VarHandleCache {
|
var vh = handle;
|
||||||
private static final Map<ValueLayout, VarHandle> HANDLE_MAP = new ConcurrentHashMap<>();
|
if (vh == null) {
|
||||||
|
vh = varHandleInternal(LayoutPath.EMPTY_PATH_ELEMENTS);
|
||||||
|
// benign race stable field store is safe because VarHandle is thread safe
|
||||||
|
handle = vh;
|
||||||
}
|
}
|
||||||
if (handle == null) {
|
return vh;
|
||||||
// this store to stable field is safe, because return value of 'makeMemoryAccessVarHandle' has stable identity
|
|
||||||
handle = VarHandleCache.HANDLE_MAP.computeIfAbsent(self().withoutName(), _ -> varHandleInternal());
|
|
||||||
}
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final V self() {
|
|
||||||
return (V) this;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -33,6 +33,9 @@ import java.lang.invoke.VarHandle;
|
||||||
/**
|
/**
|
||||||
* Static factories for certain VarHandle/MethodHandle variants.
|
* Static factories for certain VarHandle/MethodHandle variants.
|
||||||
* <p>
|
* <p>
|
||||||
|
* Some methods take no receiver argument. In these cases, the receiver is the
|
||||||
|
* lookup class.
|
||||||
|
* <p>
|
||||||
* The methods will throw an {@link InternalError} if the lookup fails.
|
* The methods will throw an {@link InternalError} if the lookup fails.
|
||||||
* <p>
|
* <p>
|
||||||
* Here is an example of how one of these methods could be used:
|
* Here is an example of how one of these methods could be used:
|
||||||
|
@ -63,6 +66,11 @@ public final class MhUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MethodHandle findVirtual(MethodHandles.Lookup lookup,
|
||||||
|
String name,
|
||||||
|
MethodType type) {
|
||||||
|
return findVirtual(lookup, lookup.lookupClass(), name, type);
|
||||||
|
}
|
||||||
|
|
||||||
public static MethodHandle findVirtual(MethodHandles.Lookup lookup,
|
public static MethodHandle findVirtual(MethodHandles.Lookup lookup,
|
||||||
Class<?> refc,
|
Class<?> refc,
|
||||||
|
@ -75,4 +83,21 @@ public final class MhUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MethodHandle findStatic(MethodHandles.Lookup lookup,
|
||||||
|
String name,
|
||||||
|
MethodType type) {
|
||||||
|
return findStatic(lookup, lookup.lookupClass(), name, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MethodHandle findStatic(MethodHandles.Lookup lookup,
|
||||||
|
Class<?> refc,
|
||||||
|
String name,
|
||||||
|
MethodType type) {
|
||||||
|
try {
|
||||||
|
return lookup.findStatic(refc, name, type);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
throw new InternalError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ import jdk.internal.vm.vector.VectorSupport;
|
||||||
* which might be deemed to expensive; in other words, this approach prioritizes the performance of memory access over
|
* which might be deemed to expensive; in other words, this approach prioritizes the performance of memory access over
|
||||||
* that of releasing a shared memory resource.
|
* that of releasing a shared memory resource.
|
||||||
*/
|
*/
|
||||||
public class ScopedMemoryAccess {
|
public final class ScopedMemoryAccess {
|
||||||
|
|
||||||
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ public class TestAccessModes {
|
||||||
// access is unaligned
|
// access is unaligned
|
||||||
assertTrue(segment.maxByteAlignment() < layout.byteAlignment());
|
assertTrue(segment.maxByteAlignment() < layout.byteAlignment());
|
||||||
}
|
}
|
||||||
|
assertEquals(varHandle.isAccessModeSupported(mode), compatible);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ValueLayout accessLayout(MemoryLayout layout) {
|
static ValueLayout accessLayout(MemoryLayout layout) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue