Add interface to deopt method (#1124)

Co-authored-by: 残页 <31466456+canyie@users.noreply.github.com>
Co-authored-by: Wang Han <wanghan1995315@gmail.com>
This commit is contained in:
LoveSy 2021-09-18 00:05:53 +08:00 committed by GitHub
parent 8ae4738d4a
commit 42e85734c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 10 deletions

View File

@ -27,18 +27,10 @@
#include "art_class_linker.h" #include "art_class_linker.h"
namespace lspd { namespace lspd {
static std::unordered_set<void *> deopted_methods;
LSP_DEF_NATIVE_METHOD(void, ClassLinker, setEntryPointsToInterpreter, jobject method) { LSP_DEF_NATIVE_METHOD(void, ClassLinker, setEntryPointsToInterpreter, jobject method) {
void *reflected_method = yahfa::getArtMethod(env, 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); LOGD("deoptimizing method: %p", reflected_method);
art::ClassLinker::Current()->SetEntryPointsToInterpreter(reflected_method); art::ClassLinker::Current()->SetEntryPointsToInterpreter(reflected_method);
deopted_methods.insert(reflected_method);
LOGD("method deoptimized: %p", reflected_method); LOGD("method deoptimized: %p", reflected_method);
} }
@ -51,4 +43,4 @@ namespace lspd {
REGISTER_LSP_NATIVE_METHODS(ClassLinker); REGISTER_LSP_NATIVE_METHODS(ClassLinker);
} }
} } // namespace lspd

View File

@ -36,6 +36,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -147,6 +148,23 @@ public final class XposedBridge {
Log.e(TAG, logStr); 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 * 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. * that make it easier to find a method/constructor in one step.

View File

@ -37,7 +37,7 @@ public final class DynamicBridge {
Utils.logD("hooking " + hookMethod); Utils.logD("hooking " + hookMethod);
if (hookedInfo.containsKey(hookMethod)) { if (hookedInfo.containsKey(hookMethod)) {
Utils.logW("already hook method:" + hookMethod); Utils.logW("already hook method:" + hookMethod, new IllegalStateException());
return; return;
} }