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 /compiler/dex/mir_optimization.cc | |
parent | d14438f0c5071962be7fab572b54687d32d9d087 (diff) | |
download | android_art-848f70a3d73833fc1bf3032a9ff6812e429661d9.tar.gz android_art-848f70a3d73833fc1bf3032a9ff6812e429661d9.tar.bz2 android_art-848f70a3d73833fc1bf3032a9ff6812e429661d9.zip |
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 'compiler/dex/mir_optimization.cc')
-rw-r--r-- | compiler/dex/mir_optimization.cc | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc index 3482602704..25c159f2a1 100644 --- a/compiler/dex/mir_optimization.cc +++ b/compiler/dex/mir_optimization.cc @@ -18,6 +18,7 @@ #include "base/logging.h" #include "base/scoped_arena_containers.h" #include "dataflow_iterator-inl.h" +#include "dex/verified_method.h" #include "dex_flags.h" #include "driver/compiler_driver.h" #include "driver/dex_compilation_unit.h" @@ -25,10 +26,11 @@ #include "gvn_dead_code_elimination.h" #include "local_value_numbering.h" #include "mir_field_info.h" -#include "type_inference.h" +#include "mirror/string.h" #include "quick/dex_file_method_inliner.h" #include "quick/dex_file_to_method_inliner_map.h" #include "stack.h" +#include "type_inference.h" namespace art { @@ -1660,6 +1662,77 @@ void MIRGraph::BasicBlockOptimizationEnd() { temp_scoped_alloc_.reset(); } +void MIRGraph::StringChange() { + AllNodesIterator iter(this); + for (BasicBlock* bb = iter.Next(); bb != nullptr; bb = iter.Next()) { + for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) { + // Look for new instance opcodes, skip otherwise + Instruction::Code opcode = mir->dalvikInsn.opcode; + if (opcode == Instruction::NEW_INSTANCE) { + uint32_t type_idx = mir->dalvikInsn.vB; + if (cu_->compiler_driver->IsStringTypeIndex(type_idx, cu_->dex_file)) { + // Change NEW_INSTANCE and throwing half of the insn (if it exists) into CONST_4 of 0 + mir->dalvikInsn.opcode = Instruction::CONST_4; + mir->dalvikInsn.vB = 0; + MIR* check_mir = GetBasicBlock(bb->predecessors[0])->last_mir_insn; + if (check_mir != nullptr && + static_cast<int>(check_mir->dalvikInsn.opcode) == kMirOpCheck) { + check_mir->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop); + check_mir->dalvikInsn.vB = 0; + } + } + } else if ((opcode == Instruction::INVOKE_DIRECT) || + (opcode == Instruction::INVOKE_DIRECT_RANGE)) { + uint32_t method_idx = mir->dalvikInsn.vB; + DexFileMethodInliner* inliner = + cu_->compiler_driver->GetMethodInlinerMap()->GetMethodInliner(cu_->dex_file); + if (inliner->IsStringInitMethodIndex(method_idx)) { + bool is_range = (opcode == Instruction::INVOKE_DIRECT_RANGE); + uint32_t orig_this_reg = is_range ? mir->dalvikInsn.vC : mir->dalvikInsn.arg[0]; + // Remove this pointer from string init and change to static call. + mir->dalvikInsn.vA--; + if (!is_range) { + mir->dalvikInsn.opcode = Instruction::INVOKE_STATIC; + for (uint32_t i = 0; i < mir->dalvikInsn.vA; i++) { + mir->dalvikInsn.arg[i] = mir->dalvikInsn.arg[i + 1]; + } + } else { + mir->dalvikInsn.opcode = Instruction::INVOKE_STATIC_RANGE; + mir->dalvikInsn.vC++; + } + // Insert a move-result instruction to the original this pointer reg. + MIR* move_result_mir = static_cast<MIR *>(arena_->Alloc(sizeof(MIR), kArenaAllocMIR)); + move_result_mir->dalvikInsn.opcode = Instruction::MOVE_RESULT_OBJECT; + move_result_mir->dalvikInsn.vA = orig_this_reg; + move_result_mir->offset = mir->offset; + move_result_mir->m_unit_index = mir->m_unit_index; + bb->InsertMIRAfter(mir, move_result_mir); + // Add additional moves if this pointer was copied to other registers. + const VerifiedMethod* verified_method = + cu_->compiler_driver->GetVerifiedMethod(cu_->dex_file, cu_->method_idx); + DCHECK(verified_method != nullptr); + const SafeMap<uint32_t, std::set<uint32_t>>& string_init_map = + verified_method->GetStringInitPcRegMap(); + auto map_it = string_init_map.find(mir->offset); + if (map_it != string_init_map.end()) { + const std::set<uint32_t>& reg_set = map_it->second; + for (auto set_it = reg_set.begin(); set_it != reg_set.end(); ++set_it) { + MIR* move_mir = static_cast<MIR *>(arena_->Alloc(sizeof(MIR), kArenaAllocMIR)); + move_mir->dalvikInsn.opcode = Instruction::MOVE_OBJECT; + move_mir->dalvikInsn.vA = *set_it; + move_mir->dalvikInsn.vB = orig_this_reg; + move_mir->offset = mir->offset; + move_mir->m_unit_index = mir->m_unit_index; + bb->InsertMIRAfter(move_result_mir, move_mir); + } + } + } + } + } + } +} + + bool MIRGraph::EliminateSuspendChecksGate() { if ((cu_->disable_opt & (1 << kSuspendCheckElimination)) != 0 || // Disabled. GetMaxNestedLoops() == 0u || // Nothing to do. |