< prev index next >

src/hotspot/share/compiler/oopMap.hpp

Print this page

        

@@ -26,10 +26,11 @@
 #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,22 +41,23 @@
 // OopMapValue describes a single OopMap entry
 
 class frame;
 class RegisterMap;
 class OopClosure;
+class CodeBlob;
 
-class OopMapValue: public StackObj {
+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,
+  enum { type_bits                = 4, // 5,
          register_bits            = BitsPerShort - type_bits };
 
   enum { type_shift               = 0,
          register_shift           = type_bits };
 

@@ -67,17 +69,23 @@
   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 };
+         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,15 +103,18 @@
   // 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,21 +147,26 @@
 
 
 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,10 +179,12 @@
   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,10 +198,11 @@
   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,10 +213,11 @@
   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,11 +241,11 @@
   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);
+  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,50 +256,107 @@
 
   // 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);
+                                  const RegisterMap* reg_map, OopClosure* f) { oops_do(fr, reg_map, f, NULL); }
   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);
+#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,11 +395,13 @@
 
   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,29 +410,42 @@
   void print() const;
 };
 
 class OopMapStream : public StackObj {
  private:
-  CompressedReadStream* _stream;
+  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 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(); }
+  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,10 +511,37 @@
   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 >