Avoid use of std::string where we have const char*.
Removing the ClassHelper caused std::string creation for all calls to
Class::GetDescriptor and a significant performance regression. Make the
std::string an out argument so the caller can maintain it and its life time
while allowing GetDescriptor to return the common const char* case.
Don't generate GC maps when compilation is disabled.
Remove other uses of std::string that are occuring on critical paths.
Use the cheaper SkipClass in CompileMethod in CompilerDriver.
Specialize the utf8 as utf16 comparison code for the common shorter byte
encoding.
Force a bit of inlining, remove some UNLIKELYs (they are prone to pessimizing
code), add some LIKELYs.
x86-64 host 1-thread interpret-only of 57 apks:
Before: 29.539s
After: 23.467s
Regular compile:
Before: 1m35.347s
After: 1m20.056s
Bug: 16853450
Change-Id: Ic705ea24784bee24ab80084d06174cbf87d557ad
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 329b4dc..fb57fc7 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -97,7 +97,8 @@
const DexFile& dex_file = klass->GetDexFile();
const DexFile::ClassDef* class_def = klass->GetClassDef();
mirror::Class* super = klass->GetSuperClass();
- if (super == NULL && "Ljava/lang/Object;" != klass->GetDescriptor()) {
+ std::string temp;
+ if (super == NULL && strcmp("Ljava/lang/Object;", klass->GetDescriptor(&temp)) != 0) {
early_failure = true;
failure_message = " that has no super class";
} else if (super != NULL && super->IsFinal()) {
@@ -1457,10 +1458,8 @@
*/
if ((opcode_flags & Instruction::kThrow) != 0 && CurrentInsnFlags()->IsInTry()) {
saved_line_->CopyFromLine(work_line_.get());
- } else {
-#ifndef NDEBUG
+ } else if (kIsDebugBuild) {
saved_line_->FillWithGarbage();
-#endif
}
@@ -2221,6 +2220,7 @@
is_range, false);
const char* return_type_descriptor;
bool is_constructor;
+ RegType* return_type = nullptr;
if (called_method == NULL) {
uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
@@ -2230,6 +2230,19 @@
} else {
is_constructor = called_method->IsConstructor();
return_type_descriptor = called_method->GetReturnTypeDescriptor();
+ Thread* self = Thread::Current();
+ StackHandleScope<1> hs(self);
+ Handle<mirror::ArtMethod> h_called_method(hs.NewHandle(called_method));
+ MethodHelper mh(h_called_method);
+ mirror::Class* return_type_class = mh.GetReturnType(can_load_classes_);
+ if (return_type_class != nullptr) {
+ return_type = ®_types_.FromClass(return_type_descriptor,
+ return_type_class,
+ return_type_class->CannotBeAssignedFromOtherTypes());
+ } else {
+ DCHECK(!can_load_classes_ || self->IsExceptionPending());
+ self->ClearException();
+ }
}
if (is_constructor) {
/*
@@ -2271,12 +2284,14 @@
*/
work_line_->MarkRefsAsInitialized(this_type);
}
- RegType& return_type = reg_types_.FromDescriptor(class_loader_->Get(),
- return_type_descriptor, false);
- if (!return_type.IsLowHalf()) {
- work_line_->SetResultRegisterType(return_type);
+ if (return_type == nullptr) {
+ return_type = ®_types_.FromDescriptor(class_loader_->Get(),
+ return_type_descriptor, false);
+ }
+ if (!return_type->IsLowHalf()) {
+ work_line_->SetResultRegisterType(*return_type);
} else {
- work_line_->SetResultRegisterTypeWide(return_type, return_type.HighHalf(®_types_));
+ work_line_->SetResultRegisterTypeWide(*return_type, return_type->HighHalf(®_types_));
}
just_set_result = true;
break;
@@ -3121,7 +3136,8 @@
RegType* res_method_class;
if (res_method != nullptr) {
mirror::Class* klass = res_method->GetDeclaringClass();
- res_method_class = ®_types_.FromClass(klass->GetDescriptor().c_str(), klass,
+ std::string temp;
+ res_method_class = ®_types_.FromClass(klass->GetDescriptor(&temp), klass,
klass->CannotBeAssignedFromOtherTypes());
} else {
const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
@@ -3337,8 +3353,9 @@
}
if (!actual_arg_type.IsZero()) {
mirror::Class* klass = res_method->GetDeclaringClass();
+ std::string temp;
RegType& res_method_class =
- reg_types_.FromClass(klass->GetDescriptor().c_str(), klass,
+ reg_types_.FromClass(klass->GetDescriptor(&temp), klass,
klass->CannotBeAssignedFromOtherTypes());
if (!res_method_class.IsAssignableFrom(actual_arg_type)) {
Fail(actual_arg_type.IsUnresolvedTypes() ? VERIFY_ERROR_NO_CLASS :