6951083: oops and relocations should part of nmethod not CodeBlob
authortwisti
Thu, 20 May 2010 06:34:23 -0700
changeset 5686 5435e77aa3df
parent 5539 261ecc5bb65e
child 5687 b862d1f189bd
6951083: oops and relocations should part of nmethod not CodeBlob Summary: This moves the oops from Codeblob to nmethod. Reviewed-by: kvn, never
hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java
hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java
hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java
hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp
hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp
hotspot/src/os/solaris/dtrace/libjvm_db.c
hotspot/src/share/vm/asm/codeBuffer.hpp
hotspot/src/share/vm/code/codeBlob.cpp
hotspot/src/share/vm/code/codeBlob.hpp
hotspot/src/share/vm/code/codeCache.cpp
hotspot/src/share/vm/code/compiledIC.cpp
hotspot/src/share/vm/code/nmethod.cpp
hotspot/src/share/vm/code/nmethod.hpp
hotspot/src/share/vm/code/oopRecorder.cpp
hotspot/src/share/vm/code/oopRecorder.hpp
hotspot/src/share/vm/code/relocInfo.cpp
hotspot/src/share/vm/code/relocInfo.hpp
hotspot/src/share/vm/memory/iterator.cpp
hotspot/src/share/vm/runtime/sharedRuntime.cpp
hotspot/src/share/vm/runtime/vmStructs.cpp
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java	Thu May 20 06:34:23 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,8 +42,6 @@
   private static CIntegerField instructionsOffsetField;
   private static CIntegerField frameCompleteOffsetField;
   private static CIntegerField dataOffsetField;
-  private static CIntegerField oopsOffsetField;
-  private static CIntegerField oopsLengthField;
   private static CIntegerField frameSizeField;
   private static AddressField  oopMapsField;
 
@@ -72,8 +70,6 @@
     frameCompleteOffsetField = type.getCIntegerField("_frame_complete_offset");
     instructionsOffsetField  = type.getCIntegerField("_instructions_offset");
     dataOffsetField          = type.getCIntegerField("_data_offset");
-    oopsOffsetField          = type.getCIntegerField("_oops_offset");
-    oopsLengthField          = type.getCIntegerField("_oops_length");
     frameSizeField           = type.getCIntegerField("_frame_size");
     oopMapsField             = type.getAddressField("_oop_maps");
 
@@ -131,19 +127,10 @@
     return headerBegin().addOffsetTo(sizeField.getValue(addr));
   }
 
-  public Address oopsBegin() {
-    return headerBegin().addOffsetTo(oopsOffsetField.getValue(addr));
-  }
-
-  public Address oopsEnd() {
-    return oopsBegin().addOffsetTo(getOopsLength());
-  }
-
   // Offsets
   public int getRelocationOffset()   { return (int) headerSizeField.getValue(addr);         }
   public int getInstructionsOffset() { return (int) instructionsOffsetField.getValue(addr); }
   public int getDataOffset()         { return (int) dataOffsetField.getValue(addr);         }
-  public int getOopsOffset()         { return (int) oopsOffsetField.getValue(addr);         }
 
   // Sizes
   public int getSize()             { return (int) sizeField.getValue(addr);                     }
@@ -157,19 +144,9 @@
   // FIXME: add relocationContains
   public boolean instructionsContains(Address addr) { return instructionsBegin().lessThanOrEqual(addr) && instructionsEnd().greaterThan(addr); }
   public boolean dataContains(Address addr)         { return dataBegin().lessThanOrEqual(addr) && dataEnd().greaterThan(addr);                 }
-  public boolean oopsContains(Address addr)         { return oopsBegin().lessThanOrEqual(addr) && oopsEnd().greaterThan(addr);                 }
   public boolean contains(Address addr)             { return instructionsContains(addr);                                                       }
   public boolean isFrameCompleteAt(Address a)       { return instructionsContains(a) && a.minus(instructionsBegin()) >= frameCompleteOffsetField.getValue(addr); }
 
-  /** Support for oops in scopes and relocs. Note: index 0 is reserved for null. */
-  public OopHandle getOopAt(int index) {
-    if (index == 0) return null;
-    if (Assert.ASSERTS_ENABLED) {
-      Assert.that(index > 0 && index <= getOopsLength(), "must be a valid non-zero index");
-    }
-    return oopsBegin().getOopHandleAt((index - 1) * VM.getVM().getOopSize());
-  }
-
   // Reclamation support (really only used by the nmethods, but in order to get asserts to work
   // in the CodeCache they are defined virtual here)
   public boolean isZombie()             { return false; }
@@ -223,18 +200,8 @@
   }
 
   protected void printComponentsOn(PrintStream tty) {
-    // FIXME: add relocation information
     tty.println(" instructions: [" + instructionsBegin() + ", " + instructionsEnd() + "), " +
                 " data: [" + dataBegin() + ", " + dataEnd() + "), " +
-                " oops: [" + oopsBegin() + ", " + oopsEnd() + "), " +
                 " frame size: " + getFrameSize());
   }
-
-  //--------------------------------------------------------------------------------
-  // Internals only below this point
-  //
-
-  private int getOopsLength() {
-    return (int) oopsLengthField.getValue(addr);
-  }
 }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java	Thu May 20 06:34:23 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,6 +49,7 @@
   private static CIntegerField deoptOffsetField;
   private static CIntegerField origPCOffsetField;
   private static CIntegerField stubOffsetField;
+  private static CIntegerField oopsOffsetField;
   private static CIntegerField scopesDataOffsetField;
   private static CIntegerField scopesPCsOffsetField;
   private static CIntegerField dependenciesOffsetField;
@@ -98,6 +99,7 @@
     deoptOffsetField            = type.getCIntegerField("_deoptimize_offset");
     origPCOffsetField           = type.getCIntegerField("_orig_pc_offset");
     stubOffsetField             = type.getCIntegerField("_stub_offset");
+    oopsOffsetField             = type.getCIntegerField("_oops_offset");
     scopesDataOffsetField       = type.getCIntegerField("_scopes_data_offset");
     scopesPCsOffsetField        = type.getCIntegerField("_scopes_pcs_offset");
     dependenciesOffsetField     = type.getCIntegerField("_dependencies_offset");
@@ -141,7 +143,9 @@
   public Address exceptionBegin()       { return headerBegin().addOffsetTo(getExceptionOffset());    }
   public Address deoptBegin()           { return headerBegin().addOffsetTo(getDeoptOffset());        }
   public Address stubBegin()            { return headerBegin().addOffsetTo(getStubOffset());         }
-  public Address stubEnd()              { return headerBegin().addOffsetTo(getScopesDataOffset());   }
+  public Address stubEnd()              { return headerBegin().addOffsetTo(getOopsOffset());         }
+  public Address oopsBegin()            { return headerBegin().addOffsetTo(getOopsOffset());         }
+  public Address oopsEnd()              { return headerBegin().addOffsetTo(getScopesDataOffset());   }
   public Address scopesDataBegin()      { return headerBegin().addOffsetTo(getScopesDataOffset());   }
   public Address scopesDataEnd()        { return headerBegin().addOffsetTo(getScopesPCsOffset());    }
   public Address scopesPCsBegin()       { return headerBegin().addOffsetTo(getScopesPCsOffset());    }
@@ -156,6 +160,7 @@
   public int constantsSize()            { return (int) constantsEnd()   .minus(constantsBegin());    }
   public int codeSize()                 { return (int) codeEnd()        .minus(codeBegin());         }
   public int stubSize()                 { return (int) stubEnd()        .minus(stubBegin());         }
+  public int oopsSize()                 { return (int) oopsEnd()        .minus(oopsBegin());         }
   public int scopesDataSize()           { return (int) scopesDataEnd()  .minus(scopesDataBegin());   }
   public int scopesPCsSize()            { return (int) scopesPCsEnd()   .minus(scopesPCsBegin());    }
   public int dependenciesSize()         { return (int) dependenciesEnd().minus(dependenciesBegin()); }
@@ -178,6 +183,7 @@
   public boolean constantsContains   (Address addr) { return constantsBegin()   .lessThanOrEqual(addr) && constantsEnd()   .greaterThan(addr); }
   public boolean codeContains        (Address addr) { return codeBegin()        .lessThanOrEqual(addr) && codeEnd()        .greaterThan(addr); }
   public boolean stubContains        (Address addr) { return stubBegin()        .lessThanOrEqual(addr) && stubEnd()        .greaterThan(addr); }
+  public boolean oopsContains        (Address addr) { return oopsBegin()        .lessThanOrEqual(addr) && oopsEnd()        .greaterThan(addr); }
   public boolean scopesDataContains  (Address addr) { return scopesDataBegin()  .lessThanOrEqual(addr) && scopesDataEnd()  .greaterThan(addr); }
   public boolean scopesPCsContains   (Address addr) { return scopesPCsBegin()   .lessThanOrEqual(addr) && scopesPCsEnd()   .greaterThan(addr); }
   public boolean handlerTableContains(Address addr) { return handlerTableBegin().lessThanOrEqual(addr) && handlerTableEnd().greaterThan(addr); }
@@ -187,6 +193,15 @@
   public Address getEntryPoint()         { return entryPointField.getValue(addr);         }
   public Address getVerifiedEntryPoint() { return verifiedEntryPointField.getValue(addr); }
 
+  /** Support for oops in scopes and relocs. Note: index 0 is reserved for null. */
+  public OopHandle getOopAt(int index) {
+    if (index == 0) return null;
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(index > 0 && index <= oopsSize(), "must be a valid non-zero index");
+    }
+    return oopsBegin().getOopHandleAt((index - 1) * VM.getVM().getOopSize());
+  }
+
   // FIXME: add interpreter_entry_point()
   // FIXME: add lazy_interpreter_entry_point() for C2
 
@@ -338,6 +353,14 @@
     printOn(System.out);
   }
 
+  protected void printComponentsOn(PrintStream tty) {
+    // FIXME: add relocation information
+    tty.println(" instructions: [" + instructionsBegin() + ", " + instructionsEnd() + "), " +
+                " data: [" + dataBegin() + ", " + dataEnd() + "), " +
+                " oops: [" + oopsBegin() + ", " + oopsEnd() + "), " +
+                " frame size: " + getFrameSize());
+  }
+
   public String toString() {
     Method method = getMethod();
     return "NMethod for " +
@@ -367,6 +390,7 @@
   private int getExceptionOffset()    { return (int) exceptionOffsetField   .getValue(addr); }
   private int getDeoptOffset()        { return (int) deoptOffsetField       .getValue(addr); }
   private int getStubOffset()         { return (int) stubOffsetField        .getValue(addr); }
+  private int getOopsOffset()         { return (int) oopsOffsetField        .getValue(addr); }
   private int getScopesDataOffset()   { return (int) scopesDataOffsetField  .getValue(addr); }
   private int getScopesPCsOffset()    { return (int) scopesPCsOffsetField   .getValue(addr); }
   private int getDependenciesOffset() { return (int) dependenciesOffsetField.getValue(addr); }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java	Thu May 20 06:34:23 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2004 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -98,7 +98,12 @@
         }
         loc.inBlobInstructions = loc.blob.instructionsContains(a);
         loc.inBlobData         = loc.blob.dataContains(a);
-        loc.inBlobOops         = loc.blob.oopsContains(a);
+
+        if (loc.blob.isNMethod()) {
+            NMethod nm = (NMethod) loc.blob;
+            loc.inBlobOops = nm.oopsContains(a);
+        }
+
         loc.inBlobUnknownLocation = (!(loc.inBlobInstructions ||
                                        loc.inBlobData ||
                                        loc.inBlobOops));
--- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp	Thu May 20 06:34:23 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -321,7 +321,8 @@
   set_long_at(add_offset,   set_data32_simm13( long_at(add_offset),   x));
 
   // also store the value into an oop_Relocation cell, if any
-  CodeBlob* nm = CodeCache::find_blob(instruction_address());
+  CodeBlob* cb = CodeCache::find_blob(instruction_address());
+  nmethod*  nm = cb ? cb->as_nmethod_or_null() : NULL;
   if (nm != NULL) {
     RelocIterator iter(nm, instruction_address(), next_instruction_address());
     oop* oop_addr = NULL;
@@ -430,7 +431,8 @@
   set_long_at(add_offset, set_data32_simm13(long_at(add_offset), x));
 
   // also store the value into an oop_Relocation cell, if any
-  CodeBlob* nm = CodeCache::find_blob(instruction_address());
+  CodeBlob* cb = CodeCache::find_blob(instruction_address());
+  nmethod*  nm = cb ? cb->as_nmethod_or_null() : NULL;
   if (nm != NULL) {
     RelocIterator iter(nm, instruction_address(), next_instruction_address());
     oop* oop_addr = NULL;
--- a/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp	Thu May 20 06:34:23 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -232,12 +232,11 @@
   GEN_OFFS(CodeBlob, _header_size);
   GEN_OFFS(CodeBlob, _instructions_offset);
   GEN_OFFS(CodeBlob, _data_offset);
-  GEN_OFFS(CodeBlob, _oops_offset);
-  GEN_OFFS(CodeBlob, _oops_length);
   GEN_OFFS(CodeBlob, _frame_size);
   printf("\n");
 
   GEN_OFFS(nmethod, _method);
+  GEN_OFFS(nmethod, _oops_offset);
   GEN_OFFS(nmethod, _scopes_data_offset);
   GEN_OFFS(nmethod, _scopes_pcs_offset);
   GEN_OFFS(nmethod, _handler_table_offset);
--- a/hotspot/src/os/solaris/dtrace/libjvm_db.c	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c	Thu May 20 06:34:23 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -130,7 +130,7 @@
   int32_t  scopes_data_beg;     /* _scopes_data_offset */
   int32_t  scopes_data_end;
   int32_t  oops_beg;            /* _oops_offset */
-  int32_t  oops_len;            /* _oops_length */
+  int32_t  oops_end;
   int32_t  scopes_pcs_beg;      /* _scopes_pcs_offset */
   int32_t  scopes_pcs_end;
 
@@ -597,9 +597,9 @@
   CHECK_FAIL(err);
 
   /* Oops */
-  err = ps_pread(J->P, nm + OFFSET_CodeBlob_oops_offset, &N->oops_beg, SZ32);
+  err = ps_pread(J->P, nm + OFFSET_nmethod_oops_offset, &N->oops_beg, SZ32);
   CHECK_FAIL(err);
-  err = ps_pread(J->P, nm + OFFSET_CodeBlob_oops_length, &N->oops_len, SZ32);
+  err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->oops_end, SZ32);
   CHECK_FAIL(err);
 
   /* scopes_pcs */
@@ -624,8 +624,8 @@
       fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n",
                        N->orig_pc_offset);
 
-      fprintf(stderr, "\t nmethod_info: oops_beg: %#x, oops_len: %#x\n",
-                       N->oops_beg, N->oops_len);
+      fprintf(stderr, "\t nmethod_info: oops_beg: %#x, oops_end: %#x\n",
+                       N->oops_beg, N->oops_end);
 
       fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n",
                        N->scopes_data_beg, N->scopes_data_end);
@@ -959,8 +959,8 @@
     err = scope_desc_at(N, decode_offset, vf);
     CHECK_FAIL(err);
 
-    if (vf->methodIdx > N->oops_len) {
-      fprintf(stderr, "\t scopeDesc_chain: (methodIdx > oops_len) !\n");
+    if (vf->methodIdx > ((N->oops_end - N->oops_beg) / POINTER_SIZE)) {
+      fprintf(stderr, "\t scopeDesc_chain: (methodIdx > oops length) !\n");
       return -1;
     }
     err = read_pointer(N->J, N->nm + N->oops_beg + (vf->methodIdx-1)*POINTER_SIZE,
--- a/hotspot/src/share/vm/asm/codeBuffer.hpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/asm/codeBuffer.hpp	Thu May 20 06:34:23 2010 -0700
@@ -510,9 +510,9 @@
     copy_relocations_to(blob);
     copy_code_to(blob);
   }
-  void copy_oops_to(CodeBlob* blob) {
+  void copy_oops_to(nmethod* nm) {
     if (!oop_recorder()->is_unused()) {
-      oop_recorder()->copy_to(blob);
+      oop_recorder()->copy_to(nm);
     }
   }
 
--- a/hotspot/src/share/vm/code/codeBlob.cpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/code/codeBlob.cpp	Thu May 20 06:34:23 2010 -0700
@@ -66,8 +66,6 @@
   _relocation_size       = locs_size;
   _instructions_offset   = align_code_offset(header_size + locs_size);
   _data_offset           = size;
-  _oops_offset           = size;
-  _oops_length           =  0;
   _frame_size            =  0;
   set_oop_maps(NULL);
 }
@@ -94,9 +92,6 @@
   _relocation_size       = round_to(cb->total_relocation_size(), oopSize);
   _instructions_offset   = align_code_offset(header_size + _relocation_size);
   _data_offset           = _instructions_offset + round_to(cb->total_code_size(), oopSize);
-  _oops_offset           = _size - round_to(cb->total_oop_size(), oopSize);
-  _oops_length           = 0;  // temporary, until the copy_oops handshake
-  assert(_oops_offset >=   _data_offset, "codeBlob is too small");
   assert(_data_offset <= size, "codeBlob is too small");
 
   cb->copy_code_and_locs_to(this);
@@ -131,99 +126,6 @@
 }
 
 
-// Promote one word from an assembly-time handle to a live embedded oop.
-inline void CodeBlob::initialize_immediate_oop(oop* dest, jobject handle) {
-  if (handle == NULL ||
-      // As a special case, IC oops are initialized to 1 or -1.
-      handle == (jobject) Universe::non_oop_word()) {
-    (*dest) = (oop)handle;
-  } else {
-    (*dest) = JNIHandles::resolve_non_null(handle);
-  }
-}
-
-
-void CodeBlob::copy_oops(GrowableArray<jobject>* array) {
-  assert(_oops_length == 0, "do this handshake just once, please");
-  int length = array->length();
-  assert((address)(oops_begin() + length) <= data_end(), "oops big enough");
-  oop* dest = oops_begin();
-  for (int index = 0 ; index < length; index++) {
-    initialize_immediate_oop(&dest[index], array->at(index));
-  }
-  _oops_length = length;
-
-  // Now we can fix up all the oops in the code.
-  // We need to do this in the code because
-  // the assembler uses jobjects as placeholders.
-  // The code and relocations have already been
-  // initialized by the CodeBlob constructor,
-  // so it is valid even at this early point to
-  // iterate over relocations and patch the code.
-  fix_oop_relocations(NULL, NULL, /*initialize_immediates=*/ true);
-}
-
-
-relocInfo::relocType CodeBlob::reloc_type_for_address(address pc) {
-  RelocIterator iter(this, pc, pc+1);
-  while (iter.next()) {
-    return (relocInfo::relocType) iter.type();
-  }
-  // No relocation info found for pc
-  ShouldNotReachHere();
-  return relocInfo::none; // dummy return value
-}
-
-
-bool CodeBlob::is_at_poll_return(address pc) {
-  RelocIterator iter(this, pc, pc+1);
-  while (iter.next()) {
-    if (iter.type() == relocInfo::poll_return_type)
-      return true;
-  }
-  return false;
-}
-
-
-bool CodeBlob::is_at_poll_or_poll_return(address pc) {
-  RelocIterator iter(this, pc, pc+1);
-  while (iter.next()) {
-    relocInfo::relocType t = iter.type();
-    if (t == relocInfo::poll_return_type || t == relocInfo::poll_type)
-      return true;
-  }
-  return false;
-}
-
-
-void CodeBlob::fix_oop_relocations(address begin, address end,
-                                   bool initialize_immediates) {
-  // re-patch all oop-bearing instructions, just in case some oops moved
-  RelocIterator iter(this, begin, end);
-  while (iter.next()) {
-    if (iter.type() == relocInfo::oop_type) {
-      oop_Relocation* reloc = iter.oop_reloc();
-      if (initialize_immediates && reloc->oop_is_immediate()) {
-        oop* dest = reloc->oop_addr();
-        initialize_immediate_oop(dest, (jobject) *dest);
-      }
-      // Refresh the oop-related bits of this instruction.
-      reloc->fix_oop_relocation();
-    }
-
-    // There must not be any interfering patches or breakpoints.
-    assert(!(iter.type() == relocInfo::breakpoint_type
-             && iter.breakpoint_reloc()->active()),
-           "no active breakpoint");
-  }
-}
-
-void CodeBlob::do_unloading(BoolObjectClosure* is_alive,
-                            OopClosure* keep_alive,
-                            bool unloading_occurred) {
-  ShouldNotReachHere();
-}
-
 OopMap* CodeBlob::oop_map_for_return_address(address return_address) {
   address pc = return_address ;
   assert (oop_maps() != NULL, "nope");
--- a/hotspot/src/share/vm/code/codeBlob.hpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/code/codeBlob.hpp	Thu May 20 06:34:23 2010 -0700
@@ -54,17 +54,12 @@
                                                  // that range. There is a similar range(s) on returns
                                                  // which we don't detect.
   int        _data_offset;                       // offset to where data region begins
-  int        _oops_offset;                       // offset to where embedded oop table begins (inside data)
-  int        _oops_length;                       // number of embedded oops
   int        _frame_size;                        // size of stack frame
   OopMapSet* _oop_maps;                          // OopMap for this CodeBlob
   CodeComments _comments;
 
   friend class OopRecorder;
 
-  void fix_oop_relocations(address begin, address end, bool initialize_immediates);
-  inline void initialize_immediate_oop(oop* dest, jobject handle);
-
  public:
   // Returns the space needed for CodeBlob
   static unsigned int allocation_size(CodeBuffer* cb, int header_size);
@@ -115,14 +110,11 @@
   address    instructions_end() const            { return (address)    header_begin() + _data_offset; }
   address    data_begin() const                  { return (address)    header_begin() + _data_offset; }
   address    data_end() const                    { return (address)    header_begin() + _size; }
-  oop*       oops_begin() const                  { return (oop*)      (header_begin() + _oops_offset); }
-  oop*       oops_end() const                    { return                oops_begin() + _oops_length; }
 
   // Offsets
   int relocation_offset() const                  { return _header_size; }
   int instructions_offset() const                { return _instructions_offset; }
   int data_offset() const                        { return _data_offset; }
-  int oops_offset() const                        { return _oops_offset; }
 
   // Sizes
   int size() const                               { return _size; }
@@ -130,40 +122,16 @@
   int relocation_size() const                    { return (address) relocation_end() - (address) relocation_begin(); }
   int instructions_size() const                  { return instructions_end() - instructions_begin();  }
   int data_size() const                          { return data_end() - data_begin(); }
-  int oops_size() const                          { return (address) oops_end() - (address) oops_begin(); }
 
   // Containment
   bool blob_contains(address addr) const         { return header_begin()       <= addr && addr < data_end(); }
   bool relocation_contains(relocInfo* addr) const{ return relocation_begin()   <= addr && addr < relocation_end(); }
   bool instructions_contains(address addr) const { return instructions_begin() <= addr && addr < instructions_end(); }
   bool data_contains(address addr) const         { return data_begin()         <= addr && addr < data_end(); }
-  bool oops_contains(oop* addr) const            { return oops_begin()         <= addr && addr < oops_end(); }
   bool contains(address addr) const              { return instructions_contains(addr); }
   bool is_frame_complete_at(address addr) const  { return instructions_contains(addr) &&
                                                           addr >= instructions_begin() + _frame_complete_offset; }
 
-  // Relocation support
-  void fix_oop_relocations(address begin, address end) {
-    fix_oop_relocations(begin, end, false);
-  }
-  void fix_oop_relocations() {
-    fix_oop_relocations(NULL, NULL, false);
-  }
-  relocInfo::relocType reloc_type_for_address(address pc);
-  bool is_at_poll_return(address pc);
-  bool is_at_poll_or_poll_return(address pc);
-
-  // Support for oops in scopes and relocs:
-  // Note: index 0 is reserved for null.
-  oop  oop_at(int index) const                   { return index == 0? (oop)NULL: *oop_addr_at(index); }
-  oop* oop_addr_at(int index) const{             // for GC
-    // relocation indexes are biased by 1 (because 0 is reserved)
-    assert(index > 0 && index <= _oops_length, "must be a valid non-zero index");
-    return &oops_begin()[index-1];
-  }
-
-  void copy_oops(GrowableArray<jobject>* oops);
-
   // CodeCache support: really only used by the nmethods, but in order to get
   // asserts and certain bookkeeping to work in the CodeCache they are defined
   // virtual here.
@@ -175,12 +143,6 @@
 
   // GC support
   virtual bool is_alive() const                  = 0;
-  virtual void do_unloading(BoolObjectClosure* is_alive,
-                            OopClosure* keep_alive,
-                            bool unloading_occurred);
-  virtual void oops_do(OopClosure* f) = 0;
-  // (All CodeBlob subtypes other than NMethod currently have
-  // an empty oops_do() method.
 
   // OopMap for frame
   OopMapSet* oop_maps() const                    { return _oop_maps; }
@@ -245,11 +207,6 @@
   // GC/Verification support
   void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f)  { /* nothing to do */ }
   bool is_alive() const                          { return true; }
-  void do_unloading(BoolObjectClosure* is_alive,
-                    OopClosure* keep_alive,
-                    bool unloading_occurred)     { /* do nothing */ }
-
-  void oops_do(OopClosure* f)                    { /* do nothing*/ }
 
   void verify();
   void print() const                             PRODUCT_RETURN;
@@ -334,10 +291,6 @@
   // GC/Verification support
   void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f)  { /* nothing to do */ }
   bool is_alive() const                          { return true; }
-  void do_unloading(BoolObjectClosure* is_alive,
-                    OopClosure* keep_alive,
-                    bool unloading_occurred)     { /* do nothing */ }
-  void oops_do(OopClosure* f) { /* do-nothing*/ }
 
   void verify();
   void print() const                             PRODUCT_RETURN;
@@ -363,9 +316,6 @@
    {};
 
    bool is_alive() const                         { return true; }
-   void do_unloading(BoolObjectClosure* is_alive,
-                     OopClosure* keep_alive,
-                     bool unloading_occurred)    { /* do-nothing*/ }
 
    void verify(); // does nothing
    void print() const                            PRODUCT_RETURN;
@@ -423,9 +373,6 @@
   // GC for args
   void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* Nothing to do */ }
 
-  // Iteration
-  void oops_do(OopClosure* f) {}
-
   // Printing
   void print_value_on(outputStream* st) const PRODUCT_RETURN;
 
@@ -477,9 +424,6 @@
 
   // Typing
   bool is_uncommon_trap_stub() const             { return true; }
-
-  // Iteration
-  void oops_do(OopClosure* f) {}
 };
 
 
@@ -512,9 +456,6 @@
 
   // Typing
   bool is_exception_stub() const                 { return true; }
-
-  // Iteration
-  void oops_do(OopClosure* f) {}
 };
 #endif // COMPILER2
 
@@ -548,7 +489,4 @@
 
   // Typing
   bool is_safepoint_stub() const                 { return true; }
-
-  // Iteration
-  void oops_do(OopClosure* f) {}
 };
--- a/hotspot/src/share/vm/code/codeCache.cpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/code/codeCache.cpp	Thu May 20 06:34:23 2010 -0700
@@ -74,12 +74,12 @@
     total_size       += cb->size();
     header_size      += cb->header_size();
     relocation_size  += cb->relocation_size();
-    scopes_oop_size  += cb->oops_size();
     if (cb->is_nmethod()) {
-      nmethod *nm = (nmethod*)cb;
+      nmethod* nm = cb->as_nmethod_or_null();
       code_size        += nm->code_size();
       stub_size        += nm->stub_size();
 
+      scopes_oop_size  += nm->oops_size();
       scopes_data_size += nm->scopes_data_size();
       scopes_pcs_size  += nm->scopes_pcs_size();
     } else {
@@ -262,14 +262,14 @@
 }
 
 
-// Mark code blobs for unloading if they contain otherwise
-// unreachable oops.
+// Mark nmethods for unloading if they contain otherwise unreachable
+// oops.
 void CodeCache::do_unloading(BoolObjectClosure* is_alive,
                              OopClosure* keep_alive,
                              bool unloading_occurred) {
   assert_locked_or_safepoint(CodeCache_lock);
-  FOR_ALL_ALIVE_BLOBS(cb) {
-    cb->do_unloading(is_alive, keep_alive, unloading_occurred);
+  FOR_ALL_ALIVE_NMETHODS(nm) {
+    nm->do_unloading(is_alive, keep_alive, unloading_occurred);
   }
 }
 
@@ -509,9 +509,9 @@
       if (needs_cache_clean()) {
         nm->cleanup_inline_caches();
       }
-      debug_only(nm->verify();)
+      DEBUG_ONLY(nm->verify());
+      nm->fix_oop_relocations();
     }
-    cb->fix_oop_relocations();
   }
   set_needs_cache_clean(false);
   prune_scavenge_root_nmethods();
--- a/hotspot/src/share/vm/code/compiledIC.cpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/code/compiledIC.cpp	Thu May 20 06:34:23 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -441,11 +441,11 @@
 }
 
 
-inline static RelocIterator parse_ic(CodeBlob* code, address ic_call, oop* &_oop_addr, bool *is_optimized) {
+inline static RelocIterator parse_ic(nmethod* nm, address ic_call, oop* &_oop_addr, bool *is_optimized) {
    address  first_oop = NULL;
    // Mergers please note: Sun SC5.x CC insists on an lvalue for a reference parameter.
-   CodeBlob *code1 = code;
-   return virtual_call_Relocation::parse_ic(code1, ic_call, first_oop, _oop_addr, is_optimized);
+   nmethod* tmp_nm = nm;
+   return virtual_call_Relocation::parse_ic(tmp_nm, ic_call, first_oop, _oop_addr, is_optimized);
 }
 
 CompiledIC::CompiledIC(NativeCall* ic_call)
--- a/hotspot/src/share/vm/code/nmethod.cpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Thu May 20 06:34:23 2010 -0700
@@ -99,12 +99,12 @@
     code_size           += nm->code_size();
     stub_size           += nm->stub_size();
     consts_size         += nm->consts_size();
+    oops_size           += nm->oops_size();
     scopes_data_size    += nm->scopes_data_size();
     scopes_pcs_size     += nm->scopes_pcs_size();
     dependencies_size   += nm->dependencies_size();
     handler_table_size  += nm->handler_table_size();
     nul_chk_table_size  += nm->nul_chk_table_size();
-    oops_size += nm->oops_size();
   }
   void print_nmethod_stats() {
     if (nmethod_count == 0)  return;
@@ -114,12 +114,12 @@
     if (code_size != 0)           tty->print_cr(" main code      = %d", code_size);
     if (stub_size != 0)           tty->print_cr(" stub code      = %d", stub_size);
     if (consts_size != 0)         tty->print_cr(" constants      = %d", consts_size);
+    if (oops_size != 0)           tty->print_cr(" oops           = %d", oops_size);
     if (scopes_data_size != 0)    tty->print_cr(" scopes data    = %d", scopes_data_size);
     if (scopes_pcs_size != 0)     tty->print_cr(" scopes pcs     = %d", scopes_pcs_size);
     if (dependencies_size != 0)   tty->print_cr(" dependencies   = %d", dependencies_size);
     if (handler_table_size != 0)  tty->print_cr(" handler table  = %d", handler_table_size);
     if (nul_chk_table_size != 0)  tty->print_cr(" nul chk table  = %d", nul_chk_table_size);
-    if (oops_size != 0)           tty->print_cr(" oops           = %d", oops_size);
   }
 
   int native_nmethod_count;
@@ -600,7 +600,8 @@
 #endif // def HAVE_DTRACE_H
     _stub_offset             = data_offset();
     _consts_offset           = data_offset();
-    _scopes_data_offset      = data_offset();
+    _oops_offset             = data_offset();
+    _scopes_data_offset      = _oops_offset          + round_to(code_buffer->total_oop_size(), oopSize);
     _scopes_pcs_offset       = _scopes_data_offset;
     _dependencies_offset     = _scopes_pcs_offset;
     _handler_table_offset    = _dependencies_offset;
@@ -690,7 +691,8 @@
     _orig_pc_offset          = 0;
     _stub_offset             = data_offset();
     _consts_offset           = data_offset();
-    _scopes_data_offset      = data_offset();
+    _oops_offset             = data_offset();
+    _scopes_data_offset      = _oops_offset          + round_to(code_buffer->total_oop_size(), oopSize);
     _scopes_pcs_offset       = _scopes_data_offset;
     _dependencies_offset     = _scopes_pcs_offset;
     _handler_table_offset    = _dependencies_offset;
@@ -805,8 +807,9 @@
       _unwind_handler_offset   = -1;
     }
     _consts_offset           = instructions_offset() + code_buffer->total_offset_of(code_buffer->consts()->start());
-    _scopes_data_offset      = data_offset();
-    _scopes_pcs_offset       = _scopes_data_offset   + round_to(debug_info->data_size         (), oopSize);
+    _oops_offset             = data_offset();
+    _scopes_data_offset      = _oops_offset          + round_to(code_buffer->total_oop_size (), oopSize);
+    _scopes_pcs_offset       = _scopes_data_offset   + round_to(debug_info->data_size       (), oopSize);
     _dependencies_offset     = _scopes_pcs_offset    + adjust_pcs_size(debug_info->pcs_size());
     _handler_table_offset    = _dependencies_offset  + round_to(dependencies->size_in_bytes (), oopSize);
     _nul_chk_table_offset    = _handler_table_offset + round_to(handler_table->size_in_bytes(), oopSize);
@@ -990,6 +993,79 @@
 }
 
 
+// Promote one word from an assembly-time handle to a live embedded oop.
+inline void nmethod::initialize_immediate_oop(oop* dest, jobject handle) {
+  if (handle == NULL ||
+      // As a special case, IC oops are initialized to 1 or -1.
+      handle == (jobject) Universe::non_oop_word()) {
+    (*dest) = (oop) handle;
+  } else {
+    (*dest) = JNIHandles::resolve_non_null(handle);
+  }
+}
+
+
+void nmethod::copy_oops(GrowableArray<jobject>* array) {
+  //assert(oops_size() == 0, "do this handshake just once, please");
+  int length = array->length();
+  assert((address)(oops_begin() + length) <= data_end(), "oops big enough");
+  oop* dest = oops_begin();
+  for (int index = 0 ; index < length; index++) {
+    initialize_immediate_oop(&dest[index], array->at(index));
+  }
+
+  // Now we can fix up all the oops in the code.  We need to do this
+  // in the code because the assembler uses jobjects as placeholders.
+  // The code and relocations have already been initialized by the
+  // CodeBlob constructor, so it is valid even at this early point to
+  // iterate over relocations and patch the code.
+  fix_oop_relocations(NULL, NULL, /*initialize_immediates=*/ true);
+}
+
+
+bool nmethod::is_at_poll_return(address pc) {
+  RelocIterator iter(this, pc, pc+1);
+  while (iter.next()) {
+    if (iter.type() == relocInfo::poll_return_type)
+      return true;
+  }
+  return false;
+}
+
+
+bool nmethod::is_at_poll_or_poll_return(address pc) {
+  RelocIterator iter(this, pc, pc+1);
+  while (iter.next()) {
+    relocInfo::relocType t = iter.type();
+    if (t == relocInfo::poll_return_type || t == relocInfo::poll_type)
+      return true;
+  }
+  return false;
+}
+
+
+void nmethod::fix_oop_relocations(address begin, address end, bool initialize_immediates) {
+  // re-patch all oop-bearing instructions, just in case some oops moved
+  RelocIterator iter(this, begin, end);
+  while (iter.next()) {
+    if (iter.type() == relocInfo::oop_type) {
+      oop_Relocation* reloc = iter.oop_reloc();
+      if (initialize_immediates && reloc->oop_is_immediate()) {
+        oop* dest = reloc->oop_addr();
+        initialize_immediate_oop(dest, (jobject) *dest);
+      }
+      // Refresh the oop-related bits of this instruction.
+      reloc->fix_oop_relocation();
+    }
+
+    // There must not be any interfering patches or breakpoints.
+    assert(!(iter.type() == relocInfo::breakpoint_type
+             && iter.breakpoint_reloc()->active()),
+           "no active breakpoint");
+  }
+}
+
+
 ScopeDesc* nmethod::scope_desc_at(address pc) {
   PcDesc* pd = pc_desc_at(pc);
   guarantee(pd != NULL, "scope must be present");
@@ -2282,6 +2358,10 @@
                                               consts_begin(),
                                               consts_end(),
                                               consts_size());
+  if (oops_size         () > 0) tty->print_cr(" oops           [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
+                                              oops_begin(),
+                                              oops_end(),
+                                              oops_size());
   if (scopes_data_size  () > 0) tty->print_cr(" scopes data    [" INTPTR_FORMAT "," INTPTR_FORMAT "] = %d",
                                               scopes_data_begin(),
                                               scopes_data_end(),
--- a/hotspot/src/share/vm/code/nmethod.hpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/code/nmethod.hpp	Thu May 20 06:34:23 2010 -0700
@@ -105,6 +105,7 @@
 //  [Relocation]
 //  - relocation information
 //  - constant part          (doubles, longs and floats used in nmethod)
+//  - oop table
 //  [Code]
 //  - code body
 //  - exception handler
@@ -161,6 +162,7 @@
 #endif // def HAVE_DTRACE_H
   int _stub_offset;
   int _consts_offset;
+  int _oops_offset;                       // offset to where embedded oop table begins (inside data)
   int _scopes_data_offset;
   int _scopes_pcs_offset;
   int _dependencies_offset;
@@ -347,7 +349,10 @@
   address stub_begin            () const          { return           header_begin() + _stub_offset          ; }
   address stub_end              () const          { return           header_begin() + _consts_offset        ; }
   address consts_begin          () const          { return           header_begin() + _consts_offset        ; }
-  address consts_end            () const          { return           header_begin() + _scopes_data_offset   ; }
+  address consts_end            () const          { return           header_begin() + _oops_offset          ; }
+  oop*    oops_begin            () const          { return (oop*)   (header_begin() + _oops_offset)         ; }
+  oop*    oops_end              () const          { return (oop*)   (header_begin() + _scopes_data_offset)  ; }
+
   address scopes_data_begin     () const          { return           header_begin() + _scopes_data_offset   ; }
   address scopes_data_end       () const          { return           header_begin() + _scopes_pcs_offset    ; }
   PcDesc* scopes_pcs_begin      () const          { return (PcDesc*)(header_begin() + _scopes_pcs_offset   ); }
@@ -359,20 +364,24 @@
   address nul_chk_table_begin   () const          { return           header_begin() + _nul_chk_table_offset ; }
   address nul_chk_table_end     () const          { return           header_begin() + _nmethod_end_offset   ; }
 
-  int code_size         () const                  { return      code_end         () -      code_begin         (); }
-  int stub_size         () const                  { return      stub_end         () -      stub_begin         (); }
-  int consts_size       () const                  { return      consts_end       () -      consts_begin       (); }
-  int scopes_data_size  () const                  { return      scopes_data_end  () -      scopes_data_begin  (); }
-  int scopes_pcs_size   () const                  { return (intptr_t)scopes_pcs_end   () - (intptr_t)scopes_pcs_begin   (); }
-  int dependencies_size () const                  { return      dependencies_end () -      dependencies_begin (); }
-  int handler_table_size() const                  { return      handler_table_end() -      handler_table_begin(); }
-  int nul_chk_table_size() const                  { return      nul_chk_table_end() -      nul_chk_table_begin(); }
+  // Sizes
+  int code_size         () const                  { return            code_end         () -            code_begin         (); }
+  int stub_size         () const                  { return            stub_end         () -            stub_begin         (); }
+  int consts_size       () const                  { return            consts_end       () -            consts_begin       (); }
+  int oops_size         () const                  { return (address)  oops_end         () - (address)  oops_begin         (); }
+  int scopes_data_size  () const                  { return            scopes_data_end  () -            scopes_data_begin  (); }
+  int scopes_pcs_size   () const                  { return (intptr_t) scopes_pcs_end   () - (intptr_t) scopes_pcs_begin   (); }
+  int dependencies_size () const                  { return            dependencies_end () -            dependencies_begin (); }
+  int handler_table_size() const                  { return            handler_table_end() -            handler_table_begin(); }
+  int nul_chk_table_size() const                  { return            nul_chk_table_end() -            nul_chk_table_begin(); }
 
   int total_size        () const;
 
+  // Containment
   bool code_contains         (address addr) const { return code_begin         () <= addr && addr < code_end         (); }
   bool stub_contains         (address addr) const { return stub_begin         () <= addr && addr < stub_end         (); }
   bool consts_contains       (address addr) const { return consts_begin       () <= addr && addr < consts_end       (); }
+  bool oops_contains         (oop*    addr) const { return oops_begin         () <= addr && addr < oops_end         (); }
   bool scopes_data_contains  (address addr) const { return scopes_data_begin  () <= addr && addr < scopes_data_end  (); }
   bool scopes_pcs_contains   (PcDesc* addr) const { return scopes_pcs_begin   () <= addr && addr < scopes_pcs_end   (); }
   bool handler_table_contains(address addr) const { return handler_table_begin() <= addr && addr < handler_table_end(); }
@@ -431,6 +440,29 @@
   int   version() const                           { return flags.version; }
   void  set_version(int v);
 
+  // Support for oops in scopes and relocs:
+  // Note: index 0 is reserved for null.
+  oop   oop_at(int index) const                   { return index == 0 ? (oop) NULL: *oop_addr_at(index); }
+  oop*  oop_addr_at(int index) const {  // for GC
+    // relocation indexes are biased by 1 (because 0 is reserved)
+    assert(index > 0 && index <= oops_size(), "must be a valid non-zero index");
+    return &oops_begin()[index - 1];
+  }
+
+  void copy_oops(GrowableArray<jobject>* oops);
+
+  // Relocation support
+private:
+  void fix_oop_relocations(address begin, address end, bool initialize_immediates);
+  inline void initialize_immediate_oop(oop* dest, jobject handle);
+
+public:
+  void fix_oop_relocations(address begin, address end) { fix_oop_relocations(begin, end, false); }
+  void fix_oop_relocations()                           { fix_oop_relocations(NULL, NULL, false); }
+
+  bool is_at_poll_return(address pc);
+  bool is_at_poll_or_poll_return(address pc);
+
   // Non-perm oop support
   bool  on_scavenge_root_list() const                  { return (_scavenge_root_state & 1) != 0; }
  protected:
@@ -511,8 +543,8 @@
 
   void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map,
                                      OopClosure* f);
-  virtual void oops_do(OopClosure* f) { oops_do(f, false); }
-  void         oops_do(OopClosure* f, bool do_strong_roots_only);
+  void oops_do(OopClosure* f) { oops_do(f, false); }
+  void oops_do(OopClosure* f, bool do_strong_roots_only);
   bool detect_scavenge_root_oops();
   void verify_scavenge_root_oops() PRODUCT_RETURN;
 
--- a/hotspot/src/share/vm/code/oopRecorder.cpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/code/oopRecorder.cpp	Thu May 20 06:34:23 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,10 +50,10 @@
   return _handles->length() * sizeof(oop);
 }
 
-void OopRecorder::copy_to(CodeBlob* code) {
+void OopRecorder::copy_to(nmethod* nm) {
   assert(_complete, "must be frozen");
   maybe_initialize();  // get non-null handles, even if we have no oops
-  code->copy_oops(_handles);
+  nm->copy_oops(_handles);
 }
 
 void OopRecorder::maybe_initialize() {
--- a/hotspot/src/share/vm/code/oopRecorder.hpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/code/oopRecorder.hpp	Thu May 20 06:34:23 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -70,8 +70,8 @@
     return _handles->length() + first_index;
   }
 
-  // copy the generated oop table to CodeBlob
-  void copy_to(CodeBlob* code);  // => code->copy_oops(_handles)
+  // copy the generated oop table to nmethod
+  void copy_to(nmethod* nm);  // => nm->copy_oops(_handles)
 
   bool is_unused() { return _handles == NULL && !_complete; }
 #ifdef ASSERT
--- a/hotspot/src/share/vm/code/relocInfo.cpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/code/relocInfo.cpp	Thu May 20 06:34:23 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -115,24 +115,25 @@
 // ----------------------------------------------------------------------------------------------------
 // Implementation of RelocIterator
 
-void RelocIterator::initialize(CodeBlob* cb, address begin, address limit) {
+void RelocIterator::initialize(nmethod* nm, address begin, address limit) {
   initialize_misc();
 
-  if (cb == NULL && begin != NULL) {
-    // allow CodeBlob to be deduced from beginning address
-    cb = CodeCache::find_blob(begin);
+  if (nm == NULL && begin != NULL) {
+    // allow nmethod to be deduced from beginning address
+    CodeBlob* cb = CodeCache::find_blob(begin);
+    nm = cb->as_nmethod_or_null();
   }
-  assert(cb != NULL, "must be able to deduce nmethod from other arguments");
+  assert(nm != NULL, "must be able to deduce nmethod from other arguments");
 
-  _code    = cb;
-  _current = cb->relocation_begin()-1;
-  _end     = cb->relocation_end();
-  _addr    = (address) cb->instructions_begin();
+  _code    = nm;
+  _current = nm->relocation_begin() - 1;
+  _end     = nm->relocation_end();
+  _addr    = (address) nm->instructions_begin();
 
   assert(!has_current(), "just checking");
-  address code_end = cb->instructions_end();
+  address code_end = nm->instructions_end();
 
-  assert(begin == NULL || begin >= cb->instructions_begin(), "in bounds");
+  assert(begin == NULL || begin >= nm->instructions_begin(), "in bounds");
  // FIX THIS  assert(limit == NULL || limit <= code_end,     "in bounds");
   set_limits(begin, limit);
 }
@@ -754,7 +755,7 @@
     // oop is stored in the code stream
     return (oop*) pd_address_in_code();
   } else {
-    // oop is stored in table at CodeBlob::oops_begin
+    // oop is stored in table at nmethod::oops_begin
     return code()->oop_addr_at(n);
   }
 }
@@ -776,26 +777,28 @@
 }
 
 
-RelocIterator virtual_call_Relocation::parse_ic(CodeBlob* &code, address &ic_call, address &first_oop,
+RelocIterator virtual_call_Relocation::parse_ic(nmethod* &nm, address &ic_call, address &first_oop,
                                                 oop* &oop_addr, bool *is_optimized) {
   assert(ic_call != NULL, "ic_call address must be set");
   assert(ic_call != NULL || first_oop != NULL, "must supply a non-null input");
-  if (code == NULL) {
+  if (nm == NULL) {
+    CodeBlob* code;
     if (ic_call != NULL) {
       code = CodeCache::find_blob(ic_call);
     } else if (first_oop != NULL) {
       code = CodeCache::find_blob(first_oop);
     }
-    assert(code != NULL, "address to parse must be in CodeBlob");
+    nm = code->as_nmethod_or_null();
+    assert(nm != NULL, "address to parse must be in nmethod");
   }
-  assert(ic_call   == NULL || code->contains(ic_call),   "must be in CodeBlob");
-  assert(first_oop == NULL || code->contains(first_oop), "must be in CodeBlob");
+  assert(ic_call   == NULL || nm->contains(ic_call),   "must be in nmethod");
+  assert(first_oop == NULL || nm->contains(first_oop), "must be in nmethod");
 
   address oop_limit = NULL;
 
   if (ic_call != NULL) {
     // search for the ic_call at the given address
-    RelocIterator iter(code, ic_call, ic_call+1);
+    RelocIterator iter(nm, ic_call, ic_call+1);
     bool ret = iter.next();
     assert(ret == true, "relocInfo must exist at this address");
     assert(iter.addr() == ic_call, "must find ic_call");
@@ -814,7 +817,7 @@
   }
 
   // search for the first_oop, to get its oop_addr
-  RelocIterator all_oops(code, first_oop);
+  RelocIterator all_oops(nm, first_oop);
   RelocIterator iter = all_oops;
   iter.set_limit(first_oop+1);
   bool found_oop = false;
@@ -842,7 +845,7 @@
       }
     }
     guarantee(!did_reset, "cannot find ic_call");
-    iter = RelocIterator(code); // search the whole CodeBlob
+    iter = RelocIterator(nm); // search the whole nmethod
     did_reset = true;
   }
 
@@ -1175,9 +1178,9 @@
 
 // For the debugger:
 extern "C"
-void print_blob_locs(CodeBlob* cb) {
-  cb->print();
-  RelocIterator iter(cb);
+void print_blob_locs(nmethod* nm) {
+  nm->print();
+  RelocIterator iter(nm);
   iter.print();
 }
 extern "C"
--- a/hotspot/src/share/vm/code/relocInfo.hpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/code/relocInfo.hpp	Thu May 20 06:34:23 2010 -0700
@@ -512,7 +512,7 @@
   address    _limit;   // stop producing relocations after this _addr
   relocInfo* _current; // the current relocation information
   relocInfo* _end;     // end marker; we're done iterating when _current == _end
-  CodeBlob*  _code;    // compiled method containing _addr
+  nmethod*   _code;    // compiled method containing _addr
   address    _addr;    // instruction to which the relocation applies
   short      _databuf; // spare buffer for compressed data
   short*     _data;    // pointer to the relocation's data
@@ -549,7 +549,7 @@
 
   address compute_section_start(int n) const;  // out-of-line helper
 
-  void initialize(CodeBlob* nm, address begin, address limit);
+  void initialize(nmethod* nm, address begin, address limit);
 
   friend class PatchingRelocIterator;
   // make an uninitialized one, for PatchingRelocIterator:
@@ -557,7 +557,7 @@
 
  public:
   // constructor
-  RelocIterator(CodeBlob* cb,    address begin = NULL, address limit = NULL);
+  RelocIterator(nmethod* nm,     address begin = NULL, address limit = NULL);
   RelocIterator(CodeSection* cb, address begin = NULL, address limit = NULL);
 
   // get next reloc info, return !eos
@@ -592,7 +592,7 @@
   relocType    type()         const { return current()->type(); }
   int          format()       const { return (relocInfo::have_format) ? current()->format() : 0; }
   address      addr()         const { return _addr; }
-  CodeBlob*    code()         const { return _code; }
+  nmethod*     code()         const { return _code; }
   short*       data()         const { return _data; }
   int          datalen()      const { return _datalen; }
   bool     has_current()      const { return _datalen >= 0; }
@@ -790,9 +790,9 @@
 
  public:
   // accessors which only make sense for a bound Relocation
-  address   addr()         const { return binding()->addr(); }
-  CodeBlob* code()         const { return binding()->code(); }
-  bool      addr_in_const() const { return binding()->addr_in_const(); }
+  address  addr()         const { return binding()->addr(); }
+  nmethod* code()         const { return binding()->code(); }
+  bool     addr_in_const() const { return binding()->addr_in_const(); }
  protected:
   short*   data()         const { return binding()->data(); }
   int      datalen()      const { return binding()->datalen(); }
@@ -982,12 +982,12 @@
 
   // Figure out where an ic_call is hiding, given a set-oop or call.
   // Either ic_call or first_oop must be non-null; the other is deduced.
-  // Code if non-NULL must be the CodeBlob, else it is deduced.
+  // Code if non-NULL must be the nmethod, else it is deduced.
   // The address of the patchable oop is also deduced.
   // The returned iterator will enumerate over the oops and the ic_call,
   // as well as any other relocations that happen to be in that span of code.
   // Recognize relevant set_oops with:  oop_reloc()->oop_addr() == oop_addr.
-  static RelocIterator parse_ic(CodeBlob* &code, address &ic_call, address &first_oop, oop* &oop_addr, bool *is_optimized);
+  static RelocIterator parse_ic(nmethod* &nm, address &ic_call, address &first_oop, oop* &oop_addr, bool *is_optimized);
 };
 
 
@@ -1304,8 +1304,8 @@
 APPLY_TO_RELOCATIONS(EACH_CASE);
 #undef EACH_CASE
 
-inline RelocIterator::RelocIterator(CodeBlob* cb, address begin, address limit) {
-  initialize(cb, begin, limit);
+inline RelocIterator::RelocIterator(nmethod* nm, address begin, address limit) {
+  initialize(nm, begin, limit);
 }
 
 // if you are going to patch code, you should use this subclass of
@@ -1323,8 +1323,8 @@
   void        operator=(const RelocIterator&);
 
  public:
-  PatchingRelocIterator(CodeBlob* cb, address begin =NULL, address limit =NULL)
-    : RelocIterator(cb, begin, limit)                { prepass();  }
+  PatchingRelocIterator(nmethod* nm, address begin = NULL, address limit = NULL)
+    : RelocIterator(nm, begin, limit)                { prepass();  }
 
   ~PatchingRelocIterator()                           { postpass(); }
 };
--- a/hotspot/src/share/vm/memory/iterator.cpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/memory/iterator.cpp	Thu May 20 06:34:23 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,8 +58,8 @@
 }
 
 void MarkingCodeBlobClosure::do_code_blob(CodeBlob* cb) {
-  if (!cb->is_nmethod())  return;
-  nmethod* nm = (nmethod*) cb;
+  nmethod* nm = cb->as_nmethod_or_null();
+  if (nm == NULL)  return;
   if (!nm->test_set_oops_do_mark()) {
     NOT_PRODUCT(if (TraceScavenge)  nm->print_on(tty, "oops_do, 1st visit\n"));
     do_newly_marked_nmethod(nm);
@@ -74,11 +74,14 @@
 
 void CodeBlobToOopClosure::do_code_blob(CodeBlob* cb) {
   if (!_do_marking) {
-    NOT_PRODUCT(if (TraceScavenge && Verbose && cb->is_nmethod())  ((nmethod*)cb)->print_on(tty, "oops_do, unmarked visit\n"));
+    nmethod* nm = cb->as_nmethod_or_null();
+    NOT_PRODUCT(if (TraceScavenge && Verbose && nm != NULL)  nm->print_on(tty, "oops_do, unmarked visit\n"));
     // This assert won't work, since there are lots of mini-passes
     // (mostly in debug mode) that co-exist with marking phases.
     //assert(!(cb->is_nmethod() && ((nmethod*)cb)->test_oops_do_mark()), "found marked nmethod during mark-free phase");
-    cb->oops_do(_cl);
+    if (nm != NULL) {
+      nm->oops_do(_cl);
+    }
   } else {
     MarkingCodeBlobClosure::do_code_blob(cb);
   }
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp	Thu May 20 06:34:23 2010 -0700
@@ -1435,7 +1435,7 @@
       // for the rest of its life! Just another racing bug in the life of
       // fixup_callers_callsite ...
       //
-      RelocIterator iter(cb, call->instruction_address(), call->next_instruction_address());
+      RelocIterator iter(nm, call->instruction_address(), call->next_instruction_address());
       iter.next();
       assert(iter.has_current(), "must have a reloc at java call site");
       relocInfo::relocType typ = iter.reloc()->type();
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Thu May 20 01:34:22 2010 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Thu May 20 06:34:23 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-2010 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -607,8 +607,6 @@
   nonstatic_field(CodeBlob,                    _instructions_offset,                          int)                                   \
   nonstatic_field(CodeBlob,                    _frame_complete_offset,                        int)                                   \
   nonstatic_field(CodeBlob,                    _data_offset,                                  int)                                   \
-  nonstatic_field(CodeBlob,                    _oops_offset,                                  int)                                   \
-  nonstatic_field(CodeBlob,                    _oops_length,                                  int)                                   \
   nonstatic_field(CodeBlob,                    _frame_size,                                   int)                                   \
   nonstatic_field(CodeBlob,                    _oop_maps,                                     OopMapSet*)                            \
                                                                                                                                      \
@@ -626,6 +624,8 @@
   nonstatic_field(nmethod,             _deoptimize_offset,                            int)                                   \
   nonstatic_field(nmethod,             _orig_pc_offset,                               int)                                   \
   nonstatic_field(nmethod,             _stub_offset,                                  int)                                   \
+  nonstatic_field(nmethod,             _consts_offset,                                int)                                   \
+  nonstatic_field(nmethod,             _oops_offset,                                  int)                                   \
   nonstatic_field(nmethod,             _scopes_data_offset,                           int)                                   \
   nonstatic_field(nmethod,             _scopes_pcs_offset,                            int)                                   \
   nonstatic_field(nmethod,             _dependencies_offset,                          int)                                   \