From 42e85734c23d327a23db05bb24db0fbcee135300 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Sat, 18 Sep 2021 00:05:53 +0800 Subject: [PATCH] Add interface to deopt method (#1124) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 残页 <31466456+canyie@users.noreply.github.com> Co-authored-by: Wang Han --- .../main/cpp/main/src/jni/art_class_linker.cpp | 10 +--------- .../de/robv/android/xposed/XposedBridge.java | 18 ++++++++++++++++++ .../lspd/yahfa/dexmaker/DynamicBridge.java | 2 +- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/core/src/main/cpp/main/src/jni/art_class_linker.cpp b/core/src/main/cpp/main/src/jni/art_class_linker.cpp index af72280a..9f7895b5 100644 --- a/core/src/main/cpp/main/src/jni/art_class_linker.cpp +++ b/core/src/main/cpp/main/src/jni/art_class_linker.cpp @@ -27,18 +27,10 @@ #include "art_class_linker.h" namespace lspd { - - static std::unordered_set deopted_methods; - LSP_DEF_NATIVE_METHOD(void, ClassLinker, setEntryPointsToInterpreter, jobject method) { void *reflected_method = yahfa::getArtMethod(env, method); - if (deopted_methods.contains(reflected_method)) { - LOGD("method %p has been deopted before, skip...", reflected_method); - return; - } LOGD("deoptimizing method: %p", reflected_method); art::ClassLinker::Current()->SetEntryPointsToInterpreter(reflected_method); - deopted_methods.insert(reflected_method); LOGD("method deoptimized: %p", reflected_method); } @@ -51,4 +43,4 @@ namespace lspd { REGISTER_LSP_NATIVE_METHODS(ClassLinker); } -} +} // namespace lspd diff --git a/core/src/main/java/de/robv/android/xposed/XposedBridge.java b/core/src/main/java/de/robv/android/xposed/XposedBridge.java index 1dcb22b4..dda39178 100644 --- a/core/src/main/java/de/robv/android/xposed/XposedBridge.java +++ b/core/src/main/java/de/robv/android/xposed/XposedBridge.java @@ -36,6 +36,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.reflect.Proxy; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -147,6 +148,23 @@ public final class XposedBridge { Log.e(TAG, logStr); } + /** + * Deoptimize a method to avoid callee being inlined. + * + * @param deoptimizedMethod The method to deoptmize. Generally it should be a caller of a method + * that is inlined. + */ + public static void deoptimizeMethod(Member deoptimizedMethod) { + if (!(deoptimizedMethod instanceof Executable)) { + throw new IllegalArgumentException("Only methods and constructors can be deoptimized: " + deoptimizedMethod.toString()); + } else if (Modifier.isAbstract(deoptimizedMethod.getModifiers())) { + throw new IllegalArgumentException("Cannot deoptimize abstract methods: " + deoptimizedMethod); + } else if (Proxy.isProxyClass(deoptimizedMethod.getDeclaringClass())) { + throw new IllegalArgumentException("Cannot deoptimize methods from proxy class: " + deoptimizedMethod); + } + YahfaHooker.deoptMethodNative((Executable) deoptimizedMethod); + } + /** * Hook any method (or constructor) with the specified callback. See below for some wrappers * that make it easier to find a method/constructor in one step. diff --git a/core/src/main/java/org/lsposed/lspd/yahfa/dexmaker/DynamicBridge.java b/core/src/main/java/org/lsposed/lspd/yahfa/dexmaker/DynamicBridge.java index f0e66bb2..b72c49ac 100644 --- a/core/src/main/java/org/lsposed/lspd/yahfa/dexmaker/DynamicBridge.java +++ b/core/src/main/java/org/lsposed/lspd/yahfa/dexmaker/DynamicBridge.java @@ -37,7 +37,7 @@ public final class DynamicBridge { Utils.logD("hooking " + hookMethod); if (hookedInfo.containsKey(hookMethod)) { - Utils.logW("already hook method:" + hookMethod); + Utils.logW("already hook method:" + hookMethod, new IllegalStateException()); return; }