summaryrefslogtreecommitdiffstats
path: root/runtime/verifier
diff options
context:
space:
mode:
authorJeff Hao <jeffhao@google.com>2014-01-15 13:49:50 -0800
committerJeff Hao <jeffhao@google.com>2015-04-27 18:54:52 -0700
commit848f70a3d73833fc1bf3032a9ff6812e429661d9 (patch)
treeb0349b3a40aab5a915af491b100659a5ca9fbbf6 /runtime/verifier
parentd14438f0c5071962be7fab572b54687d32d9d087 (diff)
downloadart-848f70a3d73833fc1bf3032a9ff6812e429661d9.zip
art-848f70a3d73833fc1bf3032a9ff6812e429661d9.tar.gz
art-848f70a3d73833fc1bf3032a9ff6812e429661d9.tar.bz2
Replace String CharArray with internal uint16_t array.
Summary of high level changes: - Adds compiler inliner support to identify string init methods - Adds compiler support (quick & optimizing) with new invoke code path that calls method off the thread pointer - Adds thread entrypoints for all string init methods - Adds map to verifier to log when receiver of string init has been copied to other registers. used by compiler and interpreter Change-Id: I797b992a8feb566f9ad73060011ab6f51eb7ce01
Diffstat (limited to 'runtime/verifier')
-rw-r--r--runtime/verifier/method_verifier.cc20
-rw-r--r--runtime/verifier/method_verifier.h16
-rw-r--r--runtime/verifier/register_line.cc13
-rw-r--r--runtime/verifier/register_line.h3
4 files changed, 49 insertions, 3 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 065df05..475fe8b 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -516,6 +516,23 @@ mirror::ArtMethod* MethodVerifier::FindInvokedMethodAtDexPc(uint32_t dex_pc) {
return GetQuickInvokedMethod(inst, register_line, is_range, false);
}
+SafeMap<uint32_t, std::set<uint32_t>> MethodVerifier::FindStringInitMap(mirror::ArtMethod* m) {
+ Thread* self = Thread::Current();
+ StackHandleScope<3> hs(self);
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(m->GetDexCache()));
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(m->GetClassLoader()));
+ Handle<mirror::ArtMethod> method(hs.NewHandle(m));
+ MethodVerifier verifier(self, m->GetDexFile(), dex_cache, class_loader, &m->GetClassDef(),
+ m->GetCodeItem(), m->GetDexMethodIndex(), method, m->GetAccessFlags(),
+ true, true, false, true);
+ return verifier.FindStringInitMap();
+}
+
+SafeMap<uint32_t, std::set<uint32_t>>& MethodVerifier::FindStringInitMap() {
+ Verify();
+ return GetStringInitPcRegMap();
+}
+
bool MethodVerifier::Verify() {
// If there aren't any instructions, make sure that's expected, then exit successfully.
if (code_item_ == nullptr) {
@@ -2445,7 +2462,8 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
* Replace the uninitialized reference with an initialized one. We need to do this for all
* registers that have the same object instance in them, not just the "this" register.
*/
- work_line_->MarkRefsAsInitialized(this, this_type);
+ const uint32_t this_reg = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
+ work_line_->MarkRefsAsInitialized(this, this_type, this_reg, work_insn_idx_);
}
if (return_type == nullptr) {
return_type = &reg_types_.FromDescriptor(GetClassLoader(), return_type_descriptor,
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 2914b7c..452d1dd 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -199,6 +199,9 @@ class MethodVerifier {
static mirror::ArtMethod* FindInvokedMethodAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static SafeMap<uint32_t, std::set<uint32_t>> FindStringInitMap(mirror::ArtMethod* m)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
static void Init() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static void Shutdown();
@@ -263,6 +266,10 @@ class MethodVerifier {
return (method_access_flags_ & kAccStatic) != 0;
}
+ SafeMap<uint32_t, std::set<uint32_t>>& GetStringInitPcRegMap() {
+ return string_init_pc_reg_map_;
+ }
+
private:
// Private constructor for dumping.
MethodVerifier(Thread* self, const DexFile* dex_file, Handle<mirror::DexCache> dex_cache,
@@ -307,6 +314,9 @@ class MethodVerifier {
mirror::ArtMethod* FindInvokedMethodAtDexPc(uint32_t dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SafeMap<uint32_t, std::set<uint32_t>>& FindStringInitMap()
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
/*
* Compute the width of the instruction at each address in the instruction stream, and store it in
* insn_flags_. Addresses that are in the middle of an instruction, or that are part of switch
@@ -743,6 +753,12 @@ class MethodVerifier {
MethodVerifier* link_;
friend class art::Thread;
+
+ // Map of dex pcs of invocations of java.lang.String.<init> to the set of other registers that
+ // contain the uninitialized this pointer to that invoke. Will contain no entry if there are
+ // no other registers.
+ SafeMap<uint32_t, std::set<uint32_t>> string_init_pc_reg_map_;
+
DISALLOW_COPY_AND_ASSIGN(MethodVerifier);
};
std::ostream& operator<<(std::ostream& os, const MethodVerifier::FailureKind& rhs);
diff --git a/runtime/verifier/register_line.cc b/runtime/verifier/register_line.cc
index ed588fc..8445751 100644
--- a/runtime/verifier/register_line.cc
+++ b/runtime/verifier/register_line.cc
@@ -127,14 +127,25 @@ bool RegisterLine::VerifyRegisterTypeWide(MethodVerifier* verifier, uint32_t vsr
return true;
}
-void RegisterLine::MarkRefsAsInitialized(MethodVerifier* verifier, const RegType& uninit_type) {
+void RegisterLine::MarkRefsAsInitialized(MethodVerifier* verifier, const RegType& uninit_type,
+ uint32_t this_reg, uint32_t dex_pc) {
DCHECK(uninit_type.IsUninitializedTypes());
+ bool is_string = !uninit_type.IsUnresolvedTypes() && uninit_type.GetClass()->IsStringClass();
const RegType& init_type = verifier->GetRegTypeCache()->FromUninitialized(uninit_type);
size_t changed = 0;
for (uint32_t i = 0; i < num_regs_; i++) {
if (GetRegisterType(verifier, i).Equals(uninit_type)) {
line_[i] = init_type.GetId();
changed++;
+ if (i != this_reg && is_string) {
+ auto it = verifier->GetStringInitPcRegMap().find(dex_pc);
+ if (it != verifier->GetStringInitPcRegMap().end()) {
+ it->second.insert(i);
+ } else {
+ std::set<uint32_t> reg_set = { i };
+ verifier->GetStringInitPcRegMap().Put(dex_pc, reg_set);
+ }
+ }
}
}
DCHECK_GT(changed, 0u);
diff --git a/runtime/verifier/register_line.h b/runtime/verifier/register_line.h
index 376dbf1..0de0d9c 100644
--- a/runtime/verifier/register_line.h
+++ b/runtime/verifier/register_line.h
@@ -138,7 +138,8 @@ class RegisterLine {
* reference type. This is called when an appropriate constructor is invoked -- all copies of
* the reference must be marked as initialized.
*/
- void MarkRefsAsInitialized(MethodVerifier* verifier, const RegType& uninit_type)
+ void MarkRefsAsInitialized(MethodVerifier* verifier, const RegType& uninit_type,
+ uint32_t this_reg, uint32_t dex_pc)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
/*