1 /*
  2  * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 #ifndef SHARE_COMPILER_METHODLIVENESS_HPP
 26 #define SHARE_COMPILER_METHODLIVENESS_HPP
 27 
 28 #include "utilities/bitMap.hpp"
 29 #include "utilities/growableArray.hpp"
 30 
 31 class ciMethod;
 32 
 33 class MethodLivenessResult : public ResourceBitMap {
 34  private:
 35   bool _is_valid;
 36 
 37  public:
 38   MethodLivenessResult()
 39     : ResourceBitMap()
 40     , _is_valid(false)
 41   {}
 42 
 43   MethodLivenessResult(idx_t size_in_bits)
 44     : ResourceBitMap(size_in_bits)
 45     , _is_valid(false)
 46   {}
 47 
 48   void set_is_valid() { _is_valid = true; }
 49   bool is_valid() const { return _is_valid; }
 50 
 51 #ifdef ASSERT
 52   bool at(idx_t index) const {
 53     assert(is_valid(), "reading invalid");
 54     return ResourceBitMap::at(index);
 55   }
 56 #endif
 57 };
 58 
 59 class MethodLiveness : public ArenaObj {
 60  public:
 61   // The BasicBlock class is used to represent a basic block in the
 62   // liveness analysis.
 63   class BasicBlock : public ArenaObj {
 64    private:
 65     // This class is only used by the MethodLiveness class.
 66     friend class MethodLiveness;
 67 
 68     // The analyzer which created this basic block.
 69     MethodLiveness* _analyzer;
 70 
 71     // The range of this basic block is [start_bci,limit_bci)
 72     int _start_bci;
 73     int _limit_bci;
 74 
 75     // The liveness at the start of the block;
 76     ArenaBitMap _entry;
 77 
 78     // The summarized liveness effects of our direct successors reached
 79     // by normal control flow
 80     ArenaBitMap _normal_exit;
 81 
 82     // The summarized liveness effects of our direct successors reached
 83     // by exceptional control flow
 84     ArenaBitMap _exception_exit;
 85 
 86     // These members hold the results of the last call to
 87     // compute_gen_kill_range().  _gen is the set of locals
 88     // used before they are defined in the range.  _kill is the
 89     // set of locals defined before they are used.
 90     ArenaBitMap _gen;
 91     ArenaBitMap _kill;
 92     int         _last_bci;
 93 
 94     // A list of all blocks which could come directly before this one
 95     // in normal (non-exceptional) control flow.  We propagate liveness
 96     // information to these blocks.
 97     GrowableArray<BasicBlock*>* _normal_predecessors;
 98 
 99     // A list of all blocks which could come directly before this one
100     // in exceptional control flow.
101     GrowableArray<BasicBlock*>* _exception_predecessors;
102 
103     // The following fields are used to manage a work list used in the
104     // dataflow.
105     BasicBlock *_next;
106     bool _on_work_list;
107 
108     // Our successors call this method to merge liveness information into
109     // our _normal_exit member.
110     bool merge_normal(const BitMap& other);
111 
112     // Our successors call this method to merge liveness information into
113     // our _exception_exit member.
114     bool merge_exception(const BitMap& other);
115 
116     // This helper routine is used to help compute the gen/kill pair for
117     // the block.  It is also used to answer queries.
118     void compute_gen_kill_range(ciBytecodeStream *bytes);
119 
120     // Compute the gen/kill effect of a single instruction.
121     void compute_gen_kill_single(ciBytecodeStream *instruction);
122 
123     // Helpers for compute_gen_kill_single.
124     void load_one(int local);
125     void load_two(int local);
126     void store_one(int local);
127     void store_two(int local);
128 
129     BasicBlock(MethodLiveness *analyzer, int start, int limit);
130 
131     // -- Accessors
132 
133     int start_bci() const { return _start_bci; }
134 
135     int limit_bci() const { return _limit_bci; }
136     void set_limit_bci(int limit) { _limit_bci = limit; }
137 
138     BasicBlock *next() const { return _next; }
139     void set_next(BasicBlock *next) { _next = next; }
140 
141     bool on_work_list() const { return _on_work_list; }
142     void set_on_work_list(bool val) { _on_work_list = val; }
143 
144     // -- Flow graph construction.
145 
146     // Add a basic block to our list of normal predecessors.
147     void add_normal_predecessor(BasicBlock *pred) {
148       _normal_predecessors->append_if_missing(pred);
149     }
150 
151     // Add a basic block to our list of exceptional predecessors
152     void add_exception_predecessor(BasicBlock *pred) {
153       _exception_predecessors->append_if_missing(pred);
154     }
155 
156     // Split the basic block at splitBci.  This basic block
157     // becomes the second half.  The first half is newly created.
158     BasicBlock *split(int splitBci);
159 
160     // -- Dataflow.
161 
162     void compute_gen_kill(ciMethod* method);
163 
164     // Propagate changes from this basic block
165     void propagate(MethodLiveness *ml);
166 
167     // -- Query.
168 
169     MethodLivenessResult get_liveness_at(ciMethod* method, int bci);
170 
171     // -- Debugging.
172 
173     void print_on(outputStream *os) const PRODUCT_RETURN;
174 
175   }; // End of MethodLiveness::BasicBlock
176 
177  private:
178   // The method we are analyzing.
179   ciMethod* _method;
180   ciMethod* method() const { return _method; }
181 
182   // The arena for storing structures...
183   Arena*       _arena;
184   Arena*       arena() const { return _arena; }
185 
186   // We cache the length of the method.
187   int _code_size;
188 
189   // The size of a BitMap.
190   int _bit_map_size_bits;
191 
192   // A list of all BasicBlocks.
193   BasicBlock **_block_list;
194 
195   // number of blocks
196   int  _block_count;
197 
198   // Keeps track of bci->block mapping.  One entry for each bci.  Only block starts are
199   // recorded.
200   GrowableArray<BasicBlock*>* _block_map;
201 
202   // Our work list.
203   BasicBlock *_work_list;
204 
205 #ifdef COMPILER1
206   // bcis where blocks start are marked
207   ArenaBitMap _bci_block_start;
208 #endif // COMPILER1
209 
210   // -- Graph construction & Analysis
211 
212   // Compute ranges and predecessors for basic blocks.
213   void init_basic_blocks();
214 
215   // Compute gen/kill information for all basic blocks.
216   void init_gen_kill();
217 
218   // Perform the dataflow.
219   void propagate_liveness();
220 
221  // The class MethodLiveness::BasicBlock needs special access to some
222  // of our members.
223  friend class MethodLiveness::BasicBlock;
224 
225   // And accessors.
226   int bit_map_size_bits() const { return _bit_map_size_bits; }
227 
228   // Work list manipulation routines.  Called internally by BasicBlock.
229   BasicBlock *work_list_get();
230   void work_list_add(BasicBlock *block);
231 
232  public:
233   // Create a liveness analyzer for a method
234   MethodLiveness(Arena* arena, ciMethod* method);
235 
236   // Compute liveness information for the method
237   void compute_liveness();
238 
239   // Find out which locals are live at a specific bci.
240   MethodLivenessResult get_liveness_at(int bci);
241 
242 #ifdef COMPILER1
243   const BitMap& get_bci_block_start() const { return _bci_block_start; }
244 #endif // COMPILER1
245 
246 };
247 
248 #endif // SHARE_COMPILER_METHODLIVENESS_HPP