summaryrefslogtreecommitdiffstats
path: root/compiler
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2014-09-10 14:44:24 -0700
committerIan Rogers <irogers@google.com>2014-09-12 14:57:53 -0700
commit7b078e8c04f3e1451dbdd18543c8b9692b5b067e (patch)
tree414229c6b87eb20ea24c40780752da5a3999a49a /compiler
parentf79ba17defbd9342e44ab9f3de0807054673d3c9 (diff)
downloadart-7b078e8c04f3e1451dbdd18543c8b9692b5b067e.zip
art-7b078e8c04f3e1451dbdd18543c8b9692b5b067e.tar.gz
art-7b078e8c04f3e1451dbdd18543c8b9692b5b067e.tar.bz2
Compile time performance improvements focusing on interpret-only.
Reduce virtual method dispatch in the method verifier and make more code inline-able. Add a StringPiece with const char* equality operator to avoid redundant StringPieces and strlens. Remove back link from register line to verifier and pass as argument to reduce size of RegisterLine. Remove instruction length from instruction flags and compute from the instruction, again to reduce size. Add suspend checks to resolve and verify to allow for more easy monitor inflation and reduce contention on Locks::thread_list_suspend_thread_lock_. Change ThrowEarlierClassFailure to throw pre-allocated exception. Avoid calls to Thread::Current() by passing self. Template specialize IsValidClassName. Make ANR reporting with SIGQUIT run using checkpoints rather than suspending all threads. This makes the stack/lock analysis less lock error prone. Extra Barrier assertions and condition variable time out is now returned as a boolean both from Barrier and ConditionVariable::Wait. 2 threaded host x86-64 interpret-only numbers from 341 samples: Before change: Avg 176.137ms 99% CI 3.468ms to 1060.770ms After change: Avg 139.163% 99% CI 3.027ms to 838.257ms Reduction in average compile time after change is 20.9%. Slow-down without change is 26.5%. Bug: 17471626 - Fix bug where RegTypeCache::JavaLangObject/String/Class/Throwable could return unresolved type when class loading is disabled. Bug: 17398101 Change-Id: Id59ce3cc520701c6ecf612f7152498107bc40684
Diffstat (limited to 'compiler')
-rw-r--r--compiler/dex/verified_method.cc20
-rw-r--r--compiler/driver/compiler_driver.cc13
2 files changed, 19 insertions, 14 deletions
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
index 01c8f80..9f0a696 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -38,7 +38,7 @@
#include "verifier/dex_gc_map.h"
#include "verifier/method_verifier.h"
#include "verifier/method_verifier-inl.h"
-#include "verifier/register_line.h"
+#include "verifier/reg_type-inl.h"
#include "verifier/register_line-inl.h"
namespace art {
@@ -127,7 +127,7 @@ bool VerifiedMethod::GenerateGcMap(verifier::MethodVerifier* method_verifier) {
dex_gc_map_.push_back((i >> 8) & 0xFF);
}
verifier::RegisterLine* line = method_verifier->GetRegLine(i);
- line->WriteReferenceBitMap(dex_gc_map_, ref_bitmap_bytes);
+ line->WriteReferenceBitMap(method_verifier, &dex_gc_map_, ref_bitmap_bytes);
}
}
DCHECK_EQ(dex_gc_map_.size(), table_size);
@@ -151,7 +151,7 @@ void VerifiedMethod::VerifyGcMap(verifier::MethodVerifier* method_verifier,
map_index++;
verifier::RegisterLine* line = method_verifier->GetRegLine(i);
for (size_t j = 0; j < code_item->registers_size_; j++) {
- if (line->GetRegisterType(j).IsNonZeroReferenceTypes()) {
+ if (line->GetRegisterType(method_verifier, j).IsNonZeroReferenceTypes()) {
DCHECK_LT(j / 8, map.RegWidth());
DCHECK_EQ((reg_bitmap[j / 8] >> (j % 8)) & 1, 1);
} else if ((j / 8) < map.RegWidth()) {
@@ -178,7 +178,7 @@ void VerifiedMethod::ComputeGcMapSizes(verifier::MethodVerifier* method_verifier
local_gc_points++;
max_insn = i;
verifier::RegisterLine* line = method_verifier->GetRegLine(i);
- max_ref_reg = line->GetMaxNonZeroReferenceReg(max_ref_reg);
+ max_ref_reg = line->GetMaxNonZeroReferenceReg(method_verifier, max_ref_reg);
}
}
*gc_points = local_gc_points;
@@ -217,7 +217,8 @@ void VerifiedMethod::GenerateDevirtMap(verifier::MethodVerifier* method_verifier
bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE) ||
(inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE);
const verifier::RegType&
- reg_type(line->GetRegisterType(is_range ? inst->VRegC_3rc() : inst->VRegC_35c()));
+ reg_type(line->GetRegisterType(method_verifier,
+ is_range ? inst->VRegC_3rc() : inst->VRegC_35c()));
if (!reg_type.HasClass()) {
// We will compute devirtualization information only when we know the Class of the reg type.
@@ -284,17 +285,20 @@ void VerifiedMethod::GenerateSafeCastSet(verifier::MethodVerifier* method_verifi
const verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
bool is_safe_cast = false;
if (code == Instruction::CHECK_CAST) {
- const verifier::RegType& reg_type(line->GetRegisterType(inst->VRegA_21c()));
+ const verifier::RegType& reg_type(line->GetRegisterType(method_verifier,
+ inst->VRegA_21c()));
const verifier::RegType& cast_type =
method_verifier->ResolveCheckedClass(inst->VRegB_21c());
is_safe_cast = cast_type.IsStrictlyAssignableFrom(reg_type);
} else {
- const verifier::RegType& array_type(line->GetRegisterType(inst->VRegB_23x()));
+ const verifier::RegType& array_type(line->GetRegisterType(method_verifier,
+ inst->VRegB_23x()));
// We only know its safe to assign to an array if the array type is precise. For example,
// an Object[] can have any type of object stored in it, but it may also be assigned a
// String[] in which case the stores need to be of Strings.
if (array_type.IsPreciseReference()) {
- const verifier::RegType& value_type(line->GetRegisterType(inst->VRegA_23x()));
+ const verifier::RegType& value_type(line->GetRegisterType(method_verifier,
+ inst->VRegA_23x()));
const verifier::RegType& component_type = method_verifier->GetRegTypeCache()
->GetComponentType(array_type, method_verifier->GetClassLoader());
is_safe_cast = component_type.IsStrictlyAssignableFrom(value_type);
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index db6a01e..bbd1939 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1725,15 +1725,15 @@ static void VerifyClass(const ParallelCompilationManager* manager, size_t class_
*/
Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file)));
std::string error_msg;
- if (verifier::MethodVerifier::VerifyClass(&dex_file, dex_cache, class_loader, &class_def, true,
- &error_msg) ==
+ if (verifier::MethodVerifier::VerifyClass(soa.Self(), &dex_file, dex_cache, class_loader,
+ &class_def, true, &error_msg) ==
verifier::MethodVerifier::kHardFailure) {
LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor)
<< " because: " << error_msg;
}
} else if (!SkipClass(jclass_loader, dex_file, klass.Get())) {
CHECK(klass->IsResolved()) << PrettyClass(klass.Get());
- class_linker->VerifyClass(klass);
+ class_linker->VerifyClass(soa.Self(), klass);
if (klass->IsErroneous()) {
// ClassLinker::VerifyClass throws, which isn't useful in the compiler.
@@ -1778,7 +1778,7 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl
if (klass->IsVerified()) {
// Attempt to initialize the class but bail if we either need to initialize the super-class
// or static fields.
- manager->GetClassLinker()->EnsureInitialized(klass, false, false);
+ manager->GetClassLinker()->EnsureInitialized(soa.Self(), klass, false, false);
if (!klass->IsInitialized()) {
// We don't want non-trivial class initialization occurring on multiple threads due to
// deadlock problems. For example, a parent class is initialized (holding its lock) that
@@ -1792,7 +1792,7 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl
ObjectLock<mirror::Class> lock(soa.Self(), h_klass);
// Attempt to initialize allowing initialization of parent classes but still not static
// fields.
- manager->GetClassLinker()->EnsureInitialized(klass, false, true);
+ manager->GetClassLinker()->EnsureInitialized(soa.Self(), klass, false, true);
if (!klass->IsInitialized()) {
// We need to initialize static fields, we only do this for image classes that aren't
// marked with the $NoPreloadHolder (which implies this should not be initialized early).
@@ -1811,7 +1811,8 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl
// Run the class initializer in transaction mode.
runtime->EnterTransactionMode(&transaction);
const mirror::Class::Status old_status = klass->GetStatus();
- bool success = manager->GetClassLinker()->EnsureInitialized(klass, true, true);
+ bool success = manager->GetClassLinker()->EnsureInitialized(soa.Self(), klass, true,
+ true);
// TODO we detach transaction from runtime to indicate we quit the transactional
// mode which prevents the GC from visiting objects modified during the transaction.
// Ensure GC is not run so don't access freed objects when aborting transaction.