Skip to content

Commit

Permalink
Avoid Unsafe usage where possible
Browse files Browse the repository at this point in the history
  • Loading branch information
SirYwell committed Aug 20, 2023
1 parent fe33be5 commit 9b13768
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 111 deletions.
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

0 comments on commit 9b13768

Please sign in to comment.