summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Elliott Hughes <enh@google.com> 2013-01-07 12:00:42 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2013-01-07 12:00:43 -0800
commit1a25aa432314bcf008c11e3514afc0b7aeb64d5c (patch)
treed6a9831d89fde0f4a31762f4514d9d42f8c41e56
parent1e5ba286ab9e815e3121b408019fcaad0d4b17ec (diff)
parent80537bb742dff4ccdf6d04b1c0bb7d2179acc8cb (diff)
Merge "Fix and reenable lock dumping in stack dumps." into dalvik-dev
-rw-r--r--src/heap.cc5
-rw-r--r--src/monitor.cc58
-rw-r--r--src/signal_catcher.cc2
-rw-r--r--src/thread.cc10
-rw-r--r--src/thread.h3
-rw-r--r--src/timing_logger.h8
-rw-r--r--src/verifier/method_verifier.cc17
-rw-r--r--src/verifier/method_verifier.h4
-rw-r--r--src/verifier/reg_type.cc2
-rw-r--r--src/verifier/reg_type.h41
-rw-r--r--src/verifier/reg_type_cache.cc45
-rw-r--r--src/verifier/reg_type_cache.h5
-rw-r--r--src/verifier/reg_type_test.cc2
13 files changed, 112 insertions, 90 deletions
diff --git a/src/heap.cc b/src/heap.cc
index 7edbcf0460..1cdc9c904c 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -396,7 +396,8 @@ void Heap::DumpGcPerformanceInfo() {
LOG(INFO) << "Total time spent in GC: " << PrettyDuration(total_duration);
LOG(INFO) << "Mean GC size throughput: "
<< PrettySize(GetTotalBytesFreed() / total_seconds) << "/s";
- LOG(INFO) << "Mean GC object throughput: " << GetTotalObjectsFreed() / total_seconds << "/s";
+ LOG(INFO) << "Mean GC object throughput: "
+ << (GetTotalObjectsFreed() / total_seconds) << " objects/s";
}
LOG(INFO) << "Total number of allocations: " << total_objects_allocated;
LOG(INFO) << "Total bytes allocated " << PrettySize(total_bytes_allocated);
@@ -406,7 +407,7 @@ void Heap::DumpGcPerformanceInfo() {
<< PrettyDuration(allocation_time / total_objects_allocated);
}
LOG(INFO) << "Total mutator paused time: " << PrettyDuration(total_paused_time);
- LOG(INFO) << "Total time waiting for GC to complete time: " << PrettyDuration(total_wait_time_);
+ LOG(INFO) << "Total time waiting for GC to complete: " << PrettyDuration(total_wait_time_);
}
Heap::~Heap() {
diff --git a/src/monitor.cc b/src/monitor.cc
index 6172136d4a..33383ebc59 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -901,41 +901,35 @@ void Monitor::DescribeLocks(std::ostream& os, StackVisitor* stack_visitor) {
return; // No "tries" implies no synchronization, so no held locks to report.
}
- // TODO: Enable dex register lock descriptions, disabling as for the portable path GetVReg is
- // unimplemented. There is also a possible deadlock relating to the verifier calling
- // ClassLoader.loadClass and reentering managed code whilst the ThreadList lock is held.
- const bool kEnableDexRegisterLockDescriptions = false;
- if (kEnableDexRegisterLockDescriptions) {
- // Ask the verifier for the dex pcs of all the monitor-enter instructions corresponding to
- // the locks held in this stack frame.
- std::vector<uint32_t> monitor_enter_dex_pcs;
- verifier::MethodVerifier::FindLocksAtDexPc(m, stack_visitor->GetDexPc(), monitor_enter_dex_pcs);
- if (monitor_enter_dex_pcs.empty()) {
- return;
- }
+ // Ask the verifier for the dex pcs of all the monitor-enter instructions corresponding to
+ // the locks held in this stack frame.
+ std::vector<uint32_t> monitor_enter_dex_pcs;
+ verifier::MethodVerifier::FindLocksAtDexPc(m, stack_visitor->GetDexPc(), monitor_enter_dex_pcs);
+ if (monitor_enter_dex_pcs.empty()) {
+ return;
+ }
- // Verification is an iterative process, so it can visit the same monitor-enter instruction
- // repeatedly with increasingly accurate type information. Our callers don't want to see
- // duplicates.
- STLSortAndRemoveDuplicates(&monitor_enter_dex_pcs);
-
- for (size_t i = 0; i < monitor_enter_dex_pcs.size(); ++i) {
- // The verifier works in terms of the dex pcs of the monitor-enter instructions.
- // We want the registers used by those instructions (so we can read the values out of them).
- uint32_t dex_pc = monitor_enter_dex_pcs[i];
- uint16_t monitor_enter_instruction = code_item->insns_[dex_pc];
-
- // Quick sanity check.
- if ((monitor_enter_instruction & 0xff) != Instruction::MONITOR_ENTER) {
- LOG(FATAL) << "expected monitor-enter @" << dex_pc << "; was "
- << reinterpret_cast<void*>(monitor_enter_instruction);
- }
+ // Verification is an iterative process, so it can visit the same monitor-enter instruction
+ // repeatedly with increasingly accurate type information. We don't want duplicates.
+ // TODO: is this fixed if we share the other std::vector-returning verifier code?
+ STLSortAndRemoveDuplicates(&monitor_enter_dex_pcs);
+
+ for (size_t i = 0; i < monitor_enter_dex_pcs.size(); ++i) {
+ // The verifier works in terms of the dex pcs of the monitor-enter instructions.
+ // We want the registers used by those instructions (so we can read the values out of them).
+ uint32_t dex_pc = monitor_enter_dex_pcs[i];
+ uint16_t monitor_enter_instruction = code_item->insns_[dex_pc];
- uint16_t monitor_register = ((monitor_enter_instruction >> 8) & 0xff);
- Object* o = reinterpret_cast<Object*>(stack_visitor->GetVReg(m, monitor_register,
- kReferenceVReg));
- DumpLockedObject(os, o);
+ // Quick sanity check.
+ if ((monitor_enter_instruction & 0xff) != Instruction::MONITOR_ENTER) {
+ LOG(FATAL) << "expected monitor-enter @" << dex_pc << "; was "
+ << reinterpret_cast<void*>(monitor_enter_instruction);
}
+
+ uint16_t monitor_register = ((monitor_enter_instruction >> 8) & 0xff);
+ Object* o = reinterpret_cast<Object*>(stack_visitor->GetVReg(m, monitor_register,
+ kReferenceVReg));
+ DumpLockedObject(os, o);
}
}
diff --git a/src/signal_catcher.cc b/src/signal_catcher.cc
index 9fdf4e9927..c021dd1d2c 100644
--- a/src/signal_catcher.cc
+++ b/src/signal_catcher.cc
@@ -124,7 +124,7 @@ void SignalCatcher::HandleSigQuit() {
thread_list->SuspendAll();
Thread* self = Thread::Current();
Locks::mutator_lock_->AssertExclusiveHeld(self);
- const char* old_cause = self->StartAssertNoThreadSuspension("Handling sigquit");
+ const char* old_cause = self->StartAssertNoThreadSuspension("Handling SIGQUIT");
ThreadState old_state = self->SetStateUnsafe(kRunnable);
std::ostringstream os;
diff --git a/src/thread.cc b/src/thread.cc
index 484806e3f9..439e8f60fa 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -773,7 +773,11 @@ void Thread::DumpState(std::ostream& os, const Thread* thread, pid_t tid) {
}
os << " prio=" << priority
<< " tid=" << thread->GetThinLockId()
- << " " << thread->GetState() << "\n";
+ << " " << thread->GetState();
+ if (thread->IsStillStarting()) {
+ os << " (still starting up)";
+ }
+ os << "\n";
} else {
os << '"' << ::art::GetThreadName(tid) << '"'
<< " prio=" << priority
@@ -996,12 +1000,12 @@ Thread::Thread(bool daemon)
bool Thread::IsStillStarting() const {
// You might think you can check whether the state is kStarting, but for much of thread startup,
- // the thread might also be in kVmWait.
+ // the thread is in kNative; it might also be in kVmWait.
// You might think you can check whether the peer is NULL, but the peer is actually created and
// assigned fairly early on, and needs to be.
// It turns out that the last thing to change is the thread name; that's a good proxy for "has
// this thread _ever_ entered kRunnable".
- return (*name_ == kThreadNameDuringStartup);
+ return (jpeer_ == NULL && opeer_ == NULL) || (*name_ == kThreadNameDuringStartup);
}
void Thread::AssertNoPendingException() const {
diff --git a/src/thread.h b/src/thread.h
index e8f69dba4f..ea499600fe 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -289,8 +289,7 @@ class PACKED(4) Thread {
}
bool HasPeer() const {
- CHECK(jpeer_ == NULL);
- return opeer_ != NULL;
+ return jpeer_ != NULL || opeer_ != NULL;
}
RuntimeStats* GetStats() {
diff --git a/src/timing_logger.h b/src/timing_logger.h
index b0a3e660c4..3b3dcfc1aa 100644
--- a/src/timing_logger.h
+++ b/src/timing_logger.h
@@ -175,9 +175,11 @@ class CumulativeLogger {
mean -= mean % (divisor / 1000);
std_dev -= std_dev % (divisor / 1000);
}
- os << name_ << ": " << std::setw(8)
- << FormatDuration(mean * kAdjust, tu) << " std_dev "
- << FormatDuration(std_dev * kAdjust, tu) << " " << labels_[i] << "\n";
+ os << StringPrintf("%s: %10s (std_dev %8s) %s\n",
+ name_.c_str(),
+ FormatDuration(mean * kAdjust, tu).c_str(),
+ FormatDuration(std_dev * kAdjust, tu).c_str(),
+ labels_[i].c_str());
}
uint64_t total_mean_x2 = total_time_squared_;
uint64_t mean_total_ns = GetTotalTime();
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index 41098cb75c..6611d3ca58 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -295,7 +295,7 @@ MethodVerifier::FailureKind MethodVerifier::VerifyMethod(uint32_t method_idx, co
uint64_t start_ns = NanoTime();
MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item, method_idx,
- method, method_access_flags);
+ method, method_access_flags, true);
if (verifier.Verify()) {
// Verification completed, however failures may be pending that didn't cause the verification
// to hard fail.
@@ -331,7 +331,7 @@ void MethodVerifier::VerifyMethodAndDump(std::ostream& os, uint32_t dex_method_i
const DexFile::CodeItem* code_item, AbstractMethod* method,
uint32_t method_access_flags) {
MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item,
- dex_method_idx, method, method_access_flags);
+ dex_method_idx, method, method_access_flags, true);
verifier.Verify();
verifier.DumpFailures(os);
os << verifier.info_messages_.str();
@@ -346,15 +346,17 @@ std::vector<int32_t> MethodVerifier::DescribeVRegs(uint32_t dex_method_idx,
AbstractMethod* method,
uint32_t method_access_flags, uint32_t dex_pc) {
MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item,
- dex_method_idx, method, method_access_flags);
+ dex_method_idx, method, method_access_flags, true);
verifier.Verify();
return verifier.DescribeVRegs(dex_pc);
}
MethodVerifier::MethodVerifier(const DexFile* dex_file, DexCache* dex_cache,
ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item,
- uint32_t dex_method_idx, AbstractMethod* method, uint32_t method_access_flags)
- : work_insn_idx_(-1),
+ uint32_t dex_method_idx, AbstractMethod* method, uint32_t method_access_flags,
+ bool can_load_classes)
+ : reg_types_(can_load_classes),
+ work_insn_idx_(-1),
dex_method_idx_(dex_method_idx),
foo_method_(method),
method_access_flags_(method_access_flags),
@@ -368,7 +370,8 @@ MethodVerifier::MethodVerifier(const DexFile* dex_file, DexCache* dex_cache,
have_pending_hard_failure_(false),
have_pending_runtime_throw_failure_(false),
new_instance_count_(0),
- monitor_enter_count_(0) {
+ monitor_enter_count_(0),
+ can_load_classes_(can_load_classes) {
}
void MethodVerifier::FindLocksAtDexPc(AbstractMethod* m, uint32_t dex_pc,
@@ -376,7 +379,7 @@ void MethodVerifier::FindLocksAtDexPc(AbstractMethod* m, uint32_t dex_pc,
MethodHelper mh(m);
MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(),
mh.GetClassDefIndex(), mh.GetCodeItem(), m->GetDexMethodIndex(),
- m, m->GetAccessFlags());
+ m, m->GetAccessFlags(), false);
verifier.interesting_dex_pc_ = dex_pc;
verifier.monitor_enter_dex_pcs_ = &monitor_enter_dex_pcs;
verifier.FindLocksAtDexPc();
diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h
index b6762692eb..a02cc258b7 100644
--- a/src/verifier/method_verifier.h
+++ b/src/verifier/method_verifier.h
@@ -227,7 +227,7 @@ class MethodVerifier {
private:
explicit MethodVerifier(const DexFile* dex_file, DexCache* dex_cache,
ClassLoader* class_loader, uint32_t class_def_idx, const DexFile::CodeItem* code_item,
- uint32_t method_idx, AbstractMethod* method, uint32_t access_flags)
+ uint32_t method_idx, AbstractMethod* method, uint32_t access_flags, bool can_load_classes)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Adds the given string to the beginning of the last failure message.
@@ -670,6 +670,8 @@ class MethodVerifier {
// The number of occurrences of specific opcodes.
size_t new_instance_count_;
size_t monitor_enter_count_;
+
+ const bool can_load_classes_;
};
std::ostream& operator<<(std::ostream& os, const MethodVerifier::FailureKind& rhs);
diff --git a/src/verifier/reg_type.cc b/src/verifier/reg_type.cc
index dc41cebc56..ab1da1e2c3 100644
--- a/src/verifier/reg_type.cc
+++ b/src/verifier/reg_type.cc
@@ -173,7 +173,7 @@ const RegType& RegType::GetSuperClass(RegTypeCache* cache) const {
}
} else {
if (!IsUnresolvedMergedReference() && !IsUnresolvedSuperClass() &&
- GetDescriptor()->CharAt(0) == '[') {
+ GetDescriptor()[0] == '[') {
// Super class of all arrays is Object.
return cache->JavaLangObject(true);
} else {
diff --git a/src/verifier/reg_type.h b/src/verifier/reg_type.h
index c610e06388..65ee88a639 100644
--- a/src/verifier/reg_type.h
+++ b/src/verifier/reg_type.h
@@ -263,9 +263,8 @@ class RegType {
Class* GetClass() const {
DCHECK(!IsUnresolvedReference());
- DCHECK(klass_or_descriptor_ != NULL);
- DCHECK(klass_or_descriptor_->IsClass());
- return down_cast<Class*>(klass_or_descriptor_);
+ DCHECK(klass_ != NULL);
+ return klass_;
}
bool IsJavaLangObject() const {
@@ -274,7 +273,7 @@ class RegType {
bool IsArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
- return GetDescriptor()->CharAt(0) == '[';
+ return descriptor_[0] == '[';
} else if (HasClass()) {
return GetClass()->IsArrayClass();
} else {
@@ -285,8 +284,8 @@ class RegType {
bool IsObjectArrayTypes() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
if (IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
// Primitive arrays will always resolve
- DCHECK(GetDescriptor()->CharAt(1) == 'L' || GetDescriptor()->CharAt(1) == '[');
- return GetDescriptor()->CharAt(0) == '[';
+ DCHECK(descriptor_[1] == 'L' || descriptor_[1] == '[');
+ return descriptor_[0] == '[';
} else if (HasClass()) {
Class* type = GetClass();
return type->IsArrayClass() && !type->GetComponentType()->IsPrimitive();
@@ -330,11 +329,9 @@ class RegType {
return IsUnresolvedTypes() || (IsNonZeroReferenceTypes() && GetClass()->IsInstantiable());
}
- String* GetDescriptor() const {
+ std::string GetDescriptor() const {
DCHECK(IsUnresolvedTypes() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass());
- DCHECK(klass_or_descriptor_ != NULL);
- DCHECK(klass_or_descriptor_->GetClass()->IsStringClass());
- return down_cast<String*>(klass_or_descriptor_);
+ return descriptor_;
}
uint16_t GetId() const {
@@ -402,9 +399,9 @@ class RegType {
private:
friend class RegTypeCache;
- RegType(Type type, Object* klass_or_descriptor,
+ RegType(Type type, Class* klass,
uint32_t allocation_pc_or_constant_or_merged_types, uint16_t cache_id)
- : type_(type), klass_or_descriptor_(klass_or_descriptor),
+ : type_(type), klass_(klass),
allocation_pc_or_constant_or_merged_types_(allocation_pc_or_constant_or_merged_types),
cache_id_(cache_id) {
DCHECK(IsConstant() || IsConstantLo() || IsConstantHi() ||
@@ -412,16 +409,26 @@ class RegType {
allocation_pc_or_constant_or_merged_types == 0);
if (!IsConstant() && !IsLongConstant() && !IsLongConstantHigh() && !IsUndefined() &&
!IsConflict() && !IsUnresolvedMergedReference() && !IsUnresolvedSuperClass()) {
- DCHECK(klass_or_descriptor != NULL);
- DCHECK(IsUnresolvedTypes() || klass_or_descriptor_->IsClass());
- DCHECK(!IsUnresolvedTypes() || klass_or_descriptor_->GetClass()->IsStringClass());
+ DCHECK(klass_ != NULL);
+ DCHECK(klass_->IsClass());
+ DCHECK(!IsUnresolvedTypes());
}
}
+ RegType(Type type, const std::string& descriptor, uint32_t allocation_pc, uint16_t cache_id)
+ : type_(type),
+ klass_(NULL),
+ descriptor_(descriptor),
+ allocation_pc_or_constant_or_merged_types_(allocation_pc),
+ cache_id_(cache_id) {
+ }
+
const Type type_; // The current type of the register
- // If known the type of the register, else a String for the descriptor
- Object* klass_or_descriptor_;
+ // If known the type of the register...
+ Class* klass_;
+ // ...else a String for the descriptor.
+ std::string descriptor_;
// Overloaded field that:
// - if IsConstant() holds a 32bit constant value
diff --git a/src/verifier/reg_type_cache.cc b/src/verifier/reg_type_cache.cc
index 1b91321b13..3bf5ad886a 100644
--- a/src/verifier/reg_type_cache.cc
+++ b/src/verifier/reg_type_cache.cc
@@ -74,11 +74,11 @@ const RegType& RegTypeCache::From(RegType::Type type, ClassLoader* loader, const
DCHECK_GT(entries_.size(), static_cast<size_t>(type));
RegType* entry = entries_[type];
if (entry == NULL) {
- Class* klass = NULL;
+ Class* c = NULL;
if (strlen(descriptor) != 0) {
- klass = Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor);
+ c = Runtime::Current()->GetClassLinker()->FindSystemClass(descriptor);
}
- entry = new RegType(type, klass, 0, type);
+ entry = new RegType(type, c, 0, type);
entries_[type] = entry;
}
return *entry;
@@ -95,30 +95,37 @@ const RegType& RegTypeCache::From(RegType::Type type, ClassLoader* loader, const
return *cur_entry;
}
} else if (cur_entry->IsUnresolvedReference() &&
- cur_entry->GetDescriptor()->Equals(descriptor)) {
+ cur_entry->GetDescriptor() == descriptor) {
return *cur_entry;
}
}
- Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, loader);
- if (klass != NULL) {
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Class* c;
+ if (can_load_classes_) {
+ c = class_linker->FindClass(descriptor, loader);
+ } else {
+ c = class_linker->LookupClass(descriptor, loader);
+ }
+ if (c != NULL) {
// Able to resolve so create resolved register type that is precise if we
// know the type is final.
- RegType* entry = new RegType(klass->IsFinal() ? RegType::kRegTypePreciseReference
- : RegType::kRegTypeReference,
- klass, 0, entries_.size());
+ RegType* entry = new RegType(c->IsFinal() ? RegType::kRegTypePreciseReference
+ : RegType::kRegTypeReference,
+ c, 0, entries_.size());
entries_.push_back(entry);
return *entry;
} else {
// TODO: we assume unresolved, but we may be able to do better by validating whether the
// descriptor string is valid
// Unable to resolve so create unresolved register type
- DCHECK(Thread::Current()->IsExceptionPending());
- Thread::Current()->ClearException();
+ if (can_load_classes_) {
+ DCHECK(Thread::Current()->IsExceptionPending());
+ Thread::Current()->ClearException();
+ } else {
+ DCHECK(!Thread::Current()->IsExceptionPending());
+ }
if (IsValidDescriptor(descriptor)) {
- String* string_descriptor =
- Runtime::Current()->GetInternTable()->InternStrong(descriptor);
- RegType* entry = new RegType(RegType::kRegTypeUnresolvedReference, string_descriptor, 0,
- entries_.size());
+ RegType* entry = new RegType(RegType::kRegTypeUnresolvedReference, descriptor, 0, entries_.size());
entries_.push_back(entry);
return *entry;
} else {
@@ -214,7 +221,7 @@ const RegType& RegTypeCache::FromUnresolvedSuperClass(const RegType& child) {
const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocation_pc) {
RegType* entry;
if (type.IsUnresolvedTypes()) {
- String* descriptor = type.GetDescriptor();
+ std::string descriptor(type.GetDescriptor());
for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
RegType* cur_entry = entries_[i];
if (cur_entry->IsUnresolvedAndUninitializedReference() &&
@@ -245,7 +252,7 @@ const RegType& RegTypeCache::Uninitialized(const RegType& type, uint32_t allocat
const RegType& RegTypeCache::FromUninitialized(const RegType& uninit_type) {
RegType* entry;
if (uninit_type.IsUnresolvedTypes()) {
- String* descriptor = uninit_type.GetDescriptor();
+ std::string descriptor(uninit_type.GetDescriptor());
for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
RegType* cur_entry = entries_[i];
if (cur_entry->IsUnresolvedReference() && cur_entry->GetDescriptor() == descriptor) {
@@ -271,7 +278,7 @@ const RegType& RegTypeCache::UninitializedThisArgument(const RegType& type) {
// TODO: implement descriptor version.
RegType* entry;
if (type.IsUnresolvedTypes()) {
- String* descriptor = type.GetDescriptor();
+ std::string descriptor(type.GetDescriptor());
for (size_t i = RegType::kRegTypeLastFixedLocation + 1; i < entries_.size(); i++) {
RegType* cur_entry = entries_[i];
if (cur_entry->IsUnresolvedAndUninitializedThisReference() &&
@@ -354,7 +361,7 @@ const RegType& RegTypeCache::FromCat2ConstHi(int32_t value, bool precise) {
const RegType& RegTypeCache::GetComponentType(const RegType& array, ClassLoader* loader) {
CHECK(array.IsArrayTypes());
if (array.IsUnresolvedTypes()) {
- std::string descriptor(array.GetDescriptor()->ToModifiedUtf8());
+ std::string descriptor(array.GetDescriptor());
std::string component(descriptor.substr(1, descriptor.size() - 1));
return FromDescriptor(loader, component.c_str(), false);
} else {
diff --git a/src/verifier/reg_type_cache.h b/src/verifier/reg_type_cache.h
index 1cd3fba0bd..54f42fd857 100644
--- a/src/verifier/reg_type_cache.h
+++ b/src/verifier/reg_type_cache.h
@@ -26,7 +26,8 @@ namespace verifier {
class RegTypeCache {
public:
- explicit RegTypeCache() : entries_(RegType::kRegTypeLastFixedLocation + 1) {
+ explicit RegTypeCache(bool can_load_classes)
+ : entries_(RegType::kRegTypeLastFixedLocation + 1), can_load_classes_(can_load_classes) {
Undefined(); // ensure Undefined is initialized
}
~RegTypeCache() {
@@ -142,6 +143,8 @@ class RegTypeCache {
private:
// The allocated entries
std::vector<RegType*> entries_;
+ // Whether or not we're allowed to load classes.
+ const bool can_load_classes_;
DISALLOW_COPY_AND_ASSIGN(RegTypeCache);
};
diff --git a/src/verifier/reg_type_test.cc b/src/verifier/reg_type_test.cc
index 18e9a65cf4..c66477c84c 100644
--- a/src/verifier/reg_type_test.cc
+++ b/src/verifier/reg_type_test.cc
@@ -27,7 +27,7 @@ class RegTypeTest : public CommonTest {};
TEST_F(RegTypeTest, Primitives) {
ScopedObjectAccess soa(Thread::Current());
- RegTypeCache cache;
+ RegTypeCache cache(true);
const RegType& bool_reg_type = cache.Boolean();
EXPECT_FALSE(bool_reg_type.IsUndefined());