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/markWord.hpp"
  30 #include "oops/oop.inline.hpp"
  31 #include "runtime/biasedLocking.hpp"
  32 
  33 // This implementation uses the existing mark bits in an object for
  34 // marking. Objects that are marked must later have their headers restored.
  35 // As most objects are unlocked and don't have their identity hash computed
  36 // we don't have to save their headers. Instead we save the headers that
  37 // are "interesting". Later when the headers are restored this implementation
  38 // restores all headers to their initial value and then restores the few
  39 // objects that had interesting headers.
  40 //
  41 // Future work: This implementation currently uses growable arrays to save
  42 // the oop and header of interesting objects. As an optimization we could
  43 // use the same technique as the GC and make use of the unused area
  44 // between top() and end().
  45 //
  46 
  47 // An ObjectClosure used to restore the mark bits of an object
  48 class RestoreMarksClosure : public ObjectClosure {
  49  public:
  50   void do_object(oop o) {
  51     if (o != NULL) {
  52       markWord mark = o->mark();
  53       if (mark.is_marked()) {
  54         o->init_mark();
  55       }
  56     }
  57   }
  58 };
  59 
  60 DefaultObjectMarker::DefaultObjectMarker() :
  61   _saved_oop_stack(NULL),
  62   _saved_mark_stack(NULL) {
  63   set_needs_reset(true);
  64 }
  65 
  66 // initialize ObjectMarker - prepares for object marking
  67 bool DefaultObjectMarker::init() {
  68   assert(Thread::current()->is_VM_thread(), "must be VMThread");
  69 
  70   // prepare heap for iteration
  71   Universe::heap()->ensure_parsability(false);  // no need to retire TLABs
  72 
  73   // create stacks for interesting headers
  74   _saved_mark_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<markWord>(4000, true);
  75   _saved_oop_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<oop>(4000, true);
  76 
  77   if (UseBiasedLocking) {
  78     BiasedLocking::preserve_marks();
  79   }
  80 
  81   return true;
  82 }
  83 
  84 // Object marking is done so restore object headers
  85 void DefaultObjectMarker::done() {
  86   // iterate over all objects and restore the mark bits to
  87   // their initial value
  88   RestoreMarksClosure blk;
  89   if (needs_reset()) {
  90     Universe::heap()->object_iterate(&blk);
  91   } else {
  92     // We don't need to reset mark bits on this call, but reset the
  93     // flag to the default for the next call.
  94     set_needs_reset(true);
  95   }
  96 
  97   // now restore the interesting headers
  98   for (int i = 0; i < _saved_oop_stack->length(); i++) {
  99     oop o = _saved_oop_stack->at(i);
 100     markWord mark = _saved_mark_stack->at(i);
 101     o->set_mark(mark);
 102   }
 103 
 104   if (UseBiasedLocking) {
 105     BiasedLocking::restore_marks();
 106   }
 107 
 108   // free the stacks
 109   delete _saved_oop_stack;
 110   delete _saved_mark_stack;
 111 
 112   delete this;
 113 }
 114 
 115 // mark an object
 116 bool DefaultObjectMarker::mark(oop o) {
 117   assert(Universe::heap()->is_in(o), "sanity check");
 118 
 119   // object's mark word
 120   markWord mark = o->mark();
 121   if (mark.is_marked()) {
 122     return false;
 123   }
 124 
 125   if (o->mark_must_be_preserved(mark)) {
 126     _saved_mark_stack->push(mark);
 127     _saved_oop_stack->push(o);
 128   }
 129 
 130   // mark the object
 131   o->set_mark(markWord::prototype().set_marked());
 132   return true;
 133 }
 134 
 135 // return true if object is marked
 136 bool DefaultObjectMarker::marked(oop o) {
 137   return o->mark().is_marked();
 138 }