methodLiveness.hpp revision 1472
0N/A/*
1472N/A * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1472N/A * or visit www.oracle.com if you need additional information or have any
1472N/A * questions.
0N/A *
0N/A */
0N/A
0N/Aclass ciMethod;
0N/A
0N/Aclass MethodLivenessResult : public BitMap {
0N/A private:
0N/A bool _is_valid;
0N/A
0N/A public:
342N/A MethodLivenessResult(BitMap::bm_word_t* map, idx_t size_in_bits)
0N/A : BitMap(map, size_in_bits)
0N/A , _is_valid(false)
0N/A {}
0N/A
0N/A MethodLivenessResult(idx_t size_in_bits)
0N/A : BitMap(size_in_bits)
0N/A , _is_valid(false)
0N/A {}
0N/A
0N/A void set_is_valid() { _is_valid = true; }
0N/A bool is_valid() { return _is_valid; }
0N/A};
0N/A
0N/Aclass MethodLiveness : public ResourceObj {
0N/A public:
0N/A // The BasicBlock class is used to represent a basic block in the
0N/A // liveness analysis.
0N/A class BasicBlock : public ResourceObj {
0N/A private:
0N/A // This class is only used by the MethodLiveness class.
0N/A friend class MethodLiveness;
0N/A
0N/A // The analyzer which created this basic block.
0N/A MethodLiveness* _analyzer;
0N/A
0N/A // The range of this basic block is [start_bci,limit_bci)
0N/A int _start_bci;
0N/A int _limit_bci;
0N/A
0N/A // The liveness at the start of the block;
0N/A BitMap _entry;
0N/A
0N/A // The summarized liveness effects of our direct successors reached
0N/A // by normal control flow
0N/A BitMap _normal_exit;
0N/A
0N/A // The summarized liveness effects of our direct successors reached
0N/A // by exceptional control flow
0N/A BitMap _exception_exit;
0N/A
0N/A // These members hold the results of the last call to
0N/A // compute_gen_kill_range(). _gen is the set of locals
0N/A // used before they are defined in the range. _kill is the
0N/A // set of locals defined before they are used.
0N/A BitMap _gen;
0N/A BitMap _kill;
0N/A int _last_bci;
0N/A
0N/A // A list of all blocks which could come directly before this one
0N/A // in normal (non-exceptional) control flow. We propagate liveness
0N/A // information to these blocks.
0N/A GrowableArray<BasicBlock*>* _normal_predecessors;
0N/A
0N/A // A list of all blocks which could come directly before this one
0N/A // in exceptional control flow.
0N/A GrowableArray<BasicBlock*>* _exception_predecessors;
0N/A
0N/A // The following fields are used to manage a work list used in the
0N/A // dataflow.
0N/A BasicBlock *_next;
0N/A bool _on_work_list;
0N/A
0N/A // Our successors call this method to merge liveness information into
0N/A // our _normal_exit member.
0N/A bool merge_normal(BitMap other);
0N/A
0N/A // Our successors call this method to merge liveness information into
0N/A // our _exception_exit member.
0N/A bool merge_exception(BitMap other);
0N/A
0N/A // This helper routine is used to help compute the gen/kill pair for
0N/A // the block. It is also used to answer queries.
0N/A void compute_gen_kill_range(ciBytecodeStream *bytes);
0N/A
0N/A // Compute the gen/kill effect of a single instruction.
0N/A void compute_gen_kill_single(ciBytecodeStream *instruction);
0N/A
0N/A // Helpers for compute_gen_kill_single.
0N/A void load_one(int local);
0N/A void load_two(int local);
0N/A void store_one(int local);
0N/A void store_two(int local);
0N/A
0N/A BasicBlock(MethodLiveness *analyzer, int start, int limit);
0N/A
0N/A // -- Accessors
0N/A
0N/A int start_bci() const { return _start_bci; }
0N/A
0N/A int limit_bci() const { return _limit_bci; }
0N/A void set_limit_bci(int limit) { _limit_bci = limit; }
0N/A
0N/A BasicBlock *next() const { return _next; }
0N/A void set_next(BasicBlock *next) { _next = next; }
0N/A
0N/A bool on_work_list() const { return _on_work_list; }
0N/A void set_on_work_list(bool val) { _on_work_list = val; }
0N/A
0N/A // -- Flow graph construction.
0N/A
0N/A // Add a basic block to our list of normal predecessors.
0N/A void add_normal_predecessor(BasicBlock *pred) {
0N/A _normal_predecessors->append_if_missing(pred);
0N/A }
0N/A
0N/A // Add a basic block to our list of exceptional predecessors
0N/A void add_exception_predecessor(BasicBlock *pred) {
0N/A _exception_predecessors->append_if_missing(pred);
0N/A }
0N/A
0N/A // Split the basic block at splitBci. This basic block
0N/A // becomes the second half. The first half is newly created.
0N/A BasicBlock *split(int splitBci);
0N/A
0N/A // -- Dataflow.
0N/A
0N/A void compute_gen_kill(ciMethod* method);
0N/A
0N/A // Propagate changes from this basic block
0N/A void propagate(MethodLiveness *ml);
0N/A
0N/A // -- Query.
0N/A
0N/A MethodLivenessResult get_liveness_at(ciMethod* method, int bci);
0N/A
0N/A // -- Debugging.
0N/A
0N/A void print_on(outputStream *os) const PRODUCT_RETURN;
0N/A
0N/A }; // End of MethodLiveness::BasicBlock
0N/A
0N/A private:
0N/A // The method we are analyzing.
0N/A ciMethod* _method;
0N/A ciMethod* method() const { return _method; }
0N/A
0N/A // The arena for storing structures...
0N/A Arena* _arena;
0N/A Arena* arena() const { return _arena; }
0N/A
0N/A // We cache the length of the method.
0N/A int _code_size;
0N/A
0N/A // The size of a BitMap.
0N/A int _bit_map_size_bits;
0N/A int _bit_map_size_words;
0N/A
0N/A // A list of all BasicBlocks.
0N/A BasicBlock **_block_list;
0N/A
0N/A // number of blocks
0N/A int _block_count;
0N/A
0N/A // Keeps track of bci->block mapping. One entry for each bci. Only block starts are
0N/A // recorded.
0N/A GrowableArray<BasicBlock*>* _block_map;
0N/A
0N/A // Our work list.
0N/A BasicBlock *_work_list;
0N/A
0N/A#ifdef COMPILER1
0N/A // bcis where blocks start are marked
0N/A BitMap _bci_block_start;
0N/A#endif // COMPILER1
0N/A
0N/A // -- Graph construction & Analysis
0N/A
0N/A // Compute ranges and predecessors for basic blocks.
0N/A void init_basic_blocks();
0N/A
0N/A // Compute gen/kill information for all basic blocks.
0N/A void init_gen_kill();
0N/A
0N/A // Perform the dataflow.
0N/A void propagate_liveness();
0N/A
0N/A // The class MethodLiveness::BasicBlock needs special access to some
0N/A // of our members.
0N/A friend class MethodLiveness::BasicBlock;
0N/A
0N/A // And accessors.
0N/A int bit_map_size_bits() const { return _bit_map_size_bits; }
0N/A int bit_map_size_words() const { return _bit_map_size_words; }
0N/A
0N/A // Work list manipulation routines. Called internally by BasicBlock.
0N/A BasicBlock *work_list_get();
0N/A void work_list_add(BasicBlock *block);
0N/A
0N/A // -- Timing and Statistics.
0N/A
0N/A
0N/A // Timers
0N/A static elapsedTimer _time_build_graph;
0N/A static elapsedTimer _time_gen_kill;
0N/A static elapsedTimer _time_flow;
0N/A static elapsedTimer _time_query;
0N/A static elapsedTimer _time_total;
0N/A
0N/A#ifndef PRODUCT
0N/A
0N/A // Counts
0N/A static long _total_bytes;
0N/A static int _total_methods;
0N/A
0N/A static long _total_blocks;
0N/A static int _max_method_blocks;
0N/A
0N/A static long _total_edges;
0N/A static int _max_block_edges;
0N/A
0N/A static long _total_exc_edges;
0N/A static int _max_block_exc_edges;
0N/A
0N/A static long _total_method_locals;
0N/A static int _max_method_locals;
0N/A
0N/A static long _total_locals_queried;
0N/A static long _total_live_locals_queried;
0N/A
0N/A static long _total_visits;
0N/A
0N/A#endif
0N/A
0N/A public:
0N/A // Create a liveness analyzer for a method
0N/A MethodLiveness(Arena* arena, ciMethod* method);
0N/A
0N/A // Compute liveness information for the method
0N/A void compute_liveness();
0N/A
0N/A // Find out which locals are live at a specific bci.
0N/A MethodLivenessResult get_liveness_at(int bci);
0N/A
0N/A#ifdef COMPILER1
0N/A const BitMap get_bci_block_start() const { return _bci_block_start; }
0N/A#endif // COMPILER1
0N/A
0N/A static void print_times() PRODUCT_RETURN;
0N/A};