Skip to content

Commit 6d096e8

Browse files
committed
Merge 1.20 into 1.20.2
2 parents fbacc85 + 3eff8c7 commit 6d096e8

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

common/src/main/java/org/embeddedt/modernfix/common/mixin/bugfix/buffer_builder_leak/BufferBuilderMixin.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,29 @@
22

33
import com.mojang.blaze3d.vertex.BufferBuilder;
44
import org.embeddedt.modernfix.ModernFix;
5-
import org.lwjgl.system.MemoryUtil;
5+
import org.embeddedt.modernfix.render.UnsafeBufferHelper;
66
import org.spongepowered.asm.mixin.Mixin;
77
import org.spongepowered.asm.mixin.Shadow;
8+
import org.spongepowered.asm.mixin.injection.At;
9+
import org.spongepowered.asm.mixin.injection.Inject;
10+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
811

912
import java.nio.ByteBuffer;
1013

1114
@Mixin(BufferBuilder.class)
1215
public class BufferBuilderMixin {
1316
@Shadow private ByteBuffer buffer;
1417

15-
private static final MemoryUtil.MemoryAllocator ALLOCATOR = MemoryUtil.getAllocator(false);
1618
private static boolean leakReported = false;
1719

20+
/**
21+
* Ensure UnsafeBufferHelper is classloaded early, to avoid Forge's event transformer showing an error in the log.
22+
*/
23+
@Inject(method = "<clinit>", at = @At(value = "RETURN"))
24+
private static void initUnsafeBufferHelper(CallbackInfo ci) {
25+
UnsafeBufferHelper.init();
26+
}
27+
1828
@Override
1929
protected void finalize() throws Throwable {
2030
try {
@@ -25,7 +35,7 @@ protected void finalize() throws Throwable {
2535
leakReported = true;
2636
ModernFix.LOGGER.warn("One or more BufferBuilders have been leaked, ModernFix will attempt to correct this.");
2737
}
28-
ALLOCATOR.free(MemoryUtil.memAddress0(buf));
38+
UnsafeBufferHelper.free(buf);
2939
buffer = null;
3040
}
3141
} finally {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package org.embeddedt.modernfix.render;
2+
3+
import org.embeddedt.modernfix.ModernFix;
4+
import org.lwjgl.system.MemoryUtil;
5+
import sun.misc.Unsafe;
6+
7+
import java.lang.reflect.Field;
8+
import java.nio.ByteBuffer;
9+
10+
/**
11+
* Helper that frees ByteBuffers allocated by BufferBuilders, and nulls out the address pointer
12+
* to prevent double frees.
13+
*
14+
* @author Moulberry
15+
*/
16+
public class UnsafeBufferHelper {
17+
private static final MemoryUtil.MemoryAllocator ALLOCATOR = MemoryUtil.getAllocator(false);
18+
19+
private static sun.misc.Unsafe UNSAFE = null;
20+
private static long ADDRESS = -1;
21+
22+
static {
23+
try {
24+
final Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
25+
theUnsafe.setAccessible(true);
26+
UNSAFE = (Unsafe)theUnsafe.get(null);
27+
28+
final Field addressField = MemoryUtil.class.getDeclaredField("ADDRESS");
29+
addressField.setAccessible(true);
30+
ADDRESS = addressField.getLong(null);
31+
} catch(Throwable t) {
32+
ModernFix.LOGGER.error("Could load unsafe/buffer address", t);
33+
}
34+
}
35+
36+
public static void init() {
37+
38+
}
39+
40+
public static void free(ByteBuffer buf) {
41+
if(UNSAFE != null && ADDRESS >= 0) {
42+
// set the address to 0 to prevent double free
43+
long address = UNSAFE.getAndSetLong(buf, ADDRESS, 0);
44+
if(address != 0) {
45+
ALLOCATOR.free(address);
46+
}
47+
} else {
48+
ALLOCATOR.free(MemoryUtil.memAddress0(buf));
49+
}
50+
}
51+
}

0 commit comments

Comments
 (0)