1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_COMPILER_OPTIMIZING_GRAPH_CHECKER_H_ 18 #define ART_COMPILER_OPTIMIZING_GRAPH_CHECKER_H_ 19 20 #include <ostream> 21 22 #include "base/arena_bit_vector.h" 23 #include "base/bit_vector-inl.h" 24 #include "base/scoped_arena_allocator.h" 25 #include "nodes.h" 26 27 namespace art { 28 29 class CodeGenerator; 30 31 // A control-flow graph visitor performing various checks. 32 class GraphChecker : public HGraphDelegateVisitor { 33 public: 34 explicit GraphChecker(HGraph* graph, 35 CodeGenerator* codegen = nullptr, 36 const char* dump_prefix = "art::GraphChecker: ") HGraphDelegateVisitor(graph)37 : HGraphDelegateVisitor(graph), 38 errors_(graph->GetAllocator()->Adapter(kArenaAllocGraphChecker)), 39 dump_prefix_(dump_prefix), 40 allocator_(graph->GetArenaStack()), 41 seen_ids_(&allocator_, graph->GetCurrentInstructionId(), false, kArenaAllocGraphChecker), 42 codegen_(codegen) { 43 seen_ids_.ClearAllBits(); 44 } 45 46 // Check the whole graph. The pass_change parameter indicates whether changes 47 // may have occurred during the just executed pass. The default value is 48 // conservatively "true" (something may have changed). The last_size parameter 49 // and return value pass along the observed graph sizes. 50 size_t Run(bool pass_change = true, size_t last_size = 0); 51 52 void VisitBasicBlock(HBasicBlock* block) override; 53 54 void VisitInstruction(HInstruction* instruction) override; 55 void VisitPhi(HPhi* phi) override; 56 57 void VisitBinaryOperation(HBinaryOperation* op) override; 58 void VisitBooleanNot(HBooleanNot* instruction) override; 59 void VisitBoundType(HBoundType* instruction) override; 60 void VisitBoundsCheck(HBoundsCheck* check) override; 61 void VisitCheckCast(HCheckCast* check) override; 62 void VisitCondition(HCondition* op) override; 63 void VisitConstant(HConstant* instruction) override; 64 void VisitDeoptimize(HDeoptimize* instruction) override; 65 void VisitIf(HIf* instruction) override; 66 void VisitInstanceOf(HInstanceOf* check) override; 67 void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) override; 68 void VisitLoadException(HLoadException* load) override; 69 void VisitNeg(HNeg* instruction) override; 70 void VisitPackedSwitch(HPackedSwitch* instruction) override; 71 void VisitReturn(HReturn* ret) override; 72 void VisitReturnVoid(HReturnVoid* ret) override; 73 void VisitSelect(HSelect* instruction) override; 74 void VisitTryBoundary(HTryBoundary* try_boundary) override; 75 void VisitTypeConversion(HTypeConversion* instruction) override; 76 77 void VisitVecOperation(HVecOperation* instruction) override; 78 79 void CheckTypeCheckBitstringInput(HTypeCheckInstruction* check, 80 size_t input_pos, 81 bool check_value, 82 uint32_t expected_value, 83 const char* name); 84 void HandleTypeCheckInstruction(HTypeCheckInstruction* instruction); 85 void HandleLoop(HBasicBlock* loop_header); 86 void HandleBooleanInput(HInstruction* instruction, size_t input_index); 87 88 // Was the last visit of the graph valid? IsValid()89 bool IsValid() const { 90 return errors_.empty(); 91 } 92 93 // Get the list of detected errors. GetErrors()94 const ArenaVector<std::string>& GetErrors() const { 95 return errors_; 96 } 97 98 // Print detected errors on output stream `os`. Dump(std::ostream & os)99 void Dump(std::ostream& os) const { 100 for (size_t i = 0, e = errors_.size(); i < e; ++i) { 101 os << dump_prefix_ << errors_[i] << std::endl; 102 } 103 } 104 105 // Enable/Disable the reference type info check. 106 // 107 // Return: the previous status of the check. 108 bool SetRefTypeInfoCheckEnabled(bool value = true) { 109 bool old_value = check_reference_type_info_; 110 check_reference_type_info_ = value; 111 return old_value; 112 } 113 114 protected: 115 // Report a new error. AddError(const std::string & error)116 void AddError(const std::string& error) { 117 errors_.push_back(error); 118 } 119 120 // The block currently visited. 121 HBasicBlock* current_block_ = nullptr; 122 // Errors encountered while checking the graph. 123 ArenaVector<std::string> errors_; 124 125 private: 126 // String displayed before dumped errors. 127 const char* const dump_prefix_; 128 ScopedArenaAllocator allocator_; 129 ArenaBitVector seen_ids_; 130 // Whether to perform the reference type info check for instructions which use or produce 131 // object references, e.g. HNewInstance, HLoadClass. 132 // The default value is true. 133 bool check_reference_type_info_ = true; 134 135 // Used to access target information. 136 CodeGenerator* codegen_; 137 138 DISALLOW_COPY_AND_ASSIGN(GraphChecker); 139 }; 140 141 } // namespace art 142 143 #endif // ART_COMPILER_OPTIMIZING_GRAPH_CHECKER_H_ 144