Skip to content

Commit

Permalink
Suddenly Android: disable final fields for JIT to get rid of staticFi…
Browse files Browse the repository at this point in the history
…eldBase/staticFieldOffset
  • Loading branch information
xxDark committed Jun 5, 2022
1 parent df02091 commit 6e79544
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
21 changes: 20 additions & 1 deletion src/main/java/dev/xdark/ssvm/jit/JitCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import dev.xdark.ssvm.mirror.JavaClass;
import dev.xdark.ssvm.mirror.JavaField;
import dev.xdark.ssvm.mirror.JavaMethod;
import dev.xdark.ssvm.util.UnsafeUtil;
import dev.xdark.ssvm.util.VMHelper;
import dev.xdark.ssvm.value.DoubleValue;
import dev.xdark.ssvm.value.FloatValue;
Expand Down Expand Up @@ -70,6 +71,7 @@
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public final class JitCompiler {

static final boolean CAN_USE_STATIC_FINAL;
private static final AtomicInteger CLASS_ID = new AtomicInteger();
private static final ClassType JIT_INVOKER = ClassType.of(JitInvoker.class);
private static final ClassType CTX = ClassType.of(ExecutionContext.class);
Expand Down Expand Up @@ -318,7 +320,11 @@ public static JitClass compile(JavaMethod jm, int flags) {
writer.visitSource(jm.toString(), null);
Set<Object> constants = compiler.constants.keySet();
if (!constants.isEmpty()) {
writer.visitField(ACC_PRIVATE | ACC_STATIC | ACC_FINAL, "constants", "[Ljava/lang/Object;", null, null);
int constantsAcc = ACC_PRIVATE | ACC_STATIC;
if (CAN_USE_STATIC_FINAL) {
constantsAcc |= ACC_FINAL;
}
writer.visitField(constantsAcc, "constants", "[Ljava/lang/Object;", null, null);
}

byte[] bc = writer.toByteArray();
Expand Down Expand Up @@ -1759,6 +1765,19 @@ private static Access getStatic(ClassType owner, String name, ClassType rt) {
return new Access(GETSTATIC, owner, name, rt);
}

static {
boolean canUseStaticFinal;
try {
UnsafeUtil.get().staticFieldBase(JitCompiler.class.getDeclaredField("CAN_USE_STATIC_FINAL"));
canUseStaticFinal = true;
} catch (NoSuchFieldException ex) {
throw new ExceptionInInitializerError(ex);
} catch (NoSuchMethodError ex) {
canUseStaticFinal = false;
}
CAN_USE_STATIC_FINAL = canUseStaticFinal;
}

private static final class ClassType {

final Type type;
Expand Down
10 changes: 8 additions & 2 deletions src/main/java/dev/xdark/ssvm/jit/JitInstaller.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,14 @@ public void install(JavaMethod method, ClassDefiner definer, JitClass jitClass)
Class.forName(c.getName(), true, c.getClassLoader());
} catch(ClassNotFoundException ignored) {
}
Unsafe u = UnsafeUtil.get();
u.putObject(u.staticFieldBase(field), u.staticFieldOffset(field), constants.toArray());
Object[] constantsArray = constants.toArray();
if (JitCompiler.CAN_USE_STATIC_FINAL) {
Unsafe unsafe = UnsafeUtil.get();
unsafe.putObject(unsafe.staticFieldBase(field), unsafe.staticFieldOffset(field), constantsArray);
} else {
field.setAccessible(true);
field.set(null, constantsArray);
}
}
JitInvoker cons = (JitInvoker) c.getConstructor().newInstance();
VirtualMachine vm = method.getOwner().getVM();
Expand Down

0 comments on commit 6e79544

Please sign in to comment.