View Javadoc
1   /*
2    * Copyright (c) 2000, 2012, 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.memory;
26  
27  import java.io.*;
28  import java.util.*;
29  import sun.jvm.hotspot.debugger.*;
30  import sun.jvm.hotspot.types.*;
31  import sun.jvm.hotspot.runtime.*;
32  
33  /** <P> The (supported) Generation hierarchy currently looks like this: </P>
34  
35      <ul>
36      <li> Generation
37        <ul>
38        <li> CardGeneration
39          <ul>
40          <li> OneContigSpaceCardGeneration
41            <ul>
42            <li> TenuredGeneration
43            </ul>
44          </ul>
45        <li> DefNewGeneration
46        </ul>
47      </ul>
48  */
49  
50  
51  public abstract class Generation extends VMObject {
52    private static long          reservedFieldOffset;
53    private static long          virtualSpaceFieldOffset;
54    private static CIntegerField levelField;
55    protected static final int  K = 1024;
56    // Fields for class StatRecord
57    private static Field         statRecordField;
58    private static CIntegerField invocationField;
59  
60    // constants from Name enum
61    private static int NAME_DEF_NEW;
62    private static int NAME_PAR_NEW;
63    private static int NAME_MARK_SWEEP_COMPACT;
64    private static int NAME_CONCURRENT_MARK_SWEEP;
65    private static int NAME_OTHER;
66  
67    static {
68      VM.registerVMInitializedObserver(new Observer() {
69          public void update(Observable o, Object data) {
70            initialize(VM.getVM().getTypeDataBase());
71          }
72        });
73    }
74  
75    private static synchronized void initialize(TypeDataBase db) {
76      Type type = db.lookupType("Generation");
77  
78      reservedFieldOffset     = type.getField("_reserved").getOffset();
79      virtualSpaceFieldOffset = type.getField("_virtual_space").getOffset();
80      levelField              = type.getCIntegerField("_level");
81      // StatRecord
82      statRecordField         = type.getField("_stat_record");
83      type                    = db.lookupType("Generation::StatRecord");
84      invocationField         = type.getCIntegerField("invocations");
85  
86      // constants from Generation::Name
87      NAME_DEF_NEW = db.lookupIntConstant("Generation::DefNew").intValue();
88      NAME_PAR_NEW = db.lookupIntConstant("Generation::ParNew").intValue();
89      NAME_MARK_SWEEP_COMPACT = db.lookupIntConstant("Generation::MarkSweepCompact").intValue();
90      NAME_CONCURRENT_MARK_SWEEP = db.lookupIntConstant("Generation::ConcurrentMarkSweep").intValue();
91      NAME_OTHER = db.lookupIntConstant("Generation::Other").intValue();
92    }
93  
94    public Generation(Address addr) {
95      super(addr);
96    }
97  
98    public static class Name {
99      public static final Name DEF_NEW = new Name("DefNew");
100     public static final Name PAR_NEW = new Name("ParNew");
101     public static final Name MARK_SWEEP_COMPACT = new Name("MarkSweepCompact");
102     public static final Name CONCURRENT_MARK_SWEEP = new Name("ConcurrentMarkSweep");
103     public static final Name OTHER = new Name("Other");
104 
105     private Name(String value) {
106       this.value = value;
107     }
108 
109     private String value;
110     public String toString() {
111       return value;
112     }
113   }
114 
115   public Generation.Name kind() {
116     return Generation.Name.OTHER;
117   }
118 
119   static Generation.Name nameForEnum(int value) {
120      if (value == NAME_DEF_NEW) {
121         return Name.DEF_NEW;
122      } else if (value == NAME_PAR_NEW) {
123         return Name.PAR_NEW;
124      } else if (value == NAME_MARK_SWEEP_COMPACT) {
125         return Name.MARK_SWEEP_COMPACT;
126      } else if (value == NAME_CONCURRENT_MARK_SWEEP) {
127         return Name.CONCURRENT_MARK_SWEEP;
128      } else if (value == NAME_OTHER) {
129         return Name.OTHER;
130      } else {
131         throw new RuntimeException("should not reach here");
132      }
133   }
134 
135   public GenerationSpec spec() {
136     return ((GenCollectedHeap) VM.getVM().getUniverse().heap()).spec(level());
137   }
138 
139   public int level() {
140     return (int) levelField.getValue(addr);
141   }
142 
143   public int invocations() {
144     return getStatRecord().getInvocations();
145   }
146 
147   /** The maximum number of object bytes the generation can currently
148       hold. */
149   public abstract long capacity();
150 
151   /** The number of used bytes in the gen. */
152   public abstract long used();
153 
154   /** The number of free bytes in the gen. */
155   public abstract long free();
156 
157   /** The largest number of contiguous free words in the generation,
158       including expansion. (VM's version assumes it is called at a
159       safepoint.)  */
160   public abstract long contiguousAvailable();
161 
162   public MemRegion reserved() {
163     return new MemRegion(addr.addOffsetTo(reservedFieldOffset));
164   }
165 
166   /** Returns a region guaranteed to contain all the objects in the
167       generation. */
168   public MemRegion usedRegion() {
169     return reserved();
170   }
171 
172   /* Returns "TRUE" iff "p" points into an allocated object in the
173      generation. */
174   public boolean isIn(Address p) {
175     GenerationIsInClosure blk = new GenerationIsInClosure(p);
176     spaceIterate(blk);
177     return (blk.space() != null);
178   }
179 
180   /** Returns "TRUE" iff "p" points into the reserved area of the
181      generation. */
182   public boolean isInReserved(Address p) {
183     return reserved().contains(p);
184   }
185 
186   protected VirtualSpace virtualSpace() {
187     return (VirtualSpace) VMObjectFactory.newObject(VirtualSpace.class, addr.addOffsetTo(virtualSpaceFieldOffset));
188   }
189 
190   public abstract String name();
191 
192   /** Equivalent to spaceIterate(blk, false) */
193   public void spaceIterate(SpaceClosure blk) {
194     spaceIterate(blk, false);
195   }
196 
197   /** Iteration - do not use for time critical operations */
198   public abstract void spaceIterate(SpaceClosure blk, boolean usedOnly);
199 
200   public void print() { printOn(System.out); }
201   public abstract void printOn(PrintStream tty);
202 
203   public static class StatRecord extends VMObject {
204     public StatRecord(Address addr) {
205       super(addr);
206     }
207 
208     public int getInvocations() {
209       return (int) invocationField.getValue(addr);
210     }
211 
212   }
213 
214   private StatRecord getStatRecord() {
215     return (StatRecord) VMObjectFactory.newObject(Generation.StatRecord.class, addr.addOffsetTo(statRecordField.getOffset()));
216   }
217 }