• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/macros.h"
25 #include "base/scoped_arena_allocator.h"
26 #include "nodes.h"
27 
28 namespace art HIDDEN {
29 
30 class CodeGenerator;
31 
32 // A control-flow graph visitor performing various checks.
33 class GraphChecker : public HGraphDelegateVisitor {
34  public:
35   explicit GraphChecker(HGraph* graph,
36                         CodeGenerator* codegen = nullptr,
37                         const char* dump_prefix = "art::GraphChecker: ")
HGraphDelegateVisitor(graph)38     : HGraphDelegateVisitor(graph),
39       errors_(graph->GetAllocator()->Adapter(kArenaAllocGraphChecker)),
40       dump_prefix_(dump_prefix),
41       allocator_(graph->GetArenaStack()),
42       seen_ids_(&allocator_, graph->GetCurrentInstructionId(), false, kArenaAllocGraphChecker),
43       codegen_(codegen) {
44     seen_ids_.ClearAllBits();
45   }
46 
47   // Check the whole graph. The pass_change parameter indicates whether changes
48   // may have occurred during the just executed pass. The default value is
49   // conservatively "true" (something may have changed). The last_size parameter
50   // and return value pass along the observed graph sizes.
51   size_t Run(bool pass_change = true, size_t last_size = 0);
52 
53   void VisitBasicBlock(HBasicBlock* block) override;
54 
55   void VisitInstruction(HInstruction* instruction) override;
56   void VisitPhi(HPhi* phi) override;
57 
58   void VisitArraySet(HArraySet* instruction) override;
59   void VisitBinaryOperation(HBinaryOperation* op) override;
60   void VisitBooleanNot(HBooleanNot* instruction) override;
61   void VisitBoundType(HBoundType* instruction) override;
62   void VisitBoundsCheck(HBoundsCheck* check) override;
63   void VisitCheckCast(HCheckCast* check) override;
64   void VisitCondition(HCondition* op) override;
65   void VisitConstant(HConstant* instruction) override;
66   void VisitDeoptimize(HDeoptimize* instruction) override;
67   void VisitIf(HIf* instruction) override;
68   void VisitInstanceOf(HInstanceOf* check) override;
69   void VisitInvoke(HInvoke* invoke) override;
70   void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) override;
71   void VisitLoadClass(HLoadClass* load) override;
72   void VisitLoadException(HLoadException* load) override;
73   void VisitMonitorOperation(HMonitorOperation* monitor_operation) override;
74   void VisitNeg(HNeg* instruction) override;
75   void VisitPackedSwitch(HPackedSwitch* instruction) override;
76   void VisitReturn(HReturn* ret) override;
77   void VisitReturnVoid(HReturnVoid* ret) override;
78   void VisitSelect(HSelect* instruction) override;
79   void VisitTryBoundary(HTryBoundary* try_boundary) override;
80   void VisitTypeConversion(HTypeConversion* instruction) override;
81 
82   void VisitVecOperation(HVecOperation* instruction) override;
83 
84   void CheckTypeCheckBitstringInput(HTypeCheckInstruction* check,
85                                     size_t input_pos,
86                                     bool check_value,
87                                     uint32_t expected_value,
88                                     const char* name);
89   void HandleTypeCheckInstruction(HTypeCheckInstruction* instruction);
90   void HandleLoop(HBasicBlock* loop_header);
91   void HandleBooleanInput(HInstruction* instruction, size_t input_index);
92 
93   // Was the last visit of the graph valid?
IsValid()94   bool IsValid() const {
95     return errors_.empty();
96   }
97 
98   // Get the list of detected errors.
GetErrors()99   const ArenaVector<std::string>& GetErrors() const {
100     return errors_;
101   }
102 
103   // Print detected errors on output stream `os`.
Dump(std::ostream & os)104   void Dump(std::ostream& os) const {
105     for (size_t i = 0, e = errors_.size(); i < e; ++i) {
106       os << dump_prefix_ << errors_[i] << std::endl;
107     }
108   }
109 
110  protected:
111   // Report a new error.
AddError(const std::string & error)112   void AddError(const std::string& error) {
113     errors_.push_back(error);
114   }
115 
116   // The block currently visited.
117   HBasicBlock* current_block_ = nullptr;
118   // Errors encountered while checking the graph.
119   ArenaVector<std::string> errors_;
120 
121  private:
122   void VisitReversePostOrder();
123 
124   // Checks that the graph's flags are set correctly.
125   void CheckGraphFlags();
126 
127   // String displayed before dumped errors.
128   const char* const dump_prefix_;
129   ScopedArenaAllocator allocator_;
130   ArenaBitVector seen_ids_;
131 
132   // Used to access target information.
133   CodeGenerator* codegen_;
134 
135   struct FlagInfo {
136     bool seen_try_boundary = false;
137     bool seen_monitor_operation = false;
138     bool seen_loop = false;
139     bool seen_irreducible_loop = false;
140     bool seen_SIMD = false;
141     bool seen_bounds_checks = false;
142     bool seen_always_throwing_invokes = false;
143   };
144   FlagInfo flag_info_;
145 
146   DISALLOW_COPY_AND_ASSIGN(GraphChecker);
147 };
148 
149 }  // namespace art
150 
151 #endif  // ART_COMPILER_OPTIMIZING_GRAPH_CHECKER_H_
152