1 /*
   2  * Copyright (c) 2017, 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 #include "precompiled.hpp"
  25 #include "gc/shared/preservedMarks.inline.hpp"
  26 #include "unittest.hpp"
  27 
  28 class ScopedDisabledBiasedLocking {
  29   bool _orig;
  30 public:
  31   ScopedDisabledBiasedLocking() : _orig(UseBiasedLocking) { UseBiasedLocking = false; }
  32   ~ScopedDisabledBiasedLocking() { UseBiasedLocking = _orig; }
  33 };
  34 
  35 // Class to create a "fake" oop with a mark that will
  36 // return true for calls to must_be_preserved().
  37 class FakeOop {
  38   oopDesc _oop;
  39 
  40 public:
  41   FakeOop() : _oop() { _oop.set_mark(originalMark()); }
  42 
  43   oop get_oop() { return &_oop; }
  44   markOop mark() { return _oop.mark(); }
  45   void set_mark(markOop m) { _oop.set_mark(m); }
  46   void forward_to(oop obj) {
  47     markOop m = markOopDesc::encode_pointer_as_mark(obj);
  48     _oop.set_mark(m);
  49   }
  50 
  51   static markOop originalMark() { return markOop(markOopDesc::lock_mask_in_place); }
  52   static markOop changedMark()  { return markOop(0x4711); }
  53 };
  54 
  55 TEST_VM(PreservedMarks, iterate_and_restore) {
  56   // Need to disable biased locking to easily
  57   // create oops that "must_be_preseved"
  58   ScopedDisabledBiasedLocking dbl;
  59 
  60   PreservedMarks pm;
  61   FakeOop o1;
  62   FakeOop o2;
  63   FakeOop o3;
  64   FakeOop o4;
  65 
  66   // Make sure initial marks are correct.
  67   ASSERT_EQ(o1.mark(), FakeOop::originalMark());
  68   ASSERT_EQ(o2.mark(), FakeOop::originalMark());
  69   ASSERT_EQ(o3.mark(), FakeOop::originalMark());
  70   ASSERT_EQ(o4.mark(), FakeOop::originalMark());
  71 
  72   // Change the marks and verify change.
  73   o1.set_mark(FakeOop::changedMark());
  74   o2.set_mark(FakeOop::changedMark());
  75   ASSERT_EQ(o1.mark(), FakeOop::changedMark());
  76   ASSERT_EQ(o2.mark(), FakeOop::changedMark());
  77 
  78   // Push o1 and o2 to have their marks preserved.
  79   pm.push(o1.get_oop(), o1.mark());
  80   pm.push(o2.get_oop(), o2.mark());
  81 
  82   // Fake a move from o1->o3 and o2->o4.
  83   o1.forward_to(o3.get_oop());
  84   o2.forward_to(o4.get_oop());
  85   ASSERT_EQ(o1.get_oop()->forwardee(), o3.get_oop());
  86   ASSERT_EQ(o2.get_oop()->forwardee(), o4.get_oop());
  87   // Adjust will update the PreservedMarks stack to
  88   // make sure the mark is updated at the new location.
  89   pm.adjust_during_full_gc();
  90 
  91   // Restore all preserved and verify that the changed
  92   // mark is now present at o3 and o4.
  93   pm.restore();
  94   ASSERT_EQ(o3.mark(), FakeOop::changedMark());
  95   ASSERT_EQ(o4.mark(), FakeOop::changedMark());
  96 }