View Javadoc
1   /*
2    * Copyright (c) 2000, 2013, 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.code;
26  
27  import java.io.*;
28  import java.util.*;
29  import sun.jvm.hotspot.debugger.*;
30  import sun.jvm.hotspot.memory.*;
31  import sun.jvm.hotspot.oops.*;
32  import sun.jvm.hotspot.runtime.*;
33  import sun.jvm.hotspot.types.*;
34  import sun.jvm.hotspot.utilities.*;
35  
36  public class NMethod extends CodeBlob {
37    private static long          pcDescSize;
38    private static AddressField  methodField;
39    /** != InvocationEntryBci if this nmethod is an on-stack replacement method */
40    private static CIntegerField entryBCIField;
41    /** To support simple linked-list chaining of nmethods */
42    private static AddressField  osrLinkField;
43    private static AddressField  scavengeRootLinkField;
44    private static JByteField    scavengeRootStateField;
45  
46    /** Offsets for different nmethod parts */
47    private static CIntegerField exceptionOffsetField;
48    private static CIntegerField deoptOffsetField;
49    private static CIntegerField deoptMhOffsetField;
50    private static CIntegerField origPCOffsetField;
51    private static CIntegerField stubOffsetField;
52    private static CIntegerField oopsOffsetField;
53    private static CIntegerField metadataOffsetField;
54    private static CIntegerField scopesDataOffsetField;
55    private static CIntegerField scopesPCsOffsetField;
56    private static CIntegerField dependenciesOffsetField;
57    private static CIntegerField handlerTableOffsetField;
58    private static CIntegerField nulChkTableOffsetField;
59    private static CIntegerField nmethodEndOffsetField;
60  
61    /** Offsets for entry points */
62    /** Entry point with class check */
63    private static AddressField  entryPointField;
64    /** Entry point without class check */
65    private static AddressField  verifiedEntryPointField;
66    /** Entry point for on stack replacement */
67    private static AddressField  osrEntryPointField;
68  
69    // FIXME: add access to flags (how?)
70  
71    /** NMethod Flushing lock (if non-zero, then the nmethod is not removed) */
72    private static JIntField     lockCountField;
73  
74    /** not_entrant method removal. Each mark_sweep pass will update
75        this mark to current sweep invocation count if it is seen on the
76        stack.  An not_entrant method can be removed when there is no
77        more activations, i.e., when the _stack_traversal_mark is less than
78        current sweep traversal index. */
79    private static CIntegerField stackTraversalMarkField;
80  
81    private static CIntegerField compLevelField;
82  
83    static {
84      VM.registerVMInitializedObserver(new Observer() {
85          public void update(Observable o, Object data) {
86            initialize(VM.getVM().getTypeDataBase());
87          }
88        });
89    }
90  
91    private static void initialize(TypeDataBase db) {
92      Type type = db.lookupType("nmethod");
93  
94      methodField                 = type.getAddressField("_method");
95      entryBCIField               = type.getCIntegerField("_entry_bci");
96      osrLinkField                = type.getAddressField("_osr_link");
97      scavengeRootLinkField       = type.getAddressField("_scavenge_root_link");
98      scavengeRootStateField      = type.getJByteField("_scavenge_root_state");
99  
100     exceptionOffsetField        = type.getCIntegerField("_exception_offset");
101     deoptOffsetField            = type.getCIntegerField("_deoptimize_offset");
102     deoptMhOffsetField          = type.getCIntegerField("_deoptimize_mh_offset");
103     origPCOffsetField           = type.getCIntegerField("_orig_pc_offset");
104     stubOffsetField             = type.getCIntegerField("_stub_offset");
105     oopsOffsetField             = type.getCIntegerField("_oops_offset");
106     metadataOffsetField         = type.getCIntegerField("_metadata_offset");
107     scopesDataOffsetField       = type.getCIntegerField("_scopes_data_offset");
108     scopesPCsOffsetField        = type.getCIntegerField("_scopes_pcs_offset");
109     dependenciesOffsetField     = type.getCIntegerField("_dependencies_offset");
110     handlerTableOffsetField     = type.getCIntegerField("_handler_table_offset");
111     nulChkTableOffsetField      = type.getCIntegerField("_nul_chk_table_offset");
112     nmethodEndOffsetField       = type.getCIntegerField("_nmethod_end_offset");
113     entryPointField             = type.getAddressField("_entry_point");
114     verifiedEntryPointField     = type.getAddressField("_verified_entry_point");
115     osrEntryPointField          = type.getAddressField("_osr_entry_point");
116     lockCountField              = type.getJIntField("_lock_count");
117     stackTraversalMarkField     = type.getCIntegerField("_stack_traversal_mark");
118     compLevelField              = type.getCIntegerField("_comp_level");
119     pcDescSize = db.lookupType("PcDesc").getSize();
120   }
121 
122   public NMethod(Address addr) {
123     super(addr);
124   }
125 
126 
127   // Accessors
128   public Address getAddress() {
129     return addr;
130   }
131 
132   public Method getMethod() {
133     return (Method)Metadata.instantiateWrapperFor(methodField.getValue(addr));
134   }
135 
136   // Type info
137   public boolean isNMethod()      { return true;                    }
138   public boolean isJavaMethod()   { return !getMethod().isNative(); }
139   public boolean isNativeMethod() { return getMethod().isNative();  }
140   public boolean isOSRMethod()    { return getEntryBCI() != VM.getVM().getInvocationEntryBCI(); }
141 
142   /** Boundaries for different parts */
143   public Address constantsBegin()       { return contentBegin();                                     }
144   public Address constantsEnd()         { return getEntryPoint();                                    }
145   public Address instsBegin()           { return codeBegin();                                        }
146   public Address instsEnd()             { return headerBegin().addOffsetTo(getStubOffset());         }
147   public Address exceptionBegin()       { return headerBegin().addOffsetTo(getExceptionOffset());    }
148   public Address deoptHandlerBegin()    { return headerBegin().addOffsetTo(getDeoptOffset());        }
149   public Address deoptMhHandlerBegin()  { return headerBegin().addOffsetTo(getDeoptMhOffset());      }
150   public Address stubBegin()            { return headerBegin().addOffsetTo(getStubOffset());         }
151   public Address stubEnd()              { return headerBegin().addOffsetTo(getOopsOffset());         }
152   public Address oopsBegin()            { return headerBegin().addOffsetTo(getOopsOffset());         }
153   public Address oopsEnd()              { return headerBegin().addOffsetTo(getMetadataOffset());     }
154   public Address metadataBegin()        { return headerBegin().addOffsetTo(getMetadataOffset());     }
155   public Address metadataEnd()          { return headerBegin().addOffsetTo(getScopesDataOffset());   }
156   public Address scopesDataBegin()      { return headerBegin().addOffsetTo(getScopesDataOffset());   }
157   public Address scopesDataEnd()        { return headerBegin().addOffsetTo(getScopesPCsOffset());    }
158   public Address scopesPCsBegin()       { return headerBegin().addOffsetTo(getScopesPCsOffset());    }
159   public Address scopesPCsEnd()         { return headerBegin().addOffsetTo(getDependenciesOffset()); }
160   public Address dependenciesBegin()    { return headerBegin().addOffsetTo(getDependenciesOffset()); }
161   public Address dependenciesEnd()      { return headerBegin().addOffsetTo(getHandlerTableOffset()); }
162   public Address handlerTableBegin()    { return headerBegin().addOffsetTo(getHandlerTableOffset()); }
163   public Address handlerTableEnd()      { return headerBegin().addOffsetTo(getNulChkTableOffset());  }
164   public Address nulChkTableBegin()     { return headerBegin().addOffsetTo(getNulChkTableOffset());  }
165   public Address nulChkTableEnd()       { return headerBegin().addOffsetTo(getNMethodEndOffset());   }
166 
167   public int constantsSize()            { return (int) constantsEnd()   .minus(constantsBegin());    }
168   public int instsSize()                { return (int) instsEnd()       .minus(instsBegin());        }
169   public int stubSize()                 { return (int) stubEnd()        .minus(stubBegin());         }
170   public int oopsSize()                 { return (int) oopsEnd()        .minus(oopsBegin());         }
171   public int metadataSize()             { return (int) metadataEnd()    .minus(metadataBegin());     }
172   public int scopesDataSize()           { return (int) scopesDataEnd()  .minus(scopesDataBegin());   }
173   public int scopesPCsSize()            { return (int) scopesPCsEnd()   .minus(scopesPCsBegin());    }
174   public int dependenciesSize()         { return (int) dependenciesEnd().minus(dependenciesBegin()); }
175   public int handlerTableSize()         { return (int) handlerTableEnd().minus(handlerTableBegin()); }
176   public int nulChkTableSize()          { return (int) nulChkTableEnd() .minus(nulChkTableBegin());  }
177   public int origPCOffset()             { return (int) origPCOffsetField.getValue(addr);             }
178 
179   public int totalSize() {
180     return
181       constantsSize()    +
182       instsSize()        +
183       stubSize()         +
184       scopesDataSize()   +
185       scopesPCsSize()    +
186       dependenciesSize() +
187       handlerTableSize() +
188       nulChkTableSize();
189   }
190 
191   public boolean constantsContains   (Address addr) { return constantsBegin()   .lessThanOrEqual(addr) && constantsEnd()   .greaterThan(addr); }
192   public boolean instsContains       (Address addr) { return instsBegin()       .lessThanOrEqual(addr) && instsEnd()       .greaterThan(addr); }
193   public boolean stubContains        (Address addr) { return stubBegin()        .lessThanOrEqual(addr) && stubEnd()        .greaterThan(addr); }
194   public boolean oopsContains        (Address addr) { return oopsBegin()        .lessThanOrEqual(addr) && oopsEnd()        .greaterThan(addr); }
195   public boolean metadataContains    (Address addr) { return metadataBegin()    .lessThanOrEqual(addr) && metadataEnd()    .greaterThan(addr); }
196   public boolean scopesDataContains  (Address addr) { return scopesDataBegin()  .lessThanOrEqual(addr) && scopesDataEnd()  .greaterThan(addr); }
197   public boolean scopesPCsContains   (Address addr) { return scopesPCsBegin()   .lessThanOrEqual(addr) && scopesPCsEnd()   .greaterThan(addr); }
198   public boolean handlerTableContains(Address addr) { return handlerTableBegin().lessThanOrEqual(addr) && handlerTableEnd().greaterThan(addr); }
199   public boolean nulChkTableContains (Address addr) { return nulChkTableBegin() .lessThanOrEqual(addr) && nulChkTableEnd() .greaterThan(addr); }
200 
201   public int getOopsLength() { return (int) (oopsSize() / VM.getVM().getOopSize()); }
202   public int getMetadataLength() { return (int) (metadataSize() / VM.getVM().getOopSize()); }
203 
204   /** Entry points */
205   public Address getEntryPoint()         { return entryPointField.getValue(addr);         }
206   public Address getVerifiedEntryPoint() { return verifiedEntryPointField.getValue(addr); }
207 
208   /** Support for oops in scopes and relocs. Note: index 0 is reserved for null. */
209   public OopHandle getOopAt(int index) {
210     if (index == 0) return null;
211     if (Assert.ASSERTS_ENABLED) {
212       Assert.that(index > 0 && index <= getOopsLength(), "must be a valid non-zero index");
213     }
214     return oopsBegin().getOopHandleAt((index - 1) * VM.getVM().getOopSize());
215   }
216 
217   /** Support for metadata in scopes and relocs. Note: index 0 is reserved for null. */
218   public Address getMetadataAt(int index) {
219     if (index == 0) return null;
220     if (Assert.ASSERTS_ENABLED) {
221       Assert.that(index > 0 && index <= getMetadataLength(), "must be a valid non-zero index");
222     }
223     return metadataBegin().getAddressAt((index - 1) * VM.getVM().getOopSize());
224   }
225 
226   public Method getMethodAt(int index) {
227     return (Method)Metadata.instantiateWrapperFor(getMetadataAt(index));
228   }
229 
230   // FIXME: add interpreter_entry_point()
231   // FIXME: add lazy_interpreter_entry_point() for C2
232 
233   // **********
234   // * FIXME: * ADD ACCESS TO FLAGS!!!!
235   // **********
236   // public boolean isInUse();
237   // public boolean isAlive();
238   // public boolean isNotEntrant();
239   // public boolean isZombie();
240 
241   // ********************************
242   // * MAJOR FIXME: MAJOR HACK HERE *
243   // ********************************
244   public boolean isZombie() { return false; }
245 
246   // public boolean isUnloaded();
247   // public boolean isYoung();
248   // public boolean isOld();
249   // public int     age();
250   // public boolean isMarkedForDeoptimization();
251   // public boolean isMarkedForUnloading();
252   // public boolean isMarkedForReclamation();
253   // public int     level();
254   // public int     version();
255 
256   // FIXME: add mutators for above
257   // FIXME: add exception cache access?
258 
259   /** On-stack replacement support */
260   // FIXME: add mutators
261   public int getOSREntryBCI() {
262     if (Assert.ASSERTS_ENABLED) {
263       Assert.that(getEntryBCI() != VM.getVM().getInvocationEntryBCI(), "wrong kind of nmethod");
264     }
265     return getEntryBCI();
266   }
267 
268   public NMethod getOSRLink() {
269     return (NMethod) VMObjectFactory.newObject(NMethod.class, osrLinkField.getValue(addr));
270   }
271 
272   public NMethod getScavengeRootLink() {
273     return (NMethod) VMObjectFactory.newObject(NMethod.class, scavengeRootLinkField.getValue(addr));
274   }
275 
276   public int getScavengeRootState() {
277     return (int) scavengeRootStateField.getValue(addr);
278   }
279 
280   // MethodHandle
281   public boolean isMethodHandleReturn(Address returnPc) {
282     // Hard to read a bit fields from Java and it's only there for performance
283     // so just go directly to the PCDesc
284     // if (!hasMethodHandleInvokes())  return false;
285     PCDesc pd = getPCDescAt(returnPc);
286     if (pd == null)
287       return false;
288     return pd.isMethodHandleInvoke();
289   }
290 
291   // Deopt
292   // Return true is the PC is one would expect if the frame is being deopted.
293   public boolean isDeoptPc      (Address pc) { return isDeoptEntry(pc) || isDeoptMhEntry(pc); }
294   public boolean isDeoptEntry   (Address pc) { return pc == deoptHandlerBegin(); }
295   public boolean isDeoptMhEntry (Address pc) { return pc == deoptMhHandlerBegin(); }
296 
297   /** Tells whether frames described by this nmethod can be
298       deoptimized. Note: native wrappers cannot be deoptimized. */
299   public boolean canBeDeoptimized() { return isJavaMethod(); }
300 
301   // FIXME: add inline cache support
302   // FIXME: add flush()
303 
304   public boolean isLockedByVM() { return lockCountField.getValue(addr) > 0; }
305 
306   // FIXME: add mark_as_seen_on_stack
307   // FIXME: add can_not_entrant_be_converted
308 
309   // FIXME: add GC support
310   //  void follow_roots_or_mark_for_unloading(bool unloading_occurred, bool& marked_for_unloading);
311   //  void follow_root_or_mark_for_unloading(oop* root, bool unloading_occurred, bool& marked_for_unloading);
312   //  void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, void f(oop*));
313   //  void adjust_pointers();
314 
315   /** Finds a PCDesc with real-pc equal to "pc" */
316   public PCDesc getPCDescAt(Address pc) {
317     // FIXME: consider adding cache like the one down in the VM
318     for (Address p = scopesPCsBegin(); p.lessThan(scopesPCsEnd()); p = p.addOffsetTo(pcDescSize)) {
319       PCDesc pcDesc = new PCDesc(p);
320       if (pcDesc.getRealPC(this).equals(pc)) {
321         return pcDesc;
322       }
323     }
324     return null;
325   }
326 
327   /** ScopeDesc for an instruction */
328   public ScopeDesc getScopeDescAt(Address pc) {
329     PCDesc pd = getPCDescAt(pc);
330     if (Assert.ASSERTS_ENABLED) {
331       Assert.that(pd != null, "scope must be present");
332     }
333     return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getObjDecodeOffset(), pd.getReexecute());
334   }
335 
336   /** This is only for use by the debugging system, and is only
337       intended for use in the topmost frame, where we are not
338       guaranteed to be at a PC for which we have a PCDesc. It finds
339       the PCDesc with realPC closest to the current PC. */
340   public PCDesc getPCDescNearDbg(Address pc) {
341     PCDesc bestGuessPCDesc = null;
342     long bestDistance = 0;
343     for (Address p = scopesPCsBegin(); p.lessThan(scopesPCsEnd()); p = p.addOffsetTo(pcDescSize)) {
344       PCDesc pcDesc = new PCDesc(p);
345       // In case pc is null
346       long distance = -pcDesc.getRealPC(this).minus(pc);
347       if ((bestGuessPCDesc == null) ||
348           ((distance >= 0) && (distance < bestDistance))) {
349         bestGuessPCDesc = pcDesc;
350         bestDistance    = distance;
351       }
352     }
353     return bestGuessPCDesc;
354   }
355 
356   PCDesc find_pc_desc(long pc, boolean approximate) {
357     return find_pc_desc_internal(pc, approximate);
358   }
359 
360   // Finds a PcDesc with real-pc equal to "pc"
361   PCDesc find_pc_desc_internal(long pc, boolean approximate) {
362     long base_address = VM.getAddressValue(codeBegin());
363     int pc_offset = (int) (pc - base_address);
364 
365     // Fallback algorithm: quasi-linear search for the PcDesc
366     // Find the last pc_offset less than the given offset.
367     // The successor must be the required match, if there is a match at all.
368     // (Use a fixed radix to avoid expensive affine pointer arithmetic.)
369     Address lower = scopesPCsBegin();
370     Address upper = scopesPCsEnd();
371     upper = upper.addOffsetTo(-pcDescSize); // exclude final sentinel
372     if (lower.greaterThan(upper))  return null;  // native method; no PcDescs at all
373 
374     // Take giant steps at first (4096, then 256, then 16, then 1)
375     int LOG2_RADIX = 4;
376     int RADIX = (1 << LOG2_RADIX);
377     Address mid;
378     for (int step = (1 << (LOG2_RADIX*3)); step > 1; step >>= LOG2_RADIX) {
379       while ((mid = lower.addOffsetTo(step * pcDescSize)).lessThan(upper)) {
380         PCDesc m = new PCDesc(mid);
381         if (m.getPCOffset() < pc_offset) {
382           lower = mid;
383         } else {
384           upper = mid;
385           break;
386         }
387       }
388     }
389     // Sneak up on the value with a linear search of length ~16.
390     while (true) {
391       mid = lower.addOffsetTo(pcDescSize);
392       PCDesc m = new PCDesc(mid);
393       if (m.getPCOffset() < pc_offset) {
394         lower = mid;
395       } else {
396         upper = mid;
397         break;
398       }
399     }
400 
401     PCDesc u = new PCDesc(upper);
402     if (match_desc(u, pc_offset, approximate)) {
403       return u;
404     } else {
405       return null;
406     }
407   }
408 
409   // ScopeDesc retrieval operation
410   PCDesc pc_desc_at(long pc)   { return find_pc_desc(pc, false); }
411   // pc_desc_near returns the first PCDesc at or after the givne pc.
412   PCDesc pc_desc_near(long pc) { return find_pc_desc(pc, true); }
413 
414   // Return a the last scope in (begin..end]
415   public ScopeDesc scope_desc_in(long begin, long end) {
416     PCDesc p = pc_desc_near(begin+1);
417     if (p != null && VM.getAddressValue(p.getRealPC(this)) <= end) {
418       return new ScopeDesc(this, p.getScopeDecodeOffset(), p.getObjDecodeOffset(), p.getReexecute());
419     }
420     return null;
421   }
422 
423   static boolean match_desc(PCDesc pc, int pc_offset, boolean approximate) {
424     if (!approximate) {
425       return pc.getPCOffset() == pc_offset;
426     } else {
427       PCDesc prev = new PCDesc(pc.getAddress().addOffsetTo(-pcDescSize));
428        return prev.getPCOffset() < pc_offset && pc_offset <= pc.getPCOffset();
429     }
430   }
431 
432   /** This is only for use by the debugging system, and is only
433       intended for use in the topmost frame, where we are not
434       guaranteed to be at a PC for which we have a PCDesc. It finds
435       the ScopeDesc closest to the current PC. NOTE that this may
436       return NULL for compiled methods which don't have any
437       ScopeDescs! */
438   public ScopeDesc getScopeDescNearDbg(Address pc) {
439     PCDesc pd = getPCDescNearDbg(pc);
440     if (pd == null) return null;
441     return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getObjDecodeOffset(), pd.getReexecute());
442   }
443 
444   public Map/*<Address, PCDesc>*/ getSafepoints() {
445     Map safepoints = new HashMap(); // Map<Address, PCDesc>
446     sun.jvm.hotspot.debugger.Address p = null;
447     for (p = scopesPCsBegin(); p.lessThan(scopesPCsEnd());
448          p = p.addOffsetTo(pcDescSize)) {
449        PCDesc pcDesc = new PCDesc(p);
450        sun.jvm.hotspot.debugger.Address pc = pcDesc.getRealPC(this);
451        safepoints.put(pc, pcDesc);
452     }
453     return safepoints;
454   }
455 
456   // FIXME: add getPCOffsetForBCI()
457   // FIXME: add embeddedOopAt()
458   // FIXME: add isDependentOn()
459   // FIXME: add isPatchableAt()
460 
461   /** Support for code generation. Only here for proof-of-concept. */
462   public static int getEntryPointOffset()            { return (int) entryPointField.getOffset();            }
463   public static int getVerifiedEntryPointOffset()    { return (int) verifiedEntryPointField.getOffset();    }
464   public static int getOSREntryPointOffset()         { return (int) osrEntryPointField.getOffset();         }
465   public static int getEntryBCIOffset()              { return (int) entryBCIField.getOffset();              }
466   /** NOTE: renamed from "method_offset_in_bytes" */
467   public static int getMethodOffset()                { return (int) methodField.getOffset();                }
468 
469   public void print() {
470     printOn(System.out);
471   }
472 
473   protected void printComponentsOn(PrintStream tty) {
474     // FIXME: add relocation information
475     tty.println(" content: [" + contentBegin() + ", " + contentEnd() + "), " +
476                 " code: [" + codeBegin() + ", " + codeEnd() + "), " +
477                 " data: [" + dataBegin() + ", " + dataEnd() + "), " +
478                 " oops: [" + oopsBegin() + ", " + oopsEnd() + "), " +
479                 " frame size: " + getFrameSize());
480   }
481 
482   public String toString() {
483     Method method = getMethod();
484     return "NMethod for " +
485             method.getMethodHolder().getName().asString() + "." +
486             method.getName().asString() + method.getSignature().asString() + "==>n" +
487             super.toString();
488   }
489 
490   public String flagsToString() {
491     // FIXME need access to flags...
492     return "";
493   }
494 
495   public String getName() {
496     Method method = getMethod();
497     return "NMethod for " +
498            method.getMethodHolder().getName().asString() + "." +
499            method.getName().asString() +
500            method.getSignature().asString();
501   }
502 
503   public void dumpReplayData(PrintStream out) {
504     HashMap h = new HashMap();
505     for (int i = 1; i < getMetadataLength(); i++) {
506       Metadata meta = Metadata.instantiateWrapperFor(getMetadataAt(i));
507       System.err.println(meta);
508       if (h.get(meta) != null) continue;
509       h.put(meta, meta);
510       if (meta instanceof InstanceKlass) {
511         ((InstanceKlass)meta).dumpReplayData(out);
512       } else if (meta instanceof Method) {
513         ((Method)meta).dumpReplayData(out);
514         MethodData mdo = ((Method)meta).getMethodData();
515         if (mdo != null) {
516           mdo.dumpReplayData(out);
517         }
518       }
519     }
520     Method method = getMethod();
521     if (h.get(method) == null) {
522       method.dumpReplayData(out);
523       MethodData mdo = method.getMethodData();
524       if (mdo != null) {
525         mdo.dumpReplayData(out);
526       }
527     }
528     if (h.get(method.getMethodHolder()) == null) {
529       ((InstanceKlass)method.getMethodHolder()).dumpReplayData(out);
530     }
531     Klass holder = method.getMethodHolder();
532     out.println("compile " + holder.getName().asString() + " " +
533                 OopUtilities.escapeString(method.getName().asString()) + " " +
534                 method.getSignature().asString() + " " +
535                 getEntryBCI() + " " + getCompLevel());
536 
537   }
538 
539   //--------------------------------------------------------------------------------
540   // Internals only below this point
541   //
542 
543   private int getEntryBCI()           { return (int) entryBCIField          .getValue(addr); }
544   private int getExceptionOffset()    { return (int) exceptionOffsetField   .getValue(addr); }
545   private int getDeoptOffset()        { return (int) deoptOffsetField       .getValue(addr); }
546   private int getDeoptMhOffset()      { return (int) deoptMhOffsetField     .getValue(addr); }
547   private int getStubOffset()         { return (int) stubOffsetField        .getValue(addr); }
548   private int getOopsOffset()         { return (int) oopsOffsetField        .getValue(addr); }
549   private int getMetadataOffset()     { return (int) metadataOffsetField    .getValue(addr); }
550   private int getScopesDataOffset()   { return (int) scopesDataOffsetField  .getValue(addr); }
551   private int getScopesPCsOffset()    { return (int) scopesPCsOffsetField   .getValue(addr); }
552   private int getDependenciesOffset() { return (int) dependenciesOffsetField.getValue(addr); }
553   private int getHandlerTableOffset() { return (int) handlerTableOffsetField.getValue(addr); }
554   private int getNulChkTableOffset()  { return (int) nulChkTableOffsetField .getValue(addr); }
555   private int getNMethodEndOffset()   { return (int) nmethodEndOffsetField  .getValue(addr); }
556   private int getCompLevel()          { return (int) compLevelField         .getValue(addr); }
557 }