summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Victor Chang <vichang@google.com> 2022-08-02 15:26:06 +0100
committer Victor Chang <vichang@google.com> 2022-08-04 09:55:13 +0000
commitc3f4364b73a3291d3c930fbd5f52220e37cefa1d (patch)
tree9e39ba0d2a20493d06e22cfbe1e65da5441d527c
parentc0398effdea1b4991287155fc1b2ea3f1e7565e0 (diff)
Avoid creating unnecessary StackFrameInfo objects in StackWalker.getCallerClass() implementation
Bug: 240965799 Test: atest CtsLibcoreOjTestCases:test.java.lang.StackWalker Change-Id: I5b528137e5805849b1e24d0e37c4b10fb3fc0040
-rw-r--r--runtime/native/java_lang_StackStreamFactory.cc2
-rw-r--r--runtime/thread.cc47
2 files changed, 30 insertions, 19 deletions
diff --git a/runtime/native/java_lang_StackStreamFactory.cc b/runtime/native/java_lang_StackStreamFactory.cc
index b4ad042a47..f876c1014b 100644
--- a/runtime/native/java_lang_StackStreamFactory.cc
+++ b/runtime/native/java_lang_StackStreamFactory.cc
@@ -43,7 +43,7 @@ static jint StackStreamFactory_nativeFetchStackFrameInfo(JNIEnv* env, jclass,
static JNINativeMethod gMethods[] = {
FAST_NATIVE_METHOD(StackStreamFactory, nativeGetStackAnchor, "()Ljava/lang/Object;"),
- FAST_NATIVE_METHOD(StackStreamFactory, nativeFetchStackFrameInfo, "(JLjava/lang/Object;III[Ljava/lang/StackFrameInfo;)I"),
+ FAST_NATIVE_METHOD(StackStreamFactory, nativeFetchStackFrameInfo, "(JLjava/lang/Object;III[Ljava/lang/Object;)I"),
};
void register_java_lang_StackStreamFactory(JNIEnv* env) {
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 48b7b481d3..db43afe33f 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -3157,7 +3157,7 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(
return result;
}
-static ObjPtr<mirror::StackFrameInfo> InitStackFrameInfo(
+[[nodiscard]] static ObjPtr<mirror::StackFrameInfo> InitStackFrameInfo(
const ScopedObjectAccessAlreadyRunnable& soa,
ClassLinker* class_linker,
Handle<mirror::StackFrameInfo> stackFrameInfo,
@@ -3219,9 +3219,11 @@ static ObjPtr<mirror::StackFrameInfo> InitStackFrameInfo(
return stackFrameInfo.Get();
}
+constexpr jlong FILL_CLASS_REFS_ONLY = 0x2; // StackStreamFactory.FILL_CLASS_REFS_ONLY
+
jint Thread::InternalStackTraceToStackFrameInfoArray(
const ScopedObjectAccessAlreadyRunnable& soa,
- [[maybe_unused]] jlong mode, // See java.lang.StackStreamFactory for the mode flags
+ jlong mode, // See java.lang.StackStreamFactory for the mode flags
jobject internal,
jint startLevel,
jint batchSize,
@@ -3232,8 +3234,8 @@ jint Thread::InternalStackTraceToStackFrameInfoArray(
int32_t depth = soa.Decode<mirror::Array>(internal)->GetLength() - 1;
DCHECK_GE(depth, 0);
- StackHandleScope<5> hs(soa.Self());
- Handle<mirror::ObjectArray<mirror::Object>> frames =
+ StackHandleScope<6> hs(soa.Self());
+ Handle<mirror::ObjectArray<mirror::Object>> framesOrClasses =
hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Object>>(output_array));
jint endBufferIndex = startBufferIndex;
@@ -3242,11 +3244,14 @@ jint Thread::InternalStackTraceToStackFrameInfoArray(
return endBufferIndex;
}
- int32_t bufferSize = frames->GetLength();
+ int32_t bufferSize = framesOrClasses->GetLength();
if (startBufferIndex < 0 || startBufferIndex >= bufferSize) {
return endBufferIndex;
}
+ // The FILL_CLASS_REFS_ONLY flag is defined in AbstractStackWalker.fetchStackFrames() javadoc.
+ bool isClassArray = (mode & FILL_CLASS_REFS_ONLY) != 0;
+
Handle<mirror::ObjectArray<mirror::Object>> decoded_traces =
hs.NewHandle(soa.Decode<mirror::Object>(internal)->AsObjectArray<mirror::Object>());
// Methods and dex PC trace is element 0.
@@ -3260,26 +3265,32 @@ jint Thread::InternalStackTraceToStackFrameInfoArray(
DCHECK(sfi_class != nullptr);
MutableHandle<mirror::StackFrameInfo> frame = hs.NewHandle<mirror::StackFrameInfo>(nullptr);
+ MutableHandle<mirror::Class> clazz = hs.NewHandle<mirror::Class>(nullptr);
for (uint32_t i = static_cast<uint32_t>(startLevel); i < static_cast<uint32_t>(depth); ++i) {
if (endBufferIndex >= startBufferIndex + batchSize || endBufferIndex >= bufferSize) {
break;
}
- // Prepare parameters for fields in StackFrameInfo
ArtMethod* method = method_trace->GetElementPtrSize<ArtMethod*>(i, kRuntimePointerSize);
- uint32_t dex_pc = method_trace->GetElementPtrSize<uint32_t>(
- i + static_cast<uint32_t>(method_trace->GetLength()) / 2, kRuntimePointerSize);
+ if (isClassArray) {
+ clazz.Assign(method->GetDeclaringClass());
+ framesOrClasses->Set(endBufferIndex, clazz.Get());
+ } else {
+ // Prepare parameters for fields in StackFrameInfo
+ uint32_t dex_pc = method_trace->GetElementPtrSize<uint32_t>(
+ i + static_cast<uint32_t>(method_trace->GetLength()) / 2, kRuntimePointerSize);
- ObjPtr<mirror::Object> frameObject = frames->Get(endBufferIndex);
- // If libcore didn't allocate the object, we just stop here, but it's unlikely.
- if (frameObject == nullptr || !frameObject->InstanceOf(sfi_class.Get())) {
- break;
- }
- frame.Assign(ObjPtr<mirror::StackFrameInfo>::DownCast(frameObject));
- frame.Assign(InitStackFrameInfo(soa, class_linker, frame, method, dex_pc));
- // Break if InitStackFrameInfo fails to allocate objects or assign the fields.
- if (frame == nullptr) {
- break;
+ ObjPtr<mirror::Object> frameObject = framesOrClasses->Get(endBufferIndex);
+ // If libcore didn't allocate the object, we just stop here, but it's unlikely.
+ if (frameObject == nullptr || !frameObject->InstanceOf(sfi_class.Get())) {
+ break;
+ }
+ frame.Assign(ObjPtr<mirror::StackFrameInfo>::DownCast(frameObject));
+ frame.Assign(InitStackFrameInfo(soa, class_linker, frame, method, dex_pc));
+ // Break if InitStackFrameInfo fails to allocate objects or assign the fields.
+ if (frame == nullptr) {
+ break;
+ }
}
++endBufferIndex;