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 }