markOop.hpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.24 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 // Bit-format of markOop:
00025 //  sentinel:1 near_death:1 tagged_contents:1 age:7 hash:20 tag:2 = 32 bits
00026 //  - sentinel is needed during pointer reversal in garbage collection 
00027 //    to distinguish markOops from roots of oops. markOops are used termination
00028 //    elements in the pointer list.
00029 //    During normal execution the sentinel is 1 but the but may be used for
00030 //    marking during special vm operations like dependency checking.
00031 //  - near_death is set by the memory system iff weak pointers keep the object alive.
00032 //  - tagged_contents indicates the is no untagged data in the object.
00033 //  - age contains the age of the object when residing in the new generation.
00034 //    (during garbage collection, age is used to store the size of the object).
00035 //    PLEASE DO NOT CHANGE THE AGE FIELD since the garbage collector relies on the size.
00036 //  - hash contains the identity hash value.
00037 //  - tag contains the special mark tag
00038 
00039 class markOopDesc: public oopDesc {
00040  private:
00041   unsigned int value()  const { return (unsigned int) this; }
00042   friend   int assign_hash(markOop& m);
00043 
00044   enum { no_hash    = 0, 
00045          first_hash = 1};
00046 
00047   enum { sentinel_bits         = 1,
00048          near_death_bits       = 1,
00049          tagged_contents_bits  = 1,
00050          age_bits              = 7,
00051          hash_bits             = BitsPerWord - sentinel_bits - near_death_bits - tagged_contents_bits - age_bits - Tag_Size };
00052 
00053   enum { hash_shift            = Tag_Size,
00054          age_shift             = hash_bits             + hash_shift,
00055          tagged_contents_shift = age_bits              + age_shift,
00056          near_death_shift      = tagged_contents_bits  + tagged_contents_shift,
00057          sentinel_shift        = near_death_bits       + near_death_shift };
00058 
00059   enum { hash_mask                     = nthMask(hash_bits),
00060          hash_mask_in_place            = hash_mask << hash_shift,
00061          age_mask                      = nthMask(age_bits),
00062          age_mask_in_place             = age_mask << age_shift,
00063          tagged_contents_mask          = nthMask(tagged_contents_bits),
00064          tagged_contents_mask_in_place = tagged_contents_mask << tagged_contents_shift,
00065          near_death_mask               = nthMask(near_death_bits),
00066          near_death_mask_in_place      = near_death_mask << near_death_shift,
00067          sentinel_mask                 = nthMask(sentinel_bits),
00068          sentinel_mask_in_place        = sentinel_mask << sentinel_shift };
00069 
00070 
00071   enum { no_hash_in_place           = no_hash     << hash_shift,
00072          first_hash_in_place        = first_hash  << hash_shift,
00073          untagged_contents_in_place = 1           << tagged_contents_shift };
00074 
00075   enum { sentinel_is_place = 1 << sentinel_shift } ;
00076  public:
00077   enum { max_age = age_mask };
00078   // accessors
00079   bool    has_sentinel()      const { return maskBits(value(), sentinel_mask_in_place) != 0; }
00080   markOop set_sentinel()      const { return markOop( sentinel_is_place | value()); } 
00081   markOop clear_sentinel()    const { return markOop(~sentinel_is_place & value()); }
00082 
00083   bool has_tagged_contents()  const { return maskBits(value(), tagged_contents_mask_in_place) != 0; }
00084 
00085   bool    is_near_death()     const { return maskBits(value(), near_death_mask_in_place) != 0; }
00086   markOop set_near_death()    const { return markOop( near_death_mask_in_place | value()); } 
00087   markOop clear_near_death()  const { return markOop(~near_death_mask_in_place & value()); }
00088 
00089   // klass invalidation (via sentinel bit)
00090   bool    is_klass_invalid()  const { return !has_sentinel();  }
00091   markOop set_klass_invalid() const { return clear_sentinel(); }
00092   markOop clear_klass_invalid() const { return set_sentinel(); }
00093 
00094   // tells if context has forward reference to an unoptimized context(via sentinel bit)
00095   static int context_forward_bit_mask() { return near_death_mask_in_place; }
00096   bool    has_context_forward() const { return is_near_death();  }
00097   markOop set_context_forward() const { return set_near_death(); }
00098 
00099   // notification queue check
00100   bool    is_queued()    const { return !has_sentinel();  }
00101   markOop set_queued()   const { return clear_sentinel(); }
00102   markOop clear_queued() const { return set_sentinel();   }
00103 
00104   // age operations
00105   int        age()            const { return maskBits(value(), age_mask_in_place)  >> age_shift; }
00106   markOop    set_age(int v)   const {
00107     assert((v & ~age_mask) == 0, "shouldn't overflow field");
00108     return markOop((value() & ~age_mask_in_place) | ((v & age_mask) << age_shift));
00109   }
00110   markOop    incr_age()       const { return age() == max_age ? markOop(this) : set_age(age() + 1); }
00111 
00112   // hash operations
00113   int        hash()           const { return maskBits(value(), hash_mask_in_place) >> hash_shift; }
00114   markOop    set_hash(int v)  const {
00115     if ((v & hash_mask) == 0) v = first_hash; // avoid no_hash
00116     markOop val = markOop((value() & ~hash_mask_in_place) | ((v & hash_mask) << hash_shift));
00117     assert(val->hash() != no_hash, "should have hash now");
00118     return val;
00119   }
00120   bool       has_valid_hash() const { return hash() != no_hash; }
00121 
00122   // markOop prototypes
00123   static markOop tagged_prototype() {
00124     return markOop(sentinel_is_place | no_hash_in_place | Mark_Tag);
00125   }
00126   static markOop untagged_prototype() {
00127     return markOop(sentinel_is_place | untagged_contents_in_place | no_hash_in_place | Mark_Tag);
00128   }
00129 
00130   // badOop
00131   static markOop bad() {
00132     return markOop(sentinel_is_place | first_hash_in_place | Mark_Tag);
00133   }
00134 
00135   friend int hash_markOop(markOop& m) {
00136     int v = m->hash();
00137     return v == no_hash ? assign_hash(m) : v;
00138   }
00139 
00140   // printing
00141   void print_on(outputStream* st);
00142 
00143   static int masked_hash(int v) { return v & hash_mask; }
00144 };
00145 
00146 # define badOop markOopDesc::bad()
00147 
00148 // tells whether p is a root to an oop or a markOop
00149 // used during pointer reversal during GC.
00150 inline bool is_oop_root(oop* p) { return !markOop(p)->has_sentinel(); }

Generated on Mon Oct 9 13:37:14 2006 for Strongtalk VM by  doxygen 1.4.7