Knock 0.5s off the Calculator startup time.
Down to 2.5s on mysid. We now only mess around with std::strings when we need
to synthesize a descriptor. If we can just hand out a const char* straight from
the dex file -- which most of the time we can -- we now do.
Change-Id: Iddec7062d8bd578bd25f671eb4d597e9ed064d65
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index c335ba9..736853a 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -35,7 +35,7 @@
ASSERT_TRUE(primitive->GetClass() != NULL);
ASSERT_EQ(primitive->GetClass(), primitive->GetClass()->GetClass());
EXPECT_TRUE(primitive->GetClass()->GetSuperClass() != NULL);
- ASSERT_STREQ(descriptor.c_str(), primitive_ch.GetDescriptor().c_str());
+ ASSERT_STREQ(descriptor.c_str(), primitive_ch.GetDescriptor());
EXPECT_TRUE(primitive->GetSuperClass() == NULL);
EXPECT_FALSE(primitive->HasSuperClass());
EXPECT_TRUE(primitive->GetClassLoader() == NULL);
@@ -68,7 +68,7 @@
const ClassLoader* class_loader) {
Class* array = class_linker_->FindClass(array_descriptor, class_loader);
ClassHelper array_component_ch(array->GetComponentType());
- EXPECT_STREQ(component_type.c_str(), array_component_ch.GetDescriptor().c_str());
+ EXPECT_STREQ(component_type.c_str(), array_component_ch.GetDescriptor());
EXPECT_EQ(class_loader, array->GetClassLoader());
AssertArrayClass(array_descriptor, array);
}
@@ -79,7 +79,7 @@
ASSERT_TRUE(array->GetClass() != NULL);
ASSERT_EQ(array->GetClass(), array->GetClass()->GetClass());
EXPECT_TRUE(array->GetClass()->GetSuperClass() != NULL);
- ASSERT_STREQ(array_descriptor.c_str(), kh.GetDescriptor().c_str());
+ ASSERT_STREQ(array_descriptor.c_str(), kh.GetDescriptor());
EXPECT_TRUE(array->GetSuperClass() != NULL);
EXPECT_EQ(class_linker_->FindSystemClass("Ljava/lang/Object;"), array->GetSuperClass());
EXPECT_TRUE(array->HasSuperClass());
@@ -110,10 +110,10 @@
ObjectArray<InterfaceEntry>* iftable = array->GetIfTable();
ASSERT_TRUE(iftable != NULL);
kh.ChangeClass(kh.GetInterface(0));
- EXPECT_STREQ(kh.GetDescriptor().c_str(), "Ljava/lang/Cloneable;");
+ EXPECT_STREQ(kh.GetDescriptor(), "Ljava/lang/Cloneable;");
kh.ChangeClass(array);
kh.ChangeClass(kh.GetInterface(1));
- EXPECT_STREQ(kh.GetDescriptor().c_str(), "Ljava/io/Serializable;");
+ EXPECT_STREQ(kh.GetDescriptor(), "Ljava/io/Serializable;");
}
void AssertMethod(Class* klass, Method* method) {
@@ -154,7 +154,7 @@
void AssertClass(const std::string& descriptor, Class* klass) {
ClassHelper kh(klass);
- EXPECT_STREQ(descriptor.c_str(), kh.GetDescriptor().c_str());
+ EXPECT_STREQ(descriptor.c_str(), kh.GetDescriptor());
if (descriptor == "Ljava/lang/Object;") {
EXPECT_FALSE(klass->HasSuperClass());
} else {
@@ -279,7 +279,7 @@
ASSERT_TRUE(descriptor != NULL);
Class* klass = class_linker_->FindSystemClass(descriptor);
ASSERT_TRUE(klass != NULL);
- EXPECT_STREQ(descriptor.c_str(), ClassHelper(klass).GetDescriptor().c_str());
+ EXPECT_STREQ(descriptor.c_str(), ClassHelper(klass).GetDescriptor());
EXPECT_EQ(class_loader, klass->GetClassLoader());
if (klass->IsPrimitive()) {
AssertPrimitiveClass(descriptor, klass);
@@ -670,7 +670,7 @@
ASSERT_TRUE(JavaLangObject->GetClass() != NULL);
ASSERT_EQ(JavaLangObject->GetClass(), JavaLangObject->GetClass()->GetClass());
EXPECT_EQ(JavaLangObject, JavaLangObject->GetClass()->GetSuperClass());
- ASSERT_STREQ(kh.GetDescriptor().c_str(), "Ljava/lang/Object;");
+ ASSERT_STREQ(kh.GetDescriptor(), "Ljava/lang/Object;");
EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL);
EXPECT_FALSE(JavaLangObject->HasSuperClass());
EXPECT_TRUE(JavaLangObject->GetClassLoader() == NULL);
@@ -707,7 +707,7 @@
ASSERT_TRUE(MyClass->GetClass() != NULL);
ASSERT_EQ(MyClass->GetClass(), MyClass->GetClass()->GetClass());
EXPECT_EQ(JavaLangObject, MyClass->GetClass()->GetSuperClass());
- ASSERT_STREQ(kh.GetDescriptor().c_str(), "LMyClass;");
+ ASSERT_STREQ(kh.GetDescriptor(), "LMyClass;");
EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
EXPECT_TRUE(MyClass->HasSuperClass());
EXPECT_EQ(class_loader.get(), MyClass->GetClassLoader());
@@ -821,7 +821,7 @@
Field* s0 = statics->FindStaticField("s0", "Z");
FieldHelper fh(s0);
- EXPECT_STREQ(ClassHelper(s0->GetClass()).GetDescriptor().c_str(), "Ljava/lang/reflect/Field;");
+ EXPECT_STREQ(ClassHelper(s0->GetClass()).GetDescriptor(), "Ljava/lang/reflect/Field;");
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimBoolean);
EXPECT_EQ(true, s0->GetBoolean(NULL));
s0->SetBoolean(NULL, false);
@@ -995,7 +995,7 @@
Class* klass = class_linker_->GetClassRoot(ClassLinker::ClassRoot(i));
kh.ChangeClass(klass);
EXPECT_TRUE(kh.GetDescriptor() != NULL);
- EXPECT_STREQ(kh.GetDescriptor().c_str(),
+ EXPECT_STREQ(kh.GetDescriptor(),
class_linker_->GetClassRootDescriptor(ClassLinker::ClassRoot(i))) << " i = " << i;
}
}
diff --git a/src/debugger.cc b/src/debugger.cc
index b524359..4cfc34e 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -2447,7 +2447,7 @@
while (count--) {
AllocRecord* record = &recent_allocation_records_[idx];
- class_names.Add(ClassHelper(record->type).GetDescriptor().c_str());
+ class_names.Add(ClassHelper(record->type).GetDescriptor());
MethodHelper mh;
for (size_t i = 0; i < kMaxAllocRecordStackDepth; i++) {
@@ -2506,7 +2506,7 @@
JDWP::Append4BE(bytes, record->byte_count);
JDWP::Append2BE(bytes, record->thin_lock_id);
kh.ChangeClass(record->type);
- JDWP::Append2BE(bytes, class_names.IndexOf(kh.GetDescriptor().c_str()));
+ JDWP::Append2BE(bytes, class_names.IndexOf(kh.GetDescriptor()));
JDWP::Append1BE(bytes, stack_depth);
MethodHelper mh;
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 36c9d38..46a5bec 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -893,7 +893,7 @@
return true;
}
Class* super = klass->GetSuperClass();
- if (super == NULL && ClassHelper(klass).GetDescriptor() != "Ljava/lang/Object;") {
+ if (super == NULL && StringPiece(ClassHelper(klass).GetDescriptor()) != "Ljava/lang/Object;") {
LOG(ERROR) << "Verifier rejected class " << PrettyClass(klass) << " that has no super class";
return false;
}
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index 5b2f54e..0a8d051 100644
--- a/src/dex_verifier.h
+++ b/src/dex_verifier.h
@@ -241,7 +241,7 @@
* the perversion of Object being assignable to an interface type (note, however, that we don't
* allow assignment of Object or Interface to any concrete class and are therefore type safe).
*
- * [1] Java bytecode verifcation: algorithms and formalizations, Xavier Leroy
+ * [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy
*/
static Class* ClassJoin(Class* s, Class* t);
diff --git a/src/heap.cc b/src/heap.cc
index 129c6f4..fe5ca7a 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -163,7 +163,7 @@
ScopedHeapLock lock;
DCHECK(klass == NULL || (klass->IsClassClass() && byte_count >= sizeof(Class)) ||
(klass->IsVariableSize() || klass->GetObjectSize() == byte_count) ||
- ClassHelper(klass).GetDescriptor().empty());
+ strlen(ClassHelper(klass).GetDescriptor()) == 0);
DCHECK_GE(byte_count, sizeof(Object));
Object* obj = AllocateLocked(byte_count);
if (obj != NULL) {
diff --git a/src/java_lang_reflect_Array.cc b/src/java_lang_reflect_Array.cc
index 50bfb83..1d8b526 100644
--- a/src/java_lang_reflect_Array.cc
+++ b/src/java_lang_reflect_Array.cc
@@ -44,7 +44,7 @@
// old code assumed this but if you recurse from "[Foo" to "Foo" to "oo",
// you shouldn't assume there isn't a class "oo".
}
- std::string sub_array_descriptor(ClassHelper(array_class).GetDescriptor(), 1);
+ std::string sub_array_descriptor(ClassHelper(array_class).GetDescriptor() + 1);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Class* sub_array_class = class_linker->FindClass(sub_array_descriptor,
array_class->GetClassLoader());
@@ -80,7 +80,7 @@
DCHECK(javaDimArray != NULL);
Object* dimensions_obj = Decode<Object*>(env, javaDimArray);
DCHECK(dimensions_obj->IsArrayInstance());
- DCHECK_STREQ(ClassHelper(dimensions_obj->GetClass()).GetDescriptor().c_str(), "[I");
+ DCHECK_STREQ(ClassHelper(dimensions_obj->GetClass()).GetDescriptor(), "[I");
IntArray* dimensions_array = down_cast<IntArray*>(dimensions_obj);
// Verify dimensions.
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 9ace57a..82d826e 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -335,7 +335,7 @@
static void ThrowNoSuchMethodError(ScopedJniThreadState& ts, Class* c, const char* name, const char* sig, const char* kind) {
ts.Self()->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;",
- "no %s method \"%s.%s%s\"", kind, ClassHelper(c).GetDescriptor().c_str(), name, sig);
+ "no %s method \"%s.%s%s\"", kind, ClassHelper(c).GetDescriptor(), name, sig);
}
static jmethodID FindMethodID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
@@ -394,7 +394,7 @@
ts.Self()->ClearException();
ts.Self()->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"no type \"%s\" found and so no field \"%s\" could be found in class "
- "\"%s\" or its superclasses", sig, name, ClassHelper(c).GetDescriptor().c_str());
+ "\"%s\" or its superclasses", sig, name, ClassHelper(c).GetDescriptor());
return NULL;
}
if (is_static) {
@@ -405,7 +405,7 @@
if (field == NULL) {
ts.Self()->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"no \"%s\" field \"%s\" in class \"%s\" or its superclasses", sig,
- name, ClassHelper(c).GetDescriptor().c_str());
+ name, ClassHelper(c).GetDescriptor());
return NULL;
}
return EncodeField(field);
diff --git a/src/object_utils.h b/src/object_utils.h
index c086fb8..0c93b43 100644
--- a/src/object_utils.h
+++ b/src/object_utils.h
@@ -22,6 +22,7 @@
#include "dex_file.h"
#include "object.h"
#include "runtime.h"
+#include "UniquePtr.h"
#include <string>
@@ -29,12 +30,14 @@
class ClassHelper {
public:
- ClassHelper() : class_def_(NULL), class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL),
- interface_type_list_(NULL), klass_(NULL) {}
- ClassHelper(const Class* c) : class_def_(NULL), class_linker_(NULL), dex_cache_(NULL),
- dex_file_(NULL), interface_type_list_(NULL), klass_(c) {}
- ClassHelper(const Class* c, ClassLinker* l) : class_def_(NULL), class_linker_(l),
- dex_cache_(NULL), dex_file_(NULL), interface_type_list_(NULL), klass_(c) {}
+ ClassHelper(const Class* c = NULL, ClassLinker* l = NULL)
+ : class_def_(NULL),
+ class_linker_(l),
+ dex_cache_(NULL),
+ dex_file_(NULL),
+ interface_type_list_(NULL),
+ klass_(c) {
+ }
void ChangeClass(const Class* new_c) {
DCHECK(new_c != NULL);
@@ -50,26 +53,29 @@
class_def_ = NULL;
}
- std::string GetDescriptor() {
+ // The returned const char* is only guaranteed to be valid for the lifetime of the ClassHelper.
+ // If you need it longer, copy it into a std::string.
+ const char* GetDescriptor() {
if (klass_->IsArrayClass()) {
std::string result("[");
const Class* saved_klass = klass_;
ChangeClass(klass_->GetComponentType());
result += GetDescriptor();
ChangeClass(saved_klass);
- return result;
- } else if (klass_->IsPrimitive()){
- std::string result;
- result += Primitive::DescriptorChar(klass_->GetPrimitiveType());
- return result;
+ descriptor_ = result;
+ return descriptor_.c_str();
+ } else if (klass_->IsPrimitive()) {
+ return Primitive::Descriptor(klass_->GetPrimitiveType());
} else if (klass_->IsProxyClass()) {
- return GetClassLinker()->GetDescriptorForProxy(klass_);
+ descriptor_ = GetClassLinker()->GetDescriptorForProxy(klass_);
+ return descriptor_.c_str();
} else {
const DexFile& dex_file = GetDexFile();
const DexFile::TypeId& type_id = dex_file.GetTypeId(klass_->GetDexTypeIndex());
return dex_file.GetTypeDescriptor(type_id);
}
}
+
const DexFile::ClassDef* GetClassDef() {
const DexFile::ClassDef* result = class_def_;
if (result == NULL) {
@@ -78,6 +84,7 @@
}
return result;
}
+
uint32_t NumInterfaces() {
if (klass_->IsPrimitive()) {
return 0;
@@ -93,11 +100,13 @@
}
}
}
+
uint16_t GetInterfaceTypeIdx(uint32_t idx) {
DCHECK(!klass_->IsPrimitive());
DCHECK(!klass_->IsArrayClass());
return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
}
+
Class* GetInterface(uint32_t idx) {
DCHECK(!klass_->IsPrimitive());
if (klass_->IsArrayClass()) {
@@ -117,6 +126,7 @@
return interface;
}
}
+
const char* GetSourceFile() {
std::string descriptor(GetDescriptor());
const DexFile& dex_file = GetDexFile();
@@ -127,6 +137,7 @@
return dex_file.GetSourceFile(*dex_class_def);
}
}
+
std::string GetLocation() {
return GetDexCache()->GetLocation()->ToModifiedUtf8();
}
@@ -153,6 +164,7 @@
}
return result;
}
+
DexCache* GetDexCache() {
DexCache* result = dex_cache_;
if (result == NULL) {
@@ -161,6 +173,7 @@
}
return result;
}
+
ClassLinker* GetClassLinker() {
ClassLinker* result = class_linker_;
if (result == NULL) {
@@ -176,6 +189,7 @@
const DexFile* dex_file_;
const DexFile::TypeList* interface_type_list_;
const Class* klass_;
+ std::string descriptor_;
DISALLOW_COPY_AND_ASSIGN(ClassHelper);
};
diff --git a/src/primitive.h b/src/primitive.h
index 402a2b5..ae2e487 100644
--- a/src/primitive.h
+++ b/src/primitive.h
@@ -88,29 +88,29 @@
return ComponentSize(type) <= 4 ? 4 : 8;
}
- static char DescriptorChar(Type type) {
+ static const char* Descriptor(Type type) {
switch (type) {
case kPrimBoolean:
- return 'Z';
+ return "Z";
case kPrimByte:
- return 'B';
+ return "B";
case kPrimChar:
- return 'C';
+ return "C";
case kPrimShort:
- return 'S';
+ return "S";
case kPrimInt:
- return 'I';
+ return "I";
case kPrimFloat:
- return 'F';
+ return "F";
case kPrimLong:
- return 'J';
+ return "J";
case kPrimDouble:
- return 'D';
+ return "D";
case kPrimVoid:
- return 'V';
+ return "V";
default:
LOG(FATAL) << "Primitive char conversion on invalid type " << static_cast<int>(type);
- return 0;
+ return NULL;
}
}
diff --git a/src/utils.cc b/src/utils.cc
index 24e0429..0d6aff9 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -126,8 +126,7 @@
}
std::string PrettyDescriptor(Primitive::Type type) {
- char descriptor_char = Primitive::DescriptorChar(type);
- std::string descriptor_string(1, descriptor_char);
+ std::string descriptor_string(Primitive::Descriptor(type));
return PrettyDescriptor(descriptor_string);
}