diff options
author | Jeff Hao <jeffhao@google.com> | 2014-01-15 13:49:50 -0800 |
---|---|---|
committer | Jeff Hao <jeffhao@google.com> | 2015-04-27 18:54:52 -0700 |
commit | 848f70a3d73833fc1bf3032a9ff6812e429661d9 (patch) | |
tree | b0349b3a40aab5a915af491b100659a5ca9fbbf6 /runtime/verifier | |
parent | d14438f0c5071962be7fab572b54687d32d9d087 (diff) | |
download | art-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.cc | 20 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.h | 16 | ||||
-rw-r--r-- | runtime/verifier/register_line.cc | 13 | ||||
-rw-r--r-- | runtime/verifier/register_line.h | 3 |
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 = ®_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_); /* |