/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_OOPS_GENERATEOOPMAP_HPP
#define SHARE_VM_OOPS_GENERATEOOPMAP_HPP
#include "interpreter/bytecodeStream.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/universe.inline.hpp"
#include "oops/methodOop.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/signature.hpp"
// Forward definition
class MethodOopMap;
class GenerateOopMap;
class BasicBlock;
class CellTypeState;
class StackMap;
// These two should be removed. But requires som code to be cleaned up
// RetTable
//
// Contains maping between jsr targets and there return addresses. One-to-many mapping
//
private:
public:
RetTableEntry(int target, RetTableEntry *next) { _target_bci=target; _jsrs = new GrowableArray<intptr_t>(_init_nof_jsrs); _next = next; }
// Query
// Update entry
};
private:
static int _init_nof_entries;
public:
};
//
// CellTypeState
//
private:
unsigned int _state;
// Masks for separating the BITS and INFO portions of a CellTypeState
// These constant are used for manipulating the BITS portion of a
// CellTypeState
// These constants are used for manipulating the INFO portion of a
// CellTypeState
// Within the INFO data, these values are used to distinguish different
// kinds of references.
// 0 if it is a "line" reference.
// These values are used to initialize commonly used CellTypeState
// constants.
enum { bottom_value = 0,
public:
// Since some C++ constructors generate poor code for declarations of the
// form...
//
// CellTypeState vector[length];
//
// ...we avoid making a constructor for this class. CellTypeState values
// should be constructed using one of the make_* methods:
// Causes SS10 warning.
// assert(s.is_valid_state(), "check to see if CellTypeState is valid");
return s;
}
return make_any(0);
}
}
}
(slot_num & ref_data_mask));
}
(bci & ref_data_mask));
}
}
// Query methods:
bool is_valid_state() const {
// Uninitialized and value cells must contain no data in their info field:
return false;
}
// The top bit is only set when all info bits are set:
return false;
}
// The not_bottom_bit must be set when any other info bit is set:
return false;
}
return true;
}
int get_info() const {
return (_state & info_data_mask);
}
bool is_lock_reference() const {
}
bool is_nonlock_reference() const {
}
}
char to_char() const;
// Merge
// Debugging output
// Default values of common values
};
//
// BasicBlockStruct
//
private:
public:
enum Constants {
// >=0 // Alive and has a merged state
};
// All basicblocks that are unreachable are going to have a _stack_top == _dead_basic_block.
// This info. is setup in a pre-parse before the real abstract interpretation starts.
};
//
// GenerateOopMap
//
// Main class used to compute the pointer-maps in a MethodOop
//
protected:
// _monitor_top is set to this constant to indicate that a monitor matching
// problem was encountered prior to this point in control flow.
// Main variables
// to be safe.
// Working Cell type state
int _stack_top;
int _monitor_top;
// Timing and statistics
// Cell type methods
void init_state();
void make_context_uninitialized ();
CellTypeState pop ();
bool detailed);
void report_monitor_mismatch (const char *msg);
// Basicblock info
int _gc_points;
int _bb_count;
// Basicblocks methods
void initialize_bb ();
}
}
}
// Dead code detection
void mark_reachable_code();
// Interpretation methods (primary)
void do_interpretation ();
void init_basic_blocks ();
void setup_method_entry_state ();
void interp_all ();
// Interpretation methods (secondary)
void do_monitorenter (int bci);
void do_monitorexit (int bci);
void do_return_monitor_check ();
void do_checkcast ();
// Error handling
void report_error (const char *format, ...);
void verify_error (const char *format, ...);
// Create result set
bool _report_result;
bool _report_result_for_send; // Unfortunatly, stackmaps for sends are special, so we need some extra
void report_result ();
// Initvars
void initialize_vars ();
void add_to_ref_init_set (int localNo);
// Conflicts rewrite logic
int * _new_var_map;
void record_refval_conflict (int varNo);
void rewrite_refval_conflicts ();
bool rewrite_load_or_store (BytecodeStream *i, Bytecodes::Code bc, Bytecodes::Code bc0, unsigned int varNo);
// List of bci's where a return address is on top of the stack
bool stack_top_holds_ret_addr (int bci);
void compute_ret_adr_at_TOS ();
// Helper method. Can be used in subclasses to fx. calculate gc_points. If the current instuction
// is a control transfer, then calls the jmpFct all possible destinations.
friend class RelocCallback;
public:
// Compute the map.
void compute_map(TRAPS);
void result_for_basicblock(int bci); // Do a callback on fill_stackmap_for_opcodes for basicblock containing bci
// Query
static void print_time();
// Monitor query
// Specialization methods. Intended use:
// - possible_gc_point must return true for every bci for which the stackmaps must be returned
// - fill_stackmap_prolog is called just before the result is reported. The arguments tells the estimated
// number of gc points
// - fill_stackmap_for_opcodes is called once for each bytecode index in order (0...code_length-1)
// - fill_stackmap_epilog is called after all results has been reported. Note: Since the algorithm does not report
// stackmaps for deadcode, fewer gc_points might have been encounted than assumed during the epilog. It is the
// responsibility of the subclass to count the correct number.
// - fill_init_vars are called once with the result of the init_vars computation
//
// All these methods are used during a call to: compute_map. Note: Non of the return results are valid
// after compute_map returns, since all values are allocated as resource objects.
//
// All virtual method must be implemented in subclasses
virtual bool allow_rewrites () const { return false; }
virtual bool report_results () const { return true; }
virtual bool report_init_vars () const { return true; }
int stackTop) { ShouldNotReachHere(); }
};
//
// Subclass of the GenerateOopMap Class that just do rewrites of the method, if needed.
// It does not store any oopmaps.
//
private:
bool _must_clear_locals;
virtual bool report_results() const { return false; }
virtual bool report_init_vars() const { return true; }
virtual bool allow_rewrites() const { return true; }
virtual void fill_stackmap_epilog () {}
int stack_top) {}
virtual void fill_init_vars (GrowableArray<intptr_t> *init_vars) { _must_clear_locals = init_vars->length() > 0; }
#ifndef PRODUCT
// Statistics
static int _nof_invocations;
static int _nof_rewrites;
static int _nof_relocations;
#endif
public:
ResolveOopMapConflicts(methodHandle method) : GenerateOopMap(method) { _must_clear_locals = false; };
};
//
// Subclass used by the compiler to generate pairing infomation
//
private:
virtual bool report_results() const { return false; }
virtual bool report_init_vars() const { return false; }
virtual bool allow_rewrites() const { return false; }
virtual void fill_stackmap_epilog () {}
int stack_top) {}
public:
// Call compute_map(CHECK) to generate info.
};
#endif // SHARE_VM_OOPS_GENERATEOOPMAP_HPP