summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Victor Chang <vichang@google.com> 2023-10-06 14:24:54 +0100
committer Victor Chang <vichang@google.com> 2023-10-10 09:16:10 +0000
commited04dc23003dc5611a1e5b2ac2190b633dc6193e (patch)
tree0bb1da6dbb8d662cd523ee3a9e30eb6a046913c8
parent30ec3a148e19fba2d54cdf482b16a9b82bec6da4 (diff)
Speed-up Class.getSimpleName()
Bug: 303631821 Test: atest LibcoreBenchmarkTests:libcore.benchmark.ClassTest Change-Id: I106aed4fe24b9138005c4928a7690d10c6df1d0a
-rw-r--r--runtime/mirror/string-inl.h14
-rw-r--r--runtime/mirror/string.cc18
-rw-r--r--runtime/mirror/string.h6
-rw-r--r--runtime/native/java_lang_Class.cc39
4 files changed, 66 insertions, 11 deletions
diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h
index 66e0ef0bdb..0d18b78044 100644
--- a/runtime/mirror/string-inl.h
+++ b/runtime/mirror/string-inl.h
@@ -67,6 +67,20 @@ int32_t String::FastIndexOf(MemoryType* chars, int32_t ch, int32_t start) {
return -1;
}
+template <typename MemoryType>
+int32_t String::LastIndexOf(MemoryType* chars, int32_t ch, int32_t from_index) {
+ DCHECK_LT(from_index, GetLength());
+ const MemoryType* start = chars;
+ const MemoryType* p = chars + from_index;
+ while (p >= start) {
+ if (*p == ch) {
+ return p - chars;
+ }
+ p--;
+ }
+ return -1;
+}
+
inline int32_t String::ComputeHashCode() {
uint32_t hash = IsCompressed()
? ComputeUtf16Hash(GetValueCompressed(), GetLength())
diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc
index 839e01a045..2a26d50d79 100644
--- a/runtime/mirror/string.cc
+++ b/runtime/mirror/string.cc
@@ -37,10 +37,10 @@ namespace mirror {
int32_t String::FastIndexOf(int32_t ch, int32_t start) {
int32_t count = GetLength();
- if (start < 0) {
+ if (start >= count) {
+ return -1;
+ } else if (start < 0) {
start = 0;
- } else if (start > count) {
- start = count;
}
if (IsCompressed()) {
return FastIndexOf<uint8_t>(GetValueCompressed(), ch, start);
@@ -49,6 +49,18 @@ int32_t String::FastIndexOf(int32_t ch, int32_t start) {
}
}
+int32_t String::LastIndexOf(int32_t ch) {
+ int32_t count = GetLength();
+ if (count == 0) {
+ return -1;
+ }
+ if (IsCompressed()) {
+ return LastIndexOf<uint8_t>(GetValueCompressed(), ch, count - 1);
+ } else {
+ return LastIndexOf<uint16_t>(GetValue(), ch, count - 1);
+ }
+}
+
int32_t String::ComputeAndSetHashCode() {
int32_t new_hash_code = ComputeHashCode();
SetHashCode(new_hash_code);
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index 90eb09211c..c0f9b39b1f 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -215,6 +215,12 @@ class MANAGED String final : public Object {
int32_t FastIndexOf(MemoryType* chars, int32_t ch, int32_t start)
REQUIRES_SHARED(Locks::mutator_lock_);
+ int32_t LastIndexOf(int32_t ch) REQUIRES_SHARED(Locks::mutator_lock_);
+
+ template <typename MemoryType>
+ int32_t LastIndexOf(MemoryType* chars, int32_t ch, int32_t from_index)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
int32_t CompareTo(ObjPtr<String> other) REQUIRES_SHARED(Locks::mutator_lock_);
static ObjPtr<CharArray> ToCharArray(Handle<String> h_this, Thread* self)
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 5e54f85b9d..83736668bb 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -681,22 +681,45 @@ static jint Class_getInnerClassFlags(JNIEnv* env, jobject javaThis, jint default
return mirror::Class::GetInnerClassFlags(klass, defaultValue);
}
-static jstring Class_getInnerClassName(JNIEnv* env, jobject javaThis) {
+static jstring Class_getSimpleNameNative(JNIEnv* env, jobject javaThis) {
ScopedFastNativeObjectAccess soa(env);
- StackHandleScope<1> hs(soa.Self());
+ StackHandleScope<3> hs(soa.Self());
Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
+ MutableHandle<mirror::String> h_name(hs.NewHandle<mirror::String>(nullptr));
+ MutableHandle<mirror::String> h_inner_name(hs.NewHandle<mirror::String>(nullptr));
if (klass->IsObsoleteObject()) {
ThrowRuntimeException("Obsolete Object!");
return nullptr;
}
- if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
- return nullptr;
+ if (!klass->IsProxyClass() && klass->GetDexCache() != nullptr) {
+ ObjPtr<mirror::String> class_name = nullptr;
+ if (annotations::GetInnerClass(klass, &class_name)) {
+ if (class_name == nullptr) { // Anonymous class
+ gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
+ return soa.AddLocalReference<jstring>(
+ mirror::String::AllocEmptyString(soa.Self(), allocator_type));
+ }
+ h_inner_name.Assign(class_name);
+ if (annotations::GetDeclaringClass(klass) != nullptr || // member class
+ annotations::GetEnclosingMethod(klass) != nullptr) { // local class
+ return soa.AddLocalReference<jstring>(h_inner_name.Get());
+ }
+ }
}
- ObjPtr<mirror::String> class_name = nullptr;
- if (!annotations::GetInnerClass(klass, &class_name)) {
+
+ h_name.Assign(mirror::Class::ComputeName(klass));
+ if (h_name == nullptr) {
return nullptr;
}
- return soa.AddLocalReference<jstring>(class_name);
+ int32_t dot_index = h_name->LastIndexOf('.');
+ if (dot_index < 0) {
+ return soa.AddLocalReference<jstring>(h_name.Get());
+ }
+ int32_t start_index = dot_index + 1;
+ int32_t length = h_name->GetLength() - start_index;
+ gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
+ return soa.AddLocalReference<jstring>(
+ mirror::String::AllocFromString(soa.Self(), length, h_name, start_index, allocator_type));
}
static jobjectArray Class_getSignatureAnnotation(JNIEnv* env, jobject javaThis) {
@@ -971,7 +994,6 @@ static JNINativeMethod gMethods[] = {
FAST_NATIVE_METHOD(Class, getEnclosingConstructorNative, "()Ljava/lang/reflect/Constructor;"),
FAST_NATIVE_METHOD(Class, getEnclosingMethodNative, "()Ljava/lang/reflect/Method;"),
FAST_NATIVE_METHOD(Class, getInnerClassFlags, "(I)I"),
- FAST_NATIVE_METHOD(Class, getInnerClassName, "()Ljava/lang/String;"),
FAST_NATIVE_METHOD(Class, getInterfacesInternal, "()[Ljava/lang/Class;"),
FAST_NATIVE_METHOD(Class, getPrimitiveClass, "(Ljava/lang/String;)Ljava/lang/Class;"),
FAST_NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"),
@@ -981,6 +1003,7 @@ static JNINativeMethod gMethods[] = {
FAST_NATIVE_METHOD(Class, getPublicDeclaredFields, "()[Ljava/lang/reflect/Field;"),
FAST_NATIVE_METHOD(Class, getRecordAnnotationElement, "(Ljava/lang/String;Ljava/lang/Class;)[Ljava/lang/Object;"),
FAST_NATIVE_METHOD(Class, getSignatureAnnotation, "()[Ljava/lang/String;"),
+ FAST_NATIVE_METHOD(Class, getSimpleNameNative, "()Ljava/lang/String;"),
FAST_NATIVE_METHOD(Class, isAnonymousClass, "()Z"),
FAST_NATIVE_METHOD(Class, isDeclaredAnnotationPresent, "(Ljava/lang/Class;)Z"),
FAST_NATIVE_METHOD(Class, isRecord0, "()Z"),