Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid Unsafe usage where possible #2403

Merged
merged 1 commit into from
Sep 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {

private static final MethodHandle methodGetVisibleChunk;

private static final int CHUNKSECTION_BASE;
private static final int CHUNKSECTION_SHIFT;

private static final Field fieldLock;
private static final long fieldLockOffset;

private static final Field fieldGameEventDispatcherSections;
private static final MethodHandle methodremoveBlockEntityTicker;
Expand Down Expand Up @@ -127,15 +123,12 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
getVisibleChunkIfPresent.setAccessible(true);
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);

Unsafe unsafe = ReflectionUtils.getUnsafe();
if (!PaperLib.isPaper()) {

fieldLock = PalettedContainer.class.getDeclaredField(Refraction.pickName("lock", "m"));
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
fieldLock.setAccessible(true);
} else {
// in paper, the used methods are synchronized properly
fieldLock = null;
fieldLockOffset = -1;
}

fieldGameEventDispatcherSections = LevelChunk.class.getDeclaredField(Refraction.pickName(
Expand All @@ -152,13 +145,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {

fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
fieldRemove.setAccessible(true);

CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class);
int scale = unsafe.arrayIndexScale(LevelChunkSection[].class);
if ((scale & (scale - 1)) != 0) {
throw new Error("data type scale not a power of two");
}
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
} catch (RuntimeException e) {
throw e;
} catch (Throwable rethrow) {
Expand All @@ -173,9 +159,8 @@ static boolean setSectionAtomic(
LevelChunkSection value,
int layer
) {
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
if (layer >= 0 && layer < sections.length) {
return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value);
return ReflectionUtils.compareAndSet(sections, expected, value, layer);
}
return false;
}
Expand All @@ -190,14 +175,13 @@ static DelegateSemaphore applyLock(LevelChunkSection section) {
}
try {
synchronized (section) {
Unsafe unsafe = ReflectionUtils.getUnsafe();
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
Semaphore currentLock = (Semaphore) unsafe.getObject(blocks, fieldLockOffset);
Semaphore currentLock = (Semaphore) fieldLock.get(blocks);
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
return delegateSemaphore;
}
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
unsafe.putObject(blocks, fieldLockOffset, newLock);
fieldLock.set(blocks, newLock);
return newLock;
}
} catch (Throwable e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean creat
}
};

ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider);
chunkSourceField.set(freshWorld, freshChunkProvider);
//let's start then
structureManager = server.getStructureManager();
threadedLevelLightEngine = freshChunkProvider.getLightEngine();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {

private static final MethodHandle methodGetVisibleChunk;

private static final int CHUNKSECTION_BASE;
private static final int CHUNKSECTION_SHIFT;

private static final Field fieldThreadingDetector;
private static final long fieldThreadingDetectorOffset;

private static final Field fieldLock;
private static final long fieldLockOffset;

private static final MethodHandle methodRemoveGameEventListener;
private static final MethodHandle methodremoveTickingBlockEntity;
Expand Down Expand Up @@ -136,20 +130,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
getVisibleChunkIfPresent.setAccessible(true);
methodGetVisibleChunk = MethodHandles.lookup().unreflect(getVisibleChunkIfPresent);

Unsafe unsafe = ReflectionUtils.getUnsafe();
if (!PaperLib.isPaper()) {
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector);

fieldThreadingDetector.setAccessible(true);
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
fieldLock.setAccessible(true);
} else {
// in paper, the used methods are synchronized properly
fieldThreadingDetector = null;
fieldThreadingDetectorOffset = -1;

fieldLock = null;
fieldLockOffset = -1;
}

Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
Expand All @@ -169,13 +158,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {

fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "p"));
fieldRemove.setAccessible(true);

CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class);
int scale = unsafe.arrayIndexScale(LevelChunkSection[].class);
if ((scale & (scale - 1)) != 0) {
throw new Error("data type scale not a power of two");
}
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
} catch (RuntimeException e) {
throw e;
} catch (Throwable rethrow) {
Expand All @@ -190,9 +172,8 @@ static boolean setSectionAtomic(
LevelChunkSection value,
int layer
) {
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
if (layer >= 0 && layer < sections.length) {
return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value);
return ReflectionUtils.compareAndSet(sections, expected, value, layer);
}
return false;
}
Expand All @@ -207,19 +188,15 @@ static DelegateSemaphore applyLock(LevelChunkSection section) {
}
try {
synchronized (section) {
Unsafe unsafe = ReflectionUtils.getUnsafe();
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject(
blocks,
fieldThreadingDetectorOffset
);
ThreadingDetector currentThreadingDetector = (ThreadingDetector) fieldThreadingDetector.get(blocks);
synchronized (currentThreadingDetector) {
Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset);
Semaphore currentLock = (Semaphore) fieldLock.get(currentThreadingDetector);
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
return delegateSemaphore;
}
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock);
fieldLock.set(currentThreadingDetector, newLock);
return newLock;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean creat
}
};

ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider);
chunkSourceField.set(freshWorld, freshChunkProvider);
//let's start then
structureManager = server.getStructureManager();
threadedLevelLightEngine = freshChunkProvider.getLightEngine();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {

private static final MethodHandle methodGetVisibleChunk;

private static final int CHUNKSECTION_BASE;
private static final int CHUNKSECTION_SHIFT;

private static final Field fieldThreadingDetector;
private static final long fieldThreadingDetectorOffset;

private static final Field fieldLock;
private static final long fieldLockOffset;

private static final MethodHandle methodRemoveGameEventListener;
private static final MethodHandle methodremoveTickingBlockEntity;
Expand Down Expand Up @@ -149,20 +143,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
getVisibleChunkIfPresent.setAccessible(true);
methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent);

Unsafe unsafe = ReflectionUtils.getUnsafe();
if (!PaperLib.isPaper()) {
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector);

fieldThreadingDetector.setAccessible(true);
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
fieldLock.setAccessible(true);
} else {
// in paper, the used methods are synchronized properly
fieldThreadingDetector = null;
fieldThreadingDetectorOffset = -1;

fieldLock = null;
fieldLockOffset = -1;
}

Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
Expand All @@ -185,12 +174,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "q"));
fieldRemove.setAccessible(true);

CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class);
int scale = unsafe.arrayIndexScale(LevelChunkSection[].class);
if ((scale & (scale - 1)) != 0) {
throw new Error("data type scale not a power of two");
}
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
boolean chunkRewrite;
try {
ServerLevel.class.getDeclaredMethod("getEntityLookup");
Expand Down Expand Up @@ -226,9 +209,8 @@ static boolean setSectionAtomic(
LevelChunkSection value,
int layer
) {
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
if (layer >= 0 && layer < sections.length) {
return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value);
return ReflectionUtils.compareAndSet(sections, expected, value, layer);
}
return false;
}
Expand All @@ -243,19 +225,15 @@ static DelegateSemaphore applyLock(LevelChunkSection section) {
}
try {
synchronized (section) {
Unsafe unsafe = ReflectionUtils.getUnsafe();
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject(
blocks,
fieldThreadingDetectorOffset
);
ThreadingDetector currentThreadingDetector = (ThreadingDetector) fieldThreadingDetector.get(blocks);
synchronized (currentThreadingDetector) {
Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset);
Semaphore currentLock = (Semaphore) fieldLock.get(currentThreadingDetector);
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
return delegateSemaphore;
}
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock);
fieldLock.set(currentThreadingDetector, newLock);
return newLock;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean creat
}


ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider);
chunkSourceField.set(freshWorld, freshChunkProvider);
//let's start then
structureTemplateManager = server.getStructureManager();
threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {

private static final MethodHandle methodGetVisibleChunk;

private static final int CHUNKSECTION_BASE;
private static final int CHUNKSECTION_SHIFT;

private static final Field fieldThreadingDetector;
private static final long fieldThreadingDetectorOffset;

private static final Field fieldLock;
private static final long fieldLockOffset;

private static final MethodHandle methodRemoveGameEventListener;
private static final MethodHandle methodremoveTickingBlockEntity;
Expand Down Expand Up @@ -158,20 +152,15 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
getVisibleChunkIfPresent.setAccessible(true);
methodGetVisibleChunk = lookup.unreflect(getVisibleChunkIfPresent);

Unsafe unsafe = ReflectionUtils.getUnsafe();
if (!PaperLib.isPaper()) {
fieldThreadingDetector = PalettedContainer.class.getDeclaredField(Refraction.pickName("threadingDetector", "f"));
fieldThreadingDetectorOffset = unsafe.objectFieldOffset(fieldThreadingDetector);

fieldThreadingDetector.setAccessible(true);
fieldLock = ThreadingDetector.class.getDeclaredField(Refraction.pickName("lock", "c"));
fieldLockOffset = unsafe.objectFieldOffset(fieldLock);
fieldLock.setAccessible(true);
} else {
// in paper, the used methods are synchronized properly
fieldThreadingDetector = null;
fieldThreadingDetectorOffset = -1;

fieldLock = null;
fieldLockOffset = -1;
}

Method removeGameEventListener = LevelChunk.class.getDeclaredMethod(
Expand All @@ -194,12 +183,6 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
fieldRemove = BlockEntity.class.getDeclaredField(Refraction.pickName("remove", "q"));
fieldRemove.setAccessible(true);

CHUNKSECTION_BASE = unsafe.arrayBaseOffset(LevelChunkSection[].class);
int scale = unsafe.arrayIndexScale(LevelChunkSection[].class);
if ((scale & (scale - 1)) != 0) {
throw new Error("data type scale not a power of two");
}
CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale);
boolean chunkRewrite;
try {
ServerLevel.class.getDeclaredMethod("getEntityLookup");
Expand Down Expand Up @@ -249,9 +232,8 @@ static boolean setSectionAtomic(
LevelChunkSection value,
int layer
) {
long offset = ((long) layer << CHUNKSECTION_SHIFT) + CHUNKSECTION_BASE;
if (layer >= 0 && layer < sections.length) {
return ReflectionUtils.getUnsafe().compareAndSwapObject(sections, offset, expected, value);
return ReflectionUtils.compareAndSet(sections, expected, value, layer);
}
return false;
}
Expand All @@ -266,19 +248,15 @@ static DelegateSemaphore applyLock(LevelChunkSection section) {
}
try {
synchronized (section) {
Unsafe unsafe = ReflectionUtils.getUnsafe();
PalettedContainer<net.minecraft.world.level.block.state.BlockState> blocks = section.getStates();
ThreadingDetector currentThreadingDetector = (ThreadingDetector) unsafe.getObject(
blocks,
fieldThreadingDetectorOffset
);
ThreadingDetector currentThreadingDetector = (ThreadingDetector) fieldThreadingDetector.get(blocks);
synchronized (currentThreadingDetector) {
Semaphore currentLock = (Semaphore) unsafe.getObject(currentThreadingDetector, fieldLockOffset);
Semaphore currentLock = (Semaphore) fieldLock.get(currentThreadingDetector);
if (currentLock instanceof DelegateSemaphore delegateSemaphore) {
return delegateSemaphore;
}
DelegateSemaphore newLock = new DelegateSemaphore(1, currentLock);
unsafe.putObject(currentThreadingDetector, fieldLockOffset, newLock);
fieldLock.set(currentThreadingDetector, newLock);
return newLock;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ public ChunkAccess getChunk(int x, int z, ChunkStatus chunkstatus, boolean creat
}


ReflectionUtils.unsafeSet(chunkSourceField, freshWorld, freshChunkProvider);
chunkSourceField.set(freshWorld, freshChunkProvider);
//let's start then
structureTemplateManager = server.getStructureManager();
threadedLevelLightEngine = new NoOpLightEngine(freshChunkProvider);
Expand Down
Loading
Loading