diff options
| -rw-r--r-- | compiler/dex/frontend.cc | 4 | ||||
| -rw-r--r-- | compiler/dex/mir_analysis.cc | 2 | ||||
| -rw-r--r-- | compiler/dex/mir_graph.h | 8 | ||||
| -rw-r--r-- | compiler/dex/vreg_analysis.cc | 28 |
4 files changed, 41 insertions, 1 deletions
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc index 84e1a9451b..89b1a753c6 100644 --- a/compiler/dex/frontend.cc +++ b/compiler/dex/frontend.cc @@ -957,6 +957,10 @@ static CompiledMethod* CompileMethod(CompilerDriver& driver, CompiledMethod* result = NULL; + if (cu.mir_graph->PuntToInterpreter()) { + return NULL; + } + cu.cg->Materialize(); cu.NewTimingSplit("Dedupe"); /* deduping takes up the vast majority of time in GetCompiledMethod(). */ diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc index 2ec17dedaf..1350665097 100644 --- a/compiler/dex/mir_analysis.cc +++ b/compiler/dex/mir_analysis.cc @@ -1011,7 +1011,7 @@ bool MIRGraph::SkipCompilation() { } // Contains a pattern we don't want to compile? - if (punt_to_interpreter_) { + if (PuntToInterpreter()) { return true; } diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index 27b8ca43aa..15c0aa4eaf 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -958,6 +958,14 @@ class MIRGraph { bool SetHigh(int index, bool is_high); bool SetHigh(int index); + bool PuntToInterpreter() { + return punt_to_interpreter_; + } + + void SetPuntToInterpreter(bool val) { + punt_to_interpreter_ = val; + } + char* GetDalvikDisassembly(const MIR* mir); void ReplaceSpecialChars(std::string& str); std::string GetSSAName(int ssa_reg); diff --git a/compiler/dex/vreg_analysis.cc b/compiler/dex/vreg_analysis.cc index c4af9cb55c..db383c4d0b 100644 --- a/compiler/dex/vreg_analysis.cc +++ b/compiler/dex/vreg_analysis.cc @@ -123,6 +123,16 @@ bool MIRGraph::SetHigh(int index) { */ bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { SSARepresentation *ssa_rep = mir->ssa_rep; + + /* + * The dex bytecode definition does not explicitly outlaw the definition of the same + * virtual register to be used in both a 32-bit and 64-bit pair context. However, dx + * does not generate this pattern (at least recently). Further, in the next revision of + * dex, we will forbid this. To support the few cases in the wild, detect this pattern + * and punt to the interpreter. + */ + bool type_mismatch = false; + if (ssa_rep) { uint64_t attrs = GetDataFlowAttributes(mir); const int* uses = ssa_rep->uses; @@ -145,6 +155,7 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { } } + // Handles uses int next = 0; if (attrs & DF_UA) { @@ -162,6 +173,7 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { SRegToVReg(uses[next + 1])); next += 2; } else { + type_mismatch |= reg_location_[uses[next]].wide; next++; } } @@ -180,6 +192,7 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { SRegToVReg(uses[next + 1])); next += 2; } else { + type_mismatch |= reg_location_[uses[next]].wide; next++; } } @@ -196,6 +209,8 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { reg_location_[uses[next + 1]].high_word = true; DCHECK_EQ(SRegToVReg(uses[next])+1, SRegToVReg(uses[next + 1])); + } else { + type_mismatch |= reg_location_[uses[next]].wide; } } @@ -205,6 +220,7 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { (mir->dalvikInsn.opcode == Instruction::RETURN_OBJECT)) { switch (cu_->shorty[0]) { case 'I': + type_mismatch |= reg_location_[uses[0]].wide; changed |= SetCore(uses[0]); break; case 'J': @@ -215,6 +231,7 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { reg_location_[uses[1]].high_word = true; break; case 'F': + type_mismatch |= reg_location_[uses[0]].wide; changed |= SetFp(uses[0]); break; case 'D': @@ -225,6 +242,7 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { reg_location_[uses[1]].high_word = true; break; case 'L': + type_mismatch |= reg_location_[uses[0]].wide; changed |= SetRef(uses[0]); break; default: break; @@ -261,6 +279,7 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { (mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC_RANGE))) { reg_location_[uses[next]].defined = true; reg_location_[uses[next]].ref = true; + type_mismatch |= reg_location_[uses[next]].wide; next++; } uint32_t cpos = 1; @@ -286,12 +305,15 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { i++; break; case 'F': + type_mismatch |= reg_location_[uses[i]].wide; ssa_rep->fp_use[i] = true; break; case 'L': + type_mismatch |= reg_location_[uses[i]].wide; changed |= SetRef(uses[i]); break; default: + type_mismatch |= reg_location_[uses[i]].wide; changed |= SetCore(uses[i]); break; } @@ -367,6 +389,12 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { } } } + if (type_mismatch) { + LOG(WARNING) << "Deprecated dex type mismatch, interpreting " + << PrettyMethod(cu_->method_idx, *cu_->dex_file); + LOG(INFO) << "@ 0x" << std::hex << mir->offset; + SetPuntToInterpreter(true); + } return changed; } |