Revert^2 "Add hooks in palette for reporting JNI invocations."
Test: test.py
Bug: 140968481
Change-Id: I3ebbec153040b9bcfe4fb86618c15d2f9c93abb6
diff --git a/libartpalette/Android.bp b/libartpalette/Android.bp
index 66e8bda..e8b7fd8 100644
--- a/libartpalette/Android.bp
+++ b/libartpalette/Android.bp
@@ -54,7 +54,10 @@
// support both prebuilts and sources present simultaneously.
"//prebuilts/module_sdk/art/current/host-exports",
],
- header_libs: ["libbase_headers"],
+ header_libs: [
+ "libbase_headers",
+ "jni_headers",
+ ],
target: {
// Targets supporting dlopen build the client library which loads
// and binds the methods in the libartpalette-system library.
diff --git a/libartpalette/include/palette/palette_hooks.h b/libartpalette/include/palette/palette_hooks.h
index 14e7b3f..40e09fa 100644
--- a/libartpalette/include/palette/palette_hooks.h
+++ b/libartpalette/include/palette/palette_hooks.h
@@ -19,6 +19,8 @@
#include "palette_types.h"
+#include "jni.h"
+
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
@@ -39,6 +41,15 @@
// Notify the Hooks object that the runtime is loading a .oat file.
void (*NotifyOatFileLoaded)(const char* path);
+
+ // Whether to report JNI method entry/exit.
+ int (*ShouldReportJniInvocations)();
+
+ // Notify the Hooks object that a native call is starting.
+ void (*NotifyBeginJniInvocation)(JNIEnv* env);
+
+ // Notify the Hooks object that a native call is ending.
+ void (*NotifyEndJniInvocation)(JNIEnv* env);
} paletteHooksInterface;
struct PaletteHooks {
@@ -56,6 +67,15 @@
void NotifyOatFileLoaded(const char* path) {
return functions->NotifyOatFileLoaded(path);
}
+ int ShouldReportJniInvocations() {
+ return functions->ShouldReportJniInvocations();
+ }
+ void NotifyBeginJniInvocation(JNIEnv* env) {
+ return functions->NotifyBeginJniInvocation(env);
+ }
+ void NotifyEndJniInvocation(JNIEnv* env) {
+ return functions->NotifyEndJniInvocation(env);
+ }
#endif
};
diff --git a/runtime/entrypoints/quick/quick_default_init_entrypoints.h b/runtime/entrypoints/quick/quick_default_init_entrypoints.h
index ae9bdd6..d74561d 100644
--- a/runtime/entrypoints/quick/quick_default_init_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_default_init_entrypoints.h
@@ -20,6 +20,7 @@
#include "base/logging.h" // FOR VLOG_IS_ON.
#include "entrypoints/jni/jni_entrypoints.h"
#include "entrypoints/runtime_asm_entrypoints.h"
+#include "palette/palette.h"
#include "quick_alloc_entrypoints.h"
#include "quick_default_externs.h"
#include "quick_entrypoints.h"
@@ -129,6 +130,17 @@
// Tiered JIT support
qpoints->pUpdateInlineCache = art_quick_update_inline_cache;
qpoints->pCompileOptimized = art_quick_compile_optimized;
+
+ PaletteHooks* hooks = nullptr;
+ if (PaletteGetHooks(&hooks) == PALETTE_STATUS_OK && hooks->ShouldReportJniInvocations()) {
+ qpoints->pJniMethodStart = JniMonitoredMethodStart;
+ qpoints->pJniMethodStartSynchronized = JniMonitoredMethodStartSynchronized;
+ qpoints->pJniMethodEnd = JniMonitoredMethodEnd;
+ qpoints->pJniMethodEndSynchronized = JniMonitoredMethodEndSynchronized;
+ qpoints->pJniMethodEndWithReference = JniMonitoredMethodEndWithReference;
+ qpoints->pJniMethodEndWithReferenceSynchronized =
+ JniMonitoredMethodEndWithReferenceSynchronized;
+ }
}
} // namespace art
diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h
index d9fbbc7..d41a276 100644
--- a/runtime/entrypoints/quick/quick_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_entrypoints.h
@@ -79,6 +79,28 @@
jobject locked, Thread* self)
NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+// JNI entrypoints when monitoring entry/exit.
+extern uint32_t JniMonitoredMethodStart(Thread* self) NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+extern uint32_t JniMonitoredMethodStartSynchronized(jobject to_lock, Thread* self)
+ NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+extern void JniMonitoredMethodEnd(uint32_t saved_local_ref_cookie, Thread* self)
+ NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+extern void JniMonitoredMethodEndSynchronized(uint32_t saved_local_ref_cookie,
+ jobject locked,
+ Thread* self)
+ NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+extern mirror::Object* JniMonitoredMethodEndWithReference(jobject result,
+ uint32_t saved_local_ref_cookie,
+ Thread* self)
+ NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+
+extern mirror::Object* JniMonitoredMethodEndWithReferenceSynchronized(
+ jobject result,
+ uint32_t saved_local_ref_cookie,
+ jobject locked, Thread* self)
+ NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
+
+
extern "C" mirror::String* artStringBuilderAppend(uint32_t format,
const uint32_t* args,
Thread* self)
@@ -88,7 +110,6 @@
Thread* self)
NO_THREAD_SAFETY_ANALYSIS HOT_ATTR;
-
// Read barrier entrypoints.
//
// Compilers for ARM, ARM64 can insert a call to these
diff --git a/runtime/entrypoints/quick/quick_jni_entrypoints.cc b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
index 7d55817..82ec04b 100644
--- a/runtime/entrypoints/quick/quick_jni_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_jni_entrypoints.cc
@@ -21,9 +21,20 @@
#include "entrypoints/entrypoint_utils-inl.h"
#include "indirect_reference_table.h"
#include "mirror/object-inl.h"
+#include "palette/palette.h"
+#include "palette/palette_hooks.h"
#include "thread-inl.h"
#include "verify_object.h"
+// For methods that monitor JNI invocations and report their begin/end to
+// palette hooks.
+#define MONITOR_JNI(kind) \
+ PaletteHooks* hooks = nullptr; \
+ if (PaletteGetHooks(&hooks) == PALETTE_STATUS_OK && \
+ hooks->ShouldReportJniInvocations()) { \
+ hooks->kind(self->GetJniEnv()); \
+ } \
+
namespace art {
static_assert(sizeof(IRTSegmentState) == sizeof(uint32_t), "IRTSegmentState size unexpected");
@@ -224,6 +235,7 @@
// @CriticalNative does not do a state transition. @FastNative usually does not do a state
// transition either but it performs a suspend check that may do state transitions.
if (LIKELY(normal_native)) {
+ MONITOR_JNI(NotifyEndJniInvocation);
GoToRunnable(self);
} else if (fast_native) {
GoToRunnableFast(self);
@@ -277,4 +289,44 @@
}
}
+extern uint32_t JniMonitoredMethodStart(Thread* self) {
+ uint32_t result = JniMethodStart(self);
+ MONITOR_JNI(NotifyBeginJniInvocation);
+ return result;
+}
+
+extern uint32_t JniMonitoredMethodStartSynchronized(jobject to_lock, Thread* self) {
+ uint32_t result = JniMethodStartSynchronized(to_lock, self);
+ MONITOR_JNI(NotifyBeginJniInvocation);
+ return result;
+}
+
+extern void JniMonitoredMethodEnd(uint32_t saved_local_ref_cookie, Thread* self) {
+ MONITOR_JNI(NotifyEndJniInvocation);
+ return JniMethodEnd(saved_local_ref_cookie, self);
+}
+
+extern void JniMonitoredMethodEndSynchronized(uint32_t saved_local_ref_cookie,
+ jobject locked,
+ Thread* self) {
+ MONITOR_JNI(NotifyEndJniInvocation);
+ return JniMethodEndSynchronized(saved_local_ref_cookie, locked, self);
+}
+
+extern mirror::Object* JniMonitoredMethodEndWithReference(jobject result,
+ uint32_t saved_local_ref_cookie,
+ Thread* self) {
+ MONITOR_JNI(NotifyEndJniInvocation);
+ return JniMethodEndWithReference(result, saved_local_ref_cookie, self);
+}
+
+extern mirror::Object* JniMonitoredMethodEndWithReferenceSynchronized(
+ jobject result,
+ uint32_t saved_local_ref_cookie,
+ jobject locked,
+ Thread* self) {
+ MONITOR_JNI(NotifyEndJniInvocation);
+ return JniMethodEndWithReferenceSynchronized(result, saved_local_ref_cookie, locked, self);
+}
+
} // namespace art