-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathIntrinsics.java
More file actions
80 lines (68 loc) · 2.5 KB
/
Intrinsics.java
File metadata and controls
80 lines (68 loc) · 2.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package roj.util.optimizer;
import org.jetbrains.annotations.Nullable;
import roj.asm.ClassNode;
import roj.asm.Opcodes;
import roj.io.IOUtil;
import roj.reflect.Reflection;
import roj.text.logging.Logger;
import roj.util.ByteList;
import java.lang.reflect.Method;
/**
* @author Roj234
* @since 2024/10/12 16:59
*/
public class Intrinsics {
private static final Logger LOGGER = Logger.getLogger("Intrinsics");
private static final Assembler assembler;
private static final CodeInjector linker;
static {
CodeInjector tmp;
try {
var c = ClassNode.parseSkeleton(IOUtil.getResourceIL("roj/util/optimizer/JVMCI.class"));
c.parent(Reflection.MAGIC_ACCESSOR_CLASS);
tmp = (CodeInjector) Reflection.createInstance(CodeInjector.class, c, false);
} catch (Throwable e) {
if (e.getCause() instanceof NoClassDefFoundError) {
LOGGER.error("添加 -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI 虚拟机参数以启用LiteralASM");
} else {
LOGGER.error("Intrinsics初始化失败", e);
}
tmp = null;
}
linker = tmp;
if (tmp != null) {
assembler = Assembler.getInstance();
if (!assembler.platform().equals("win64")) {
System.out.println("[警告]截至目前,只有win64平台的汇编器经过了实际验证,其它平台可能无法正常使用");
}
} else {
assembler = null;
}
}
public static boolean available() {return linker != null;}
public static boolean linkNative(@Nullable Object library, Class<?> caller) {
if (linker == null || LibraryLoader.INSTANCE == null) return false;
var nl = library instanceof String s ? LibraryLoader.INSTANCE.loadLibrary(caller, s) : library;
for (Method method : caller.getDeclaredMethods()) {
if ((method.getModifiers()&Opcodes.ACC_STATIC) != 0) {
var jni = method.getAnnotation(IntrinsicCandidate.class);
if (jni != null) linkSymbol(nl, method, jni.value(), jni.cdecl());
}
}
return true;
}
private static void linkSymbol(Object library, Method method, String symbol, boolean cdecl) {
if (symbol.isEmpty()) symbol = method.getName();
long address = LibraryLoader.INSTANCE.find(library, symbol);
if (address == 0) throw new UnsatisfiedLinkError("找不到符号(导出函数) "+symbol);
var buf = new ByteList();
if (cdecl) assembler.javaToCdecl(buf, method.getParameterTypes(), method.getParameterAnnotations());
assembler.emitCall(buf, address);
byte[] asm = buf.toByteArrayAndFree();
try {
linker.injectCode(method, asm, asm.length);
} catch (Exception e) {
e.printStackTrace();
}
}
}