1 /* 2 * Copyright 2000-2002 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.code; 26 27 import java.util.*; 28 import sun.jvm.hotspot.debugger.*; 29 import sun.jvm.hotspot.runtime.*; 30 import sun.jvm.hotspot.types.*; 31 import sun.jvm.hotspot.utilities.*; 32 33 /** <P> A port of the VM's StubQueue. Note that the VM implicitly 34 knows the type of the objects contained in each StubQueue because 35 it passes in an instance of a StubInterface to the StubQueue's 36 constructor; the goal in the VM was to save space in the generated 37 code. In the SA APIs the pattern has been to use the 38 VirtualConstructor mechanism to instantiate wrapper objects of the 39 appropriate type for objects down in the VM; see, for example, the 40 CodeCache, which identifies NMethods, RuntimeStubs, etc. </P> 41 42 <P> In this port we eliminate the StubInterface in favor of 43 passing in the class corresponding to the type of Stub which this 44 StubQueue contains. </P> */ 45 46 public class StubQueue extends VMObject { 47 // FIXME: add the rest of the fields 48 private static AddressField stubBufferField; 49 private static CIntegerField bufferLimitField; 50 private static CIntegerField queueBeginField; 51 private static CIntegerField queueEndField; 52 private static CIntegerField numberOfStubsField; 53 54 // The type of the contained stubs (i.e., InterpreterCodelet, 55 // ICStub). Must be a subclass of type Stub. 56 private Class stubType; 57 58 static { 59 VM.registerVMInitializedObserver(new Observer() { 60 public void update(Observable o, Object data) { 61 initialize(VM.getVM().getTypeDataBase()); 62 } 63 }); 64 } 65 66 private static synchronized void initialize(TypeDataBase db) { 67 Type type = db.lookupType("StubQueue"); 68 69 stubBufferField = type.getAddressField("_stub_buffer"); 70 bufferLimitField = type.getCIntegerField("_buffer_limit"); 71 queueBeginField = type.getCIntegerField("_queue_begin"); 72 queueEndField = type.getCIntegerField("_queue_end"); 73 numberOfStubsField = type.getCIntegerField("_number_of_stubs"); 74 } 75 76 public StubQueue(Address addr, Class stubType) { 77 super(addr); 78 this.stubType = stubType; 79 } 80 81 public boolean contains(Address pc) { 82 if (pc == null) return false; 83 long offset = pc.minus(getStubBuffer()); 84 return ((0 <= offset) && (offset < getBufferLimit())); 85 } 86 87 public Stub getStubContaining(Address pc) { 88 if (contains(pc)) { 89 int i = 0; 90 for (Stub s = getFirst(); s != null; s = getNext(s)) { 91 if (stubContains(s, pc)) { 92 return s; 93 } 94 } 95 } 96 return null; 97 } 98 99 public boolean stubContains(Stub s, Address pc) { 100 return (s.codeBegin().lessThanOrEqual(pc) && s.codeEnd().greaterThan(pc)); 101 } 102 103 public int getNumberOfStubs() { 104 return (int) numberOfStubsField.getValue(addr); 105 } 106 107 public Stub getFirst() { 108 return ((getNumberOfStubs() > 0) ? getStubAt(getQueueBegin()) : null); 109 } 110 111 public Stub getNext(Stub s) { 112 long i = getIndexOf(s) + getStubSize(s); 113 if (i == getBufferLimit()) { 114 i = 0; 115 } 116 return ((i == getQueueEnd()) ? null : getStubAt(i)); 117 } 118 119 public Stub getPrev(Stub s) { 120 if (getIndexOf(s) == getQueueBegin()) { 121 return null; 122 } 123 124 Stub temp = getFirst(); 125 Stub prev = null; 126 while (temp != null && getIndexOf(temp) != getIndexOf(s)) { 127 prev = temp; 128 temp = getNext(temp); 129 } 130 131 return prev; 132 } 133 134 //-------------------------------------------------------------------------------- 135 // Internals only below this point 136 // 137 138 private long getQueueBegin() { 139 return queueBeginField.getValue(addr); 140 } 141 142 private long getQueueEnd() { 143 return queueEndField.getValue(addr); 144 } 145 146 private long getBufferLimit() { 147 return bufferLimitField.getValue(addr); 148 } 149 150 private Address getStubBuffer() { 151 return stubBufferField.getValue(addr); 152 } 153 154 private Stub getStubAt(long offset) { 155 checkIndex(offset); 156 return (Stub) VMObjectFactory.newObject(stubType, getStubBuffer().addOffsetTo(offset)); 157 } 158 159 private long getIndexOf(Stub s) { 160 long i = s.getAddress().minus(getStubBuffer()); 161 checkIndex(i); 162 return i; 163 } 164 165 private long getStubSize(Stub s) { 166 return s.getSize(); 167 } 168 169 private void checkIndex(long i) { 170 if (Assert.ASSERTS_ENABLED) { 171 Assert.that(0 <= i && i < getBufferLimit() && (i % VM.getVM().getAddressSize() == 0), "illegal index"); 172 } 173 } 174 }