< prev index next >

src/hotspot/share/compiler/oopMap.hpp

Print this page

        

*** 26,35 **** --- 26,36 ---- #define SHARE_COMPILER_OOPMAP_HPP #include "code/compressedStream.hpp" #include "code/vmreg.hpp" #include "memory/allocation.hpp" + #include "memory/iterator.hpp" #include "oops/oopsHierarchy.hpp" // Interface for generating the frame map for compiled code. A frame map // describes for a specific pc whether each register and frame stack slot is: // Oop - A GC root for current frame
*** 40,61 **** // OopMapValue describes a single OopMap entry class frame; class RegisterMap; class OopClosure; ! class OopMapValue: public StackObj { friend class VMStructs; private: short _value; int value() const { return _value; } void set_value(int value) { _value = value; } short _content_reg; public: // Constants ! enum { type_bits = 4, register_bits = BitsPerShort - type_bits }; enum { type_shift = 0, register_shift = type_bits }; --- 41,63 ---- // OopMapValue describes a single OopMap entry class frame; class RegisterMap; class OopClosure; + class CodeBlob; ! class OopMapValue { friend class VMStructs; private: short _value; int value() const { return _value; } void set_value(int value) { _value = value; } short _content_reg; public: // Constants ! enum { type_bits = 4, // 5, register_bits = BitsPerShort - type_bits }; enum { type_shift = 0, register_shift = type_bits };
*** 67,83 **** enum oop_types { // must fit in type_bits unused_value =0, // powers of 2, for masking OopMapStream oop_value = 1, narrowoop_value = 2, callee_saved_value = 4, ! derived_oop_value= 8 }; // Constructors OopMapValue () { set_value(0); set_content_reg(VMRegImpl::Bad()); } OopMapValue (VMReg reg, oop_types t) { set_reg_type(reg, t); set_content_reg(VMRegImpl::Bad()); } OopMapValue (VMReg reg, oop_types t, VMReg reg2) { set_reg_type(reg, t); set_content_reg(reg2); } OopMapValue (CompressedReadStream* stream) { read_from(stream); } // Archiving void write_on(CompressedWriteStream* stream) { stream->write_int(value()); if(is_callee_saved() || is_derived_oop()) { --- 69,91 ---- enum oop_types { // must fit in type_bits unused_value =0, // powers of 2, for masking OopMapStream oop_value = 1, narrowoop_value = 2, callee_saved_value = 4, ! derived_oop_value= 8, ! /*live_value = 16*/ }; // Constructors OopMapValue () { set_value(0); set_content_reg(VMRegImpl::Bad()); } OopMapValue (VMReg reg, oop_types t) { set_reg_type(reg, t); set_content_reg(VMRegImpl::Bad()); } OopMapValue (VMReg reg, oop_types t, VMReg reg2) { set_reg_type(reg, t); set_content_reg(reg2); } OopMapValue (CompressedReadStream* stream) { read_from(stream); } + OopMapValue (const OopMapValue& o) : _value(o._value), _content_reg(o._content_reg) {} + + bool equals(const OopMapValue& o) { + return _value == o._value && _content_reg == o._content_reg; + } // Archiving void write_on(CompressedWriteStream* stream) { stream->write_int(value()); if(is_callee_saved() || is_derived_oop()) {
*** 95,109 **** --- 103,120 ---- // Querying bool is_oop() { return mask_bits(value(), type_mask_in_place) == oop_value; } bool is_narrowoop() { return mask_bits(value(), type_mask_in_place) == narrowoop_value; } bool is_callee_saved() { return mask_bits(value(), type_mask_in_place) == callee_saved_value; } bool is_derived_oop() { return mask_bits(value(), type_mask_in_place) == derived_oop_value; } + // bool is_live() { return mask_bits(value(), type_mask_in_place) == live_value; } + bool is_oop_or_narrow() { return is_oop() || is_narrowoop(); } void set_oop() { set_value((value() & register_mask_in_place) | oop_value); } void set_narrowoop() { set_value((value() & register_mask_in_place) | narrowoop_value); } void set_callee_saved() { set_value((value() & register_mask_in_place) | callee_saved_value); } void set_derived_oop() { set_value((value() & register_mask_in_place) | derived_oop_value); } + // void set_live() { set_value((value() & register_mask_in_place) | live_value); } VMReg reg() const { return VMRegImpl::as_VMReg(mask_bits(value(), register_mask_in_place) >> register_shift); } oop_types type() const { return (oop_types)mask_bits(value(), type_mask_in_place); } static bool legal_vm_reg_name(VMReg p) {
*** 136,156 **** --- 147,172 ---- class OopMap: public ResourceObj { friend class OopMapStream; friend class VMStructs; + friend class OopMapSet; + friend class OopMapSort; private: int _pc_offset; // offset in the code that this OopMap corresponds to int _omv_count; // number of OopMapValues in the stream + int _num_oops; // number of oops + int _index; // index in OopMapSet CompressedWriteStream* _write_stream; debug_only( OopMapValue::oop_types* _locs_used; int _locs_length;) // Accessors int omv_count() const { return _omv_count; } void set_omv_count(int value) { _omv_count = value; } void increment_count() { _omv_count++; } + void increment_num_oops() { _num_oops++; } CompressedWriteStream* write_stream() const { return _write_stream; } void set_write_stream(CompressedWriteStream* value) { _write_stream = value; } private: enum DeepCopyToken { _deep_copy_token };
*** 163,172 **** --- 179,190 ---- int offset() const { return _pc_offset; } void set_offset(int o) { _pc_offset = o; } int count() const { return _omv_count; } int data_size() const { return write_stream()->position(); } address data() const { return write_stream()->buffer(); } + int num_oops() const { return _num_oops; } + int index() const { return _index; } // Check to avoid double insertion debug_only(OopMapValue::oop_types locs_used( int indx ) { return _locs_used[indx]; }) // Construction
*** 180,189 **** --- 198,208 ---- void set_derived_oop ( VMReg local, VMReg derived_from_local_register ); void set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional); int heap_size() const; void copy_data_to(address addr) const; + void copy_and_sort_data_to(address addr) const; OopMap* deep_copy(); bool has_derived_pointer() const PRODUCT_RETURN0; bool legal_vm_reg_name(VMReg local) {
*** 194,203 **** --- 213,223 ---- void print_on(outputStream* st) const; void print() const; bool equals(const OopMap* other) const; }; + class ImmutableOopMap; class OopMapSet : public ResourceObj { friend class VMStructs; private: int _om_count;
*** 221,231 **** int size() const { return _om_count; } // returns the OopMap at a given index OopMap* at(int index) const { assert((index >= 0) && (index <= om_count()),"bad index"); return _om_data[index]; } // Collect OopMaps. ! void add_gc_map(int pc, OopMap* map); // Returns the only oop map. Used for reconstructing // Adapter frames during deoptimization OopMap* singular_oop_map(); --- 241,251 ---- int size() const { return _om_count; } // returns the OopMap at a given index OopMap* at(int index) const { assert((index >= 0) && (index <= om_count()),"bad index"); return _om_data[index]; } // Collect OopMaps. ! int add_gc_map(int pc, OopMap* map); // Returns the only oop map. Used for reconstructing // Adapter frames during deoptimization OopMap* singular_oop_map();
*** 236,285 **** // Methods oops_do() and all_do() filter out NULL oops and // oop == CompressedOops::base() before passing oops // to closures. // Iterates through frame for a compiled method static void oops_do (const frame* fr, ! const RegisterMap* reg_map, OopClosure* f); static void update_register_map(const frame* fr, RegisterMap *reg_map); ! // Iterates through frame for a compiled method for dead ones and values, too ! static void all_do(const frame* fr, const RegisterMap* reg_map, ! OopClosure* oop_fn, ! void derived_oop_fn(oop* base, oop* derived), ! OopClosure* value_fn); // Printing void print_on(outputStream* st) const; void print() const; }; class ImmutableOopMapBuilder; class ImmutableOopMap { friend class OopMapStream; friend class VMStructs; #ifdef ASSERT friend class ImmutableOopMapBuilder; #endif private: int _count; // contains the number of entries in this OopMap address data_addr() const { return (address) this + sizeof(ImmutableOopMap); } public: ImmutableOopMap(const OopMap* oopmap); bool has_derived_pointer() const PRODUCT_RETURN0; int count() const { return _count; } #ifdef ASSERT int nr_of_bytes() const; // this is an expensive operation, only used in debug builds #endif // Printing void print_on(outputStream* st) const; void print() const; }; class ImmutableOopMapSet; class ImmutableOopMap; class OopMapSet; --- 256,362 ---- // Methods oops_do() and all_do() filter out NULL oops and // oop == CompressedOops::base() before passing oops // to closures. + static const ImmutableOopMap* find_map(const CodeBlob* cb, address pc); + static const ImmutableOopMap* find_map(const frame *fr); + // Iterates through frame for a compiled method + static void oops_do (const frame* fr, const RegisterMap* reg_map, + OopClosure* f, DerivedOopClosure* df); static void oops_do (const frame* fr, ! const RegisterMap* reg_map, OopClosure* f) { oops_do(fr, reg_map, f, NULL); } static void update_register_map(const frame* fr, RegisterMap *reg_map); ! #ifndef PRODUCT ! static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map); ! #endif ! ! // // Iterates through frame for a compiled method for dead ones and values, too ! // static void all_do(const frame* fr, const RegisterMap* reg_map, ! // OopClosure* oop_fn, ! // DerivedOopClosure* derived_oop_fn, ! // OopClosure* value_fn); // Printing void print_on(outputStream* st) const; void print() const; }; class ImmutableOopMapBuilder; + class ExplodedOopMap : public CHeapObj<mtCode> { + private: + OopMapValue* _oopValues; + OopMapValue* _calleeSavedValues; + OopMapValue* _derivedValues; + + int _nrOopValues; + int _nrCalleeSavedValuesCount; + int _nrDerivedValues; + + OopMapValue* copyOopMapValues(const ImmutableOopMap* oopMap, int mask, int* nr); + public: + ExplodedOopMap(const ImmutableOopMap* oopMap); + OopMapValue* values(int mask); + int count(int mask); + + bool has_derived() const { return _nrDerivedValues > 0; } + }; + + class ExplodedOopMapStream; + + class OopMapClosure : public Closure { + public: + virtual void do_value(VMReg reg, OopMapValue::oop_types type) = 0; + }; + + template <typename OopFnT, typename DerivedOopFnT, typename ValueFilterT> + class OopMapDo; + class ImmutableOopMap { friend class OopMapStream; friend class VMStructs; + friend class ExplodedOopMapStream; + template <typename OopFnT, typename DerivedOopFnT, typename ValueFilterT> + friend class OopMapDo; #ifdef ASSERT friend class ImmutableOopMapBuilder; #endif private: + ExplodedOopMap* _exploded; + mutable address _freeze_stub; + mutable address _thaw_stub; int _count; // contains the number of entries in this OopMap + int _num_oops; address data_addr() const { return (address) this + sizeof(ImmutableOopMap); } public: ImmutableOopMap(const OopMap* oopmap); + void set_exploded(ExplodedOopMap* exploded) { _exploded = exploded; } + bool has_exploded() const { return _exploded != NULL; } bool has_derived_pointer() const PRODUCT_RETURN0; + bool has_derived() const { return _exploded->has_derived(); } // DEBUG rbackman int count() const { return _count; } + int num_oops() const { return _num_oops; } #ifdef ASSERT int nr_of_bytes() const; // this is an expensive operation, only used in debug builds #endif + void oops_do(const frame* fr, const RegisterMap* reg_map, OopClosure* f, DerivedOopClosure* df) const; + void all_do(const frame *fr, int mask, OopMapClosure* fn) const; + void update_register_map(const frame* fr, RegisterMap *reg_map) const; + // Printing void print_on(outputStream* st) const; void print() const; + + void generate_stub(const CodeBlob* cb) const; + address freeze_stub() const { return _freeze_stub; } + address thaw_stub() const { return _thaw_stub; } }; class ImmutableOopMapSet; class ImmutableOopMap; class OopMapSet;
*** 318,328 **** --- 395,407 ---- ImmutableOopMapPair* get_pairs() const { return (ImmutableOopMapPair*) ((address) this + sizeof(*this)); } static ImmutableOopMapSet* build_from(const OopMapSet* oopmap_set); + int find_slot_for_offset(int pc_offset) const; const ImmutableOopMap* find_map_at_offset(int pc_offset) const; + const ImmutableOopMap* find_map_at_slot(int slot, int pc_offset) const; const ImmutableOopMapPair* pair_at(int index) const { assert(index >= 0 && index < _count, "check"); return &get_pairs()[index]; } int count() const { return _count; } int nr_of_bytes() const { return _size; }
*** 331,359 **** void print() const; }; class OopMapStream : public StackObj { private: ! CompressedReadStream* _stream; int _mask; int _size; int _position; bool _valid_omv; OopMapValue _omv; void find_next(); public: ! OopMapStream(OopMap* oop_map, int oop_types_mask = OopMapValue::type_mask_in_place); OopMapStream(const ImmutableOopMap* oop_map, int oop_types_mask = OopMapValue::type_mask_in_place); bool is_done() { if(!_valid_omv) { find_next(); } return !_valid_omv; } void next() { find_next(); } OopMapValue current() { return _omv; } #ifdef ASSERT ! int stream_position() const { return _stream->position(); } #endif }; class ImmutableOopMapBuilder { private: class Mapping; private: --- 410,451 ---- void print() const; }; class OopMapStream : public StackObj { private: ! CompressedReadStream _stream; int _mask; int _size; int _position; bool _valid_omv; OopMapValue _omv; void find_next(); public: ! OopMapStream(const OopMap* oop_map, int oop_types_mask = OopMapValue::type_mask_in_place); OopMapStream(const ImmutableOopMap* oop_map, int oop_types_mask = OopMapValue::type_mask_in_place); bool is_done() { if(!_valid_omv) { find_next(); } return !_valid_omv; } void next() { find_next(); } OopMapValue current() { return _omv; } #ifdef ASSERT ! int stream_position() const { return _stream.position(); } #endif }; + class ExplodedOopMapStream : public StackObj { + private: + int _current; + int _max; + OopMapValue* _values; + public: + ExplodedOopMapStream(const ImmutableOopMap* oopMap, int mask) : _current(0), _max(oopMap->_exploded->count(mask)), _values(oopMap->_exploded->values(mask)) {} + bool is_done() const { return _current >= _max; } + void next() { ++_current; } + OopMapValue current() { return _values[_current]; } + }; + + class ImmutableOopMapBuilder { private: class Mapping; private:
*** 419,428 **** --- 511,547 ---- void fill_pair(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set); int fill_map(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set); void fill(ImmutableOopMapSet* set, int size); }; + class SkipNullValue { + public: + static inline bool should_skip(oop val); + }; + + class IncludeAllValues { + public: + static bool should_skip(oop value) { return false; } + }; + + template <typename OopFnT, typename DerivedOopFnT, typename ValueFilterT> + class OopMapDo { + private: + OopFnT* _oop_fn; + DerivedOopFnT* _derived_oop_fn; + public: + OopMapDo(OopFnT* oop_fn, DerivedOopFnT* derived_oop_fn) : _oop_fn(oop_fn), _derived_oop_fn(derived_oop_fn) {} + template <typename RegisterMapT> + void oops_do(const frame* fr, const RegisterMapT* reg_map, const ImmutableOopMap* oopmap); + private: + template <typename OopMapStreamT, typename RegisterMapT> + void iterate_oops_do(const frame *fr, const RegisterMapT *reg_map, const ImmutableOopMap* oopmap); + template <typename OopMapStreamT, typename RegisterMapT> + void walk_derived_pointers(const frame *fr, const ImmutableOopMap* map, const RegisterMapT *reg_map); + template <typename OopMapStreamT, typename RegisterMapT> + void walk_derived_pointers1(OopMapStreamT& oms, const frame *fr, const RegisterMapT *reg_map); + }; // Derived pointer support. This table keeps track of all derived points on a // stack. It is cleared before each scavenge/GC. During the traversal of all // oops, it is filled in with references to all locations that contains a // derived oop (assumed to be very few). When the GC is complete, the derived
< prev index next >