1 /*
  2  * Copyright (c) 2001, 2023, 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 package sun.jvm.hotspot.runtime;
 26 
 27 import java.util.*;
 28 
 29 import sun.jvm.hotspot.oops.*;
 30 import sun.jvm.hotspot.utilities.*;
 31 import sun.jvm.hotspot.debugger.*;
 32 import sun.jvm.hotspot.types.*;
 33 import sun.jvm.hotspot.utilities.Observable;
 34 import sun.jvm.hotspot.utilities.Observer;
 35 
 36 public class ObjectSynchronizer {
 37   static {
 38     VM.registerVMInitializedObserver(new Observer() {
 39         public void update(Observable o, Object data) {
 40           initialize(VM.getVM().getTypeDataBase());
 41         }
 42       });
 43   }
 44 
 45   private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
 46     Type objectSynchronizerType = db.lookupType("ObjectSynchronizer");
 47     Type monitorListType = db.lookupType("MonitorList");
 48     Address monitorListAddr = objectSynchronizerType.getField("_in_use_list").getStaticFieldAddress();
 49     inUseListHead = monitorListType.getAddressField("_head").getAddress(monitorListAddr);
 50   }
 51 
 52   public long identityHashValueFor(Oop obj) {
 53     Mark mark = obj.getMark();
 54     if (mark.isUnlocked()) {
 55       // FIXME: can not generate marks in debugging system
 56       return mark.hash();
 57     } else if (mark.hasMonitor()) {
 58       ObjectMonitor monitor = mark.monitor();
 59       Mark temp = monitor.header();
 60       return temp.hash();
 61     } else {
 62       if (Assert.ASSERTS_ENABLED) {
 63         Assert.that(VM.getVM().isDebugging(), "Can not access displaced header otherwise");
 64       }
 65       if (mark.hasDisplacedMarkHelper()) {
 66         Mark temp = mark.displacedMarkHelper();
 67         return temp.hash();
 68       }
 69       // FIXME: can not do anything else here in debugging system
 70       return 0;
 71     }
 72   }
 73 
 74   public static Iterator objectMonitorIterator() {
 75     return new ObjectMonitorIterator();
 76   }
 77 
 78   private static class ObjectMonitorIterator implements Iterator {
 79 
 80     // JVMTI raw monitors are not included in _in_use_list and
 81     // are not returned by this Iterator.
 82 
 83     ObjectMonitorIterator() {
 84       mon = inUseListHead == null ? null : new ObjectMonitor(inUseListHead);
 85     }
 86 
 87     public boolean hasNext() {
 88       return (mon != null);
 89     }
 90 
 91     public Object next() {
 92       ObjectMonitor ret = mon;
 93       if (ret == null) {
 94         throw new NoSuchElementException();
 95       }
 96       // advance to next entry
 97       Address nextMon = mon.nextOM();
 98       mon = nextMon == null ? null : new ObjectMonitor(nextMon);
 99 
100       return ret;
101     }
102 
103     public void remove() {
104       throw new UnsupportedOperationException();
105     }
106 
107     private ObjectMonitor mon;
108   }
109 
110   private static Address inUseListHead;
111 
112 }