1 /* 2 * Copyright (c) 2001, 2014, 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 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 34 public class ObjectSynchronizer { 35 static { 36 VM.registerVMInitializedObserver(new Observer() { 37 public void update(Observable o, Object data) { 38 initialize(VM.getVM().getTypeDataBase()); 39 } 40 }); 41 } 42 43 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { 44 Type type; 45 try { 46 type = db.lookupType("ObjectSynchronizer"); 47 AddressField blockListField; 48 blockListField = type.getAddressField("gBlockList"); 49 gBlockListAddr = blockListField.getValue(); 50 blockSize = db.lookupIntConstant("ObjectSynchronizer::_BLOCKSIZE").intValue(); 51 defaultCacheLineSize = db.lookupIntConstant("DEFAULT_CACHE_LINE_SIZE").intValue(); 52 } catch (RuntimeException e) { } 53 type = db.lookupType("ObjectMonitor"); 54 objectMonitorTypeSize = type.getSize(); 55 if ((objectMonitorTypeSize % defaultCacheLineSize) != 0) { 56 // sizeof(ObjectMonitor) is not already a multiple of a cache line. 57 // The ObjectMonitor allocation code in ObjectSynchronizer pads each 58 // ObjectMonitor in a block to the next cache line boundary. 59 int needLines = ((int)objectMonitorTypeSize / defaultCacheLineSize) + 1; 60 objectMonitorTypeSize = needLines * defaultCacheLineSize; 61 } 62 } 63 64 public long identityHashValueFor(Oop obj) { 65 Mark mark = obj.getMark(); 66 if (mark.isUnlocked()) { 67 // FIXME: can not generate marks in debugging system 68 return mark.hash(); 69 } else if (mark.hasMonitor()) { 70 ObjectMonitor monitor = mark.monitor(); 71 Mark temp = monitor.header(); 72 return temp.hash(); 73 } else { 74 if (Assert.ASSERTS_ENABLED) { 75 Assert.that(VM.getVM().isDebugging(), "Can not access displaced header otherwise"); 76 } 77 if (mark.hasDisplacedMarkHelper()) { 78 Mark temp = mark.displacedMarkHelper(); 79 return temp.hash(); 80 } 81 // FIXME: can not do anything else here in debugging system 82 return 0; 83 } 84 } 85 86 public static Iterator objectMonitorIterator() { 87 if (gBlockListAddr != null) { 88 return new ObjectMonitorIterator(); 89 } else { 90 return null; 91 } 92 } 93 94 private static class ObjectMonitorIterator implements Iterator { 95 96 // JVMTI raw monitors are not pointed by gBlockList 97 // and are not included by this Iterator. May add them later. 98 99 ObjectMonitorIterator() { 100 blockAddr = gBlockListAddr; 101 index = blockSize - 1; 102 block = new ObjectMonitor(blockAddr); 103 } 104 105 public boolean hasNext() { 106 return (index > 0 || block.freeNext() != null); 107 } 108 109 public Object next() { 110 Address addr; 111 if (index == 0) { 112 // advance to next block 113 blockAddr = block.freeNext(); 114 if (blockAddr == null) { 115 throw new NoSuchElementException(); 116 } 117 block = new ObjectMonitor(blockAddr); 118 index = blockSize - 1; 119 } 120 addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize); 121 index --; 122 return new ObjectMonitor(addr); 123 } 124 125 public void remove() { 126 throw new UnsupportedOperationException(); 127 } 128 129 private ObjectMonitor block; 130 private int index; 131 private Address blockAddr; 132 } 133 134 private static Address gBlockListAddr; 135 private static int blockSize; 136 private static int defaultCacheLineSize; 137 private static long objectMonitorTypeSize; 138 139 }