1 /*
   2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 
  27 #include "gc/shared/objectMarker.hpp"
  28 #include "memory/iterator.hpp"
  29 #include "oops/oop.inline.hpp"
  30 #include "runtime/biasedLocking.hpp"
  31 
  32 // This implementation uses the existing mark bits in an object for
  33 // marking. Objects that are marked must later have their headers restored.
  34 // As most objects are unlocked and don't have their identity hash computed
  35 // we don't have to save their headers. Instead we save the headers that
  36 // are "interesting". Later when the headers are restored this implementation
  37 // restores all headers to their initial value and then restores the few
  38 // objects that had interesting headers.
  39 //
  40 // Future work: This implementation currently uses growable arrays to save
  41 // the oop and header of interesting objects. As an optimization we could
  42 // use the same technique as the GC and make use of the unused area
  43 // between top() and end().
  44 //
  45 
  46 // An ObjectClosure used to restore the mark bits of an object
  47 class RestoreMarksClosure : public ObjectClosure {
  48  public:
  49   void do_object(oop o) {
  50     if (o != NULL) {
  51       markWord mark = o->mark();
  52       if (mark.is_marked()) {
  53         o->init_mark();
  54       }
  55     }
  56   }
  57 };
  58 
  59 DefaultObjectMarker::DefaultObjectMarker() :
  60   _saved_oop_stack(NULL),
  61   _saved_mark_stack(NULL) {
  62   set_needs_reset(true);
  63 }
  64 
  65 // initialize ObjectMarker - prepares for object marking
  66 bool DefaultObjectMarker::init() {
  67   assert(Thread::current()->is_VM_thread(), "must be VMThread");
  68 
  69   // prepare heap for iteration
  70   Universe::heap()->ensure_parsability(false);  // no need to retire TLABs
  71 
  72   // create stacks for interesting headers
  73   _saved_mark_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<markWord>(4000, true);
  74   _saved_oop_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<oop>(4000, true);
  75 
  76   if (UseBiasedLocking) {
  77     BiasedLocking::preserve_marks();
  78   }
  79 
  80   return true;
  81 }
  82 
  83 // Object marking is done so restore object headers
  84 void DefaultObjectMarker::done() {
  85   // iterate over all objects and restore the mark bits to
  86   // their initial value
  87   RestoreMarksClosure blk;
  88   if (needs_reset()) {
  89     Universe::heap()->object_iterate(&blk);
  90   } else {
  91     // We don't need to reset mark bits on this call, but reset the
  92     // flag to the default for the next call.
  93     set_needs_reset(true);
  94   }
  95 
  96   // now restore the interesting headers
  97   for (int i = 0; i < _saved_oop_stack->length(); i++) {
  98     oop o = _saved_oop_stack->at(i);
  99     markWord mark = _saved_mark_stack->at(i);
 100     o->set_mark(mark);
 101   }
 102 
 103   if (UseBiasedLocking) {
 104     BiasedLocking::restore_marks();
 105   }
 106 
 107   // free the stacks
 108   delete _saved_oop_stack;
 109   delete _saved_mark_stack;
 110 
 111   delete this;
 112 }
 113 
 114 // mark an object
 115 bool DefaultObjectMarker::mark(oop o) {
 116   assert(Universe::heap()->is_in(o), "sanity check");
 117 
 118   // object's mark word
 119   markWord mark = o->mark();
 120   if (mark.is_marked()) {
 121     return false;
 122   }
 123 
 124   if (o->mark_must_be_preserved(mark)) {
 125     _saved_mark_stack->push(mark);
 126     _saved_oop_stack->push(o);
 127   }
 128 
 129   // mark the object
 130   o->set_mark(markWord::prototype().set_marked());
 131   return true;
 132 }
 133 
 134 // return true if object is marked
 135 bool DefaultObjectMarker::marked(oop o) {
 136   return o->mark().is_marked();
 137 }