changeset 1499:e9ff18c4ace7

Merge
author jrose
date Wed, 02 Jun 2010 22:45:42 -0700
parents dfe27f03244a ca3dceda776c
children f56e28f22410 02e771df338e 3a9de63b2209
files agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java agent/src/share/classes/sun/jvm/hotspot/oops/Oop.java agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java agent/src/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java make/solaris/makefiles/defs.make src/cpu/sparc/vm/assembler_sparc.hpp src/cpu/sparc/vm/c1_FrameMap_sparc.cpp src/cpu/sparc/vm/c1_FrameMap_sparc.hpp src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp src/cpu/sparc/vm/c1_Runtime1_sparc.cpp src/cpu/sparc/vm/copy_sparc.hpp src/cpu/sparc/vm/frame_sparc.cpp src/cpu/sparc/vm/interp_masm_sparc.cpp src/cpu/sparc/vm/interp_masm_sparc.hpp src/cpu/sparc/vm/methodHandles_sparc.cpp src/cpu/sparc/vm/nativeInst_sparc.cpp src/cpu/sparc/vm/register_definitions_sparc.cpp src/cpu/sparc/vm/runtime_sparc.cpp src/cpu/sparc/vm/sharedRuntime_sparc.cpp src/cpu/sparc/vm/sparc.ad src/cpu/sparc/vm/stubGenerator_sparc.cpp src/cpu/sparc/vm/stubRoutines_sparc.hpp src/cpu/sparc/vm/templateInterpreter_sparc.cpp src/cpu/sparc/vm/templateTable_sparc.cpp src/cpu/sparc/vm/vm_version_sparc.cpp src/cpu/x86/vm/assembler_x86.cpp src/cpu/x86/vm/assembler_x86.hpp src/cpu/x86/vm/c1_FrameMap_x86.cpp src/cpu/x86/vm/c1_FrameMap_x86.hpp src/cpu/x86/vm/c1_LIRAssembler_x86.cpp src/cpu/x86/vm/c1_LIRGenerator_x86.cpp src/cpu/x86/vm/c1_Runtime1_x86.cpp src/cpu/x86/vm/interp_masm_x86_32.cpp src/cpu/x86/vm/interp_masm_x86_32.hpp src/cpu/x86/vm/interp_masm_x86_64.cpp src/cpu/x86/vm/interp_masm_x86_64.hpp src/cpu/x86/vm/register_definitions_x86.cpp src/cpu/x86/vm/runtime_x86_32.cpp src/cpu/x86/vm/sharedRuntime_x86_64.cpp src/cpu/x86/vm/templateInterpreter_x86_32.cpp src/cpu/x86/vm/templateInterpreter_x86_64.cpp src/cpu/x86/vm/templateTable_x86_32.cpp src/cpu/x86/vm/templateTable_x86_64.cpp src/cpu/x86/vm/x86_32.ad src/cpu/x86/vm/x86_64.ad src/os/solaris/dtrace/generateJvmOffsets.cpp src/os/solaris/dtrace/libjvm_db.c src/share/vm/asm/codeBuffer.hpp src/share/vm/c1/c1_FrameMap.hpp src/share/vm/c1/c1_GraphBuilder.cpp src/share/vm/c1/c1_IR.cpp src/share/vm/c1/c1_IR.hpp src/share/vm/c1/c1_LIR.cpp src/share/vm/c1/c1_LIR.hpp src/share/vm/c1/c1_LIRAssembler.cpp src/share/vm/c1/c1_LIRAssembler.hpp src/share/vm/c1/c1_LIRGenerator.cpp src/share/vm/ci/ciMethod.cpp src/share/vm/ci/ciStreams.cpp src/share/vm/ci/ciStreams.hpp src/share/vm/ci/ciTypeFlow.cpp src/share/vm/classfile/verifier.cpp src/share/vm/classfile/verifier.hpp src/share/vm/code/codeBlob.cpp src/share/vm/code/codeBlob.hpp src/share/vm/code/codeCache.cpp src/share/vm/code/compiledIC.cpp src/share/vm/code/nmethod.cpp src/share/vm/code/nmethod.hpp src/share/vm/code/oopRecorder.cpp src/share/vm/code/oopRecorder.hpp src/share/vm/code/relocInfo.cpp src/share/vm/code/relocInfo.hpp src/share/vm/compiler/compileBroker.cpp src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp src/share/vm/gc_interface/collectedHeap.cpp src/share/vm/includeDB_core src/share/vm/interpreter/bytecode.cpp src/share/vm/interpreter/bytecode.hpp src/share/vm/interpreter/bytecodeStream.cpp src/share/vm/interpreter/bytecodeStream.hpp src/share/vm/interpreter/bytecodeTracer.cpp src/share/vm/interpreter/bytecodes.cpp src/share/vm/interpreter/bytecodes.hpp src/share/vm/interpreter/interpreter.cpp src/share/vm/interpreter/interpreterRuntime.cpp src/share/vm/interpreter/interpreterRuntime.hpp src/share/vm/interpreter/rewriter.cpp src/share/vm/interpreter/rewriter.hpp src/share/vm/interpreter/templateTable.cpp src/share/vm/interpreter/templateTable.hpp src/share/vm/memory/iterator.cpp src/share/vm/memory/space.cpp src/share/vm/memory/threadLocalAllocBuffer.inline.hpp src/share/vm/memory/universe.cpp src/share/vm/oops/arrayOop.hpp src/share/vm/oops/constantPoolKlass.cpp src/share/vm/oops/constantPoolOop.cpp src/share/vm/oops/constantPoolOop.hpp src/share/vm/oops/generateOopMap.cpp src/share/vm/oops/methodKlass.cpp src/share/vm/oops/oop.hpp src/share/vm/oops/oop.inline.hpp src/share/vm/opto/bytecodeInfo.cpp src/share/vm/opto/compile.cpp src/share/vm/opto/connode.cpp src/share/vm/opto/lcm.cpp src/share/vm/opto/matcher.cpp src/share/vm/opto/matcher.hpp src/share/vm/opto/parse2.cpp src/share/vm/prims/jvmtiClassFileReconstituter.cpp src/share/vm/prims/jvmtiExport.cpp src/share/vm/prims/jvmtiExport.hpp src/share/vm/prims/methodComparator.cpp src/share/vm/prims/methodHandleWalk.cpp src/share/vm/runtime/arguments.cpp src/share/vm/runtime/globals.hpp src/share/vm/runtime/sharedRuntime.cpp src/share/vm/runtime/vmStructs.cpp src/share/vm/utilities/copy.hpp src/share/vm/utilities/globalDefinitions.cpp src/share/vm/utilities/globalDefinitions.hpp
diffstat 133 files changed, 1894 insertions(+), 1312 deletions(-) [+]
line wrap: on
line diff
--- a/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java	Tue Jun 01 11:48:33 2010 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/code/CodeBlob.java	Wed Jun 02 22:45:42 2010 -0700
@@ -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/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java	Tue Jun 01 11:48:33 2010 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java	Tue Jun 01 11:48:33 2010 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java	Wed Jun 02 22:45:42 2010 -0700
@@ -73,18 +73,11 @@
 
    public CompactibleFreeListSpace(Address addr) {
       super(addr);
-      if ( VM.getVM().isLP64() ) {
-         heapWordSize = 8;
-         IndexSetStart = 1;
-         IndexSetStride = 1;
-      }
-      else {
-         heapWordSize = 4;
-         IndexSetStart = 2;
-         IndexSetStride = 2;
-      }
-
-      IndexSetSize = 257;
+      VM vm = VM.getVM();
+      heapWordSize   = vm.getHeapWordSize();
+      IndexSetStart  = vm.getMinObjAlignmentInBytes() / heapWordSize;
+      IndexSetStride = IndexSetStart;
+      IndexSetSize   = 257;
    }
 
    // Accessing block offset table
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/Oop.java	Tue Jun 01 11:48:33 2010 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Oop.java	Wed Jun 02 22:45:42 2010 -0700
@@ -128,7 +128,7 @@
 
   // Align the object size.
   public static long alignObjectSize(long size) {
-    return VM.getVM().alignUp(size, VM.getVM().getMinObjAlignment());
+    return VM.getVM().alignUp(size, VM.getVM().getMinObjAlignmentInBytes());
   }
 
   // All vm's align longs, so pad out certain offsets.
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java	Tue Jun 01 11:48:33 2010 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java	Wed Jun 02 22:45:42 2010 -0700
@@ -93,6 +93,7 @@
   /** alignment constants */
   private boolean      isLP64;
   private int          bytesPerLong;
+  private int          objectAlignmentInBytes;
   private int          minObjAlignmentInBytes;
   private int          logMinObjAlignmentInBytes;
   private int          heapWordSize;
@@ -313,9 +314,6 @@
       isLP64 = debugger.getMachineDescription().isLP64();
     }
     bytesPerLong = db.lookupIntConstant("BytesPerLong").intValue();
-    minObjAlignmentInBytes = db.lookupIntConstant("MinObjAlignmentInBytes").intValue();
-    // minObjAlignment = db.lookupIntConstant("MinObjAlignment").intValue();
-    logMinObjAlignmentInBytes = db.lookupIntConstant("LogMinObjAlignmentInBytes").intValue();
     heapWordSize = db.lookupIntConstant("HeapWordSize").intValue();
     oopSize  = db.lookupIntConstant("oopSize").intValue();
 
@@ -323,6 +321,15 @@
     uintxType = db.lookupType("uintx");
     boolType = (CIntegerType) db.lookupType("bool");
 
+    minObjAlignmentInBytes = getObjectAlignmentInBytes();
+    if (minObjAlignmentInBytes == 8) {
+      logMinObjAlignmentInBytes = 3;
+    } else if (minObjAlignmentInBytes == 16) {
+      logMinObjAlignmentInBytes = 4;
+    } else {
+      throw new RuntimeException("Object alignment " + minObjAlignmentInBytes + " not yet supported");
+    }
+
     if (isCompressedOopsEnabled()) {
       // Size info for oops within java objects is fixed
       heapOopSize = (int)getIntSize();
@@ -492,10 +499,6 @@
   }
 
   /** Get minimum object alignment in bytes. */
-  public int getMinObjAlignment() {
-    return minObjAlignmentInBytes;
-  }
-
   public int getMinObjAlignmentInBytes() {
     return minObjAlignmentInBytes;
   }
@@ -754,6 +757,14 @@
     return compressedOopsEnabled.booleanValue();
   }
 
+  public int getObjectAlignmentInBytes() {
+    if (objectAlignmentInBytes == 0) {
+        Flag flag = getCommandLineFlag("ObjectAlignmentInBytes");
+        objectAlignmentInBytes = (flag == null) ? 8 : (int)flag.getIntx();
+    }
+    return objectAlignmentInBytes;
+  }
+
   // returns null, if not available.
   public Flag[] getCommandLineFlags() {
     if (commandLineFlags == null) {
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java	Tue Jun 01 11:48:33 2010 -0700
+++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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/make/solaris/makefiles/defs.make	Tue Jun 01 11:48:33 2010 -0700
+++ b/make/solaris/makefiles/defs.make	Wed Jun 02 22:45:42 2010 -0700
@@ -80,12 +80,10 @@
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.so 
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.so 
   EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.so 
-  ifeq ($(ARCH),sparc)
-    EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.so
-    EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.so
-    EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.so
-    EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.so
-  endif
+  EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.so
+  EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.so
+  EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.so
+  EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.so
 endif
 
 EXPORT_LIST += $(EXPORT_JRE_LIB_ARCH_DIR)/libsaproc.so
--- a/src/cpu/sparc/vm/assembler_sparc.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/assembler_sparc.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -87,6 +87,7 @@
 // JSR 292 fixed register usages:
 REGISTER_DECLARATION(Register, G5_method_type        , G5);
 REGISTER_DECLARATION(Register, G3_method_handle      , G3);
+REGISTER_DECLARATION(Register, L7_mh_SP_save         , L7);
 
 // The compiler requires that G5_megamorphic_method is G5_inline_cache_klass,
 // because a single patchable "set" instruction (NativeMovConstReg,
--- a/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. 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
@@ -345,6 +345,13 @@
 }
 
 
+// JSR 292
+LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
+  assert(L7 == L7_mh_SP_save, "must be same register");
+  return L7_opr;
+}
+
+
 bool FrameMap::validate_frame() {
   int max_offset = in_bytes(framesize_in_bytes());
   int java_index = 0;
--- a/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -143,6 +143,3 @@
 
   static bool is_caller_save_register (LIR_Opr  reg);
   static bool is_caller_save_register (Register r);
-
-  // JSR 292
-  static LIR_Opr& method_handle_invoke_SP_save_opr() { return L7_opr; }
--- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -736,7 +736,8 @@
 
 void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
   __ call(op->addr(), rtype);
-  // the peephole pass fills the delay slot
+  // The peephole pass fills the delay slot, add_call_info is done in
+  // LIR_Assembler::emit_delay.
 }
 
 
@@ -745,7 +746,8 @@
   __ set_oop((jobject)Universe::non_oop_word(), G5_inline_cache_reg);
   __ relocate(rspec);
   __ call(op->addr(), relocInfo::none);
-  // the peephole pass fills the delay slot
+  // The peephole pass fills the delay slot, add_call_info is done in
+  // LIR_Assembler::emit_delay.
 }
 
 
@@ -766,16 +768,6 @@
 }
 
 
-void LIR_Assembler::preserve_SP(LIR_OpJavaCall* op) {
-  Unimplemented();
-}
-
-
-void LIR_Assembler::restore_SP(LIR_OpJavaCall* op) {
-  Unimplemented();
-}
-
-
 // load with 32-bit displacement
 int LIR_Assembler::load(Register s, int disp, Register d, BasicType ld_type, CodeEmitInfo *info) {
   int load_offset = code_offset();
@@ -2934,7 +2926,7 @@
 
   // we may also be emitting the call info for the instruction
   // which we are the delay slot of.
-  CodeEmitInfo * call_info = op->call_info();
+  CodeEmitInfo* call_info = op->call_info();
   if (call_info) {
     add_call_info(code_offset(), call_info);
   }
@@ -3159,6 +3151,7 @@
               tty->print_cr("delayed");
               inst->at(i - 1)->print();
               inst->at(i)->print();
+              tty->cr();
             }
 #endif
             continue;
@@ -3174,8 +3167,8 @@
       case lir_static_call:
       case lir_virtual_call:
       case lir_icvirtual_call:
-      case lir_optvirtual_call: {
-        LIR_Op* delay_op = NULL;
+      case lir_optvirtual_call:
+      case lir_dynamic_call: {
         LIR_Op* prev = inst->at(i - 1);
         if (LIRFillDelaySlots && prev && prev->code() == lir_move && prev->info() == NULL &&
             (op->code() != lir_virtual_call ||
@@ -3192,15 +3185,14 @@
             tty->print_cr("delayed");
             inst->at(i - 1)->print();
             inst->at(i)->print();
+            tty->cr();
           }
 #endif
           continue;
         }
 
-        if (!delay_op) {
-          delay_op = new LIR_OpDelay(new LIR_Op0(lir_nop), op->as_OpJavaCall()->info());
-          inst->insert_before(i + 1, delay_op);
-        }
+        LIR_Op* delay_op = new LIR_OpDelay(new LIR_Op0(lir_nop), op->as_OpJavaCall()->info());
+        inst->insert_before(i + 1, delay_op);
         break;
       }
     }
--- a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -221,7 +221,7 @@
   if (needs_card_mark) {
     LIR_Opr ptr = new_pointer_register();
     __ add(base_opr, LIR_OprFact::intptrConst(offset), ptr);
-    return new LIR_Address(ptr, 0, type);
+    return new LIR_Address(ptr, type);
   } else {
     return new LIR_Address(base_opr, offset, type);
   }
@@ -231,7 +231,7 @@
 void LIRGenerator::increment_counter(address counter, int step) {
   LIR_Opr pointer = new_pointer_register();
   __ move(LIR_OprFact::intptrConst(counter), pointer);
-  LIR_Address* addr = new LIR_Address(pointer, 0, T_INT);
+  LIR_Address* addr = new LIR_Address(pointer, T_INT);
   increment_counter(addr, step);
 }
 
@@ -1159,7 +1159,7 @@
       if (type == T_ARRAY || type == T_OBJECT) {
         LIR_Opr tmp = new_pointer_register();
         __ add(base_op, index_op, tmp);
-        addr = new LIR_Address(tmp, 0, type);
+        addr = new LIR_Address(tmp, type);
       } else {
         addr = new LIR_Address(base_op, index_op, type);
       }
--- a/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -679,8 +679,15 @@
         __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address),
                         G2_thread, Oissuing_pc->after_save());
         __ verify_not_null_oop(Oexception->after_save());
-        __ jmp(O0, 0);
-        __ delayed()->restore();
+
+        // Restore SP from L7 if the exception PC is a MethodHandle call site.
+        __ mov(O0, G5);  // Save the target address.
+        __ lduw(Address(G2_thread, JavaThread::is_method_handle_return_offset()), L0);
+        __ tst(L0);  // Condition codes are preserved over the restore.
+        __ restore();
+
+        __ jmp(G5, 0);
+        __ delayed()->movcc(Assembler::notZero, false, Assembler::icc, L7_mh_SP_save, SP);  // Restore SP if required.
       }
       break;
 
--- a/src/cpu/sparc/vm/copy_sparc.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/copy_sparc.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -154,7 +154,7 @@
 }
 
 static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value) {
-  assert(MinObjAlignmentInBytes == BytesPerLong, "need alternate implementation");
+  assert(MinObjAlignmentInBytes >= BytesPerLong, "need alternate implementation");
 
    julong* to = (julong*)tohw;
    julong  v  = ((julong)value << 32) | value;
@@ -162,7 +162,7 @@
    // and be equal to 0 on 64-bit platform.
    size_t odd = count % (BytesPerLong / HeapWordSize) ;
 
-   size_t aligned_count = align_object_size(count - odd) / HeapWordsPerLong;
+   size_t aligned_count = align_object_offset(count - odd) / HeapWordsPerLong;
    julong* end = ((julong*)tohw) + aligned_count - 1;
    while (to <= end) {
      DEBUG_ONLY(count -= BytesPerLong / HeapWordSize ;)
--- a/src/cpu/sparc/vm/frame_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/frame_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -336,9 +336,11 @@
 #endif // ASSERT
 }
 
-frame::frame(intptr_t* sp, intptr_t* younger_sp, bool younger_frame_adjusted_stack) {
-  _sp = sp;
-  _younger_sp = younger_sp;
+frame::frame(intptr_t* sp, intptr_t* younger_sp, bool younger_frame_is_interpreted) :
+  _sp(sp),
+  _younger_sp(younger_sp),
+  _deopt_state(unknown),
+  _sp_adjustment_by_callee(0) {
   if (younger_sp == NULL) {
     // make a deficient frame which doesn't know where its PC is
     _pc = NULL;
@@ -352,20 +354,32 @@
     // wrong.  (the _last_native_pc will have the right value)
     // So do not put add any asserts on the _pc here.
   }
-  if (younger_frame_adjusted_stack) {
-    // compute adjustment to this frame's SP made by its interpreted callee
-    _sp_adjustment_by_callee = (intptr_t*)((intptr_t)younger_sp[I5_savedSP->sp_offset_in_saved_window()] +
-                                             STACK_BIAS) - sp;
-  } else {
-    _sp_adjustment_by_callee = 0;
+
+  if (_pc != NULL)
+    _cb = CodeCache::find_blob(_pc);
+
+  // Check for MethodHandle call sites.
+  if (_cb != NULL) {
+    nmethod* nm = _cb->as_nmethod_or_null();
+    if (nm != NULL) {
+      if (nm->is_deopt_mh_entry(_pc) || nm->is_method_handle_return(_pc)) {
+        _sp_adjustment_by_callee = (intptr_t*) ((intptr_t) sp[L7_mh_SP_save->sp_offset_in_saved_window()] + STACK_BIAS) - sp;
+        // The SP is already adjusted by this MH call site, don't
+        // overwrite this value with the wrong interpreter value.
+        younger_frame_is_interpreted = false;
+      }
+    }
   }
 
-  _deopt_state = unknown;
+  if (younger_frame_is_interpreted) {
+    // compute adjustment to this frame's SP made by its interpreted callee
+    _sp_adjustment_by_callee = (intptr_t*) ((intptr_t) younger_sp[I5_savedSP->sp_offset_in_saved_window()] + STACK_BIAS) - sp;
+  }
 
-  // It is important that frame be fully construct when we do this lookup
-  // as get_original_pc() needs correct value for unextended_sp()
+  // It is important that the frame is fully constructed when we do
+  // this lookup as get_deopt_original_pc() needs a correct value for
+  // unextended_sp() which uses _sp_adjustment_by_callee.
   if (_pc != NULL) {
-    _cb = CodeCache::find_blob(_pc);
     address original_pc = nmethod::get_deopt_original_pc(this);
     if (original_pc != NULL) {
       _pc = original_pc;
@@ -462,9 +476,8 @@
 
   if (is_entry_frame()) return sender_for_entry_frame(map);
 
-  intptr_t* younger_sp     = sp();
-  intptr_t* sp             = sender_sp();
-  bool      adjusted_stack = false;
+  intptr_t* younger_sp = sp();
+  intptr_t* sp         = sender_sp();
 
   // Note:  The version of this operation on any platform with callee-save
   //        registers must update the register map (if not null).
@@ -483,8 +496,8 @@
   // interpreted but its pc is in the code cache (for c1 -> osr_frame_return_id stub), so it must be
   // explicitly recognized.
 
-  adjusted_stack = is_interpreted_frame();
-  if (adjusted_stack) {
+  bool frame_is_interpreted = is_interpreted_frame();
+  if (frame_is_interpreted) {
     map->make_integer_regs_unsaved();
     map->shift_window(sp, younger_sp);
   } else if (_cb != NULL) {
@@ -503,7 +516,7 @@
       }
     }
   }
-  return frame(sp, younger_sp, adjusted_stack);
+  return frame(sp, younger_sp, frame_is_interpreted);
 }
 
 
--- a/src/cpu/sparc/vm/interp_masm_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/interp_masm_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -720,25 +720,30 @@
 
 
 void InterpreterMacroAssembler::get_cache_index_at_bcp(Register cache, Register tmp,
-                                                       int bcp_offset, bool giant_index) {
+                                                       int bcp_offset, size_t index_size) {
   assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
-  if (!giant_index) {
+  if (index_size == sizeof(u2)) {
     get_2_byte_integer_at_bcp(bcp_offset, cache, tmp, Unsigned);
-  } else {
+  } else if (index_size == sizeof(u4)) {
     assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic");
     get_4_byte_integer_at_bcp(bcp_offset, cache, tmp);
     assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
     xor3(tmp, -1, tmp);  // convert to plain index
+  } else if (index_size == sizeof(u1)) {
+    assert(EnableMethodHandles, "tiny index used only for EnableMethodHandles");
+    ldub(Lbcp, bcp_offset, tmp);
+  } else {
+    ShouldNotReachHere();
   }
 }
 
 
 void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register tmp,
-                                                           int bcp_offset, bool giant_index) {
+                                                           int bcp_offset, size_t index_size) {
   assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
   assert_different_registers(cache, tmp);
   assert_not_delayed();
-  get_cache_index_at_bcp(cache, tmp, bcp_offset, giant_index);
+  get_cache_index_at_bcp(cache, tmp, bcp_offset, index_size);
   // convert from field index to ConstantPoolCacheEntry index and from
   // word index to byte offset
   sll(tmp, exact_log2(in_words(ConstantPoolCacheEntry::size()) * BytesPerWord), tmp);
@@ -747,12 +752,15 @@
 
 
 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp,
-                                                               int bcp_offset, bool giant_index) {
+                                                               int bcp_offset, size_t index_size) {
   assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
   assert_different_registers(cache, tmp);
   assert_not_delayed();
-  assert(!giant_index,"NYI");
-  get_2_byte_integer_at_bcp(bcp_offset, cache, tmp, Unsigned);
+  if (index_size == sizeof(u2)) {
+    get_2_byte_integer_at_bcp(bcp_offset, cache, tmp, Unsigned);
+  } else {
+    ShouldNotReachHere();  // other sizes not supported here
+  }
               // convert from field index to ConstantPoolCacheEntry index
               // and from word index to byte offset
   sll(tmp, exact_log2(in_words(ConstantPoolCacheEntry::size()) * BytesPerWord), tmp);
--- a/src/cpu/sparc/vm/interp_masm_sparc.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/interp_masm_sparc.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -182,9 +182,9 @@
                                   Register   Rdst,
                                   setCCOrNot should_set_CC = dont_set_CC );
 
-  void get_cache_and_index_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false);
-  void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false);
-  void get_cache_index_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false);
+  void get_cache_and_index_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
+  void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
+  void get_cache_index_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
 
 
   // common code
--- a/src/cpu/sparc/vm/methodHandles_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -375,10 +375,10 @@
       Register O0_scratch = O0_argslot;
       int stackElementSize = Interpreter::stackElementSize;
 
-      // Make space on the stack for the arguments.
-      __ sub(SP,    4*stackElementSize, SP);
-      __ sub(Gargs, 3*stackElementSize, Gargs);
-      //__ sub(Lesp,  3*stackElementSize, Lesp);
+      // Make space on the stack for the arguments and set Gargs
+      // correctly.
+      __ sub(SP, 4*stackElementSize, SP);  // Keep stack aligned.
+      __ add(SP, (frame::varargs_offset)*wordSize - 1*Interpreter::stackElementSize + STACK_BIAS + BytesPerWord, Gargs);
 
       // void raiseException(int code, Object actual, Object required)
       __ st(    O1_scratch, Address(Gargs, 2*stackElementSize));  // code
--- a/src/cpu/sparc/vm/nativeInst_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/nativeInst_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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/src/cpu/sparc/vm/register_definitions_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/register_definitions_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. 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
@@ -142,9 +142,12 @@
 REGISTER_DEFINITION(Register, G3_scratch);
 REGISTER_DEFINITION(Register, G4_scratch);
 REGISTER_DEFINITION(Register, Gtemp);
+REGISTER_DEFINITION(Register, Lentry_args);
+
+// JSR 292
 REGISTER_DEFINITION(Register, G5_method_type);
 REGISTER_DEFINITION(Register, G3_method_handle);
-REGISTER_DEFINITION(Register, Lentry_args);
+REGISTER_DEFINITION(Register, L7_mh_SP_save);
 
 #ifdef CC_INTERP
 REGISTER_DEFINITION(Register, Lstate);
--- a/src/cpu/sparc/vm/runtime_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/runtime_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. 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
@@ -116,6 +116,11 @@
   __ mov(O0, G3_scratch);             // Move handler address to temp
   __ restore();
 
+  // Restore SP from L7 if the exception PC is a MethodHandle call site.
+  __ lduw(Address(G2_thread, JavaThread::is_method_handle_return_offset()), O7);
+  __ tst(O7);
+  __ movcc(Assembler::notZero, false, Assembler::icc, L7_mh_SP_save, SP);
+
   // G3_scratch contains handler address
   // Since this may be the deopt blob we must set O7 to look like we returned
   // from the original pc that threw the exception
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -908,26 +908,13 @@
   // O0-O5          - Outgoing args in compiled layout
   // O6             - Adjusted or restored SP
   // O7             - Valid return address
-  // L0-L7, I0-I7    - Caller's temps (no frame pushed yet)
+  // L0-L7, I0-I7   - Caller's temps (no frame pushed yet)
   // F0-F7          - more outgoing args
 
 
   // Gargs is the incoming argument base, and also an outgoing argument.
   __ sub(Gargs, BytesPerWord, Gargs);
 
-#ifdef ASSERT
-  {
-    // on entry OsavedSP and SP should be equal
-    Label ok;
-    __ cmp(O5_savedSP, SP);
-    __ br(Assembler::equal, false, Assembler::pt, ok);
-    __ delayed()->nop();
-    __ stop("I5_savedSP not set");
-    __ should_not_reach_here();
-    __ bind(ok);
-  }
-#endif
-
   // ON ENTRY TO THE CODE WE ARE MAKING, WE HAVE AN INTERPRETED FRAME
   // WITH O7 HOLDING A VALID RETURN PC
   //
--- a/src/cpu/sparc/vm/sparc.ad	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/sparc.ad	Wed Jun 02 22:45:42 2010 -0700
@@ -534,7 +534,10 @@
 //       The "return address" is the address of the call instruction, plus 8.
 
 int MachCallStaticJavaNode::ret_addr_offset() {
-  return NativeCall::instruction_size;  // call; delay slot
+  int offset = NativeCall::instruction_size;  // call; delay slot
+  if (_method_handle_invoke)
+    offset += 4;  // restore SP
+  return offset;
 }
 
 int MachCallDynamicJavaNode::ret_addr_offset() {
@@ -818,6 +821,10 @@
           !(n->ideal_Opcode()==Op_ConvI2D   && ld_op==Op_LoadF) &&
           !(n->ideal_Opcode()==Op_PrefetchRead  && ld_op==Op_LoadI) &&
           !(n->ideal_Opcode()==Op_PrefetchWrite && ld_op==Op_LoadI) &&
+          !(n->ideal_Opcode()==Op_Load2I    && ld_op==Op_LoadD) &&
+          !(n->ideal_Opcode()==Op_Load4C    && ld_op==Op_LoadD) &&
+          !(n->ideal_Opcode()==Op_Load4S    && ld_op==Op_LoadD) &&
+          !(n->ideal_Opcode()==Op_Load8B    && ld_op==Op_LoadD) &&
           !(n->rule() == loadUB_rule)) {
         verify_oops_warning(n, n->ideal_Opcode(), ld_op);
       }
@@ -829,6 +836,9 @@
           !(n->ideal_Opcode()==Op_StoreI && st_op==Op_StoreF) &&
           !(n->ideal_Opcode()==Op_StoreF && st_op==Op_StoreI) &&
           !(n->ideal_Opcode()==Op_StoreL && st_op==Op_StoreI) &&
+          !(n->ideal_Opcode()==Op_Store2I && st_op==Op_StoreD) &&
+          !(n->ideal_Opcode()==Op_Store4C && st_op==Op_StoreD) &&
+          !(n->ideal_Opcode()==Op_Store8B && st_op==Op_StoreD) &&
           !(n->ideal_Opcode()==Op_StoreD && st_op==Op_StoreI && n->rule() == storeD0_rule)) {
         verify_oops_warning(n, n->ideal_Opcode(), st_op);
       }
@@ -1750,6 +1760,12 @@
 // registers?  True for Intel but false for most RISCs
 const bool Matcher::clone_shift_expressions = false;
 
+bool Matcher::narrow_oop_use_complex_address() {
+  NOT_LP64(ShouldNotCallThis());
+  assert(UseCompressedOops, "only for compressed oops code");
+  return false;
+}
+
 // Is it better to copy float constants, or load them directly from memory?
 // Intel can load a float constant from a direct address, requiring no
 // extra registers.  Most RISCs will have to materialize an address into a
@@ -1858,7 +1874,7 @@
 }
 
 const RegMask Matcher::method_handle_invoke_SP_save_mask() {
-  return RegMask();
+  return L7_REGP_mask;
 }
 
 %}
@@ -2441,6 +2457,16 @@
                     /*preserve_g2=*/true, /*force far call*/true);
   %}
 
+  enc_class preserve_SP %{
+    MacroAssembler _masm(&cbuf);
+    __ mov(SP, L7_mh_SP_save);
+  %}
+
+  enc_class restore_SP %{
+    MacroAssembler _masm(&cbuf);
+    __ mov(L7_mh_SP_save, SP);
+  %}
+
   enc_class Java_Static_Call (method meth) %{    // JAVA STATIC CALL
     // CALL to fixup routine.  Fixup routine uses ScopeDesc info to determine
     // who we intended to call.
@@ -9213,6 +9239,7 @@
 // Call Java Static Instruction
 instruct CallStaticJavaDirect( method meth ) %{
   match(CallStaticJava);
+  predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke());
   effect(USE meth);
 
   size(8);
@@ -9223,6 +9250,20 @@
   ins_pipe(simple_call);
 %}
 
+// Call Java Static Instruction (method handle version)
+instruct CallStaticJavaHandle(method meth, l7RegP l7_mh_SP_save) %{
+  match(CallStaticJava);
+  predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
+  effect(USE meth, KILL l7_mh_SP_save);
+
+  size(8);
+  ins_cost(CALL_COST);
+  format %{ "CALL,static/MethodHandle" %}
+  ins_encode(preserve_SP, Java_Static_Call(meth), restore_SP, call_epilog);
+  ins_pc_relative(1);
+  ins_pipe(simple_call);
+%}
+
 // Call Java Dynamic Instruction
 instruct CallDynamicJavaDirect( method meth ) %{
   match(CallDynamicJava);
--- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -2911,16 +2911,6 @@
     // arraycopy stubs used by compilers
     generate_arraycopy_stubs();
 
-    // generic method handle stubs
-    if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) {
-      for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
-           ek < MethodHandles::_EK_LIMIT;
-           ek = MethodHandles::EntryKind(1 + (int)ek)) {
-        StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek));
-        MethodHandles::generate_method_handle_stub(_masm, ek);
-      }
-    }
-
     // Don't initialize the platform math functions since sparc
     // doesn't have intrinsics for these operations.
   }
--- a/src/cpu/sparc/vm/stubRoutines_sparc.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/stubRoutines_sparc.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -43,7 +43,7 @@
 
 // MethodHandles adapters
 enum method_handles_platform_dependent_constants {
-  method_handles_adapters_code_size = 5000
+  method_handles_adapters_code_size = 6000
 };
 
 class Sparc {
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -204,7 +204,7 @@
   // out of the main line of code...
   if (EnableInvokeDynamic) {
     __ bind(L_giant_index);
-    __ get_cache_and_index_at_bcp(cache, G1_scratch, 1, true);
+    __ get_cache_and_index_at_bcp(cache, G1_scratch, 1, sizeof(u4));
     __ ba(false, L_got_cache);
     __ delayed()->nop();
   }
--- a/src/cpu/sparc/vm/templateTable_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/templateTable_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1949,23 +1949,30 @@
 }
 
 // ----------------------------------------------------------------------------
-void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) {
-  assert(byte_no == 1 || byte_no == 2, "byte_no out of range");
-  bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic);
-
+void TemplateTable::resolve_cache_and_index(int byte_no,
+                                            Register result,
+                                            Register Rcache,
+                                            Register index,
+                                            size_t index_size) {
   // Depends on cpCacheOop layout!
-  const int shift_count = (1 + byte_no)*BitsPerByte;
   Label resolved;
 
-  __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
-  if (is_invokedynamic) {
-    // We are resolved if the f1 field contains a non-null CallSite object.
+  __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
+  if (byte_no == f1_oop) {
+    // We are resolved if the f1 field contains a non-null object (CallSite, etc.)
+    // This kind of CP cache entry does not need to match the flags byte, because
+    // there is a 1-1 relation between bytecode type and CP entry type.
+    assert_different_registers(result, Rcache);
     __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() +
-              ConstantPoolCacheEntry::f1_offset(), Lbyte_code);
-    __ tst(Lbyte_code);
+              ConstantPoolCacheEntry::f1_offset(), result);
+    __ tst(result);
     __ br(Assembler::notEqual, false, Assembler::pt, resolved);
     __ delayed()->set((int)bytecode(), O1);
   } else {
+    assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
+    assert(result == noreg, "");  //else change code for setting result
+    const int shift_count = (1 + byte_no)*BitsPerByte;
+
     __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() +
               ConstantPoolCacheEntry::indices_offset(), Lbyte_code);
 
@@ -1992,7 +1999,10 @@
   // first time invocation - must resolve first
   __ call_VM(noreg, entry, O1);
   // Update registers with resolved info
-  __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
+  __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
+  if (result != noreg)
+    __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() +
+              ConstantPoolCacheEntry::f1_offset(), result);
   __ bind(resolved);
 }
 
@@ -2001,7 +2011,8 @@
                                                Register Ritable_index,
                                                Register Rflags,
                                                bool is_invokevirtual,
-                                               bool is_invokevfinal) {
+                                               bool is_invokevfinal,
+                                               bool is_invokedynamic) {
   // Uses both G3_scratch and G4_scratch
   Register Rcache = G3_scratch;
   Register Rscratch = G4_scratch;
@@ -2025,11 +2036,15 @@
 
   if (is_invokevfinal) {
     __ get_cache_and_index_at_bcp(Rcache, Rscratch, 1);
+    __ ld_ptr(Rcache, method_offset, Rmethod);
+  } else if (byte_no == f1_oop) {
+    // Resolved f1_oop goes directly into 'method' register.
+    resolve_cache_and_index(byte_no, Rmethod, Rcache, Rscratch, sizeof(u4));
   } else {
-    resolve_cache_and_index(byte_no, Rcache, Rscratch);
+    resolve_cache_and_index(byte_no, noreg, Rcache, Rscratch, sizeof(u2));
+    __ ld_ptr(Rcache, method_offset, Rmethod);
   }
 
-  __ ld_ptr(Rcache, method_offset, Rmethod);
   if (Ritable_index != noreg) {
     __ ld_ptr(Rcache, index_offset, Ritable_index);
   }
@@ -2110,7 +2125,7 @@
   Register Rflags = G1_scratch;
   ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset();
 
-  resolve_cache_and_index(byte_no, Rcache, index);
+  resolve_cache_and_index(byte_no, noreg, Rcache, index, sizeof(u2));
   jvmti_post_field_access(Rcache, index, is_static, false);
   load_field_cp_cache_entry(Rclass, Rcache, index, Roffset, Rflags, is_static);
 
@@ -2475,7 +2490,7 @@
   Register Rflags = G1_scratch;
   ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset();
 
-  resolve_cache_and_index(byte_no, Rcache, index);
+  resolve_cache_and_index(byte_no, noreg, Rcache, index, sizeof(u2));
   jvmti_post_field_mod(Rcache, index, is_static);
   load_field_cp_cache_entry(Rclass, Rcache, index, Roffset, Rflags, is_static);
 
@@ -2816,6 +2831,7 @@
 
 void TemplateTable::invokevirtual(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f2_byte, "use this argument");
 
   Register Rscratch = G3_scratch;
   Register Rtemp = G4_scratch;
@@ -2823,7 +2839,7 @@
   Register Rrecv = G5_method;
   Label notFinal;
 
-  load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, true);
+  load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, true, false, false);
   __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
 
   // Check for vfinal
@@ -2864,9 +2880,10 @@
 
 void TemplateTable::fast_invokevfinal(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f2_byte, "use this argument");
 
   load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Lscratch, true,
-                             /*is_invokevfinal*/true);
+                             /*is_invokevfinal*/true, false);
   __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
   invokevfinal_helper(G3_scratch, Lscratch);
 }
@@ -2901,12 +2918,13 @@
 
 void TemplateTable::invokespecial(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f1_byte, "use this argument");
 
   Register Rscratch = G3_scratch;
   Register Rtemp = G4_scratch;
   Register Rret = Lscratch;
 
-  load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, false);
+  load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, /*virtual*/ false, false, false);
   __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
 
   __ verify_oop(G5_method);
@@ -2934,12 +2952,13 @@
 
 void TemplateTable::invokestatic(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f1_byte, "use this argument");
 
   Register Rscratch = G3_scratch;
   Register Rtemp = G4_scratch;
   Register Rret = Lscratch;
 
-  load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, false);
+  load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, /*virtual*/ false, false, false);
   __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
 
   __ verify_oop(G5_method);
@@ -2992,6 +3011,7 @@
 
 void TemplateTable::invokeinterface(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f1_byte, "use this argument");
 
   Register Rscratch = G4_scratch;
   Register Rret = G3_scratch;
@@ -3001,7 +3021,7 @@
   Register Rflags = O1;
   assert_different_registers(Rscratch, G5_method);
 
-  load_invoke_cp_cache_entry(byte_no, Rinterface, Rindex, Rflags, false);
+  load_invoke_cp_cache_entry(byte_no, Rinterface, Rindex, Rflags, /*virtual*/ false, false, false);
   __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
 
   // get receiver
@@ -3118,6 +3138,7 @@
 
 void TemplateTable::invokedynamic(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f1_oop, "use this argument");
 
   if (!EnableInvokeDynamic) {
     // We should not encounter this bytecode if !EnableInvokeDynamic.
@@ -3132,7 +3153,6 @@
 
   // G5: CallSite object (f1)
   // XX: unused (f2)
-  // G3: receiver address
   // XX: flags (unused)
 
   Register G5_callsite = G5_method;
@@ -3140,7 +3160,8 @@
   Register Rtemp       = G1_scratch;
   Register Rret        = Lscratch;
 
-  load_invoke_cp_cache_entry(byte_no, G5_callsite, noreg, Rret, false);
+  load_invoke_cp_cache_entry(byte_no, G5_callsite, noreg, Rret,
+                             /*virtual*/ false, /*vfinal*/ false, /*indy*/ true);
   __ mov(SP, O5_savedSP);  // record SP that we wanted the callee to restore
 
   __ verify_oop(G5_callsite);
--- a/src/cpu/sparc/vm/vm_version_sparc.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/sparc/vm/vm_version_sparc.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -65,13 +65,6 @@
       FLAG_SET_DEFAULT(UseInlineCaches, false);
     }
 #ifdef _LP64
-    // Single issue niagara1 is slower for CompressedOops
-    // but niagaras after that it's fine.
-    if (!is_niagara1_plus()) {
-      if (FLAG_IS_DEFAULT(UseCompressedOops)) {
-        FLAG_SET_ERGO(bool, UseCompressedOops, false);
-      }
-    }
     // 32-bit oops don't make sense for the 64-bit VM on sparc
     // since the 32-bit VM has the same registers and smaller objects.
     Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
--- a/src/cpu/x86/vm/assembler_x86.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/assembler_x86.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -8185,9 +8185,14 @@
     assert (Universe::heap() != NULL, "java heap should be initialized");
     movl(dst, Address(src, oopDesc::klass_offset_in_bytes()));
     if (Universe::narrow_oop_shift() != 0) {
-      assert(Address::times_8 == LogMinObjAlignmentInBytes &&
-             Address::times_8 == Universe::narrow_oop_shift(), "decode alg wrong");
-      movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
+      assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
+      if (LogMinObjAlignmentInBytes == Address::times_8) {
+        movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
+      } else {
+        // OK to use shift since we don't need to preserve flags.
+        shlq(dst, LogMinObjAlignmentInBytes);
+        movq(dst, Address(r12_heapbase, dst, Address::times_1, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
+      }
     } else {
       movq(dst, Address(dst, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
     }
@@ -8361,31 +8366,43 @@
 }
 
 void  MacroAssembler::decode_heap_oop_not_null(Register r) {
+  // Note: it will change flags
   assert (UseCompressedOops, "should only be used for compressed headers");
   assert (Universe::heap() != NULL, "java heap should be initialized");
   // Cannot assert, unverified entry point counts instructions (see .ad file)
   // vtableStubs also counts instructions in pd_code_size_limit.
   // Also do not verify_oop as this is called by verify_oop.
   if (Universe::narrow_oop_shift() != 0) {
-    assert (Address::times_8 == LogMinObjAlignmentInBytes &&
-            Address::times_8 == Universe::narrow_oop_shift(), "decode alg wrong");
-    // Don't use Shift since it modifies flags.
-    leaq(r, Address(r12_heapbase, r, Address::times_8, 0));
+    assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
+    shlq(r, LogMinObjAlignmentInBytes);
+    if (Universe::narrow_oop_base() != NULL) {
+      addq(r, r12_heapbase);
+    }
   } else {
     assert (Universe::narrow_oop_base() == NULL, "sanity");
   }
 }
 
 void  MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) {
+  // Note: it will change flags
   assert (UseCompressedOops, "should only be used for compressed headers");
   assert (Universe::heap() != NULL, "java heap should be initialized");
   // Cannot assert, unverified entry point counts instructions (see .ad file)
   // vtableStubs also counts instructions in pd_code_size_limit.
   // Also do not verify_oop as this is called by verify_oop.
   if (Universe::narrow_oop_shift() != 0) {
-    assert (Address::times_8 == LogMinObjAlignmentInBytes &&
-            Address::times_8 == Universe::narrow_oop_shift(), "decode alg wrong");
-    leaq(dst, Address(r12_heapbase, src, Address::times_8, 0));
+    assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
+    if (LogMinObjAlignmentInBytes == Address::times_8) {
+      leaq(dst, Address(r12_heapbase, src, Address::times_8, 0));
+    } else {
+      if (dst != src) {
+        movq(dst, src);
+      }
+      shlq(dst, LogMinObjAlignmentInBytes);
+      if (Universe::narrow_oop_base() != NULL) {
+        addq(dst, r12_heapbase);
+      }
+    }
   } else if (dst != src) {
     assert (Universe::narrow_oop_base() == NULL, "sanity");
     movq(dst, src);
--- a/src/cpu/x86/vm/assembler_x86.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/assembler_x86.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -135,6 +135,9 @@
 
 #endif // _LP64
 
+// JSR 292 fixed register usages:
+REGISTER_DECLARATION(Register, rbp_mh_SP_save, rbp);
+
 // Address is an abstraction used to represent a memory location
 // using any of the amd64 addressing modes with one object.
 //
--- a/src/cpu/x86/vm/c1_FrameMap_x86.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/c1_FrameMap_x86.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. 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
@@ -309,6 +309,13 @@
 }
 
 
+// JSR 292
+LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
+  assert(rbp == rbp_mh_SP_save, "must be same register");
+  return rbp_opr;
+}
+
+
 bool FrameMap::validate_frame() {
   return true;
 }
--- a/src/cpu/x86/vm/c1_FrameMap_x86.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/c1_FrameMap_x86.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -126,6 +126,3 @@
     assert(i >= 0 && i < nof_caller_save_xmm_regs, "out of bounds");
     return _caller_save_xmm_regs[i];
   }
-
-  // JSR 292
-  static LIR_Opr& method_handle_invoke_SP_save_opr() { return rbp_opr; }
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -2462,9 +2462,18 @@
       }
 #endif // _LP64
     } else {
+#ifdef _LP64
+      Register r_lo;
+      if (right->type() == T_OBJECT || right->type() == T_ARRAY) {
+        r_lo = right->as_register();
+      } else {
+        r_lo = right->as_register_lo();
+      }
+#else
       Register r_lo = right->as_register_lo();
       Register r_hi = right->as_register_hi();
       assert(l_lo != r_hi, "overwriting registers");
+#endif
       switch (code) {
         case lir_logic_and:
           __ andptr(l_lo, r_lo);
@@ -2784,7 +2793,7 @@
   assert(!os::is_MP() || (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0,
          "must be aligned");
   __ call(AddressLiteral(op->addr(), rtype));
-  add_call_info(code_offset(), op->info(), op->is_method_handle_invoke());
+  add_call_info(code_offset(), op->info());
 }
 
 
@@ -2795,7 +2804,7 @@
          (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0,
          "must be aligned");
   __ call(AddressLiteral(op->addr(), rh));
-  add_call_info(code_offset(), op->info(), op->is_method_handle_invoke());
+  add_call_info(code_offset(), op->info());
 }
 
 
@@ -2805,16 +2814,6 @@
 }
 
 
-void LIR_Assembler::preserve_SP(LIR_OpJavaCall* op) {
-  __ movptr(FrameMap::method_handle_invoke_SP_save_opr()->as_register(), rsp);
-}
-
-
-void LIR_Assembler::restore_SP(LIR_OpJavaCall* op) {
-  __ movptr(rsp, FrameMap::method_handle_invoke_SP_save_opr()->as_register());
-}
-
-
 void LIR_Assembler::emit_static_call_stub() {
   address call_pc = __ pc();
   address stub = __ start_a_stub(call_stub_size);
--- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -175,7 +175,7 @@
     // store and again for the card mark.
     LIR_Opr tmp = new_pointer_register();
     __ leal(LIR_OprFact::address(addr), tmp);
-    return new LIR_Address(tmp, 0, type);
+    return new LIR_Address(tmp, type);
   } else {
     return addr;
   }
@@ -185,7 +185,7 @@
 void LIRGenerator::increment_counter(address counter, int step) {
   LIR_Opr pointer = new_pointer_register();
   __ move(LIR_OprFact::intptrConst(counter), pointer);
-  LIR_Address* addr = new LIR_Address(pointer, 0, T_INT);
+  LIR_Address* addr = new LIR_Address(pointer, T_INT);
   increment_counter(addr, step);
 }
 
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -782,7 +782,7 @@
   // Restore SP from BP if the exception PC is a MethodHandle call site.
   NOT_LP64(__ get_thread(thread);)
   __ cmpl(Address(thread, JavaThread::is_method_handle_return_offset()), 0);
-  __ cmovptr(Assembler::notEqual, rsp, rbp);
+  __ cmovptr(Assembler::notEqual, rsp, rbp_mh_SP_save);
 
   // continue at exception handler (return address removed)
   // note: do *not* remove arguments when unwinding the
@@ -1581,7 +1581,6 @@
           __ should_not_reach_here();
           break;
         }
-
         __ push(rax);
         __ push(rdx);
 
@@ -1605,8 +1604,8 @@
 
         // Can we store original value in the thread's buffer?
 
-        LP64_ONLY(__ movslq(tmp, queue_index);)
 #ifdef _LP64
+        __ movslq(tmp, queue_index);
         __ cmpq(tmp, 0);
 #else
         __ cmpl(queue_index, 0);
@@ -1628,13 +1627,33 @@
         __ jmp(done);
 
         __ bind(runtime);
+        __ push(rcx);
+#ifdef _LP64
+        __ push(r8);
+        __ push(r9);
+        __ push(r10);
+        __ push(r11);
+#  ifndef _WIN64
+        __ push(rdi);
+        __ push(rsi);
+#  endif
+#endif
         // load the pre-value
-        __ push(rcx);
         f.load_argument(0, rcx);
         __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), rcx, thread);
+#ifdef _LP64
+#  ifndef _WIN64
+        __ pop(rsi);
+        __ pop(rdi);
+#  endif
+        __ pop(r11);
+        __ pop(r10);
+        __ pop(r9);
+        __ pop(r8);
+#endif
         __ pop(rcx);
+        __ bind(done);
 
-        __ bind(done);
         __ pop(rdx);
         __ pop(rax);
       }
@@ -1664,13 +1683,13 @@
                                         PtrQueue::byte_offset_of_buf()));
 
         __ push(rax);
-        __ push(rdx);
+        __ push(rcx);
 
         NOT_LP64(__ get_thread(thread);)
         ExternalAddress cardtable((address)ct->byte_map_base);
         assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
 
-        const Register card_addr = rdx;
+        const Register card_addr = rcx;
 #ifdef _LP64
         const Register tmp = rscratch1;
         f.load_argument(0, card_addr);
@@ -1679,7 +1698,7 @@
         // get the address of the card
         __ addq(card_addr, tmp);
 #else
-        const Register card_index = rdx;
+        const Register card_index = rcx;
         f.load_argument(0, card_index);
         __ shrl(card_index, CardTableModRefBS::card_shift);
 
@@ -1716,12 +1735,32 @@
         __ jmp(done);
 
         __ bind(runtime);
-        NOT_LP64(__ push(rcx);)
+        __ push(rdx);
+#ifdef _LP64
+        __ push(r8);
+        __ push(r9);
+        __ push(r10);
+        __ push(r11);
+#  ifndef _WIN64
+        __ push(rdi);
+        __ push(rsi);
+#  endif
+#endif
         __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread);
-        NOT_LP64(__ pop(rcx);)
+#ifdef _LP64
+#  ifndef _WIN64
+        __ pop(rsi);
+        __ pop(rdi);
+#  endif
+        __ pop(r11);
+        __ pop(r10);
+        __ pop(r9);
+        __ pop(r8);
+#endif
+        __ pop(rdx);
+        __ bind(done);
 
-        __ bind(done);
-        __ pop(rdx);
+        __ pop(rcx);
         __ pop(rax);
 
       }
--- a/src/cpu/x86/vm/interp_masm_x86_32.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -189,11 +189,11 @@
 }
 
 
-void InterpreterMacroAssembler::get_cache_index_at_bcp(Register reg, int bcp_offset, bool giant_index) {
+void InterpreterMacroAssembler::get_cache_index_at_bcp(Register reg, int bcp_offset, size_t index_size) {
   assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
-  if (!giant_index) {
+  if (index_size == sizeof(u2)) {
     load_unsigned_short(reg, Address(rsi, bcp_offset));
-  } else {
+  } else if (index_size == sizeof(u4)) {
     assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic");
     movl(reg, Address(rsi, bcp_offset));
     // Check if the secondary index definition is still ~x, otherwise
@@ -201,14 +201,19 @@
     // plain index.
     assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
     notl(reg);  // convert to plain index
+  } else if (index_size == sizeof(u1)) {
+    assert(EnableMethodHandles, "tiny index used only for EnableMethodHandles");
+    load_unsigned_byte(reg, Address(rsi, bcp_offset));
+  } else {
+    ShouldNotReachHere();
   }
 }
 
 
 void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index,
-                                                           int bcp_offset, bool giant_index) {
+                                                           int bcp_offset, size_t index_size) {
   assert(cache != index, "must use different registers");
-  get_cache_index_at_bcp(index, bcp_offset, giant_index);
+  get_cache_index_at_bcp(index, bcp_offset, index_size);
   movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
   assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below");
   shlptr(index, 2); // convert from field index to ConstantPoolCacheEntry index
@@ -216,9 +221,9 @@
 
 
 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp,
-                                                               int bcp_offset, bool giant_index) {
+                                                               int bcp_offset, size_t index_size) {
   assert(cache != tmp, "must use different register");
-  get_cache_index_at_bcp(tmp, bcp_offset, giant_index);
+  get_cache_index_at_bcp(tmp, bcp_offset, index_size);
   assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below");
                                // convert from field index to ConstantPoolCacheEntry index
                                // and from word offset to byte offset
--- a/src/cpu/x86/vm/interp_masm_x86_32.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/interp_masm_x86_32.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -76,9 +76,9 @@
   void get_cpool_and_tags(Register cpool, Register tags)   { get_constant_pool(cpool); movptr(tags, Address(cpool, constantPoolOopDesc::tags_offset_in_bytes()));
   }
   void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
-  void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, bool giant_index = false);
-  void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false);
-  void get_cache_index_at_bcp(Register index, int bcp_offset, bool giant_index = false);
+  void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2));
+  void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
+  void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2));
 
   // Expression stack
   void f2ieee();                                           // truncate ftos to 32bits
--- a/src/cpu/x86/vm/interp_masm_x86_64.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -187,11 +187,11 @@
 
 void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
                                                        int bcp_offset,
-                                                       bool giant_index) {
+                                                       size_t index_size) {
   assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
-  if (!giant_index) {
+  if (index_size == sizeof(u2)) {
     load_unsigned_short(index, Address(r13, bcp_offset));
-  } else {
+  } else if (index_size == sizeof(u4)) {
     assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic");
     movl(index, Address(r13, bcp_offset));
     // Check if the secondary index definition is still ~x, otherwise
@@ -199,6 +199,11 @@
     // plain index.
     assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
     notl(index);  // convert to plain index
+  } else if (index_size == sizeof(u1)) {
+    assert(EnableMethodHandles, "tiny index used only for EnableMethodHandles");
+    load_unsigned_byte(index, Address(r13, bcp_offset));
+  } else {
+    ShouldNotReachHere();
   }
 }
 
@@ -206,9 +211,9 @@
 void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache,
                                                            Register index,
                                                            int bcp_offset,
-                                                           bool giant_index) {
+                                                           size_t index_size) {
   assert(cache != index, "must use different registers");
-  get_cache_index_at_bcp(index, bcp_offset, giant_index);
+  get_cache_index_at_bcp(index, bcp_offset, index_size);
   movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
   assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
   // convert from field index to ConstantPoolCacheEntry index
@@ -219,9 +224,9 @@
 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
                                                                Register tmp,
                                                                int bcp_offset,
-                                                               bool giant_index) {
+                                                               size_t index_size) {
   assert(cache != tmp, "must use different register");
-  get_cache_index_at_bcp(tmp, bcp_offset, giant_index);
+  get_cache_index_at_bcp(tmp, bcp_offset, index_size);
   assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
   // convert from field index to ConstantPoolCacheEntry index
   // and from word offset to byte offset
--- a/src/cpu/x86/vm/interp_masm_x86_64.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/interp_masm_x86_64.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -95,10 +95,10 @@
 
   void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
   void get_cache_and_index_at_bcp(Register cache, Register index,
-                                  int bcp_offset, bool giant_index = false);
+                                  int bcp_offset, size_t index_size = sizeof(u2));
   void get_cache_entry_pointer_at_bcp(Register cache, Register tmp,
-                                      int bcp_offset, bool giant_index = false);
-  void get_cache_index_at_bcp(Register index, int bcp_offset, bool giant_index = false);
+                                      int bcp_offset, size_t index_size = sizeof(u2));
+  void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2));
 
 
   void pop_ptr(Register r = rax);
--- a/src/cpu/x86/vm/register_definitions_x86.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/register_definitions_x86.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. 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,3 +115,6 @@
 REGISTER_DEFINITION(MMXRegister, mmx5 );
 REGISTER_DEFINITION(MMXRegister, mmx6 );
 REGISTER_DEFINITION(MMXRegister, mmx7 );
+
+// JSR 292
+REGISTER_DEFINITION(Register, rbp_mh_SP_save);
--- a/src/cpu/x86/vm/runtime_x86_32.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/runtime_x86_32.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. 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
@@ -117,7 +117,7 @@
 
   // Restore SP from BP if the exception PC is a MethodHandle call site.
   __ cmpl(Address(rcx, JavaThread::is_method_handle_return_offset()), 0);
-  __ cmovptr(Assembler::notEqual, rsp, rbp);
+  __ cmovptr(Assembler::notEqual, rsp, rbp_mh_SP_save);
 
   // We have a handler in rax, (could be deopt blob)
   // rdx - throwing pc, deopt blob will need it.
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -3305,7 +3305,7 @@
 
   // Restore SP from BP if the exception PC is a MethodHandle call site.
   __ cmpl(Address(r15_thread, JavaThread::is_method_handle_return_offset()), 0);
-  __ cmovptr(Assembler::notEqual, rsp, rbp);
+  __ cmovptr(Assembler::notEqual, rsp, rbp_mh_SP_save);
 
   // We have a handler in rax (could be deopt blob).
   __ mov(r8, rax);
--- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -214,7 +214,7 @@
     __ cmpb(Address(rsi, 0), Bytecodes::_invokedynamic);
     __ jcc(Assembler::equal, L_giant_index);
   }
-  __ get_cache_and_index_at_bcp(rbx, rcx, 1, false);
+  __ get_cache_and_index_at_bcp(rbx, rcx, 1, sizeof(u2));
   __ bind(L_got_cache);
   __ movl(rbx, Address(rbx, rcx,
                     Address::times_ptr, constantPoolCacheOopDesc::base_offset() +
@@ -226,7 +226,7 @@
   // out of the main line of code...
   if (EnableInvokeDynamic) {
     __ bind(L_giant_index);
-    __ get_cache_and_index_at_bcp(rbx, rcx, 1, true);
+    __ get_cache_and_index_at_bcp(rbx, rcx, 1, sizeof(u4));
     __ jmp(L_got_cache);
   }
 
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -192,7 +192,7 @@
     __ cmpb(Address(r13, 0), Bytecodes::_invokedynamic);
     __ jcc(Assembler::equal, L_giant_index);
   }
-  __ get_cache_and_index_at_bcp(rbx, rcx, 1, false);
+  __ get_cache_and_index_at_bcp(rbx, rcx, 1, sizeof(u2));
   __ bind(L_got_cache);
   __ movl(rbx, Address(rbx, rcx,
                        Address::times_ptr,
@@ -205,7 +205,7 @@
   // out of the main line of code...
   if (EnableInvokeDynamic) {
     __ bind(L_giant_index);
-    __ get_cache_and_index_at_bcp(rbx, rcx, 1, true);
+    __ get_cache_and_index_at_bcp(rbx, rcx, 1, sizeof(u4));
     __ jmp(L_got_cache);
   }
 
--- a/src/cpu/x86/vm/templateTable_x86_32.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/templateTable_x86_32.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -2012,22 +2012,29 @@
   __ membar(order_constraint);
 }
 
-void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) {
-  assert(byte_no == 1 || byte_no == 2, "byte_no out of range");
-  bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic);
-
+void TemplateTable::resolve_cache_and_index(int byte_no,
+                                            Register result,
+                                            Register Rcache,
+                                            Register index,
+                                            size_t index_size) {
   Register temp = rbx;
 
-  assert_different_registers(Rcache, index, temp);
-
-  const int shift_count = (1 + byte_no)*BitsPerByte;
+  assert_different_registers(result, Rcache, index, temp);
+
   Label resolved;
-  __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
-  if (is_invokedynamic) {
-    // we are resolved if the f1 field contains a non-null CallSite object
-    __ cmpptr(Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD);
+  __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
+  if (byte_no == f1_oop) {
+    // We are resolved if the f1 field contains a non-null object (CallSite, etc.)
+    // This kind of CP cache entry does not need to match the flags byte, because
+    // there is a 1-1 relation between bytecode type and CP entry type.
+    assert(result != noreg, ""); //else do cmpptr(Address(...), (int32_t) NULL_WORD)
+    __ movptr(result, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()));
+    __ testptr(result, result);
     __ jcc(Assembler::notEqual, resolved);
   } else {
+    assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
+    assert(result == noreg, "");  //else change code for setting result
+    const int shift_count = (1 + byte_no)*BitsPerByte;
     __ movl(temp, Address(Rcache, index, Address::times_4, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
     __ shrl(temp, shift_count);
     // have we resolved this bytecode?
@@ -2053,7 +2060,9 @@
   __ movl(temp, (int)bytecode());
   __ call_VM(noreg, entry, temp);
   // Update registers with resolved info
-  __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
+  __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
+  if (result != noreg)
+    __ movptr(result, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()));
   __ bind(resolved);
 }
 
@@ -2087,7 +2096,8 @@
                                                Register itable_index,
                                                Register flags,
                                                bool is_invokevirtual,
-                                               bool is_invokevfinal /*unused*/) {
+                                               bool is_invokevfinal /*unused*/,
+                                               bool is_invokedynamic) {
   // setup registers
   const Register cache = rcx;
   const Register index = rdx;
@@ -2109,13 +2119,18 @@
   const int index_offset = in_bytes(constantPoolCacheOopDesc::base_offset() +
                                     ConstantPoolCacheEntry::f2_offset());
 
-  resolve_cache_and_index(byte_no, cache, index);
-
-  __ movptr(method, Address(cache, index, Address::times_ptr, method_offset));
+  if (byte_no == f1_oop) {
+    // Resolved f1_oop goes directly into 'method' register.
+    assert(is_invokedynamic, "");
+    resolve_cache_and_index(byte_no, method, cache, index, sizeof(u4));
+  } else {
+    resolve_cache_and_index(byte_no, noreg, cache, index, sizeof(u2));
+    __ movptr(method, Address(cache, index, Address::times_ptr, method_offset));
+  }
   if (itable_index != noreg) {
     __ movptr(itable_index, Address(cache, index, Address::times_ptr, index_offset));
   }
-  __ movl(flags , Address(cache, index, Address::times_ptr, flags_offset ));
+  __ movl(flags, Address(cache, index, Address::times_ptr, flags_offset));
 }
 
 
@@ -2169,7 +2184,7 @@
   const Register off   = rbx;
   const Register flags = rax;
 
-  resolve_cache_and_index(byte_no, cache, index);
+  resolve_cache_and_index(byte_no, noreg, cache, index, sizeof(u2));
   jvmti_post_field_access(cache, index, is_static, false);
   load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
 
@@ -2378,7 +2393,7 @@
   const Register off   = rbx;
   const Register flags = rax;
 
-  resolve_cache_and_index(byte_no, cache, index);
+  resolve_cache_and_index(byte_no, noreg, cache, index, sizeof(u2));
   jvmti_post_field_mod(cache, index, is_static);
   load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
 
@@ -2815,10 +2830,11 @@
   // save 'interpreter return address'
   __ save_bcp();
 
-  load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual);
+  load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic);
 
   // load receiver if needed (note: no return address pushed yet)
   if (load_receiver) {
+    assert(!is_invokedynamic, "");
     __ movl(recv, flags);
     __ andl(recv, 0xFF);
     // recv count is 0 based?
@@ -2910,6 +2926,7 @@
 
 void TemplateTable::invokevirtual(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f2_byte, "use this argument");
   prepare_invoke(rbx, noreg, byte_no);
 
   // rbx,: index
@@ -2922,6 +2939,7 @@
 
 void TemplateTable::invokespecial(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f1_byte, "use this argument");
   prepare_invoke(rbx, noreg, byte_no);
   // do the call
   __ verify_oop(rbx);
@@ -2932,6 +2950,7 @@
 
 void TemplateTable::invokestatic(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f1_byte, "use this argument");
   prepare_invoke(rbx, noreg, byte_no);
   // do the call
   __ verify_oop(rbx);
@@ -2942,12 +2961,14 @@
 
 void TemplateTable::fast_invokevfinal(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f2_byte, "use this argument");
   __ stop("fast_invokevfinal not used on x86");
 }
 
 
 void TemplateTable::invokeinterface(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f1_byte, "use this argument");
   prepare_invoke(rax, rbx, byte_no);
 
   // rax,: Interface
@@ -3036,11 +3057,11 @@
     return;
   }
 
+  assert(byte_no == f1_oop, "use this argument");
   prepare_invoke(rax, rbx, byte_no);
 
   // rax: CallSite object (f1)
   // rbx: unused (f2)
-  // rcx: receiver address
   // rdx: flags (unused)
 
   if (ProfileInterpreter) {
--- a/src/cpu/x86/vm/templateTable_x86_64.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/templateTable_x86_64.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -2015,21 +2015,28 @@
   }
 }
 
-void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) {
-  assert(byte_no == 1 || byte_no == 2, "byte_no out of range");
-  bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic);
-
+void TemplateTable::resolve_cache_and_index(int byte_no,
+                                            Register result,
+                                            Register Rcache,
+                                            Register index,
+                                            size_t index_size) {
   const Register temp = rbx;
-  assert_different_registers(Rcache, index, temp);
-
-  const int shift_count = (1 + byte_no) * BitsPerByte;
+  assert_different_registers(result, Rcache, index, temp);
+
   Label resolved;
-  __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
-  if (is_invokedynamic) {
-    // we are resolved if the f1 field contains a non-null CallSite object
-    __ cmpptr(Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD);
+  __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
+  if (byte_no == f1_oop) {
+    // We are resolved if the f1 field contains a non-null object (CallSite, etc.)
+    // This kind of CP cache entry does not need to match the flags byte, because
+    // there is a 1-1 relation between bytecode type and CP entry type.
+    assert(result != noreg, ""); //else do cmpptr(Address(...), (int32_t) NULL_WORD)
+    __ movptr(result, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()));
+    __ testptr(result, result);
     __ jcc(Assembler::notEqual, resolved);
   } else {
+    assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
+    assert(result == noreg, "");  //else change code for setting result
+    const int shift_count = (1 + byte_no) * BitsPerByte;
     __ movl(temp, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
     __ shrl(temp, shift_count);
     // have we resolved this bytecode?
@@ -2064,7 +2071,9 @@
   __ call_VM(noreg, entry, temp);
 
   // Update registers with resolved info
-  __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
+  __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
+  if (result != noreg)
+    __ movptr(result, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()));
   __ bind(resolved);
 }
 
@@ -2100,7 +2109,8 @@
                                                Register itable_index,
                                                Register flags,
                                                bool is_invokevirtual,
-                                               bool is_invokevfinal /*unused*/) {
+                                               bool is_invokevfinal, /*unused*/
+                                               bool is_invokedynamic) {
   // setup registers
   const Register cache = rcx;
   const Register index = rdx;
@@ -2120,15 +2130,18 @@
   const int index_offset = in_bytes(constantPoolCacheOopDesc::base_offset() +
                                     ConstantPoolCacheEntry::f2_offset());
 
-  resolve_cache_and_index(byte_no, cache, index);
-
-  assert(wordSize == 8, "adjust code below");
-  __ movptr(method, Address(cache, index, Address::times_8, method_offset));
+  if (byte_no == f1_oop) {
+    // Resolved f1_oop goes directly into 'method' register.
+    assert(is_invokedynamic, "");
+    resolve_cache_and_index(byte_no, method, cache, index, sizeof(u4));
+  } else {
+    resolve_cache_and_index(byte_no, noreg, cache, index, sizeof(u2));
+    __ movptr(method, Address(cache, index, Address::times_ptr, method_offset));
+  }
   if (itable_index != noreg) {
-    __ movptr(itable_index,
-            Address(cache, index, Address::times_8, index_offset));
+    __ movptr(itable_index, Address(cache, index, Address::times_ptr, index_offset));
   }
-  __ movl(flags , Address(cache, index, Address::times_8, flags_offset));
+  __ movl(flags, Address(cache, index, Address::times_ptr, flags_offset));
 }
 
 
@@ -2187,7 +2200,7 @@
   const Register flags = rax;
   const Register bc = c_rarg3; // uses same reg as obj, so don't mix them
 
-  resolve_cache_and_index(byte_no, cache, index);
+  resolve_cache_and_index(byte_no, noreg, cache, index, sizeof(u2));
   jvmti_post_field_access(cache, index, is_static, false);
   load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
 
@@ -2390,7 +2403,7 @@
   const Register flags = rax;
   const Register bc    = c_rarg3;
 
-  resolve_cache_and_index(byte_no, cache, index);
+  resolve_cache_and_index(byte_no, noreg, cache, index, sizeof(u2));
   jvmti_post_field_mod(cache, index, is_static);
   load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
 
@@ -2815,10 +2828,11 @@
   // save 'interpreter return address'
   __ save_bcp();
 
-  load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual);
+  load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic);
 
   // load receiver if needed (note: no return address pushed yet)
   if (load_receiver) {
+    assert(!is_invokedynamic, "");
     __ movl(recv, flags);
     __ andl(recv, 0xFF);
     Address recv_addr(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1));
@@ -2914,6 +2928,7 @@
 
 void TemplateTable::invokevirtual(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f2_byte, "use this argument");
   prepare_invoke(rbx, noreg, byte_no);
 
   // rbx: index
@@ -2926,6 +2941,7 @@
 
 void TemplateTable::invokespecial(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f1_byte, "use this argument");
   prepare_invoke(rbx, noreg, byte_no);
   // do the call
   __ verify_oop(rbx);
@@ -2936,6 +2952,7 @@
 
 void TemplateTable::invokestatic(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f1_byte, "use this argument");
   prepare_invoke(rbx, noreg, byte_no);
   // do the call
   __ verify_oop(rbx);
@@ -2945,11 +2962,13 @@
 
 void TemplateTable::fast_invokevfinal(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f2_byte, "use this argument");
   __ stop("fast_invokevfinal not used on amd64");
 }
 
 void TemplateTable::invokeinterface(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f1_byte, "use this argument");
   prepare_invoke(rax, rbx, byte_no);
 
   // rax: Interface
@@ -3027,6 +3046,7 @@
 
 void TemplateTable::invokedynamic(int byte_no) {
   transition(vtos, vtos);
+  assert(byte_no == f1_oop, "use this argument");
 
   if (!EnableInvokeDynamic) {
     // We should not encounter this bytecode if !EnableInvokeDynamic.
@@ -3039,6 +3059,7 @@
     return;
   }
 
+  assert(byte_no == f1_oop, "use this argument");
   prepare_invoke(rax, rbx, byte_no);
 
   // rax: CallSite object (f1)
--- a/src/cpu/x86/vm/x86_32.ad	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/x86_32.ad	Wed Jun 02 22:45:42 2010 -0700
@@ -1377,6 +1377,12 @@
 // registers?  True for Intel but false for most RISCs
 const bool Matcher::clone_shift_expressions = true;
 
+bool Matcher::narrow_oop_use_complex_address() {
+  ShouldNotCallThis();
+  return true;
+}
+
+
 // Is it better to copy float constants, or load them directly from memory?
 // Intel can load a float constant from a direct address, requiring no
 // extra registers.  Most RISCs will have to materialize an address into a
@@ -1841,14 +1847,14 @@
     MacroAssembler _masm(&cbuf);
     // RBP is preserved across all calls, even compiled calls.
     // Use it to preserve RSP in places where the callee might change the SP.
-    __ movptr(rbp, rsp);
+    __ movptr(rbp_mh_SP_save, rsp);
     debug_only(int off1 = cbuf.code_size());
     assert(off1 - off0 == preserve_SP_size(), "correct size prediction");
   %}
 
   enc_class restore_SP %{
     MacroAssembler _masm(&cbuf);
-    __ movptr(rsp, rbp);
+    __ movptr(rsp, rbp_mh_SP_save);
   %}
 
   enc_class Java_Static_Call (method meth) %{    // JAVA STATIC CALL
@@ -13570,7 +13576,7 @@
 // Call Java Static Instruction (method handle version)
 // Note: If this code changes, the corresponding ret_addr_offset() and
 //       compute_padding() functions will have to be adjusted.
-instruct CallStaticJavaHandle(method meth, eBPRegP ebp) %{
+instruct CallStaticJavaHandle(method meth, eBPRegP ebp_mh_SP_save) %{
   match(CallStaticJava);
   predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
   effect(USE meth);
--- a/src/cpu/x86/vm/x86_64.ad	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/cpu/x86/vm/x86_64.ad	Wed Jun 02 22:45:42 2010 -0700
@@ -1851,29 +1851,24 @@
 void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
 {
   if (UseCompressedOops) {
-    st->print_cr("movl    rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes() #%d]\t", oopDesc::klass_offset_in_bytes());
+    st->print_cr("movl    rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
     if (Universe::narrow_oop_shift() != 0) {
-      st->print_cr("leaq    rscratch1, [r12_heapbase, r, Address::times_8, 0]");
-    }
-    st->print_cr("cmpq    rax, rscratch1\t # Inline cache check");
+      st->print_cr("\tdecode_heap_oop_not_null rscratch1, rscratch1");
+    }
+    st->print_cr("\tcmpq    rax, rscratch1\t # Inline cache check");
   } else {
-    st->print_cr("cmpq    rax, [j_rarg0 + oopDesc::klass_offset_in_bytes() #%d]\t"
-                 "# Inline cache check", oopDesc::klass_offset_in_bytes());
+    st->print_cr("\tcmpq    rax, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t"
+                 "# Inline cache check");
   }
   st->print_cr("\tjne     SharedRuntime::_ic_miss_stub");
-  st->print_cr("\tnop");
-  if (!OptoBreakpoint) {
-    st->print_cr("\tnop");
-  }
+  st->print_cr("\tnop\t# nops to align entry point");
 }
 #endif
 
 void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
 {
   MacroAssembler masm(&cbuf);
-#ifdef ASSERT
   uint code_size = cbuf.code_size();
-#endif
   if (UseCompressedOops) {
     masm.load_klass(rscratch1, j_rarg0);
     masm.cmpptr(rax, rscratch1);
@@ -1884,33 +1879,21 @@
   masm.jump_cc(Assembler::notEqual, RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
 
   /* WARNING these NOPs are critical so that verified entry point is properly
-     aligned for patching by NativeJump::patch_verified_entry() */
-  int nops_cnt = 1;
-  if (!OptoBreakpoint) {
+     4 bytes aligned for patching by NativeJump::patch_verified_entry() */
+  int nops_cnt = 4 - ((cbuf.code_size() - code_size) & 0x3);
+  if (OptoBreakpoint) {
     // Leave space for int3
-     nops_cnt += 1;
+    nops_cnt -= 1;
   }
-  if (UseCompressedOops) {
-    // ??? divisible by 4 is aligned?
-    nops_cnt += 1;
-  }
-  masm.nop(nops_cnt);
-
-  assert(cbuf.code_size() - code_size == size(ra_),
-         "checking code size of inline cache node");
+  nops_cnt &= 0x3; // Do not add nops if code is aligned.
+  if (nops_cnt > 0)
+    masm.nop(nops_cnt);
 }
 
 uint MachUEPNode::size(PhaseRegAlloc* ra_) const
 {
-  if (UseCompressedOops) {
-    if (Universe::narrow_oop_shift() == 0) {
-      return OptoBreakpoint ? 15 : 16;
-    } else {
-      return OptoBreakpoint ? 19 : 20;
-    }
-  } else {
-    return OptoBreakpoint ? 11 : 12;
-  }
+  return MachNode::size(ra_); // too many variables; just compute it
+                              // the hard way
 }
 
 
@@ -2054,6 +2037,11 @@
 // into registers?  True for Intel but false for most RISCs
 const bool Matcher::clone_shift_expressions = true;
 
+bool Matcher::narrow_oop_use_complex_address() {
+  assert(UseCompressedOops, "only for compressed oops code");
+  return (LogMinObjAlignmentInBytes <= 3);
+}
+
 // Is it better to copy float constants, or load them directly from
 // memory?  Intel can load a float constant from a direct address,
 // requiring no extra registers.  Most RISCs will have to materialize
@@ -2635,14 +2623,14 @@
     MacroAssembler _masm(&cbuf);
     // RBP is preserved across all calls, even compiled calls.
     // Use it to preserve RSP in places where the callee might change the SP.
-    __ movptr(rbp, rsp);
+    __ movptr(rbp_mh_SP_save, rsp);
     debug_only(int off1 = cbuf.code_size());
     assert(off1 - off0 == preserve_SP_size(), "correct size prediction");
   %}
 
   enc_class restore_SP %{
     MacroAssembler _masm(&cbuf);
-    __ movptr(rsp, rbp);
+    __ movptr(rsp, rbp_mh_SP_save);
   %}
 
   enc_class Java_Static_Call(method meth)
@@ -5127,7 +5115,7 @@
 // Note: x86 architecture doesn't support "scale * index + offset" without a base
 // we can't free r12 even with Universe::narrow_oop_base() == NULL.
 operand indCompressedOopOffset(rRegN reg, immL32 off) %{
-  predicate(UseCompressedOops && (Universe::narrow_oop_shift() != 0));
+  predicate(UseCompressedOops && (Universe::narrow_oop_shift() == Address::times_8));
   constraint(ALLOC_IN_RC(ptr_reg));
   match(AddP (DecodeN reg) off);
 
@@ -7742,10 +7730,11 @@
   ins_pipe(ialu_reg_long);
 %}
 
-instruct decodeHeapOop_not_null(rRegP dst, rRegN src) %{
+instruct decodeHeapOop_not_null(rRegP dst, rRegN src, rFlagsReg cr) %{
   predicate(n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull ||
             n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant);
   match(Set dst (DecodeN src));
+  effect(KILL cr);
   format %{ "decode_heap_oop_not_null $dst,$src" %}
   ins_encode %{
     Register s = $src$$Register;
@@ -12604,7 +12593,7 @@
 // Call Java Static Instruction (method handle version)
 // Note: If this code changes, the corresponding ret_addr_offset() and
 //       compute_padding() functions will have to be adjusted.
-instruct CallStaticJavaHandle(method meth, rbp_RegP rbp) %{
+instruct CallStaticJavaHandle(method meth, rbp_RegP rbp_mh_SP_save) %{
   match(CallStaticJava);
   predicate(((CallStaticJavaNode*) n)->is_method_handle_invoke());
   effect(USE meth);
--- a/src/os/solaris/dtrace/generateJvmOffsets.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/os/solaris/dtrace/generateJvmOffsets.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. 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/src/os/solaris/dtrace/libjvm_db.c	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/os/solaris/dtrace/libjvm_db.c	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. 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/src/share/vm/asm/codeBuffer.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/asm/codeBuffer.hpp	Wed Jun 02 22:45:42 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/src/share/vm/c1/c1_FrameMap.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/c1/c1_FrameMap.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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
@@ -150,6 +150,9 @@
   // Opr representing the stack_pointer on this platform
   static LIR_Opr stack_pointer();
 
+  // JSR 292
+  static LIR_Opr method_handle_invoke_SP_save_opr();
+
   static BasicTypeArray*     signature_type_array_for(const ciMethod* method);
   static BasicTypeArray*     signature_type_array_for(const char * signature);
 
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -2438,13 +2438,13 @@
       case Bytecodes::_invokestatic   : // fall through
       case Bytecodes::_invokedynamic  : // fall through
       case Bytecodes::_invokeinterface: invoke(code); break;
-      case Bytecodes::_new            : new_instance(s.get_index_big()); break;
+      case Bytecodes::_new            : new_instance(s.get_index_u2()); break;
       case Bytecodes::_newarray       : new_type_array(); break;
       case Bytecodes::_anewarray      : new_object_array(); break;
       case Bytecodes::_arraylength    : ipush(append(new ArrayLength(apop(), lock_stack()))); break;
       case Bytecodes::_athrow         : throw_op(s.cur_bci()); break;
-      case Bytecodes::_checkcast      : check_cast(s.get_index_big()); break;
-      case Bytecodes::_instanceof     : instance_of(s.get_index_big()); break;
+      case Bytecodes::_checkcast      : check_cast(s.get_index_u2()); break;
+      case Bytecodes::_instanceof     : instance_of(s.get_index_u2()); break;
       // Note: we do not have special handling for the monitorenter bytecode if DeoptC1 && DeoptOnAsyncException
       case Bytecodes::_monitorenter   : monitorenter(apop(), s.cur_bci()); break;
       case Bytecodes::_monitorexit    : monitorexit (apop(), s.cur_bci()); break;
--- a/src/share/vm/c1/c1_IR.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/c1/c1_IR.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -230,7 +230,8 @@
   , _stack(stack)
   , _exception_handlers(exception_handlers)
   , _next(NULL)
-  , _id(-1) {
+  , _id(-1)
+  , _is_method_handle_invoke(false) {
   assert(_stack != NULL, "must be non null");
   assert(_bci == SynchronizationEntryBCI || Bytecodes::is_defined(scope()->method()->java_code_at_bci(_bci)), "make sure bci points at a real bytecode");
 }
@@ -241,7 +242,8 @@
   , _exception_handlers(NULL)
   , _bci(info->_bci)
   , _scope_debug_info(NULL)
-  , _oop_map(NULL) {
+  , _oop_map(NULL)
+  , _is_method_handle_invoke(info->_is_method_handle_invoke) {
   if (lock_stack_only) {
     if (info->_stack != NULL) {
       _stack = info->_stack->copy_locks();
@@ -259,10 +261,10 @@
 }
 
 
-void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool is_method_handle_invoke) {
+void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_offset) {
   // record the safepoint before recording the debug info for enclosing scopes
   recorder->add_safepoint(pc_offset, _oop_map->deep_copy());
-  _scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/, is_method_handle_invoke);
+  _scope_debug_info->record_debug_info(recorder, pc_offset, true/*topmost*/, _is_method_handle_invoke);
   recorder->end_safepoint(pc_offset);
 }
 
--- a/src/share/vm/c1/c1_IR.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/c1/c1_IR.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -269,6 +269,7 @@
   int               _bci;
   CodeEmitInfo*     _next;
   int               _id;
+  bool              _is_method_handle_invoke;    // true if the associated call site is a MethodHandle call site.
 
   FrameMap*     frame_map() const                { return scope()->compilation()->frame_map(); }
   Compilation*  compilation() const              { return scope()->compilation(); }
@@ -287,7 +288,8 @@
     , _stack(NULL)
     , _exception_handlers(NULL)
     , _next(NULL)
-    , _id(-1) {
+    , _id(-1)
+    , _is_method_handle_invoke(false) {
   }
 
   // make a copy
@@ -302,13 +304,16 @@
   int bci() const                                { return _bci; }
 
   void add_register_oop(LIR_Opr opr);
-  void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool is_method_handle_invoke = false);
+  void record_debug_info(DebugInformationRecorder* recorder, int pc_offset);
 
   CodeEmitInfo* next() const        { return _next; }
   void set_next(CodeEmitInfo* next) { _next = next; }
 
   int id() const      { return _id; }
   void set_id(int id) { _id = id; }
+
+  bool     is_method_handle_invoke() const { return _is_method_handle_invoke;     }
+  void set_is_method_handle_invoke(bool x) {        _is_method_handle_invoke = x; }
 };
 
 
--- a/src/share/vm/c1/c1_LIR.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/c1/c1_LIR.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -715,7 +715,10 @@
       }
 
       if (opJavaCall->_info)                     do_info(opJavaCall->_info);
-      if (opJavaCall->is_method_handle_invoke()) do_temp(FrameMap::method_handle_invoke_SP_save_opr());
+      if (opJavaCall->is_method_handle_invoke()) {
+        opJavaCall->_method_handle_invoke_SP_save_opr = FrameMap::method_handle_invoke_SP_save_opr();
+        do_temp(opJavaCall->_method_handle_invoke_SP_save_opr);
+      }
       do_call();
       if (opJavaCall->_result->is_valid())       do_output(opJavaCall->_result);
 
--- a/src/share/vm/c1/c1_LIR.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/c1/c1_LIR.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -505,15 +505,22 @@
      , _type(type)
      , _disp(0) { verify(); }
 
-  LIR_Address(LIR_Opr base, int disp, BasicType type):
+  LIR_Address(LIR_Opr base, intx disp, BasicType type):
        _base(base)
      , _index(LIR_OprDesc::illegalOpr())
      , _scale(times_1)
      , _type(type)
      , _disp(disp) { verify(); }
 
+  LIR_Address(LIR_Opr base, BasicType type):
+       _base(base)
+     , _index(LIR_OprDesc::illegalOpr())
+     , _scale(times_1)
+     , _type(type)
+     , _disp(0) { verify(); }
+
 #ifdef X86
-  LIR_Address(LIR_Opr base, LIR_Opr index, Scale scale, int disp, BasicType type):
+  LIR_Address(LIR_Opr base, LIR_Opr index, Scale scale, intx disp, BasicType type):
        _base(base)
      , _index(index)
      , _scale(scale)
@@ -1033,8 +1040,9 @@
  friend class LIR_OpVisitState;
 
  private:
-  ciMethod*       _method;
-  LIR_Opr         _receiver;
+  ciMethod* _method;
+  LIR_Opr   _receiver;
+  LIR_Opr   _method_handle_invoke_SP_save_opr;  // Used in LIR_OpVisitState::visit to store the reference to FrameMap::method_handle_invoke_SP_save_opr.
 
  public:
   LIR_OpJavaCall(LIR_Code code, ciMethod* method,
@@ -1043,14 +1051,18 @@
                  CodeEmitInfo* info)
   : LIR_OpCall(code, addr, result, arguments, info)
   , _receiver(receiver)
-  , _method(method)          { assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); }
+  , _method(method)
+  , _method_handle_invoke_SP_save_opr(LIR_OprFact::illegalOpr)
+  { assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); }
 
   LIR_OpJavaCall(LIR_Code code, ciMethod* method,
                  LIR_Opr receiver, LIR_Opr result, intptr_t vtable_offset,
                  LIR_OprList* arguments, CodeEmitInfo* info)
   : LIR_OpCall(code, (address)vtable_offset, result, arguments, info)
   , _receiver(receiver)
-  , _method(method)          { assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); }
+  , _method(method)
+  , _method_handle_invoke_SP_save_opr(LIR_OprFact::illegalOpr)
+  { assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); }
 
   LIR_Opr receiver() const                       { return _receiver; }
   ciMethod* method() const                       { return _method;   }
--- a/src/share/vm/c1/c1_LIRAssembler.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/c1/c1_LIRAssembler.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -301,9 +301,9 @@
 }
 
 
-void LIR_Assembler::add_call_info(int pc_offset, CodeEmitInfo* cinfo, bool is_method_handle_invoke) {
+void LIR_Assembler::add_call_info(int pc_offset, CodeEmitInfo* cinfo) {
   flush_debug_info(pc_offset);
-  cinfo->record_debug_info(compilation()->debug_info_recorder(), pc_offset, is_method_handle_invoke);
+  cinfo->record_debug_info(compilation()->debug_info_recorder(), pc_offset);
   if (cinfo->exception_handlers() != NULL) {
     compilation()->add_exception_handlers_for_pco(pc_offset, cinfo->exception_handlers());
   }
@@ -413,12 +413,6 @@
 void LIR_Assembler::emit_call(LIR_OpJavaCall* op) {
   verify_oop_map(op->info());
 
-  // JSR 292
-  // Preserve the SP over MethodHandle call sites.
-  if (op->is_method_handle_invoke()) {
-    preserve_SP(op);
-  }
-
   if (os::is_MP()) {
     // must align calls sites, otherwise they can't be updated atomically on MP hardware
     align_call(op->code());
@@ -444,10 +438,6 @@
   default: ShouldNotReachHere();
   }
 
-  if (op->is_method_handle_invoke()) {
-    restore_SP(op);
-  }
-
 #if defined(X86) && defined(TIERED)
   // C2 leave fpu stack dirty clean it
   if (UseSSE < 2) {
--- a/src/share/vm/c1/c1_LIRAssembler.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/c1/c1_LIRAssembler.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -84,7 +84,7 @@
   Address as_Address_hi(LIR_Address* addr);
 
   // debug information
-  void add_call_info(int pc_offset, CodeEmitInfo* cinfo, bool is_method_handle_invoke = false);
+  void add_call_info(int pc_offset, CodeEmitInfo* cinfo);
   void add_debug_info_for_branch(CodeEmitInfo* info);
   void add_debug_info_for_div0(int pc_offset, CodeEmitInfo* cinfo);
   void add_debug_info_for_div0_here(CodeEmitInfo* info);
@@ -212,10 +212,6 @@
   void ic_call(     LIR_OpJavaCall* op);
   void vtable_call( LIR_OpJavaCall* op);
 
-  // JSR 292
-  void preserve_SP(LIR_OpJavaCall* op);
-  void restore_SP( LIR_OpJavaCall* op);
-
   void osr_entry();
 
   void build_frame();
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1309,7 +1309,7 @@
   __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
   if (!addr_opr->is_address()) {
     assert(addr_opr->is_register(), "must be");
-    addr_opr = LIR_OprFact::address(new LIR_Address(addr_opr, 0, T_OBJECT));
+    addr_opr = LIR_OprFact::address(new LIR_Address(addr_opr, T_OBJECT));
   }
   CodeStub* slow = new G1PreBarrierStub(addr_opr, pre_val, pre_val_patch_code,
                                         info);
@@ -1325,7 +1325,7 @@
       new_val->as_constant_ptr()->as_jobject() == NULL) return;
 
   if (!new_val->is_register()) {
-    LIR_Opr new_val_reg = new_pointer_register();
+    LIR_Opr new_val_reg = new_register(T_OBJECT);
     if (new_val->is_constant()) {
       __ move(new_val, new_val_reg);
     } else {
@@ -1337,7 +1337,7 @@
 
   if (addr->is_address()) {
     LIR_Address* address = addr->as_address_ptr();
-    LIR_Opr ptr = new_pointer_register();
+    LIR_Opr ptr = new_register(T_OBJECT);
     if (!address->index()->is_valid() && address->disp() == 0) {
       __ move(address->base(), ptr);
     } else {
@@ -1350,7 +1350,6 @@
 
   LIR_Opr xor_res = new_pointer_register();
   LIR_Opr xor_shift_res = new_pointer_register();
-
   if (TwoOperandLIRForm ) {
     __ move(addr, xor_res);
     __ logical_xor(xor_res, new_val, xor_res);
@@ -1368,7 +1367,7 @@
   }
 
   if (!new_val->is_register()) {
-    LIR_Opr new_val_reg = new_pointer_register();
+    LIR_Opr new_val_reg = new_register(T_OBJECT);
     __ leal(new_val, new_val_reg);
     new_val = new_val_reg;
   }
@@ -1377,7 +1376,7 @@
   __ cmp(lir_cond_notEqual, xor_shift_res, LIR_OprFact::intptrConst(NULL_WORD));
 
   CodeStub* slow = new G1PostBarrierStub(addr, new_val);
-  __ branch(lir_cond_notEqual, T_INT, slow);
+  __ branch(lir_cond_notEqual, LP64_ONLY(T_LONG) NOT_LP64(T_INT), slow);
   __ branch_destination(slow->continuation());
 }
 
@@ -2371,9 +2370,17 @@
   bool optimized = x->target_is_loaded() && x->target_is_final();
   assert(receiver->is_illegal() || receiver->is_equal(LIR_Assembler::receiverOpr()), "must match");
 
+  // JSR 292
+  // Preserve the SP over MethodHandle call sites.
+  ciMethod* target = x->target();
+  if (target->is_method_handle_invoke()) {
+    info->set_is_method_handle_invoke(true);
+    __ move(FrameMap::stack_pointer(), FrameMap::method_handle_invoke_SP_save_opr());
+  }
+
   switch (x->code()) {
     case Bytecodes::_invokestatic:
-      __ call_static(x->target(), result_register,
+      __ call_static(target, result_register,
                      SharedRuntime::get_resolve_static_call_stub(),
                      arg_list, info);
       break;
@@ -2383,17 +2390,17 @@
       // for final target we still produce an inline cache, in order
       // to be able to call mixed mode
       if (x->code() == Bytecodes::_invokespecial || optimized) {
-        __ call_opt_virtual(x->target(), receiver, result_register,
+        __ call_opt_virtual(target, receiver, result_register,
                             SharedRuntime::get_resolve_opt_virtual_call_stub(),
                             arg_list, info);
       } else if (x->vtable_index() < 0) {
-        __ call_icvirtual(x->target(), receiver, result_register,
+        __ call_icvirtual(target, receiver, result_register,
                           SharedRuntime::get_resolve_virtual_call_stub(),
                           arg_list, info);
       } else {
         int entry_offset = instanceKlass::vtable_start_offset() + x->vtable_index() * vtableEntry::size();
         int vtable_offset = entry_offset * wordSize + vtableEntry::method_offset_in_bytes();
-        __ call_virtual(x->target(), receiver, result_register, vtable_offset, arg_list, info);
+        __ call_virtual(target, receiver, result_register, vtable_offset, arg_list, info);
       }
       break;
     case Bytecodes::_invokedynamic: {
@@ -2432,7 +2439,7 @@
       // Load target MethodHandle from CallSite object.
       __ load(new LIR_Address(tmp, java_dyn_CallSite::target_offset_in_bytes(), T_OBJECT), receiver);
 
-      __ call_dynamic(x->target(), receiver, result_register,
+      __ call_dynamic(target, receiver, result_register,
                       SharedRuntime::get_resolve_opt_virtual_call_stub(),
                       arg_list, info);
       break;
@@ -2442,6 +2449,12 @@
       break;
   }
 
+  // JSR 292
+  // Restore the SP after MethodHandle call sites.
+  if (target->is_method_handle_invoke()) {
+    __ move(FrameMap::method_handle_invoke_SP_save_opr(), FrameMap::stack_pointer());
+  }
+
   if (x->type()->is_float() || x->type()->is_double()) {
     // Force rounding of results from non-strictfp when in strictfp
     // scope (or when we don't know the strictness of the callee, to
--- a/src/share/vm/ci/ciMethod.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/ci/ciMethod.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -690,20 +690,32 @@
 
 // ------------------------------------------------------------------
 // invokedynamic support
+
+// ------------------------------------------------------------------
+// ciMethod::is_method_handle_invoke
 //
+// Return true if the method is a MethodHandle target.
 bool ciMethod::is_method_handle_invoke() const {
-  check_is_loaded();
-  bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS);
+  bool flag = (holder()->name() == ciSymbol::java_dyn_MethodHandle() &&
+               methodOopDesc::is_method_handle_invoke_name(name()->sid()));
 #ifdef ASSERT
-  {
-    VM_ENTRY_MARK;
-    bool flag2 = get_methodOop()->is_method_handle_invoke();
-    assert(flag == flag2, "consistent");
+  if (is_loaded()) {
+    bool flag2 = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS);
+    {
+      VM_ENTRY_MARK;
+      bool flag3 = get_methodOop()->is_method_handle_invoke();
+      assert(flag2 == flag3, "consistent");
+      assert(flag  == flag3, "consistent");
+    }
   }
 #endif //ASSERT
   return flag;
 }
 
+// ------------------------------------------------------------------
+// ciMethod::is_method_handle_adapter
+//
+// Return true if the method is a generated MethodHandle adapter.
 bool ciMethod::is_method_handle_adapter() const {
   check_is_loaded();
   VM_ENTRY_MARK;
--- a/src/share/vm/ci/ciStreams.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/ci/ciStreams.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. 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
@@ -81,27 +81,21 @@
 // providing accessors for constant pool items.
 
 // ------------------------------------------------------------------
-// ciBytecodeStream::wide
-//
-// Special handling for the wide bytcode
-Bytecodes::Code ciBytecodeStream::wide()
-{
-  // Get following bytecode; do not return wide
-  Bytecodes::Code bc = (Bytecodes::Code)_pc[1];
-  _pc += 2;                     // Skip both bytecodes
-  _pc += 2;                     // Skip index always
-  if( bc == Bytecodes::_iinc )
-    _pc += 2;                   // Skip optional constant
-  _was_wide = _pc;              // Flag last wide bytecode found
-  return bc;
-}
-
-// ------------------------------------------------------------------
-// ciBytecodeStream::table
+// ciBytecodeStream::next_wide_or_table
 //
 // Special handling for switch ops
-Bytecodes::Code ciBytecodeStream::table( Bytecodes::Code bc ) {
-  switch( bc ) {                // Check for special bytecode handling
+Bytecodes::Code ciBytecodeStream::next_wide_or_table(Bytecodes::Code bc) {
+  switch (bc) {                // Check for special bytecode handling
+  case Bytecodes::_wide:
+    // Special handling for the wide bytcode
+    // Get following bytecode; do not return wide
+    assert(Bytecodes::Code(_pc[0]) == Bytecodes::_wide, "");
+    bc = Bytecodes::java_code(_raw_bc = (Bytecodes::Code)_pc[1]);
+    assert(Bytecodes::wide_length_for(bc) > 2, "must make progress");
+    _pc += Bytecodes::wide_length_for(bc);
+    _was_wide = _pc;              // Flag last wide bytecode found
+    assert(is_wide(), "accessor works right");
+    break;
 
   case Bytecodes::_lookupswitch:
     _pc++;                      // Skip wide bytecode
@@ -164,7 +158,7 @@
 int ciBytecodeStream::get_klass_index() const {
   switch(cur_bc()) {
   case Bytecodes::_ldc:
-    return get_index();
+    return get_index_u1();
   case Bytecodes::_ldc_w:
   case Bytecodes::_ldc2_w:
   case Bytecodes::_checkcast:
@@ -173,7 +167,7 @@
   case Bytecodes::_multianewarray:
   case Bytecodes::_new:
   case Bytecodes::_newarray:
-    return get_index_big();
+    return get_index_u2();
   default:
     ShouldNotReachHere();
     return 0;
@@ -199,10 +193,10 @@
 int ciBytecodeStream::get_constant_index() const {
   switch(cur_bc()) {
   case Bytecodes::_ldc:
-    return get_index();
+    return get_index_u1();
   case Bytecodes::_ldc_w:
   case Bytecodes::_ldc2_w:
-    return get_index_big();
+    return get_index_u2();
   default:
     ShouldNotReachHere();
     return 0;
@@ -239,7 +233,7 @@
          cur_bc() == Bytecodes::_putfield ||
          cur_bc() == Bytecodes::_getstatic ||
          cur_bc() == Bytecodes::_putstatic, "wrong bc");
-  return get_index_big();
+  return get_index_u2_cpcache();
 }
 
 
@@ -319,7 +313,9 @@
     ShouldNotReachHere();
   }
 #endif
-  return get_index_int();
+  if (has_index_u4())
+    return get_index_u4();  // invokedynamic
+  return get_index_u2_cpcache();
 }
 
 // ------------------------------------------------------------------
--- a/src/share/vm/ci/ciStreams.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/ci/ciStreams.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. 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
@@ -31,15 +31,19 @@
 // their original form during iteration.
 class ciBytecodeStream : StackObj {
 private:
- // Handling for the weird bytecodes
-  Bytecodes::Code wide();       // Handle wide bytecode
-  Bytecodes::Code table(Bytecodes::Code); // Handle complicated inline table
+  // Handling for the weird bytecodes
+  Bytecodes::Code next_wide_or_table(Bytecodes::Code); // Handle _wide & complicated inline table
 
   static Bytecodes::Code check_java(Bytecodes::Code c) {
     assert(Bytecodes::is_java_code(c), "should not return _fast bytecodes");
     return c;
   }
 
+  static Bytecodes::Code check_defined(Bytecodes::Code c) {
+    assert(Bytecodes::is_defined(c), "");
+    return c;
+  }
+
   ciMethod* _method;           // the method
   ciInstanceKlass* _holder;
   address _bc_start;            // Start of current bytecode for table
@@ -50,11 +54,21 @@
   address _end;                    // Past end of bytecodes
   address _pc;                     // Current PC
   Bytecodes::Code _bc;             // Current bytecode
+  Bytecodes::Code _raw_bc;         // Current bytecode, raw form
 
   void reset( address base, unsigned int size ) {
     _bc_start =_was_wide = 0;
     _start = _pc = base; _end = base + size; }
 
+  void assert_wide(bool require_wide) const {
+    if (require_wide)
+         { assert(is_wide(),  "must be a wide instruction"); }
+    else { assert(!is_wide(), "must not be a wide instruction"); }
+  }
+
+  Bytecode* bytecode() const { return Bytecode_at(_bc_start); }
+  Bytecode* next_bytecode() const { return Bytecode_at(_pc); }
+
 public:
   // End-Of-Bytecodes
   static Bytecodes::Code EOBC() {
@@ -92,11 +106,12 @@
   }
 
   address cur_bcp() const       { return _bc_start; }  // Returns bcp to current instruction
-  int next_bci() const          { return _pc -_start; }
+  int next_bci() const          { return _pc - _start; }
   int cur_bci() const           { return _bc_start - _start; }
   int instruction_size() const  { return _pc - _bc_start; }
 
   Bytecodes::Code cur_bc() const{ return check_java(_bc); }
+  Bytecodes::Code cur_bc_raw() const { return check_defined(_raw_bc); }
   Bytecodes::Code next_bc()     { return Bytecodes::java_code((Bytecodes::Code)* _pc); }
 
   // Return current ByteCode and increment PC to next bytecode, skipping all
@@ -109,85 +124,76 @@
 
     // Fetch Java bytecode
     // All rewritten bytecodes maintain the size of original bytecode.
-    _bc = Bytecodes::java_code((Bytecodes::Code)*_pc);
+    _bc = Bytecodes::java_code(_raw_bc = (Bytecodes::Code)*_pc);
     int csize = Bytecodes::length_for(_bc); // Expected size
-
-    if( _bc == Bytecodes::_wide ) {
-      _bc=wide();                           // Handle wide bytecode
-    } else if( csize == 0 ) {
-      _bc=table(_bc);                       // Handle inline tables
-    } else {
-      _pc += csize;                         // Bump PC past bytecode
+    _pc += csize;                           // Bump PC past bytecode
+    if (csize == 0) {
+      _bc = next_wide_or_table(_bc);
     }
     return check_java(_bc);
   }
 
   bool is_wide() const { return ( _pc == _was_wide ); }
 
+  // Does this instruction contain an index which refes into the CP cache?
+  bool uses_cp_cache() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); }
+
+  int get_index_u1() const {
+    return bytecode()->get_index_u1(cur_bc_raw());
+  }
+
   // Get a byte index following this bytecode.
   // If prefixed with a wide bytecode, get a wide index.
   int get_index() const {
-    assert_index_size(is_wide() ? 2 : 1);
     return (_pc == _was_wide)   // was widened?
-      ? Bytes::get_Java_u2(_bc_start+2) // yes, return wide index
-      : _bc_start[1];           // no, return narrow index
+      ? get_index_u2(true)      // yes, return wide index
+      : get_index_u1();         // no, return narrow index
   }
 
-  // Get 2-byte index (getfield/putstatic/etc)
-  int get_index_big() const {
-    assert_index_size(2);
-    return Bytes::get_Java_u2(_bc_start+1);
+  // Get 2-byte index (byte swapping depending on which bytecode)
+  int get_index_u2(bool is_wide = false) const {
+    return bytecode()->get_index_u2(cur_bc_raw(), is_wide);
   }
 
-  // Get 2-byte index (or 4-byte, for invokedynamic)
-  int get_index_int() const {
-    return has_giant_index() ? get_index_giant() : get_index_big();
+  // Get 2-byte index in native byte order.  (Rewriter::rewrite makes these.)
+  int get_index_u2_cpcache() const {
+    return bytecode()->get_index_u2_cpcache(cur_bc_raw());
   }
 
   // Get 4-byte index, for invokedynamic.
-  int get_index_giant() const {
-    assert_index_size(4);
-    return Bytes::get_native_u4(_bc_start+1);
+  int get_index_u4() const {
+    return bytecode()->get_index_u4(cur_bc_raw());
   }
 
-  bool has_giant_index() const { return (cur_bc() == Bytecodes::_invokedynamic); }
+  bool has_index_u4() const {
+    return bytecode()->has_index_u4(cur_bc_raw());
+  }
 
   // Get dimensions byte (multinewarray)
   int get_dimensions() const { return *(unsigned char*)(_pc-1); }
 
   // Sign-extended index byte/short, no widening
-  int get_byte() const { return (int8_t)(_pc[-1]); }
-  int get_short() const { return (int16_t)Bytes::get_Java_u2(_pc-2); }
-  int get_long() const  { return (int32_t)Bytes::get_Java_u4(_pc-4); }
+  int get_constant_u1()                     const { return bytecode()->get_constant_u1(instruction_size()-1, cur_bc_raw()); }
+  int get_constant_u2(bool is_wide = false) const { return bytecode()->get_constant_u2(instruction_size()-2, cur_bc_raw(), is_wide); }
 
   // Get a byte signed constant for "iinc".  Invalid for other bytecodes.
   // If prefixed with a wide bytecode, get a wide constant
-  int get_iinc_con() const {return (_pc==_was_wide) ? get_short() :get_byte();}
+  int get_iinc_con() const {return (_pc==_was_wide) ? (jshort) get_constant_u2(true) : (jbyte) get_constant_u1();}
 
   // 2-byte branch offset from current pc
-  int get_dest( ) const {
-    assert( Bytecodes::length_at(_bc_start) == sizeof(jshort)+1,  "get_dest called with bad bytecode" );
-    return _bc_start-_start + (short)Bytes::get_Java_u2(_pc-2);
+  int get_dest() const {
+    return cur_bci() + bytecode()->get_offset_s2(cur_bc_raw());
   }
 
   // 2-byte branch offset from next pc
-  int next_get_dest( ) const {
-    address next_bc_start = _pc;
-    assert( _pc < _end, "" );
-    Bytecodes::Code next_bc = (Bytecodes::Code)*_pc;
-    assert( next_bc != Bytecodes::_wide, "");
-    int next_csize = Bytecodes::length_for(next_bc);
-    assert( next_csize != 0, "" );
-    assert( next_bc <= Bytecodes::_jsr_w, "");
-    address next_pc = _pc + next_csize;
-    assert( Bytecodes::length_at(next_bc_start) == sizeof(jshort)+1,  "next_get_dest called with bad bytecode" );
-    return next_bc_start-_start + (short)Bytes::get_Java_u2(next_pc-2);
+  int next_get_dest() const {
+    assert(_pc < _end, "");
+    return next_bci() + next_bytecode()->get_offset_s2(Bytecodes::_ifeq);
   }
 
   // 4-byte branch offset from current pc
-  int get_far_dest( ) const {
-    assert( Bytecodes::length_at(_bc_start) == sizeof(jint)+1, "dest4 called with bad bytecode" );
-    return _bc_start-_start + (int)Bytes::get_Java_u4(_pc-4);
+  int get_far_dest() const {
+    return cur_bci() + bytecode()->get_offset_s4(cur_bc_raw());
   }
 
   // For a lookup or switch table, return target destination
@@ -234,22 +240,6 @@
 
   ciCPCache*  get_cpcache();
   ciCallSite* get_call_site();
-
- private:
-  void assert_index_size(int required_size) const {
-#ifdef ASSERT
-    int isize = instruction_size() - (is_wide() ? 1 : 0) - 1;
-    if (isize == 2 &&  cur_bc() == Bytecodes::_iinc)
-      isize = 1;
-    else if (isize <= 2)
-      ;                         // no change
-    else if (has_giant_index())
-      isize = 4;
-    else
-      isize = 2;
-    assert(isize = required_size, "wrong index size");
-#endif
-  }
 };
 
 
--- a/src/share/vm/ci/ciTypeFlow.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/ci/ciTypeFlow.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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
@@ -2132,6 +2132,7 @@
   if (!Bytecodes::can_trap(str.cur_bc()))  return false;
 
   switch (str.cur_bc()) {
+    // %%% FIXME: ldc of Class can generate an exception
     case Bytecodes::_ldc:
     case Bytecodes::_ldc_w:
     case Bytecodes::_ldc2_w:
--- a/src/share/vm/classfile/verifier.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/classfile/verifier.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. 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
@@ -257,6 +257,9 @@
   int num_methods = methods->length();
 
   for (int index = 0; index < num_methods; index++) {
+    // Check for recursive re-verification before each method.
+    if (was_recursively_verified())  return;
+
     methodOop m = (methodOop)methods->obj_at(index);
     if (m->is_native() || m->is_abstract()) {
       // If m is native or abstract, skip it.  It is checked in class file
@@ -265,6 +268,12 @@
     }
     verify_method(methodHandle(THREAD, m), CHECK_VERIFY(this));
   }
+
+  if (_verify_verbose || TraceClassInitialization) {
+    if (was_recursively_verified())
+      tty->print_cr("Recursive verification detected for: %s",
+          _klass->external_name());
+  }
 }
 
 void ClassVerifier::verify_method(methodHandle m, TRAPS) {
@@ -329,6 +338,9 @@
                                 // instruction in sequence
   Bytecodes::Code opcode;
   while (!bcs.is_last_bytecode()) {
+    // Check for recursive re-verification before each bytecode.
+    if (was_recursively_verified())  return;
+
     opcode = bcs.raw_next();
     u2 bci = bcs.bci();
 
@@ -413,13 +425,13 @@
           no_control_flow = false; break;
         case Bytecodes::_ldc :
           verify_ldc(
-            opcode, bcs.get_index(), &current_frame,
+            opcode, bcs.get_index_u1(), &current_frame,
             cp, bci, CHECK_VERIFY(this));
           no_control_flow = false; break;
         case Bytecodes::_ldc_w :
         case Bytecodes::_ldc2_w :
           verify_ldc(
-            opcode, bcs.get_index_big(), &current_frame,
+            opcode, bcs.get_index_u2(), &current_frame,
             cp, bci, CHECK_VERIFY(this));
           no_control_flow = false; break;
         case Bytecodes::_iload :
@@ -1185,7 +1197,7 @@
           no_control_flow = false; break;
         case Bytecodes::_new :
         {
-          index = bcs.get_index_big();
+          index = bcs.get_index_u2();
           verify_cp_class_type(index, cp, CHECK_VERIFY(this));
           VerificationType new_class_type =
             cp_index_to_type(index, cp, CHECK_VERIFY(this));
@@ -1205,7 +1217,7 @@
           no_control_flow = false; break;
         case Bytecodes::_anewarray :
           verify_anewarray(
-            bcs.get_index_big(), cp, &current_frame, CHECK_VERIFY(this));
+            bcs.get_index_u2(), cp, &current_frame, CHECK_VERIFY(this));
           no_control_flow = false; break;
         case Bytecodes::_arraylength :
           type = current_frame.pop_stack(
@@ -1218,7 +1230,7 @@
           no_control_flow = false; break;
         case Bytecodes::_checkcast :
         {
-          index = bcs.get_index_big();
+          index = bcs.get_index_u2();
           verify_cp_class_type(index, cp, CHECK_VERIFY(this));
           current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
@@ -1228,7 +1240,7 @@
           no_control_flow = false; break;
         }
         case Bytecodes::_instanceof : {
-          index = bcs.get_index_big();
+          index = bcs.get_index_u2();
           verify_cp_class_type(index, cp, CHECK_VERIFY(this));
           current_frame.pop_stack(
             VerificationType::reference_check(), CHECK_VERIFY(this));
@@ -1243,7 +1255,7 @@
           no_control_flow = false; break;
         case Bytecodes::_multianewarray :
         {
-          index = bcs.get_index_big();
+          index = bcs.get_index_u2();
           u2 dim = *(bcs.bcp()+3);
           verify_cp_class_type(index, cp, CHECK_VERIFY(this));
           VerificationType new_array_type =
@@ -1302,7 +1314,7 @@
   while (!bcs.is_last_bytecode()) {
     if (bcs.raw_next() != Bytecodes::_illegal) {
       int bci = bcs.bci();
-      if (bcs.code() == Bytecodes::_new) {
+      if (bcs.raw_code() == Bytecodes::_new) {
         code_data[bci] = NEW_OFFSET;
       } else {
         code_data[bci] = BYTECODE_OFFSET;
@@ -1473,20 +1485,9 @@
 
   // In some situations, bytecode rewriting may occur while we're verifying.
   // In this case, a constant pool cache exists and some indices refer to that
-  // instead.  Get the original index for the tag check
-  constantPoolCacheOop cache = cp->cache();
-  if (cache != NULL &&
-       ((types == (1 <<  JVM_CONSTANT_InterfaceMethodref)) ||
-        (types == (1 <<  JVM_CONSTANT_Methodref)) ||
-        (types == (1 <<  JVM_CONSTANT_Fieldref)))) {
-    int native_index = index;
-    if (Bytes::is_Java_byte_ordering_different()) {
-      native_index = Bytes::swap_u2(index);
-    }
-    assert((native_index >= 0) && (native_index < cache->length()),
-      "Must be a legal index into the cp cache");
-    index = cache->entry_at(native_index)->constant_pool_index();
-  }
+  // instead.  Be sure we don't pick up such indices by accident.
+  // We must check was_recursively_verified() before we get here.
+  guarantee(cp->cache() == NULL, "not rewritten yet");
 
   verify_cp_index(cp, index, CHECK_VERIFY(this));
   unsigned int tag = cp->tag_at(index).value();
@@ -1657,7 +1658,7 @@
   int keys, delta;
   current_frame->pop_stack(
     VerificationType::integer_type(), CHECK_VERIFY(this));
-  if (bcs->code() == Bytecodes::_tableswitch) {
+  if (bcs->raw_code() == Bytecodes::_tableswitch) {
     jint low = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize);
     jint high = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize);
     if (low > high) {
@@ -1713,7 +1714,7 @@
                                               StackMapFrame* current_frame,
                                               constantPoolHandle cp,
                                               TRAPS) {
-  u2 index = bcs->get_index_big();
+  u2 index = bcs->get_index_u2();
   verify_cp_type(index, cp, 1 << JVM_CONSTANT_Fieldref, CHECK_VERIFY(this));
 
   // Get field name and signature
@@ -1753,7 +1754,7 @@
     &sig_stream, field_type, CHECK_VERIFY(this));
   u2 bci = bcs->bci();
   bool is_assignable;
-  switch (bcs->code()) {
+  switch (bcs->raw_code()) {
     case Bytecodes::_getstatic: {
       for (int i = 0; i < n; i++) {
         current_frame->push_stack(field_type[i], CHECK_VERIFY(this));
@@ -1873,7 +1874,7 @@
         ref_class_type.name(), CHECK_VERIFY(this));
       methodOop m = instanceKlass::cast(ref_klass)->uncached_lookup_method(
         vmSymbols::object_initializer_name(),
-        cp->signature_ref_at(bcs->get_index_big()));
+        cp->signature_ref_at(bcs->get_index_u2()));
       instanceKlassHandle mh(THREAD, m->method_holder());
       if (m->is_protected() && !mh->is_same_class_package(_klass())) {
         bool assignable = current_type().is_assignable_from(
@@ -1896,8 +1897,8 @@
     bool *this_uninit, VerificationType return_type,
     constantPoolHandle cp, TRAPS) {
   // Make sure the constant pool item is the right type
-  u2 index = bcs->get_index_big();
-  Bytecodes::Code opcode = bcs->code();
+  u2 index = bcs->get_index_u2();
+  Bytecodes::Code opcode = bcs->raw_code();
   unsigned int types = (opcode == Bytecodes::_invokeinterface
                                 ? 1 << JVM_CONSTANT_InterfaceMethodref
                       : opcode == Bytecodes::_invokedynamic
--- a/src/share/vm/classfile/verifier.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/classfile/verifier.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -158,6 +158,16 @@
   methodHandle        _method; // current method being verified
   VerificationType    _this_type; // the verification type of the current class
 
+  // Some recursive calls from the verifier to the name resolver
+  // can cause the current class to be re-verified and rewritten.
+  // If this happens, the original verification should not continue,
+  // because constant pool indexes will have changed.
+  // The rewriter is preceded by the verifier.  If the verifier throws
+  // an error, rewriting is prevented.  Also, rewriting always precedes
+  // bytecode execution or compilation.  Thus, is_rewritten implies
+  // that a class has been verified and prepared for execution.
+  bool was_recursively_verified() { return _klass->is_rewritten(); }
+
  public:
   enum {
     BYTECODE_OFFSET = 1,
--- a/src/share/vm/code/codeBlob.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/code/codeBlob.cpp	Wed Jun 02 22:45:42 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/src/share/vm/code/codeBlob.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/code/codeBlob.hpp	Wed Jun 02 22:45:42 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/src/share/vm/code/codeCache.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/code/codeCache.cpp	Wed Jun 02 22:45:42 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/src/share/vm/code/compiledIC.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/code/compiledIC.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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/src/share/vm/code/nmethod.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/code/nmethod.cpp	Wed Jun 02 22:45:42 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");
@@ -1266,19 +1342,7 @@
   // and it hasn't already been reported for this nmethod then report it now.
   // (the event may have been reported earilier if the GC marked it for unloading).
   if (state == zombie) {
-
-    DTRACE_METHOD_UNLOAD_PROBE(method());
-
-    if (JvmtiExport::should_post_compiled_method_unload() &&
-        !unload_reported()) {
-      assert(method() != NULL, "checking");
-      {
-        HandleMark hm;
-        JvmtiExport::post_compiled_method_unload_at_safepoint(
-            method()->jmethod_id(), code_begin());
-      }
-      set_unload_reported();
-    }
+    post_compiled_method_unload();
   }
 
 
@@ -1430,6 +1494,12 @@
 }
 
 void nmethod::post_compiled_method_unload() {
+  if (unload_reported()) {
+    // During unloading we transition to unloaded and then to zombie
+    // and the unloading is reported during the first transition.
+    return;
+  }
+
   assert(_method != NULL && !is_unloaded(), "just checking");
   DTRACE_METHOD_UNLOAD_PROBE(method());
 
@@ -1439,8 +1509,7 @@
   if (JvmtiExport::should_post_compiled_method_unload()) {
     assert(!unload_reported(), "already unloaded");
     HandleMark hm;
-    JvmtiExport::post_compiled_method_unload_at_safepoint(
-                      method()->jmethod_id(), code_begin());
+    JvmtiExport::post_compiled_method_unload(method()->jmethod_id(), code_begin());
   }
 
   // The JVMTI CompiledMethodUnload event can be enabled or disabled at
@@ -2282,6 +2351,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/src/share/vm/code/nmethod.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/code/nmethod.hpp	Wed Jun 02 22:45:42 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/src/share/vm/code/oopRecorder.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/code/oopRecorder.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. 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/src/share/vm/code/oopRecorder.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/code/oopRecorder.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. 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/src/share/vm/code/relocInfo.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/code/relocInfo.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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/src/share/vm/code/relocInfo.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/code/relocInfo.hpp	Wed Jun 02 22:45:42 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/src/share/vm/compiler/compileBroker.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/compiler/compileBroker.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1651,14 +1651,15 @@
       log->stamp();
       log->end_elem();
     }
-  #ifndef PRODUCT
-    warning("CodeCache is full. Compiler has been disabled");
+    warning("CodeCache is full. Compiler has been disabled.");
+    warning("Try increasing the code cache size using -XX:ReservedCodeCacheSize=");
+#ifndef PRODUCT
     if (CompileTheWorld || ExitOnFullCodeCache) {
       before_exit(JavaThread::current());
       exit_globals(); // will delete tty
       vm_direct_exit(CompileTheWorld ? 0 : 1);
     }
-  #endif
+#endif
     if (UseCodeCacheFlushing) {
       NMethodSweeper::handle_full_code_cache(true);
     } else {
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -32,6 +32,23 @@
 // highest ranked  free list lock rank
 int CompactibleFreeListSpace::_lockRank = Mutex::leaf + 3;
 
+// Defaults are 0 so things will break badly if incorrectly initialized.
+int CompactibleFreeListSpace::IndexSetStart  = 0;
+int CompactibleFreeListSpace::IndexSetStride = 0;
+
+size_t MinChunkSize = 0;
+
+void CompactibleFreeListSpace::set_cms_values() {
+  // Set CMS global values
+  assert(MinChunkSize == 0, "already set");
+  #define numQuanta(x,y) ((x+y-1)/y)
+  MinChunkSize = numQuanta(sizeof(FreeChunk), MinObjAlignmentInBytes) * MinObjAlignment;
+
+  assert(IndexSetStart == 0 && IndexSetStride == 0, "already set");
+  IndexSetStart  = MinObjAlignment;
+  IndexSetStride = MinObjAlignment;
+}
+
 // Constructor
 CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs,
   MemRegion mr, bool use_adaptive_freelists,
@@ -302,7 +319,7 @@
 
 size_t CompactibleFreeListSpace::totalCountInIndexedFreeLists() const {
   size_t count = 0;
-  for (int i = MinChunkSize; i < IndexSetSize; i++) {
+  for (int i = (int)MinChunkSize; i < IndexSetSize; i++) {
     debug_only(
       ssize_t total_list_count = 0;
       for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -91,10 +91,10 @@
   enum SomeConstants {
     SmallForLinearAlloc = 16,        // size < this then use _sLAB
     SmallForDictionary  = 257,       // size < this then use _indexedFreeList
-    IndexSetSize        = SmallForDictionary,  // keep this odd-sized
-    IndexSetStart       = MinObjAlignment,
-    IndexSetStride      = MinObjAlignment
+    IndexSetSize        = SmallForDictionary  // keep this odd-sized
   };
+  static int IndexSetStart;
+  static int IndexSetStride;
 
  private:
   enum FitStrategyOptions {
@@ -278,6 +278,9 @@
   HeapWord* nearLargestChunk() const { return _nearLargestChunk; }
   void set_nearLargestChunk(HeapWord* v) { _nearLargestChunk = v; }
 
+  // Set CMS global values
+  static void set_cms_values();
+
   // Return the free chunk at the end of the space.  If no such
   // chunk exists, return NULL.
   FreeChunk* find_chunk_at_end();
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -159,7 +159,7 @@
      CardTableRS* ct, bool use_adaptive_freelists,
      FreeBlockDictionary::DictionaryChoice dictionaryChoice) :
   CardGeneration(rs, initial_byte_size, level, ct),
-  _dilatation_factor(((double)MinChunkSize)/((double)(oopDesc::header_size()))),
+  _dilatation_factor(((double)MinChunkSize)/((double)(CollectedHeap::min_fill_size()))),
   _debug_collection_type(Concurrent_collection_type)
 {
   HeapWord* bottom = (HeapWord*) _virtual_space.low();
@@ -222,7 +222,7 @@
   // promoting generation, we'll instead just use the mimimum
   // object size (which today is a header's worth of space);
   // note that all arithmetic is in units of HeapWords.
-  assert(MinChunkSize >= oopDesc::header_size(), "just checking");
+  assert(MinChunkSize >= CollectedHeap::min_fill_size(), "just checking");
   assert(_dilatation_factor >= 1.0, "from previous assert");
 }
 
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/freeChunk.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -133,9 +133,5 @@
   void print_on(outputStream* st);
 };
 
-// Alignment helpers etc.
-#define numQuanta(x,y) ((x+y-1)/y)
-enum AlignmentConstants {
-  MinChunkSize = numQuanta(sizeof(FreeChunk), MinObjAlignmentInBytes) * MinObjAlignment
-};
+extern size_t MinChunkSize;
 
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -3644,7 +3644,7 @@
   do {
     free_words = r->free()/HeapWordSize;
     // If there's too little space, no one can allocate, so we're done.
-    if (free_words < (size_t)oopDesc::header_size()) return;
+    if (free_words < CollectedHeap::min_fill_size()) return;
     // Otherwise, try to claim it.
     block = r->par_allocate(free_words);
   } while (block == NULL);
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -2523,14 +2523,14 @@
   }
   if (ParallelGCThreads > 0) {
     const size_t OverpartitionFactor = 4;
-    const size_t MinChunkSize = 8;
-    const size_t ChunkSize =
+    const size_t MinWorkUnit = 8;
+    const size_t WorkUnit =
       MAX2(_g1->n_regions() / (ParallelGCThreads * OverpartitionFactor),
-           MinChunkSize);
+           MinWorkUnit);
     _collectionSetChooser->prepareForAddMarkedHeapRegionsPar(_g1->n_regions(),
-                                                             ChunkSize);
+                                                             WorkUnit);
     ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser,
-                                            (int) ChunkSize);
+                                            (int) WorkUnit);
     _g1->workers()->run_task(&parKnownGarbageTask);
 
     assert(_g1->check_heap_region_claim_values(HeapRegion::InitialClaimValue),
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -711,6 +711,7 @@
   // object in the region.
   if (region_ptr->data_size() == RegionSize) {
     result += pointer_delta(addr, region_addr);
+    DEBUG_ONLY(PSParallelCompact::check_new_location(addr, result);)
     return result;
   }
 
@@ -1487,13 +1488,14 @@
       space->set_top_for_allocations();
     }
 
-    size_t obj_len = 8;
+    size_t min_size = CollectedHeap::min_fill_size();
+    size_t obj_len = min_size;
     while (b + obj_len <= t) {
       CollectedHeap::fill_with_object(b, obj_len);
       mark_bitmap()->mark_obj(b, obj_len);
       summary_data().add_obj(b, obj_len);
       b += obj_len;
-      obj_len = (obj_len & 0x18) + 8; // 8 16 24 32 8 16 24 32 ...
+      obj_len = (obj_len & (min_size*3)) + min_size; // 8 16 24 32 8 16 24 32 ...
     }
     if (b < t) {
       // The loop didn't completely fill to t (top); adjust top downward.
@@ -1680,11 +1682,13 @@
     //                          +-------+
 
     // Initially assume case a, c or e will apply.
-    size_t obj_len = (size_t)oopDesc::header_size();
+    size_t obj_len = CollectedHeap::min_fill_size();
     HeapWord* obj_beg = dense_prefix_end - obj_len;
 
 #ifdef  _LP64
-    if (_mark_bitmap.is_obj_end(dense_prefix_bit - 2)) {
+    if (MinObjAlignment > 1) { // object alignment > heap word size
+      // Cases a, c or e.
+    } else if (_mark_bitmap.is_obj_end(dense_prefix_bit - 2)) {
       // Case b above.
       obj_beg = dense_prefix_end - 1;
     } else if (!_mark_bitmap.is_obj_end(dense_prefix_bit - 3) &&
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1414,6 +1414,8 @@
 {
   assert(old_addr >= new_addr || space_id(old_addr) != space_id(new_addr),
          "must move left or to a different space");
+  assert(is_object_aligned((intptr_t)old_addr) && is_object_aligned((intptr_t)new_addr),
+         "checking alignment");
 }
 #endif // ASSERT
 
--- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -761,7 +761,7 @@
 
   if (p != NULL) {
     size_t remainder = s->free_in_words();
-    if (remainder < (size_t)oopDesc::header_size() && remainder > 0) {
+    if (remainder < CollectedHeap::min_fill_size() && remainder > 0) {
       s->set_top(s->top() - size);
       p = NULL;
     }
@@ -803,7 +803,7 @@
   HeapWord *p = s->cas_allocate(size);
   if (p != NULL) {
     size_t remainder = pointer_delta(s->end(), p + size);
-    if (remainder < (size_t)oopDesc::header_size() && remainder > 0) {
+    if (remainder < CollectedHeap::min_fill_size() && remainder > 0) {
       if (s->cas_deallocate(p, size)) {
         // We were the last to allocate and created a fragment less than
         // a minimal object.
--- a/src/share/vm/gc_interface/collectedHeap.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/gc_interface/collectedHeap.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -239,11 +239,11 @@
 }
 
 size_t CollectedHeap::filler_array_hdr_size() {
-  return size_t(arrayOopDesc::header_size(T_INT));
+  return size_t(align_object_offset(arrayOopDesc::header_size(T_INT))); // align to Long
 }
 
 size_t CollectedHeap::filler_array_min_size() {
-  return align_object_size(filler_array_hdr_size());
+  return align_object_size(filler_array_hdr_size()); // align to MinObjAlignment
 }
 
 size_t CollectedHeap::filler_array_max_size() {
--- a/src/share/vm/includeDB_core	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/includeDB_core	Wed Jun 02 22:45:42 2010 -0700
@@ -827,6 +827,7 @@
 ciStreams.cpp                           ciStreams.hpp
 ciStreams.cpp                           ciUtilities.hpp
 
+ciStreams.hpp                           bytecode.hpp
 ciStreams.hpp                           ciClassList.hpp
 ciStreams.hpp                           ciExceptionHandler.hpp
 ciStreams.hpp                           ciInstanceKlass.hpp
@@ -3635,6 +3636,7 @@
 rewriter.cpp                            gcLocker.hpp
 rewriter.cpp                            generateOopMap.hpp
 rewriter.cpp                            interpreter.hpp
+rewriter.cpp                            methodComparator.hpp
 rewriter.cpp                            objArrayOop.hpp
 rewriter.cpp                            oop.inline.hpp
 rewriter.cpp                            oopFactory.hpp
--- a/src/share/vm/interpreter/bytecode.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/bytecode.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -26,19 +26,12 @@
 #include "incls/_bytecode.cpp.incl"
 
 // Implementation of Bytecode
-// Should eventually get rid of these functions and use ThisRelativeObj methods instead
 
-void Bytecode::set_code(Bytecodes::Code code) {
-  Bytecodes::check(code);
-  *addr_at(0) = u_char(code);
-}
-
-
-bool Bytecode::check_must_rewrite() const {
-  assert(Bytecodes::can_rewrite(code()), "post-check only");
+bool Bytecode::check_must_rewrite(Bytecodes::Code code) const {
+  assert(Bytecodes::can_rewrite(code), "post-check only");
 
   // Some codes are conditionally rewriting.  Look closely at them.
-  switch (code()) {
+  switch (code) {
   case Bytecodes::_aload_0:
     // Even if RewriteFrequentPairs is turned on,
     // the _aload_0 code might delay its rewrite until
@@ -58,14 +51,85 @@
 }
 
 
+#ifdef ASSERT
+
+void Bytecode::assert_same_format_as(Bytecodes::Code testbc, bool is_wide) const {
+  Bytecodes::Code thisbc = Bytecodes::cast(byte_at(0));
+  if (thisbc == Bytecodes::_breakpoint)  return;  // let the assertion fail silently
+  if (is_wide) {
+    assert(thisbc == Bytecodes::_wide, "expected a wide instruction");
+    thisbc = Bytecodes::cast(byte_at(1));
+    if (thisbc == Bytecodes::_breakpoint)  return;
+  }
+  int thisflags = Bytecodes::flags(testbc, is_wide) & Bytecodes::_all_fmt_bits;
+  int testflags = Bytecodes::flags(thisbc, is_wide) & Bytecodes::_all_fmt_bits;
+  if (thisflags != testflags)
+    tty->print_cr("assert_same_format_as(%d) failed on bc=%d%s; %d != %d",
+                  (int)testbc, (int)thisbc, (is_wide?"/wide":""), testflags, thisflags);
+  assert(thisflags == testflags, "expected format");
+}
+
+void Bytecode::assert_index_size(int size, Bytecodes::Code bc, bool is_wide) {
+  int have_fmt = (Bytecodes::flags(bc, is_wide)
+                  & (Bytecodes::_fmt_has_u2 | Bytecodes::_fmt_has_u4 |
+                     Bytecodes::_fmt_not_simple |
+                     // Not an offset field:
+                     Bytecodes::_fmt_has_o));
+  int need_fmt = -1;
+  switch (size) {
+  case 1: need_fmt = 0;                      break;
+  case 2: need_fmt = Bytecodes::_fmt_has_u2; break;
+  case 4: need_fmt = Bytecodes::_fmt_has_u4; break;
+  }
+  if (is_wide)  need_fmt |= Bytecodes::_fmt_not_simple;
+  if (have_fmt != need_fmt) {
+    tty->print_cr("assert_index_size %d: bc=%d%s %d != %d", size, bc, (is_wide?"/wide":""), have_fmt, need_fmt);
+    assert(have_fmt == need_fmt, "assert_index_size");
+  }
+}
+
+void Bytecode::assert_offset_size(int size, Bytecodes::Code bc, bool is_wide) {
+  int have_fmt = Bytecodes::flags(bc, is_wide) & Bytecodes::_all_fmt_bits;
+  int need_fmt = -1;
+  switch (size) {
+  case 2: need_fmt = Bytecodes::_fmt_bo2; break;
+  case 4: need_fmt = Bytecodes::_fmt_bo4; break;
+  }
+  if (is_wide)  need_fmt |= Bytecodes::_fmt_not_simple;
+  if (have_fmt != need_fmt) {
+    tty->print_cr("assert_offset_size %d: bc=%d%s %d != %d", size, bc, (is_wide?"/wide":""), have_fmt, need_fmt);
+    assert(have_fmt == need_fmt, "assert_offset_size");
+  }
+}
+
+void Bytecode::assert_constant_size(int size, int where, Bytecodes::Code bc, bool is_wide) {
+  int have_fmt = Bytecodes::flags(bc, is_wide) & (Bytecodes::_all_fmt_bits
+                                                  // Ignore any 'i' field (for iinc):
+                                                  & ~Bytecodes::_fmt_has_i);
+  int need_fmt = -1;
+  switch (size) {
+  case 1: need_fmt = Bytecodes::_fmt_bc;                          break;
+  case 2: need_fmt = Bytecodes::_fmt_bc | Bytecodes::_fmt_has_u2; break;
+  }
+  if (is_wide)  need_fmt |= Bytecodes::_fmt_not_simple;
+  int length = is_wide ? Bytecodes::wide_length_for(bc) : Bytecodes::length_for(bc);
+  if (have_fmt != need_fmt || where + size != length) {
+    tty->print_cr("assert_constant_size %d @%d: bc=%d%s %d != %d", size, where, bc, (is_wide?"/wide":""), have_fmt, need_fmt);
+  }
+  assert(have_fmt == need_fmt, "assert_constant_size");
+  assert(where + size == length, "assert_constant_size oob");
+}
+
+void Bytecode::assert_native_index(Bytecodes::Code bc, bool is_wide) {
+  assert((Bytecodes::flags(bc, is_wide) & Bytecodes::_fmt_has_nbo) != 0, "native index");
+}
+
+#endif //ASSERT
 
 // Implementation of Bytecode_tableupswitch
 
 int Bytecode_tableswitch::dest_offset_at(int i) const {
-  address x = aligned_addr_at(1);
-  int x2 = aligned_offset(1 + (3 + i)*jintSize);
-  int val = java_signed_word_at(x2);
-  return java_signed_word_at(aligned_offset(1 + (3 + i)*jintSize));
+  return get_Java_u4_at(aligned_offset(1 + (3 + i)*jintSize));
 }
 
 
@@ -74,6 +138,7 @@
 void Bytecode_invoke::verify() const {
   Bytecodes::Code bc = adjusted_invoke_code();
   assert(is_valid(), "check invoke");
+  assert(method()->constants()->cache() != NULL, "do not call this from verifier or rewriter");
 }
 
 
@@ -116,27 +181,12 @@
 int Bytecode_invoke::index() const {
   // Note:  Rewriter::rewrite changes the Java_u2 of an invokedynamic to a native_u4,
   // at the same time it allocates per-call-site CP cache entries.
-  if (has_giant_index())
-    return Bytes::get_native_u4(bcp() + 1);
+  Bytecodes::Code stdc = Bytecodes::java_code(code());
+  Bytecode* invoke = Bytecode_at(bcp());
+  if (invoke->has_index_u4(stdc))
+    return invoke->get_index_u4(stdc);
   else
-    return Bytes::get_Java_u2(bcp() + 1);
-}
-
-
-// Implementation of Bytecode_static
-
-void Bytecode_static::verify() const {
-  assert(Bytecodes::java_code(code()) == Bytecodes::_putstatic
-      || Bytecodes::java_code(code()) == Bytecodes::_getstatic, "check static");
-}
-
-
-BasicType Bytecode_static::result_type(methodOop method) const {
-  int index = java_hwrd_at(1);
-  constantPoolOop constants = method->constants();
-  symbolOop field_type = constants->signature_ref_at(index);
-  BasicType basic_type = FieldType::basic_type(field_type);
-  return basic_type;
+    return invoke->get_index_u2_cpcache(stdc);
 }
 
 
@@ -156,7 +206,8 @@
 
 
 int Bytecode_field::index() const {
-  return java_hwrd_at(1);
+  Bytecode* invoke = Bytecode_at(bcp());
+  return invoke->get_index_u2_cpcache(Bytecodes::_getfield);
 }
 
 
@@ -164,7 +215,14 @@
 
 int Bytecode_loadconstant::index() const {
   Bytecodes::Code stdc = Bytecodes::java_code(code());
-  return stdc == Bytecodes::_ldc ? java_byte_at(1) : java_hwrd_at(1);
+  if (stdc != Bytecodes::_wide) {
+    if (Bytecodes::java_code(stdc) == Bytecodes::_ldc)
+      return get_index_u1(stdc);
+    else
+      return get_index_u2(stdc, false);
+  }
+  stdc = Bytecodes::code_at(addr_at(1));
+  return get_index_u2(stdc, true);
 }
 
 //------------------------------------------------------------------------------
--- a/src/share/vm/interpreter/bytecode.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/bytecode.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -26,92 +26,100 @@
 // relative to an objects 'this' pointer.
 
 class ThisRelativeObj VALUE_OBJ_CLASS_SPEC {
- private:
-  int     sign_extend        (int x, int size)   const     { const int s = (BytesPerInt - size)*BitsPerByte; return (x << s) >> s; }
-
  public:
   // Address computation
   address addr_at            (int offset)        const     { return (address)this + offset; }
+  int     byte_at            (int offset)        const     { return *(addr_at(offset)); }
   address aligned_addr_at    (int offset)        const     { return (address)round_to((intptr_t)addr_at(offset), jintSize); }
   int     aligned_offset     (int offset)        const     { return aligned_addr_at(offset) - addr_at(0); }
 
-  // Java unsigned accessors (using Java spec byte ordering)
-  int     java_byte_at       (int offset)        const     { return *(jubyte*)addr_at(offset); }
-  int     java_hwrd_at       (int offset)        const     { return java_byte_at(offset) << (1 * BitsPerByte) | java_byte_at(offset + 1); }
-  int     java_word_at       (int offset)        const     { return java_hwrd_at(offset) << (2 * BitsPerByte) | java_hwrd_at(offset + 2); }
-
-  // Java signed accessors (using Java spec byte ordering)
-  int     java_signed_byte_at(int offset)        const     { return sign_extend(java_byte_at(offset), 1); }
-  int     java_signed_hwrd_at(int offset)        const     { return sign_extend(java_hwrd_at(offset), 2); }
-  int     java_signed_word_at(int offset)        const     { return             java_word_at(offset)    ; }
-
-  // Fast accessors (using the machine's natural byte ordering)
-  int     fast_byte_at       (int offset)        const     { return *(jubyte *)addr_at(offset); }
-  int     fast_hwrd_at       (int offset)        const     { return *(jushort*)addr_at(offset); }
-  int     fast_word_at       (int offset)        const     { return *(juint  *)addr_at(offset); }
-
-  // Fast signed accessors (using the machine's natural byte ordering)
-  int     fast_signed_byte_at(int offset)        const     { return *(jbyte *)addr_at(offset); }
-  int     fast_signed_hwrd_at(int offset)        const     { return *(jshort*)addr_at(offset); }
-  int     fast_signed_word_at(int offset)        const     { return *(jint  *)addr_at(offset); }
-
-  // Fast manipulators (using the machine's natural byte ordering)
-  void    set_fast_byte_at   (int offset, int x) const     { *(jbyte *)addr_at(offset) = (jbyte )x; }
-  void    set_fast_hwrd_at   (int offset, int x) const     { *(jshort*)addr_at(offset) = (jshort)x; }
-  void    set_fast_word_at   (int offset, int x) const     { *(jint  *)addr_at(offset) = (jint  )x; }
+  // Word access:
+  int     get_Java_u2_at     (int offset)        const     { return Bytes::get_Java_u2(addr_at(offset)); }
+  int     get_Java_u4_at     (int offset)        const     { return Bytes::get_Java_u4(addr_at(offset)); }
+  int     get_native_u2_at   (int offset)        const     { return Bytes::get_native_u2(addr_at(offset)); }
+  int     get_native_u4_at   (int offset)        const     { return Bytes::get_native_u4(addr_at(offset)); }
 };
 
 
 // The base class for different kinds of bytecode abstractions.
 // Provides the primitive operations to manipulate code relative
 // to an objects 'this' pointer.
+// FIXME: Make this a ResourceObj, include the enclosing methodOop, and cache the opcode.
 
 class Bytecode: public ThisRelativeObj {
  protected:
   u_char byte_at(int offset) const               { return *addr_at(offset); }
-  bool check_must_rewrite() const;
+  bool check_must_rewrite(Bytecodes::Code bc) const;
 
  public:
   // Attributes
   address bcp() const                            { return addr_at(0); }
-  address next_bcp() const                       { return addr_at(0) + Bytecodes::length_at(bcp()); }
   int instruction_size() const                   { return Bytecodes::length_at(bcp()); }
 
+  // Warning: Use code() with caution on live bytecode streams.  4926272
   Bytecodes::Code code() const                   { return Bytecodes::code_at(addr_at(0)); }
   Bytecodes::Code java_code() const              { return Bytecodes::java_code(code()); }
-  bool must_rewrite() const                      { return Bytecodes::can_rewrite(code()) && check_must_rewrite(); }
-  bool is_active_breakpoint() const              { return Bytecodes::is_active_breakpoint_at(bcp()); }
-
-  int     one_byte_index() const                 { assert_index_size(1); return byte_at(1); }
-  int     two_byte_index() const                 { assert_index_size(2); return (byte_at(1) << 8) + byte_at(2); }
-
-  int     offset() const                         { return (two_byte_index() << 16) >> 16; }
-  address destination() const                    { return bcp() + offset(); }
-
-  // Attribute modification
-  void    set_code(Bytecodes::Code code);
+  bool must_rewrite(Bytecodes::Code code) const  { return Bytecodes::can_rewrite(code) && check_must_rewrite(code); }
 
   // Creation
   inline friend Bytecode* Bytecode_at(address bcp);
 
- private:
-  void assert_index_size(int required_size) const {
-#ifdef ASSERT
-    int isize = instruction_size() - 1;
-    if (isize == 2 && code() == Bytecodes::_iinc)
-      isize = 1;
-    else if (isize <= 2)
-      ;                         // no change
-    else if (code() == Bytecodes::_invokedynamic)
-      isize = 4;
-    else
-      isize = 2;
-    assert(isize = required_size, "wrong index size");
-#endif
+  // Static functions for parsing bytecodes in place.
+  int get_index_u1(Bytecodes::Code bc) const {
+    assert_same_format_as(bc); assert_index_size(1, bc);
+    return *(jubyte*)addr_at(1);
+  }
+  int get_index_u2(Bytecodes::Code bc, bool is_wide = false) const {
+    assert_same_format_as(bc, is_wide); assert_index_size(2, bc, is_wide);
+    address p = addr_at(is_wide ? 2 : 1);
+    if (can_use_native_byte_order(bc, is_wide))
+          return Bytes::get_native_u2(p);
+    else  return Bytes::get_Java_u2(p);
+  }
+  int get_index_u2_cpcache(Bytecodes::Code bc) const {
+    assert_same_format_as(bc); assert_index_size(2, bc); assert_native_index(bc);
+    return Bytes::get_native_u2(addr_at(1)) DEBUG_ONLY(+ constantPoolOopDesc::CPCACHE_INDEX_TAG);
+  }
+  int get_index_u4(Bytecodes::Code bc) const {
+    assert_same_format_as(bc); assert_index_size(4, bc);
+    assert(can_use_native_byte_order(bc), "");
+    return Bytes::get_native_u4(addr_at(1));
+  }
+  bool has_index_u4(Bytecodes::Code bc) const {
+    return bc == Bytecodes::_invokedynamic;
+  }
+
+  int get_offset_s2(Bytecodes::Code bc) const {
+    assert_same_format_as(bc); assert_offset_size(2, bc);
+    return (jshort) Bytes::get_Java_u2(addr_at(1));
+  }
+  int get_offset_s4(Bytecodes::Code bc) const {
+    assert_same_format_as(bc); assert_offset_size(4, bc);
+    return (jint) Bytes::get_Java_u4(addr_at(1));
+  }
+
+  int get_constant_u1(int offset, Bytecodes::Code bc) const {
+    assert_same_format_as(bc); assert_constant_size(1, offset, bc);
+    return *(jbyte*)addr_at(offset);
+  }
+  int get_constant_u2(int offset, Bytecodes::Code bc, bool is_wide = false) const {
+    assert_same_format_as(bc, is_wide); assert_constant_size(2, offset, bc, is_wide);
+    return (jshort) Bytes::get_Java_u2(addr_at(offset));
+  }
+
+  // These are used locally and also from bytecode streams.
+  void assert_same_format_as(Bytecodes::Code testbc, bool is_wide = false) const NOT_DEBUG_RETURN;
+  static void assert_index_size(int required_size, Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN;
+  static void assert_offset_size(int required_size, Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN;
+  static void assert_constant_size(int required_size, int where, Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN;
+  static void assert_native_index(Bytecodes::Code bc, bool is_wide = false) NOT_DEBUG_RETURN;
+  static bool can_use_native_byte_order(Bytecodes::Code bc, bool is_wide = false) {
+    return (!Bytes::is_Java_byte_ordering_different() || Bytecodes::native_byte_order(bc /*, is_wide*/));
   }
 };
 
 inline Bytecode* Bytecode_at(address bcp) {
+  // Warning: Use with caution on live bytecode streams.  4926272
   return (Bytecode*)bcp;
 }
 
@@ -124,8 +132,8 @@
   int  _offset;
 
  public:
-  int  match() const                             { return java_signed_word_at(0 * jintSize); }
-  int  offset() const                            { return java_signed_word_at(1 * jintSize); }
+  int  match() const                             { return get_Java_u4_at(0 * jintSize); }
+  int  offset() const                            { return get_Java_u4_at(1 * jintSize); }
 };
 
 
@@ -134,8 +142,8 @@
   void verify() const PRODUCT_RETURN;
 
   // Attributes
-  int  default_offset() const                    { return java_signed_word_at(aligned_offset(1 + 0*jintSize)); }
-  int  number_of_pairs() const                   { return java_signed_word_at(aligned_offset(1 + 1*jintSize)); }
+  int  default_offset() const                    { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); }
+  int  number_of_pairs() const                   { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); }
   LookupswitchPair* pair_at(int i) const         { assert(0 <= i && i < number_of_pairs(), "pair index out of bounds");
                                                    return (LookupswitchPair*)aligned_addr_at(1 + (1 + i)*2*jintSize); }
   // Creation
@@ -154,9 +162,9 @@
   void verify() const PRODUCT_RETURN;
 
   // Attributes
-  int  default_offset() const                    { return java_signed_word_at(aligned_offset(1 + 0*jintSize)); }
-  int  low_key() const                           { return java_signed_word_at(aligned_offset(1 + 1*jintSize)); }
-  int  high_key() const                          { return java_signed_word_at(aligned_offset(1 + 2*jintSize)); }
+  int  default_offset() const                    { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); }
+  int  low_key() const                           { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); }
+  int  high_key() const                          { return get_Java_u4_at(aligned_offset(1 + 2*jintSize)); }
   int  dest_offset_at(int i) const;
   int  length()                                  { return high_key()-low_key()+1; }
 
@@ -206,7 +214,6 @@
   bool is_invokedynamic() const                  { return adjusted_invoke_code() == Bytecodes::_invokedynamic; }
 
   bool has_receiver() const                      { return !is_invokestatic() && !is_invokedynamic(); }
-  bool has_giant_index() const                   { return is_invokedynamic(); }
 
   bool is_valid() const                          { return is_invokeinterface() ||
                                                           is_invokevirtual()   ||
@@ -252,26 +259,6 @@
 }
 
 
-// Abstraction for {get,put}static
-
-class Bytecode_static: public Bytecode {
- public:
-  void verify() const;
-
-  // Returns the result type of the send by inspecting the field ref
-  BasicType result_type(methodOop method) const;
-
-  // Creation
-  inline friend Bytecode_static* Bytecode_static_at(const methodOop method, address bcp);
-};
-
-inline Bytecode_static* Bytecode_static_at(const methodOop method, address bcp) {
-  Bytecode_static* b = (Bytecode_static*)bcp;
-  debug_only(b->verify());
-  return b;
-}
-
-
 // Abstraction for checkcast
 
 class Bytecode_checkcast: public Bytecode {
@@ -279,7 +266,7 @@
   void verify() const { assert(Bytecodes::java_code(code()) == Bytecodes::_checkcast, "check checkcast"); }
 
   // Returns index
-  long index() const   { return java_hwrd_at(1); };
+  long index() const   { return get_index_u2(Bytecodes::_checkcast); };
 
   // Creation
   inline friend Bytecode_checkcast* Bytecode_checkcast_at(address bcp);
@@ -299,7 +286,7 @@
   void verify() const { assert(code() == Bytecodes::_instanceof, "check instanceof"); }
 
   // Returns index
-  long index() const   { return java_hwrd_at(1); };
+  long index() const   { return get_index_u2(Bytecodes::_instanceof); };
 
   // Creation
   inline friend Bytecode_instanceof* Bytecode_instanceof_at(address bcp);
@@ -317,7 +304,7 @@
   void verify() const { assert(java_code() == Bytecodes::_new, "check new"); }
 
   // Returns index
-  long index() const   { return java_hwrd_at(1); };
+  long index() const   { return get_index_u2(Bytecodes::_new); };
 
   // Creation
   inline friend Bytecode_new* Bytecode_new_at(address bcp);
@@ -335,7 +322,7 @@
   void verify() const { assert(java_code() == Bytecodes::_multianewarray, "check new"); }
 
   // Returns index
-  long index() const   { return java_hwrd_at(1); };
+  long index() const   { return get_index_u2(Bytecodes::_multianewarray); };
 
   // Creation
   inline friend Bytecode_multianewarray* Bytecode_multianewarray_at(address bcp);
@@ -353,7 +340,7 @@
   void verify() const { assert(java_code() == Bytecodes::_anewarray, "check anewarray"); }
 
   // Returns index
-  long index() const   { return java_hwrd_at(1); };
+  long index() const   { return get_index_u2(Bytecodes::_anewarray); };
 
   // Creation
   inline friend Bytecode_anewarray* Bytecode_anewarray_at(address bcp);
--- a/src/share/vm/interpreter/bytecodeStream.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/bytecodeStream.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -48,6 +48,25 @@
       }
     }
   }
-  _code = code;
+  _raw_code = code;
   return code;
 }
+
+#ifdef ASSERT
+void BaseBytecodeStream::assert_raw_index_size(int size) const {
+  if (raw_code() == Bytecodes::_invokedynamic && is_raw()) {
+    // in raw mode, pretend indy is "bJJ__"
+    assert(size == 2, "raw invokedynamic instruction has 2-byte index only");
+  } else {
+    bytecode()->assert_index_size(size, raw_code(), is_wide());
+  }
+}
+
+void BaseBytecodeStream::assert_raw_stream(bool want_raw) const {
+  if (want_raw) {
+    assert( is_raw(), "this function only works on raw streams");
+  } else {
+    assert(!is_raw(), "this function only works on non-raw streams");
+  }
+}
+#endif //ASSERT
--- a/src/share/vm/interpreter/bytecodeStream.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/bytecodeStream.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -32,13 +32,13 @@
 // while ((c = s.next()) >= 0) {
 //   ...
 // }
-//
+
 // A RawBytecodeStream is a simple version of BytecodeStream.
 // It is used ONLY when we know the bytecodes haven't been rewritten
-// yet, such as in the rewriter or the verifier. Currently only the
-// verifier uses this class.
+// yet, such as in the rewriter or the verifier.
 
-class RawBytecodeStream: StackObj {
+// Here is the common base class for both RawBytecodeStream and BytecodeStream:
+class BaseBytecodeStream: StackObj {
  protected:
   // stream buffer
   methodHandle    _method;                       // read from method directly
@@ -49,15 +49,17 @@
   int             _end_bci;                      // bci after the current iteration interval
 
   // last bytecode read
-  Bytecodes::Code _code;
+  Bytecodes::Code _raw_code;
   bool            _is_wide;
+  bool            _is_raw;                       // false in 'cooked' BytecodeStream
+
+  // Construction
+  BaseBytecodeStream(methodHandle method) : _method(method) {
+    set_interval(0, _method->code_size());
+    _is_raw = false;
+  }
 
  public:
-  // Construction
-  RawBytecodeStream(methodHandle method) : _method(method) {
-    set_interval(0, _method->code_size());
-  }
-
   // Iteration control
   void set_interval(int beg_bci, int end_bci) {
     // iterate over the interval [beg_bci, end_bci)
@@ -72,6 +74,46 @@
     set_interval(beg_bci, _method->code_size());
   }
 
+  bool is_raw() const { return _is_raw; }
+
+  // Stream attributes
+  methodHandle    method() const                 { return _method; }
+
+  int             bci() const                    { return _bci; }
+  int             next_bci() const               { return _next_bci; }
+  int             end_bci() const                { return _end_bci; }
+
+  Bytecodes::Code raw_code() const               { return _raw_code; }
+  bool            is_wide() const                { return _is_wide; }
+  int             instruction_size() const       { return (_next_bci - _bci); }
+  bool            is_last_bytecode() const       { return _next_bci >= _end_bci; }
+
+  address         bcp() const                    { return method()->code_base() + _bci; }
+  Bytecode*       bytecode() const               { return Bytecode_at(bcp()); }
+
+  // State changes
+  void            set_next_bci(int bci)          { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; }
+
+  // Bytecode-specific attributes
+  int             dest() const                   { return bci() + bytecode()->get_offset_s2(raw_code()); }
+  int             dest_w() const                 { return bci() + bytecode()->get_offset_s4(raw_code()); }
+
+  // One-byte indices.
+  int             get_index_u1() const           { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); }
+
+ protected:
+  void assert_raw_index_size(int size) const NOT_DEBUG_RETURN;
+  void assert_raw_stream(bool want_raw) const NOT_DEBUG_RETURN;
+};
+
+class RawBytecodeStream: public BaseBytecodeStream {
+ public:
+  // Construction
+  RawBytecodeStream(methodHandle method) : BaseBytecodeStream(method) {
+    _is_raw = true;
+  }
+
+ public:
   // Iteration
   // Use raw_next() rather than next() for faster method reference
   Bytecodes::Code raw_next() {
@@ -80,7 +122,7 @@
     _bci = _next_bci;
     assert(!is_last_bytecode(), "caller should check is_last_bytecode()");
 
-    address bcp = RawBytecodeStream::bcp();
+    address bcp = this->bcp();
     code        = Bytecodes::code_or_bp_at(bcp);
 
     // set next bytecode position
@@ -90,84 +132,49 @@
              && code != Bytecodes::_lookupswitch, "can't be special bytecode");
       _is_wide = false;
       _next_bci += l;
-      _code = code;
+      _raw_code = code;
       return code;
-    } else if (code == Bytecodes::_wide && _bci + 1 >= _end_bci) {
-      return Bytecodes::_illegal;
     } else {
       return raw_next_special(code);
     }
   }
   Bytecodes::Code raw_next_special(Bytecodes::Code code);
 
-  // Stream attributes
-  methodHandle    method() const                 { return _method; }
-
-  int             bci() const                    { return _bci; }
-  int             next_bci() const               { return _next_bci; }
-  int             end_bci() const                { return _end_bci; }
-
-  Bytecodes::Code code() const                   { return _code; }
-  bool            is_wide() const                { return _is_wide; }
-  int             instruction_size() const       { return (_next_bci - _bci); }
-  bool            is_last_bytecode() const       { return _next_bci >= _end_bci; }
-
-  address         bcp() const                    { return method()->code_base() + _bci; }
-  address         next_bcp()                     { return method()->code_base() + _next_bci; }
-
-  // State changes
-  void            set_next_bci(int bci)          { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; }
-
-  // Bytecode-specific attributes
-  int             dest() const                   { return bci() + (short)Bytes::get_Java_u2(bcp() + 1); }
-  int             dest_w() const                 { return bci() + (int  )Bytes::get_Java_u4(bcp() + 1); }
-
-  // Unsigned indices, widening
-  int             get_index() const              { assert_index_size(is_wide() ? 2 : 1);
-                                                   return (is_wide()) ? Bytes::get_Java_u2(bcp() + 2) : bcp()[1]; }
-  int             get_index_big() const          { assert_index_size(2);
-                                                   return (int)Bytes::get_Java_u2(bcp() + 1);  }
-  int             get_index_int() const          { return has_giant_index() ? get_index_giant() : get_index_big(); }
-  int             get_index_giant() const        { assert_index_size(4); return Bytes::get_native_u4(bcp() + 1); }
-  int             has_giant_index() const        { return (code() == Bytecodes::_invokedynamic); }
+  // Unsigned indices, widening, with no swapping of bytes
+  int             get_index() const          { return (is_wide()) ? get_index_u2_raw(bcp() + 2) : get_index_u1(); }
+  // Get an unsigned 2-byte index, with no swapping of bytes.
+  int             get_index_u2() const       { assert(!is_wide(), ""); return get_index_u2_raw(bcp() + 1);  }
 
  private:
-  void assert_index_size(int required_size) const {
-#ifdef ASSERT
-    int isize = instruction_size() - (int)_is_wide - 1;
-    if (isize == 2 && code() == Bytecodes::_iinc)
-      isize = 1;
-    else if (isize <= 2)
-      ;                         // no change
-    else if (has_giant_index())
-      isize = 4;
-    else
-      isize = 2;
-    assert(isize = required_size, "wrong index size");
-#endif
+  int get_index_u2_raw(address p) const {
+    assert_raw_index_size(2); assert_raw_stream(true);
+    return Bytes::get_Java_u2(p);
   }
 };
 
 // In BytecodeStream, non-java bytecodes will be translated into the
 // corresponding java bytecodes.
 
-class BytecodeStream: public RawBytecodeStream {
+class BytecodeStream: public BaseBytecodeStream {
+  Bytecodes::Code _code;
+
  public:
   // Construction
-  BytecodeStream(methodHandle method) : RawBytecodeStream(method) { }
+  BytecodeStream(methodHandle method) : BaseBytecodeStream(method) { }
 
   // Iteration
   Bytecodes::Code next() {
-    Bytecodes::Code code;
+    Bytecodes::Code raw_code, code;
     // set reading position
     _bci = _next_bci;
     if (is_last_bytecode()) {
       // indicate end of bytecode stream
-      code = Bytecodes::_illegal;
+      raw_code = code = Bytecodes::_illegal;
     } else {
       // get bytecode
-      address bcp = BytecodeStream::bcp();
-      code        = Bytecodes::java_code_at(bcp);
+      address bcp = this->bcp();
+      raw_code = Bytecodes::code_at(bcp);
+      code = Bytecodes::java_code(raw_code);
       // set next bytecode position
       //
       // note that we cannot advance before having the
@@ -181,14 +188,29 @@
       _is_wide      = false;
       // check for special (uncommon) cases
       if (code == Bytecodes::_wide) {
-        code = (Bytecodes::Code)bcp[1];
+        raw_code = (Bytecodes::Code)bcp[1];
+        code = raw_code;  // wide BCs are always Java-normal
         _is_wide = true;
       }
       assert(Bytecodes::is_java_code(code), "sanity check");
     }
+    _raw_code = raw_code;
     _code = code;
     return _code;
   }
 
   bool            is_active_breakpoint() const   { return Bytecodes::is_active_breakpoint_at(bcp()); }
+  Bytecodes::Code code() const                   { return _code; }
+
+  // Unsigned indices, widening
+  int             get_index() const              { return is_wide() ? bytecode()->get_index_u2(raw_code(), true) : get_index_u1(); }
+  // Get an unsigned 2-byte index, swapping the bytes if necessary.
+  int             get_index_u2() const           { assert_raw_stream(false);
+                                                   return bytecode()->get_index_u2(raw_code(), false); }
+  // Get an unsigned 2-byte index in native order.
+  int             get_index_u2_cpcache() const   { assert_raw_stream(false);
+                                                   return bytecode()->get_index_u2_cpcache(raw_code()); }
+  int             get_index_u4() const           { assert_raw_stream(false);
+                                                   return bytecode()->get_index_u4(raw_code()); }
+  bool            has_index_u4() const           { return bytecode()->has_index_u4(raw_code()); }
 };
--- a/src/share/vm/interpreter/bytecodeTracer.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/bytecodeTracer.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -39,6 +39,7 @@
   // (Also, ensure that occasional false positives are benign.)
   methodOop _current_method;
   bool      _is_wide;
+  Bytecodes::Code _code;
   address   _next_pc;                // current decoding position
 
   void      align()                  { _next_pc = (address)round_to((intptr_t)_next_pc, sizeof(jint)); }
@@ -46,23 +47,26 @@
   short     get_short()              { short i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; }
   int       get_int()                { int i=Bytes::get_Java_u4(_next_pc); _next_pc+=4; return i; }
 
-  int       get_index()              { return *(address)_next_pc++; }
-  int       get_big_index()          { int i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; }
-  int       get_giant_index()        { int i=Bytes::get_native_u4(_next_pc); _next_pc+=4; return i; }
-  int       get_index_special()      { return (is_wide()) ? get_big_index() : get_index(); }
+  int       get_index_u1()           { return *(address)_next_pc++; }
+  int       get_index_u2()           { int i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; }
+  int       get_index_u2_cpcache()   { int i=Bytes::get_native_u2(_next_pc); _next_pc+=2; return i + constantPoolOopDesc::CPCACHE_INDEX_TAG; }
+  int       get_index_u4()           { int i=Bytes::get_native_u4(_next_pc); _next_pc+=4; return i; }
+  int       get_index_special()      { return (is_wide()) ? get_index_u2() : get_index_u1(); }
   methodOop method()                 { return _current_method; }
   bool      is_wide()                { return _is_wide; }
+  Bytecodes::Code raw_code()         { return Bytecodes::Code(_code); }
 
 
-  bool      check_index(int i, bool in_cp_cache, int& cp_index, outputStream* st = tty);
+  bool      check_index(int i, int& cp_index, outputStream* st = tty);
   void      print_constant(int i, outputStream* st = tty);
   void      print_field_or_method(int i, outputStream* st = tty);
-  void      print_attributes(Bytecodes::Code code, int bci, outputStream* st = tty);
+  void      print_attributes(int bci, outputStream* st = tty);
   void      bytecode_epilog(int bci, outputStream* st = tty);
 
  public:
   BytecodePrinter() {
     _is_wide = false;
+    _code = Bytecodes::_illegal;
   }
 
   // This method is called while executing the raw bytecodes, so none of
@@ -89,7 +93,8 @@
     } else {
       code = Bytecodes::code_at(bcp);
     }
-    int bci = bcp - method->code_base();
+    _code = code;
+     int bci = bcp - method->code_base();
     st->print("[%d] ", (int) Thread::current()->osthread()->thread_id());
     if (Verbose) {
       st->print("%8d  %4d  " INTPTR_FORMAT " " INTPTR_FORMAT " %s",
@@ -99,10 +104,11 @@
            BytecodeCounter::counter_value(), bci, Bytecodes::name(code));
     }
     _next_pc = is_wide() ? bcp+2 : bcp+1;
-    print_attributes(code, bci);
+    print_attributes(bci);
     // Set is_wide for the next one, since the caller of this doesn't skip
     // the next bytecode.
     _is_wide = (code == Bytecodes::_wide);
+    _code = Bytecodes::_illegal;
   }
 
   // Used for methodOop::print_codes().  The input bcp comes from
@@ -116,6 +122,7 @@
     if (is_wide()) {
       code = Bytecodes::code_at(bcp+1);
     }
+    _code = code;
     int bci = bcp - method->code_base();
     // Print bytecode index and name
     if (is_wide()) {
@@ -124,7 +131,7 @@
       st->print("%d %s", bci, Bytecodes::name(code));
     }
     _next_pc = is_wide() ? bcp+2 : bcp+1;
-    print_attributes(code, bci, st);
+    print_attributes(bci, st);
     bytecode_epilog(bci, st);
   }
 };
@@ -185,12 +192,13 @@
   }
 }
 
-bool BytecodePrinter::check_index(int i, bool in_cp_cache, int& cp_index, outputStream* st) {
+bool BytecodePrinter::check_index(int i, int& cp_index, outputStream* st) {
   constantPoolOop constants = method()->constants();
   int ilimit = constants->length(), climit = 0;
+  Bytecodes::Code code = raw_code();
 
   constantPoolCacheOop cache = NULL;
-  if (in_cp_cache) {
+  if (Bytecodes::uses_cp_cache(code)) {
     cache = constants->cache();
     if (cache != NULL) {
       //climit = cache->length();  // %%% private!
@@ -201,7 +209,7 @@
     }
   }
 
-  if (in_cp_cache && constantPoolCacheOopDesc::is_secondary_index(i)) {
+  if (cache != NULL && constantPoolCacheOopDesc::is_secondary_index(i)) {
     i = constantPoolCacheOopDesc::decode_secondary_index(i);
     st->print(" secondary cache[%d] of", i);
     if (i >= 0 && i < climit) {
@@ -218,8 +226,6 @@
   }
 
   if (cache != NULL) {
-    i = Bytes::swap_u2(i);
-    if (WizardMode)  st->print(" (swap=%d)", i);
     goto check_cache_index;
   }
 
@@ -234,6 +240,17 @@
   return false;
 
  check_cache_index:
+#ifdef ASSERT
+  {
+    const int CPCACHE_INDEX_TAG = constantPoolOopDesc::CPCACHE_INDEX_TAG;
+    if (i >= CPCACHE_INDEX_TAG && i < climit + CPCACHE_INDEX_TAG) {
+      i -= CPCACHE_INDEX_TAG;
+    } else {
+      st->print_cr(" CP[%d] missing bias?", i);
+      return false;
+    }
+  }
+#endif //ASSERT
   if (i >= 0 && i < climit) {
     if (cache->entry_at(i)->is_secondary_entry()) {
       st->print_cr(" secondary entry?");
@@ -248,7 +265,7 @@
 
 void BytecodePrinter::print_constant(int i, outputStream* st) {
   int orig_i = i;
-  if (!check_index(orig_i, false, i, st))  return;
+  if (!check_index(orig_i, i, st))  return;
 
   constantPoolOop constants = method()->constants();
   constantTag tag = constants->tag_at(i);
@@ -279,7 +296,7 @@
 
 void BytecodePrinter::print_field_or_method(int i, outputStream* st) {
   int orig_i = i;
-  if (!check_index(orig_i, true, i, st))  return;
+  if (!check_index(orig_i, i, st))  return;
 
   constantPoolOop constants = method()->constants();
   constantTag tag = constants->tag_at(i);
@@ -303,9 +320,9 @@
 }
 
 
-void BytecodePrinter::print_attributes(Bytecodes::Code code, int bci, outputStream* st) {
+void BytecodePrinter::print_attributes(int bci, outputStream* st) {
   // Show attributes of pre-rewritten codes
-  code = Bytecodes::java_code(code);
+  Bytecodes::Code code = Bytecodes::java_code(raw_code());
   // If the code doesn't have any fields there's nothing to print.
   // note this is ==1 because the tableswitch and lookupswitch are
   // zero size (for some reason) and we want to print stuff out for them.
@@ -323,12 +340,12 @@
       st->print_cr(" " INT32_FORMAT, get_short());
       break;
     case Bytecodes::_ldc:
-      print_constant(get_index(), st);
+      print_constant(get_index_u1(), st);
       break;
 
     case Bytecodes::_ldc_w:
     case Bytecodes::_ldc2_w:
-      print_constant(get_big_index(), st);
+      print_constant(get_index_u2(), st);
       break;
 
     case Bytecodes::_iload:
@@ -352,7 +369,7 @@
       break;
 
     case Bytecodes::_newarray: {
-        BasicType atype = (BasicType)get_index();
+        BasicType atype = (BasicType)get_index_u1();
         const char* str = type2name(atype);
         if (str == NULL || atype == T_OBJECT || atype == T_ARRAY) {
           assert(false, "Unidentified basic type");
@@ -361,15 +378,15 @@
       }
       break;
     case Bytecodes::_anewarray: {
-        int klass_index = get_big_index();
+        int klass_index = get_index_u2();
         constantPoolOop constants = method()->constants();
         symbolOop name = constants->klass_name_at(klass_index);
         st->print_cr(" %s ", name->as_C_string());
       }
       break;
     case Bytecodes::_multianewarray: {
-        int klass_index = get_big_index();
-        int nof_dims = get_index();
+        int klass_index = get_index_u2();
+        int nof_dims = get_index_u1();
         constantPoolOop constants = method()->constants();
         symbolOop name = constants->klass_name_at(klass_index);
         st->print_cr(" %s %d", name->as_C_string(), nof_dims);
@@ -451,31 +468,31 @@
     case Bytecodes::_getstatic:
     case Bytecodes::_putfield:
     case Bytecodes::_getfield:
-      print_field_or_method(get_big_index(), st);
+      print_field_or_method(get_index_u2_cpcache(), st);
       break;
 
     case Bytecodes::_invokevirtual:
     case Bytecodes::_invokespecial:
     case Bytecodes::_invokestatic:
-      print_field_or_method(get_big_index(), st);
+      print_field_or_method(get_index_u2_cpcache(), st);
       break;
 
     case Bytecodes::_invokeinterface:
-      { int i = get_big_index();
-        int n = get_index();
-        get_index();            // ignore zero byte
+      { int i = get_index_u2_cpcache();
+        int n = get_index_u1();
+        get_byte();            // ignore zero byte
         print_field_or_method(i, st);
       }
       break;
 
     case Bytecodes::_invokedynamic:
-      print_field_or_method(get_giant_index(), st);
+      print_field_or_method(get_index_u4(), st);
       break;
 
     case Bytecodes::_new:
     case Bytecodes::_checkcast:
     case Bytecodes::_instanceof:
-      { int i = get_big_index();
+      { int i = get_index_u2();
         constantPoolOop constants = method()->constants();
         symbolOop name = constants->klass_name_at(i);
         st->print_cr(" %d <%s>", i, name->as_C_string());
--- a/src/share/vm/interpreter/bytecodes.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/bytecodes.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -37,14 +37,11 @@
 
 bool            Bytecodes::_is_initialized = false;
 const char*     Bytecodes::_name          [Bytecodes::number_of_codes];
-const char*     Bytecodes::_format        [Bytecodes::number_of_codes];
-const char*     Bytecodes::_wide_format   [Bytecodes::number_of_codes];
 BasicType       Bytecodes::_result_type   [Bytecodes::number_of_codes];
 s_char          Bytecodes::_depth         [Bytecodes::number_of_codes];
-u_char          Bytecodes::_length        [Bytecodes::number_of_codes];
-bool            Bytecodes::_can_trap      [Bytecodes::number_of_codes];
+u_char          Bytecodes::_lengths       [Bytecodes::number_of_codes];
 Bytecodes::Code Bytecodes::_java_code     [Bytecodes::number_of_codes];
-bool            Bytecodes::_can_rewrite   [Bytecodes::number_of_codes];
+u_short         Bytecodes::_flags         [(1<<BitsPerByte)*2];
 
 
 Bytecodes::Code Bytecodes::code_at(methodOop method, int bci) {
@@ -91,6 +88,7 @@
       return (len > 0 && len == (int)len) ? len : -1;
     }
   }
+  // Note: Length functions must return <=0 for invalid bytecodes.
   return 0;
 }
 
@@ -124,15 +122,22 @@
 
 void Bytecodes::def(Code code, const char* name, const char* format, const char* wide_format, BasicType result_type, int depth, bool can_trap, Code java_code) {
   assert(wide_format == NULL || format != NULL, "short form must exist if there's a wide form");
+  int len  = (format      != NULL ? (int) strlen(format)      : 0);
+  int wlen = (wide_format != NULL ? (int) strlen(wide_format) : 0);
   _name          [code] = name;
-  _format        [code] = format;
-  _wide_format   [code] = wide_format;
   _result_type   [code] = result_type;
   _depth         [code] = depth;
-  _can_trap      [code] = can_trap;
-  _length        [code] = format != NULL ? (u_char)strlen(format) : 0;
+  _lengths       [code] = (wlen << 4) | (len & 0xF);
   _java_code     [code] = java_code;
-  if (java_code != code)  _can_rewrite[java_code] = true;
+  int bc_flags = 0;
+  if (can_trap)           bc_flags |= _bc_can_trap;
+  if (java_code != code)  bc_flags |= _bc_can_rewrite;
+  _flags[(u1)code+0*(1<<BitsPerByte)] = compute_flags(format,      bc_flags);
+  _flags[(u1)code+1*(1<<BitsPerByte)] = compute_flags(wide_format, bc_flags);
+  assert(is_defined(code)      == (format != NULL),      "");
+  assert(wide_is_defined(code) == (wide_format != NULL), "");
+  assert(length_for(code)      == len, "");
+  assert(wide_length_for(code) == wlen, "");
 }
 
 
@@ -140,23 +145,92 @@
 //
 // b: bytecode
 // c: signed constant, Java byte-ordering
-// i: unsigned index , Java byte-ordering
-// j: unsigned index , native byte-ordering
-// o: branch offset  , Java byte-ordering
+// i: unsigned local index, Java byte-ordering (I = native byte ordering)
+// j: unsigned CP cache index, Java byte-ordering (J = native byte ordering)
+// k: unsigned CP index, Java byte-ordering
+// o: branch offset, Java byte-ordering
 // _: unused/ignored
 // w: wide bytecode
 //
-// Note: Right now the format strings are used for 2 purposes:
+// Note: The format strings are used for 2 purposes:
 //       1. to specify the length of the bytecode
 //          (= number of characters in format string)
-//       2. to specify the bytecode attributes
-//
-//       The bytecode attributes are currently used only for bytecode tracing
-//       (see BytecodeTracer); thus if more specific format information is
-//       used, one would also have to adjust the bytecode tracer.
+//       2. to derive bytecode format flags (_fmt_has_k, etc.)
 //
 // Note: For bytecodes with variable length, the format string is the empty string.
 
+int Bytecodes::compute_flags(const char* format, int more_flags) {
+  if (format == NULL)  return 0;  // not even more_flags
+  int flags = more_flags;
+  const char* fp = format;
+  switch (*fp) {
+  case '\0':
+    flags |= _fmt_not_simple; // but variable
+    break;
+  case 'b':
+    flags |= _fmt_not_variable;  // but simple
+    ++fp;  // skip 'b'
+    break;
+  case 'w':
+    flags |= _fmt_not_variable | _fmt_not_simple;
+    ++fp;  // skip 'w'
+    guarantee(*fp == 'b', "wide format must start with 'wb'");
+    ++fp;  // skip 'b'
+    break;
+  }
+
+  int has_nbo = 0, has_jbo = 0, has_size = 0;
+  for (;;) {
+    int this_flag = 0;
+    char fc = *fp++;
+    switch (fc) {
+    case '\0':  // end of string
+      assert(flags == (jchar)flags, "change _format_flags");
+      return flags;
+
+    case '_': continue;         // ignore these
+
+    case 'j': this_flag = _fmt_has_j; has_jbo = 1; break;
+    case 'k': this_flag = _fmt_has_k; has_jbo = 1; break;
+    case 'i': this_flag = _fmt_has_i; has_jbo = 1; break;
+    case 'c': this_flag = _fmt_has_c; has_jbo = 1; break;
+    case 'o': this_flag = _fmt_has_o; has_jbo = 1; break;
+
+    // uppercase versions mark native byte order (from Rewriter)
+    // actually, only the 'J' case happens currently
+    case 'J': this_flag = _fmt_has_j; has_nbo = 1; break;
+    case 'K': this_flag = _fmt_has_k; has_nbo = 1; break;
+    case 'I': this_flag = _fmt_has_i; has_nbo = 1; break;
+    case 'C': this_flag = _fmt_has_c; has_nbo = 1; break;
+    case 'O': this_flag = _fmt_has_o; has_nbo = 1; break;
+    default:  guarantee(false, "bad char in format");
+    }
+
+    flags |= this_flag;
+
+    guarantee(!(has_jbo && has_nbo), "mixed byte orders in format");
+    if (has_nbo)
+      flags |= _fmt_has_nbo;
+
+    int this_size = 1;
+    if (*fp == fc) {
+      // advance beyond run of the same characters
+      this_size = 2;
+      while (*++fp == fc)  this_size++;
+      switch (this_size) {
+      case 2: flags |= _fmt_has_u2; break;
+      case 4: flags |= _fmt_has_u4; break;
+      default: guarantee(false, "bad rep count in format");
+      }
+    }
+    guarantee(has_size == 0 ||                     // no field yet
+              this_size == has_size ||             // same size
+              this_size < has_size && *fp == '\0', // last field can be short
+              "mixed field sizes in format");
+    has_size = this_size;
+  }
+}
+
 void Bytecodes::initialize() {
   if (_is_initialized) return;
   assert(number_of_codes <= 256, "too many bytecodes");
@@ -191,9 +265,9 @@
   def(_dconst_1            , "dconst_1"            , "b"    , NULL    , T_DOUBLE ,  2, false);
   def(_bipush              , "bipush"              , "bc"   , NULL    , T_INT    ,  1, false);
   def(_sipush              , "sipush"              , "bcc"  , NULL    , T_INT    ,  1, false);
-  def(_ldc                 , "ldc"                 , "bi"   , NULL    , T_ILLEGAL,  1, true );
-  def(_ldc_w               , "ldc_w"               , "bii"  , NULL    , T_ILLEGAL,  1, true );
-  def(_ldc2_w              , "ldc2_w"              , "bii"  , NULL    , T_ILLEGAL,  2, true );
+  def(_ldc                 , "ldc"                 , "bk"   , NULL    , T_ILLEGAL,  1, true );
+  def(_ldc_w               , "ldc_w"               , "bkk"  , NULL    , T_ILLEGAL,  1, true );
+  def(_ldc2_w              , "ldc2_w"              , "bkk"  , NULL    , T_ILLEGAL,  2, true );
   def(_iload               , "iload"               , "bi"   , "wbii"  , T_INT    ,  1, false);
   def(_lload               , "lload"               , "bi"   , "wbii"  , T_LONG   ,  2, false);
   def(_fload               , "fload"               , "bi"   , "wbii"  , T_FLOAT  ,  1, false);
@@ -351,26 +425,26 @@
   def(_dreturn             , "dreturn"             , "b"    , NULL    , T_DOUBLE , -2, true);
   def(_areturn             , "areturn"             , "b"    , NULL    , T_OBJECT , -1, true);
   def(_return              , "return"              , "b"    , NULL    , T_VOID   ,  0, true);
-  def(_getstatic           , "getstatic"           , "bjj"  , NULL    , T_ILLEGAL,  1, true );
-  def(_putstatic           , "putstatic"           , "bjj"  , NULL    , T_ILLEGAL, -1, true );
-  def(_getfield            , "getfield"            , "bjj"  , NULL    , T_ILLEGAL,  0, true );
-  def(_putfield            , "putfield"            , "bjj"  , NULL    , T_ILLEGAL, -2, true );
-  def(_invokevirtual       , "invokevirtual"       , "bjj"  , NULL    , T_ILLEGAL, -1, true);
-  def(_invokespecial       , "invokespecial"       , "bjj"  , NULL    , T_ILLEGAL, -1, true);
-  def(_invokestatic        , "invokestatic"        , "bjj"  , NULL    , T_ILLEGAL,  0, true);
-  def(_invokeinterface     , "invokeinterface"     , "bjj__", NULL    , T_ILLEGAL, -1, true);
-  def(_invokedynamic       , "invokedynamic"       , "bjjjj", NULL    , T_ILLEGAL,  0, true );
-  def(_new                 , "new"                 , "bii"  , NULL    , T_OBJECT ,  1, true );
+  def(_getstatic           , "getstatic"           , "bJJ"  , NULL    , T_ILLEGAL,  1, true );
+  def(_putstatic           , "putstatic"           , "bJJ"  , NULL    , T_ILLEGAL, -1, true );
+  def(_getfield            , "getfield"            , "bJJ"  , NULL    , T_ILLEGAL,  0, true );
+  def(_putfield            , "putfield"            , "bJJ"  , NULL    , T_ILLEGAL, -2, true );
+  def(_invokevirtual       , "invokevirtual"       , "bJJ"  , NULL    , T_ILLEGAL, -1, true);
+  def(_invokespecial       , "invokespecial"       , "bJJ"  , NULL    , T_ILLEGAL, -1, true);
+  def(_invokestatic        , "invokestatic"        , "bJJ"  , NULL    , T_ILLEGAL,  0, true);
+  def(_invokeinterface     , "invokeinterface"     , "bJJ__", NULL    , T_ILLEGAL, -1, true);
+  def(_invokedynamic       , "invokedynamic"       , "bJJJJ", NULL    , T_ILLEGAL,  0, true );
+  def(_new                 , "new"                 , "bkk"  , NULL    , T_OBJECT ,  1, true );
   def(_newarray            , "newarray"            , "bc"   , NULL    , T_OBJECT ,  0, true );
-  def(_anewarray           , "anewarray"           , "bii"  , NULL    , T_OBJECT ,  0, true );
+  def(_anewarray           , "anewarray"           , "bkk"  , NULL    , T_OBJECT ,  0, true );
   def(_arraylength         , "arraylength"         , "b"    , NULL    , T_VOID   ,  0, true );
   def(_athrow              , "athrow"              , "b"    , NULL    , T_VOID   , -1, true );
-  def(_checkcast           , "checkcast"           , "bii"  , NULL    , T_OBJECT ,  0, true );
-  def(_instanceof          , "instanceof"          , "bii"  , NULL    , T_INT    ,  0, true );
+  def(_checkcast           , "checkcast"           , "bkk"  , NULL    , T_OBJECT ,  0, true );
+  def(_instanceof          , "instanceof"          , "bkk"  , NULL    , T_INT    ,  0, true );
   def(_monitorenter        , "monitorenter"        , "b"    , NULL    , T_VOID   , -1, true );
   def(_monitorexit         , "monitorexit"         , "b"    , NULL    , T_VOID   , -1, true );
   def(_wide                , "wide"                , ""     , NULL    , T_VOID   ,  0, false);
-  def(_multianewarray      , "multianewarray"      , "biic" , NULL    , T_OBJECT ,  1, true );
+  def(_multianewarray      , "multianewarray"      , "bkkc" , NULL    , T_OBJECT ,  1, true );
   def(_ifnull              , "ifnull"              , "boo"  , NULL    , T_VOID   , -1, false);
   def(_ifnonnull           , "ifnonnull"           , "boo"  , NULL    , T_VOID   , -1, false);
   def(_goto_w              , "goto_w"              , "boooo", NULL    , T_VOID   ,  0, false);
@@ -380,35 +454,35 @@
   //  JVM bytecodes
   //  bytecode               bytecode name           format   wide f.   result tp  stk traps  std code
 
-  def(_fast_agetfield      , "fast_agetfield"      , "bjj"  , NULL    , T_OBJECT ,  0, true , _getfield       );
-  def(_fast_bgetfield      , "fast_bgetfield"      , "bjj"  , NULL    , T_INT    ,  0, true , _getfield       );
-  def(_fast_cgetfield      , "fast_cgetfield"      , "bjj"  , NULL    , T_CHAR   ,  0, true , _getfield       );
-  def(_fast_dgetfield      , "fast_dgetfield"      , "bjj"  , NULL    , T_DOUBLE ,  0, true , _getfield       );
-  def(_fast_fgetfield      , "fast_fgetfield"      , "bjj"  , NULL    , T_FLOAT  ,  0, true , _getfield       );
-  def(_fast_igetfield      , "fast_igetfield"      , "bjj"  , NULL    , T_INT    ,  0, true , _getfield       );
-  def(_fast_lgetfield      , "fast_lgetfield"      , "bjj"  , NULL    , T_LONG   ,  0, true , _getfield       );
-  def(_fast_sgetfield      , "fast_sgetfield"      , "bjj"  , NULL    , T_SHORT  ,  0, true , _getfield       );
+  def(_fast_agetfield      , "fast_agetfield"      , "bJJ"  , NULL    , T_OBJECT ,  0, true , _getfield       );
+  def(_fast_bgetfield      , "fast_bgetfield"      , "bJJ"  , NULL    , T_INT    ,  0, true , _getfield       );
+  def(_fast_cgetfield      , "fast_cgetfield"      , "bJJ"  , NULL    , T_CHAR   ,  0, true , _getfield       );
+  def(_fast_dgetfield      , "fast_dgetfield"      , "bJJ"  , NULL    , T_DOUBLE ,  0, true , _getfield       );
+  def(_fast_fgetfield      , "fast_fgetfield"      , "bJJ"  , NULL    , T_FLOAT  ,  0, true , _getfield       );
+  def(_fast_igetfield      , "fast_igetfield"      , "bJJ"  , NULL    , T_INT    ,  0, true , _getfield       );
+  def(_fast_lgetfield      , "fast_lgetfield"      , "bJJ"  , NULL    , T_LONG   ,  0, true , _getfield       );
+  def(_fast_sgetfield      , "fast_sgetfield"      , "bJJ"  , NULL    , T_SHORT  ,  0, true , _getfield       );
 
-  def(_fast_aputfield      , "fast_aputfield"      , "bjj"  , NULL    , T_OBJECT ,  0, true , _putfield       );
-  def(_fast_bputfield      , "fast_bputfield"      , "bjj"  , NULL    , T_INT    ,  0, true , _putfield       );
-  def(_fast_cputfield      , "fast_cputfield"      , "bjj"  , NULL    , T_CHAR   ,  0, true , _putfield       );
-  def(_fast_dputfield      , "fast_dputfield"      , "bjj"  , NULL    , T_DOUBLE ,  0, true , _putfield       );
-  def(_fast_fputfield      , "fast_fputfield"      , "bjj"  , NULL    , T_FLOAT  ,  0, true , _putfield       );
-  def(_fast_iputfield      , "fast_iputfield"      , "bjj"  , NULL    , T_INT    ,  0, true , _putfield       );
-  def(_fast_lputfield      , "fast_lputfield"      , "bjj"  , NULL    , T_LONG   ,  0, true , _putfield       );
-  def(_fast_sputfield      , "fast_sputfield"      , "bjj"  , NULL    , T_SHORT  ,  0, true , _putfield       );
+  def(_fast_aputfield      , "fast_aputfield"      , "bJJ"  , NULL    , T_OBJECT ,  0, true , _putfield       );
+  def(_fast_bputfield      , "fast_bputfield"      , "bJJ"  , NULL    , T_INT    ,  0, true , _putfield       );
+  def(_fast_cputfield      , "fast_cputfield"      , "bJJ"  , NULL    , T_CHAR   ,  0, true , _putfield       );
+  def(_fast_dputfield      , "fast_dputfield"      , "bJJ"  , NULL    , T_DOUBLE ,  0, true , _putfield       );
+  def(_fast_fputfield      , "fast_fputfield"      , "bJJ"  , NULL    , T_FLOAT  ,  0, true , _putfield       );
+  def(_fast_iputfield      , "fast_iputfield"      , "bJJ"  , NULL    , T_INT    ,  0, true , _putfield       );
+  def(_fast_lputfield      , "fast_lputfield"      , "bJJ"  , NULL    , T_LONG   ,  0, true , _putfield       );
+  def(_fast_sputfield      , "fast_sputfield"      , "bJJ"  , NULL    , T_SHORT  ,  0, true , _putfield       );
 
   def(_fast_aload_0        , "fast_aload_0"        , "b"    , NULL    , T_OBJECT ,  1, true , _aload_0        );
-  def(_fast_iaccess_0      , "fast_iaccess_0"      , "b_jj" , NULL    , T_INT    ,  1, true , _aload_0        );
-  def(_fast_aaccess_0      , "fast_aaccess_0"      , "b_jj" , NULL    , T_OBJECT ,  1, true , _aload_0        );
-  def(_fast_faccess_0      , "fast_faccess_0"      , "b_jj" , NULL    , T_OBJECT ,  1, true , _aload_0        );
+  def(_fast_iaccess_0      , "fast_iaccess_0"      , "b_JJ" , NULL    , T_INT    ,  1, true , _aload_0        );
+  def(_fast_aaccess_0      , "fast_aaccess_0"      , "b_JJ" , NULL    , T_OBJECT ,  1, true , _aload_0        );
+  def(_fast_faccess_0      , "fast_faccess_0"      , "b_JJ" , NULL    , T_OBJECT ,  1, true , _aload_0        );
 
   def(_fast_iload          , "fast_iload"          , "bi"   , NULL    , T_INT    ,  1, false, _iload);
   def(_fast_iload2         , "fast_iload2"         , "bi_i" , NULL    , T_INT    ,  2, false, _iload);
   def(_fast_icaload        , "fast_icaload"        , "bi_"  , NULL    , T_INT    ,  0, false, _iload);
 
   // Faster method invocation.
-  def(_fast_invokevfinal   , "fast_invokevfinal"   , "bjj"  , NULL    , T_ILLEGAL, -1, true, _invokevirtual   );
+  def(_fast_invokevfinal   , "fast_invokevfinal"   , "bJJ"  , NULL    , T_ILLEGAL, -1, true, _invokevirtual   );
 
   def(_fast_linearswitch   , "fast_linearswitch"   , ""     , NULL    , T_VOID   , -1, false, _lookupswitch   );
   def(_fast_binaryswitch   , "fast_binaryswitch"   , ""     , NULL    , T_VOID   , -1, false, _lookupswitch   );
--- a/src/share/vm/interpreter/bytecodes.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/bytecodes.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -280,17 +280,43 @@
     number_of_codes
   };
 
+  // Flag bits derived from format strings, can_trap, can_rewrite, etc.:
+  enum Flags {
+    // semantic flags:
+    _bc_can_trap      = 1<<0,     // bytecode execution can trap or block
+    _bc_can_rewrite   = 1<<1,     // bytecode execution has an alternate form
+
+    // format bits (determined only by the format string):
+    _fmt_has_c        = 1<<2,     // constant, such as sipush "bcc"
+    _fmt_has_j        = 1<<3,     // constant pool cache index, such as getfield "bjj"
+    _fmt_has_k        = 1<<4,     // constant pool index, such as ldc "bk"
+    _fmt_has_i        = 1<<5,     // local index, such as iload
+    _fmt_has_o        = 1<<6,     // offset, such as ifeq
+    _fmt_has_nbo      = 1<<7,     // contains native-order field(s)
+    _fmt_has_u2       = 1<<8,     // contains double-byte field(s)
+    _fmt_has_u4       = 1<<9,     // contains quad-byte field
+    _fmt_not_variable = 1<<10,    // not of variable length (simple or wide)
+    _fmt_not_simple   = 1<<11,    // either wide or variable length
+    _all_fmt_bits     = (_fmt_not_simple*2 - _fmt_has_c),
+
+    // Example derived format syndromes:
+    _fmt_b      = _fmt_not_variable,
+    _fmt_bc     = _fmt_b | _fmt_has_c,
+    _fmt_bi     = _fmt_b | _fmt_has_i,
+    _fmt_bkk    = _fmt_b | _fmt_has_k | _fmt_has_u2,
+    _fmt_bJJ    = _fmt_b | _fmt_has_j | _fmt_has_u2 | _fmt_has_nbo,
+    _fmt_bo2    = _fmt_b | _fmt_has_o | _fmt_has_u2,
+    _fmt_bo4    = _fmt_b | _fmt_has_o | _fmt_has_u4
+  };
+
  private:
   static bool        _is_initialized;
   static const char* _name          [number_of_codes];
-  static const char* _format        [number_of_codes];
-  static const char* _wide_format   [number_of_codes];
   static BasicType   _result_type   [number_of_codes];
   static s_char      _depth         [number_of_codes];
-  static u_char      _length        [number_of_codes];
-  static bool        _can_trap      [number_of_codes];
+  static u_char      _lengths       [number_of_codes];
   static Code        _java_code     [number_of_codes];
-  static bool        _can_rewrite   [number_of_codes];
+  static jchar       _flags         [(1<<BitsPerByte)*2]; // all second page for wide formats
 
   static void        def(Code code, const char* name, const char* format, const char* wide_format, BasicType result_type, int depth, bool can_trap);
   static void        def(Code code, const char* name, const char* format, const char* wide_format, BasicType result_type, int depth, bool can_trap, Code java_code);
@@ -322,24 +348,20 @@
    static Code       non_breakpoint_code_at(address bcp, methodOop method = NULL);
 
   // Bytecode attributes
-  static bool        is_defined     (int  code)    { return 0 <= code && code < number_of_codes && _format[code] != NULL; }
-  static bool        wide_is_defined(int  code)    { return is_defined(code) && _wide_format[code] != NULL; }
+  static bool        is_defined     (int  code)    { return 0 <= code && code < number_of_codes && flags(code, false) != 0; }
+  static bool        wide_is_defined(int  code)    { return is_defined(code) && flags(code, true) != 0; }
   static const char* name           (Code code)    { check(code);      return _name          [code]; }
-  static const char* format         (Code code)    { check(code);      return _format        [code]; }
-  static const char* wide_format    (Code code)    { return _wide_format[code]; }
   static BasicType   result_type    (Code code)    { check(code);      return _result_type   [code]; }
   static int         depth          (Code code)    { check(code);      return _depth         [code]; }
-  static int         length_for     (Code code)    { return _length[code]; }
-  static bool        can_trap       (Code code)    { check(code);      return _can_trap      [code]; }
+  // Note: Length functions must return <=0 for invalid bytecodes.
+  // Calling check(code) in length functions would throw an unwanted assert.
+  static int         length_for     (Code code)    { /*no check*/      return _lengths       [code] & 0xF; }
+  static int         wide_length_for(Code code)    { /*no check*/      return _lengths       [code] >> 4; }
+  static bool        can_trap       (Code code)    { check(code);      return has_all_flags(code, _bc_can_trap, false); }
   static Code        java_code      (Code code)    { check(code);      return _java_code     [code]; }
-  static bool        can_rewrite    (Code code)    { check(code);      return _can_rewrite   [code]; }
-  static int         wide_length_for(Code code)    {
-    if (!is_defined(code)) {
-      return 0;
-    }
-    const char* wf = wide_format(code);
-    return (wf == NULL) ? 0 : (int)strlen(wf);
-  }
+  static bool        can_rewrite    (Code code)    { check(code);      return has_all_flags(code, _bc_can_rewrite, false); }
+  static bool        native_byte_order(Code code)  { check(code);      return has_all_flags(code, _fmt_has_nbo, false); }
+  static bool        uses_cp_cache  (Code code)    { check(code);      return has_all_flags(code, _fmt_has_j, false); }
   // if 'end' is provided, it indicates the end of the code buffer which
   // should not be read past when parsing.
   static int         special_length_at(address bcp, address end = NULL);
@@ -355,6 +377,16 @@
 
   static bool        is_zero_const  (Code code)    { return (code == _aconst_null || code == _iconst_0
                                                            || code == _fconst_0 || code == _dconst_0); }
+  static int         compute_flags  (const char* format, int more_flags = 0);  // compute the flags
+  static int         flags          (int code, bool is_wide) {
+    assert(code == (u_char)code, "must be a byte");
+    return _flags[code + (is_wide ? (1<<BitsPerByte) : 0)];
+  }
+  static int         format_bits    (Code code, bool is_wide) { return flags(code, is_wide) & _all_fmt_bits; }
+  static bool        has_all_flags  (Code code, int test_flags, bool is_wide) {
+    return (flags(code, is_wide) & test_flags) == test_flags;
+  }
+
   // Initialization
   static void        initialize     ();
 };
--- a/src/share/vm/interpreter/interpreter.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/interpreter.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -226,8 +226,9 @@
 // not yet been executed (in Java semantics, not in actual operation).
 bool AbstractInterpreter::is_not_reached(methodHandle method, int bci) {
   address bcp = method->bcp_from(bci);
+  Bytecodes::Code code = Bytecodes::code_at(bcp, method());
 
-  if (!Bytecode_at(bcp)->must_rewrite()) {
+  if (!Bytecode_at(bcp)->must_rewrite(code)) {
     // might have been reached
     return false;
   }
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -63,7 +63,7 @@
 IRT_ENTRY(void, InterpreterRuntime::ldc(JavaThread* thread, bool wide))
   // access constant pool
   constantPoolOop pool = method(thread)->constants();
-  int index = wide ? two_byte_index(thread) : one_byte_index(thread);
+  int index = wide ? get_index_u2(thread, Bytecodes::_ldc_w) : get_index_u1(thread, Bytecodes::_ldc);
   constantTag tag = pool->tag_at(index);
 
   if (tag.is_unresolved_klass() || tag.is_klass()) {
@@ -135,7 +135,7 @@
 IRT_ENTRY(void, InterpreterRuntime::multianewarray(JavaThread* thread, jint* first_size_address))
   // We may want to pass in more arguments - could make this slightly faster
   constantPoolOop constants = method(thread)->constants();
-  int          i = two_byte_index(thread);
+  int          i = get_index_u2(thread, Bytecodes::_multianewarray);
   klassOop klass = constants->klass_at(i, CHECK);
   int   nof_dims = number_of_dimensions(thread);
   assert(oop(klass)->is_klass(), "not a class");
@@ -169,7 +169,7 @@
 // Quicken instance-of and check-cast bytecodes
 IRT_ENTRY(void, InterpreterRuntime::quicken_io_cc(JavaThread* thread))
   // Force resolving; quicken the bytecode
-  int which = two_byte_index(thread);
+  int which = get_index_u2(thread, Bytecodes::_checkcast);
   constantPoolOop cpool = method(thread)->constants();
   // We'd expect to assert that we're only here to quicken bytecodes, but in a multithreaded
   // program we might have seen an unquick'd bytecode in the interpreter but have another
@@ -463,7 +463,7 @@
 
   {
     JvmtiHideSingleStepping jhss(thread);
-    LinkResolver::resolve_field(info, pool, two_byte_index(thread),
+    LinkResolver::resolve_field(info, pool, get_index_u2_cpcache(thread, bytecode),
                                 bytecode, false, CHECK);
   } // end JvmtiHideSingleStepping
 
@@ -634,7 +634,7 @@
   {
     JvmtiHideSingleStepping jhss(thread);
     LinkResolver::resolve_invoke(info, receiver, pool,
-                                 two_byte_index(thread), bytecode, CHECK);
+                                 get_index_u2_cpcache(thread, bytecode), bytecode, CHECK);
     if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
       int retry_count = 0;
       while (info.resolved_method()->is_old()) {
@@ -645,7 +645,7 @@
                   "Could not resolve to latest version of redefined method");
         // method is redefined in the middle of resolve so re-try.
         LinkResolver::resolve_invoke(info, receiver, pool,
-                                     two_byte_index(thread), bytecode, CHECK);
+                                     get_index_u2_cpcache(thread, bytecode), bytecode, CHECK);
       }
     }
   } // end JvmtiHideSingleStepping
@@ -704,7 +704,7 @@
     caller_bci = caller_method->bci_from(caller_bcp);
     site_index = Bytes::get_native_u4(caller_bcp+1);
   }
-  assert(site_index == four_byte_index(thread), "");
+  assert(site_index == InterpreterRuntime::bytecode(thread)->get_index_u4(bytecode), "");
   assert(constantPoolCacheOopDesc::is_secondary_index(site_index), "proper format");
   // there is a second CPC entries that is of interest; it caches signature info:
   int main_index = pool->cache()->secondary_entry_at(site_index)->main_entry_index();
--- a/src/share/vm/interpreter/interpreterRuntime.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/interpreterRuntime.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -40,9 +40,13 @@
     return Bytecodes::code_at(bcp(thread), method(thread));
   }
   static bool      already_resolved(JavaThread *thread) { return cache_entry(thread)->is_resolved(code(thread)); }
-  static int       one_byte_index(JavaThread *thread)   { return bcp(thread)[1]; }
-  static int       two_byte_index(JavaThread *thread)   { return Bytes::get_Java_u2(bcp(thread) + 1); }
-  static int       four_byte_index(JavaThread *thread)  { return Bytes::get_native_u4(bcp(thread) + 1); }
+  static Bytecode* bytecode(JavaThread *thread)      { return Bytecode_at(bcp(thread)); }
+  static int       get_index_u1(JavaThread *thread, Bytecodes::Code bc)
+                                                        { return bytecode(thread)->get_index_u1(bc); }
+  static int       get_index_u2(JavaThread *thread, Bytecodes::Code bc)
+                                                        { return bytecode(thread)->get_index_u2(bc); }
+  static int       get_index_u2_cpcache(JavaThread *thread, Bytecodes::Code bc)
+                                                        { return bytecode(thread)->get_index_u2_cpcache(bc); }
   static int       number_of_dimensions(JavaThread *thread)  { return bcp(thread)[3]; }
 
   static ConstantPoolCacheEntry* cache_entry_at(JavaThread *thread, int i)  { return method(thread)->constants()->cache()->entry_at(i); }
--- a/src/share/vm/interpreter/rewriter.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/rewriter.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. 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
@@ -103,16 +103,15 @@
 
 
 // Rewrite a classfile-order CP index into a native-order CPC index.
-int Rewriter::rewrite_member_reference(address bcp, int offset) {
+void Rewriter::rewrite_member_reference(address bcp, int offset) {
   address p = bcp + offset;
   int  cp_index    = Bytes::get_Java_u2(p);
   int  cache_index = cp_entry_to_cp_cache(cp_index);
   Bytes::put_native_u2(p, cache_index);
-  return cp_index;
 }
 
 
-void Rewriter::rewrite_invokedynamic(address bcp, int offset, int delete_me) {
+void Rewriter::rewrite_invokedynamic(address bcp, int offset) {
   address p = bcp + offset;
   assert(p[-1] == Bytecodes::_invokedynamic, "");
   int cp_index = Bytes::get_Java_u2(p);
@@ -178,7 +177,7 @@
         case Bytecodes::_lookupswitch   : {
 #ifndef CC_INTERP
           Bytecode_lookupswitch* bc = Bytecode_lookupswitch_at(bcp);
-          bc->set_code(
+          (*bcp) = (
             bc->number_of_pairs() < BinarySwitchThreshold
             ? Bytecodes::_fast_linearswitch
             : Bytecodes::_fast_binaryswitch
@@ -197,7 +196,7 @@
           rewrite_member_reference(bcp, prefix_length+1);
           break;
         case Bytecodes::_invokedynamic:
-          rewrite_invokedynamic(bcp, prefix_length+1, int(sizeof"@@@@DELETE ME"));
+          rewrite_invokedynamic(bcp, prefix_length+1);
           break;
         case Bytecodes::_jsr            : // fall through
         case Bytecodes::_jsr_w          : nof_jsrs++;                   break;
@@ -308,5 +307,19 @@
 
     // Set up method entry points for compiler and interpreter.
     m->link_method(m, CHECK);
+
+#ifdef ASSERT
+    if (StressMethodComparator) {
+      static int nmc = 0;
+      for (int j = i; j >= 0 && j >= i-4; j--) {
+        if ((++nmc % 1000) == 0)  tty->print_cr("Have run MethodComparator %d times...", nmc);
+        bool z = MethodComparator::methods_EMCP(m(), (methodOop)_methods->obj_at(j));
+        if (j == i && !z) {
+          tty->print("MethodComparator FAIL: "); m->print(); m->print_codes();
+          assert(z, "method must compare equal to itself");
+        }
+      }
+    }
+#endif //ASSERT
   }
 }
--- a/src/share/vm/interpreter/rewriter.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/rewriter.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. 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
@@ -64,8 +64,8 @@
   void scan_method(methodOop m);
   methodHandle rewrite_jsrs(methodHandle m, TRAPS);
   void rewrite_Object_init(methodHandle m, TRAPS);
-  int  rewrite_member_reference(address bcp, int offset);
-  void rewrite_invokedynamic(address bcp, int offset, int cp_index);
+  void rewrite_member_reference(address bcp, int offset);
+  void rewrite_invokedynamic(address bcp, int offset);
 
  public:
   // Driver routine:
--- a/src/share/vm/interpreter/templateTable.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/templateTable.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -434,15 +434,15 @@
   def(Bytecodes::_dreturn             , ____|disp|clvm|____, dtos, dtos, _return             , dtos         );
   def(Bytecodes::_areturn             , ____|disp|clvm|____, atos, atos, _return             , atos         );
   def(Bytecodes::_return              , ____|disp|clvm|____, vtos, vtos, _return             , vtos         );
-  def(Bytecodes::_getstatic           , ubcp|____|clvm|____, vtos, vtos, getstatic           ,  1           );
-  def(Bytecodes::_putstatic           , ubcp|____|clvm|____, vtos, vtos, putstatic           ,  2           );
-  def(Bytecodes::_getfield            , ubcp|____|clvm|____, vtos, vtos, getfield            ,  1           );
-  def(Bytecodes::_putfield            , ubcp|____|clvm|____, vtos, vtos, putfield            ,  2           );
-  def(Bytecodes::_invokevirtual       , ubcp|disp|clvm|____, vtos, vtos, invokevirtual       ,  2           );
-  def(Bytecodes::_invokespecial       , ubcp|disp|clvm|____, vtos, vtos, invokespecial       ,  1           );
-  def(Bytecodes::_invokestatic        , ubcp|disp|clvm|____, vtos, vtos, invokestatic        ,  1           );
-  def(Bytecodes::_invokeinterface     , ubcp|disp|clvm|____, vtos, vtos, invokeinterface     ,  1           );
-  def(Bytecodes::_invokedynamic       , ubcp|disp|clvm|____, vtos, vtos, invokedynamic       ,  1           );
+  def(Bytecodes::_getstatic           , ubcp|____|clvm|____, vtos, vtos, getstatic           , f1_byte      );
+  def(Bytecodes::_putstatic           , ubcp|____|clvm|____, vtos, vtos, putstatic           , f2_byte      );
+  def(Bytecodes::_getfield            , ubcp|____|clvm|____, vtos, vtos, getfield            , f1_byte      );
+  def(Bytecodes::_putfield            , ubcp|____|clvm|____, vtos, vtos, putfield            , f2_byte      );
+  def(Bytecodes::_invokevirtual       , ubcp|disp|clvm|____, vtos, vtos, invokevirtual       , f2_byte      );
+  def(Bytecodes::_invokespecial       , ubcp|disp|clvm|____, vtos, vtos, invokespecial       , f1_byte      );
+  def(Bytecodes::_invokestatic        , ubcp|disp|clvm|____, vtos, vtos, invokestatic        , f1_byte      );
+  def(Bytecodes::_invokeinterface     , ubcp|disp|clvm|____, vtos, vtos, invokeinterface     , f1_byte      );
+  def(Bytecodes::_invokedynamic       , ubcp|disp|clvm|____, vtos, vtos, invokedynamic       , f1_oop       );
   def(Bytecodes::_new                 , ubcp|____|clvm|____, vtos, atos, _new                ,  _           );
   def(Bytecodes::_newarray            , ubcp|____|clvm|____, itos, atos, newarray            ,  _           );
   def(Bytecodes::_anewarray           , ubcp|____|clvm|____, itos, atos, anewarray           ,  _           );
@@ -502,7 +502,7 @@
   def(Bytecodes::_fast_iload2         , ubcp|____|____|____, vtos, itos, fast_iload2         ,  _       );
   def(Bytecodes::_fast_icaload        , ubcp|____|____|____, vtos, itos, fast_icaload        ,  _       );
 
-  def(Bytecodes::_fast_invokevfinal   , ubcp|disp|clvm|____, vtos, vtos, fast_invokevfinal   ,  2           );
+  def(Bytecodes::_fast_invokevfinal   , ubcp|disp|clvm|____, vtos, vtos, fast_invokevfinal   , f2_byte      );
 
   def(Bytecodes::_fast_linearswitch   , ubcp|disp|____|____, itos, vtos, fast_linearswitch   ,  _           );
   def(Bytecodes::_fast_binaryswitch   , ubcp|disp|____|____, itos, vtos, fast_binaryswitch   ,  _           );
--- a/src/share/vm/interpreter/templateTable.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/interpreter/templateTable.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -73,6 +73,7 @@
  public:
   enum Operation { add, sub, mul, div, rem, _and, _or, _xor, shl, shr, ushr };
   enum Condition { equal, not_equal, less, less_equal, greater, greater_equal };
+  enum CacheByte { f1_byte = 1, f2_byte = 2, f1_oop = 0x11 };  // byte_no codes
 
  private:
   static bool            _is_initialized;        // true if TemplateTable has been initialized
@@ -244,13 +245,18 @@
 
   static void _return(TosState state);
 
-  static void resolve_cache_and_index(int byte_no, Register cache, Register index);
+  static void resolve_cache_and_index(int byte_no,       // one of 1,2,11
+                                      Register result ,  // either noreg or output for f1/f2
+                                      Register cache,    // output for CP cache
+                                      Register index,    // output for CP index
+                                      size_t index_size); // one of 1,2,4
   static void load_invoke_cp_cache_entry(int byte_no,
                                          Register method,
                                          Register itable_index,
                                          Register flags,
-                                         bool is_invokevirtual = false,
-                                         bool is_virtual_final = false);
+                                         bool is_invokevirtual,
+                                         bool is_virtual_final,
+                                         bool is_invokedynamic);
   static void load_field_cp_cache_entry(Register obj,
                                         Register cache,
                                         Register index,
--- a/src/share/vm/memory/iterator.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/memory/iterator.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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/src/share/vm/memory/space.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/memory/space.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -861,9 +861,9 @@
   }
   size = align_object_size(size);
 
-  const size_t min_int_array_size = typeArrayOopDesc::header_size(T_INT);
-  if (size >= min_int_array_size) {
-    size_t length = (size - min_int_array_size) * (HeapWordSize / sizeof(jint));
+  const size_t array_header_size = typeArrayOopDesc::header_size(T_INT);
+  if (size >= (size_t)align_object_size(array_header_size)) {
+    size_t length = (size - array_header_size) * (HeapWordSize / sizeof(jint));
     // allocate uninitialized int array
     typeArrayOop t = (typeArrayOop) allocate(size);
     assert(t != NULL, "allocation should succeed");
@@ -871,7 +871,7 @@
     t->set_klass(Universe::intArrayKlassObj());
     t->set_length((int)length);
   } else {
-    assert((int) size == instanceOopDesc::header_size(),
+    assert(size == CollectedHeap::min_fill_size(),
            "size for smallest fake object doesn't match");
     instanceOop obj = (instanceOop) allocate(size);
     obj->set_mark(markOopDesc::prototype());
--- a/src/share/vm/memory/threadLocalAllocBuffer.inline.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/memory/threadLocalAllocBuffer.inline.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -31,7 +31,7 @@
     // Skip mangling the space corresponding to the object header to
     // ensure that the returned space is not considered parsable by
     // any concurrent GC thread.
-    size_t hdr_size = CollectedHeap::min_fill_size();
+    size_t hdr_size = oopDesc::header_size();
     Copy::fill_to_words(obj + hdr_size, size - hdr_size, badHeapWordVal);
 #endif // ASSERT
     // This addition is safe because we know that top is
--- a/src/share/vm/memory/universe.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/memory/universe.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -748,7 +748,7 @@
 // 4Gb
 static const uint64_t NarrowOopHeapMax = (uint64_t(max_juint) + 1);
 // 32Gb
-static const uint64_t OopEncodingHeapMax = NarrowOopHeapMax << LogMinObjAlignmentInBytes;
+// OopEncodingHeapMax == NarrowOopHeapMax << LogMinObjAlignmentInBytes;
 
 char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) {
   size_t base = 0;
@@ -1261,7 +1261,7 @@
 
   // decide which low-order bits we require to be clear:
   size_t alignSize = MinObjAlignmentInBytes;
-  size_t min_object_size = oopDesc::header_size();
+  size_t min_object_size = CollectedHeap::min_fill_size();
 
   // make an inclusive limit:
   uintptr_t max = (uintptr_t)high_boundary - min_object_size*wordSize;
--- a/src/share/vm/oops/arrayOop.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/oops/arrayOop.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -92,7 +92,7 @@
   static int header_size(BasicType type) {
     size_t typesize_in_bytes = header_size_in_bytes();
     return (int)(Universe::element_type_should_be_aligned(type)
-      ? align_object_size(typesize_in_bytes/HeapWordSize)
+      ? align_object_offset(typesize_in_bytes/HeapWordSize)
       : typesize_in_bytes/HeapWordSize);
   }
 
--- a/src/share/vm/oops/constantPoolKlass.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/oops/constantPoolKlass.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -310,15 +310,12 @@
   Klass::oop_print_on(obj, st);
   constantPoolOop cp = constantPoolOop(obj);
   if (cp->flags() != 0) {
-    st->print(" - flags : 0x%x", cp->flags());
+    st->print(" - flags: 0x%x", cp->flags());
     if (cp->has_pseudo_string()) st->print(" has_pseudo_string");
     if (cp->has_invokedynamic()) st->print(" has_invokedynamic");
     st->cr();
   }
-
-  // Temp. remove cache so we can do lookups with original indicies.
-  constantPoolCacheHandle cache (THREAD, cp->cache());
-  cp->set_cache(NULL);
+  st->print_cr(" - cache: " INTPTR_FORMAT, cp->cache());
 
   for (int index = 1; index < cp->length(); index++) {      // Index 0 is unused
     st->print(" - %3d : ", index);
@@ -334,8 +331,8 @@
       case JVM_CONSTANT_Fieldref :
       case JVM_CONSTANT_Methodref :
       case JVM_CONSTANT_InterfaceMethodref :
-        st->print("klass_index=%d", cp->klass_ref_index_at(index));
-        st->print(" name_and_type_index=%d", cp->name_and_type_ref_index_at(index));
+        st->print("klass_index=%d", cp->uncached_klass_ref_index_at(index));
+        st->print(" name_and_type_index=%d", cp->uncached_name_and_type_ref_index_at(index));
         break;
       case JVM_CONSTANT_UnresolvedString :
       case JVM_CONSTANT_String :
@@ -382,9 +379,6 @@
     st->cr();
   }
   st->cr();
-
-  // Restore cache
-  cp->set_cache(cache());
 }
 
 #endif
@@ -398,6 +392,9 @@
   cp->print_address_on(st);
   st->print(" for ");
   cp->pool_holder()->print_value_on(st);
+  if (cp->cache() != NULL) {
+    st->print(" cache=" PTR_FORMAT, cp->cache());
+  }
 }
 
 const char* constantPoolKlass::internal_name() const {
--- a/src/share/vm/oops/constantPoolOop.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/oops/constantPoolOop.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -297,11 +297,9 @@
 
 
 int constantPoolOopDesc::remap_instruction_operand_from_cache(int operand) {
-  // Operand was fetched by a stream using get_Java_u2, yet was stored
-  // by Rewriter::rewrite_member_reference in native order.
-  // So now we have to fix the damage by swapping back to native order.
-  assert((int)(u2)operand == operand, "clean u2");
-  int cpc_index = Bytes::swap_u2(operand);
+  int cpc_index = operand;
+  DEBUG_ONLY(cpc_index -= CPCACHE_INDEX_TAG);
+  assert((int)(u2)cpc_index == cpc_index, "clean u2");
   int member_index = cache()->entry_at(cpc_index)->constant_pool_index();
   return member_index;
 }
--- a/src/share/vm/oops/constantPoolOop.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/oops/constantPoolOop.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -434,6 +434,10 @@
   // Debugging
   const char* printable_name_at(int which) PRODUCT_RETURN0;
 
+#ifdef ASSERT
+  enum { CPCACHE_INDEX_TAG = 0x10000 };  // helps keep CP cache indices distinct from CP indices
+#endif //ASSERT
+
  private:
 
   symbolOop impl_name_ref_at(int which, bool uncached);
@@ -441,7 +445,7 @@
   int       impl_klass_ref_index_at(int which, bool uncached);
   int       impl_name_and_type_ref_index_at(int which, bool uncached);
 
-  int remap_instruction_operand_from_cache(int operand);
+  int remap_instruction_operand_from_cache(int operand);  // operand must be biased by CPCACHE_INDEX_TAG
 
   // Used while constructing constant pool (only by ClassFileParser)
   jint klass_index_at(int which) {
--- a/src/share/vm/oops/generateOopMap.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/oops/generateOopMap.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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
@@ -1254,7 +1254,7 @@
       case Bytecodes::_invokestatic:
       case Bytecodes::_invokedynamic:
       case Bytecodes::_invokeinterface:
-        int idx = currentBC->get_index_int();
+        int idx = currentBC->has_index_u4() ? currentBC->get_index_u4() : currentBC->get_index_u2();
         constantPoolOop cp    = method()->constants();
         int nameAndTypeIdx    = cp->name_and_type_ref_index_at(idx);
         int signatureIdx      = cp->signature_ref_index_at(nameAndTypeIdx);
@@ -1286,7 +1286,7 @@
       case Bytecodes::_invokestatic:
       case Bytecodes::_invokedynamic:
       case Bytecodes::_invokeinterface:
-        int idx = currentBC->get_index_int();
+        int idx = currentBC->has_index_u4() ? currentBC->get_index_u4() : currentBC->get_index_u2();
         constantPoolOop cp    = method()->constants();
         int nameAndTypeIdx    = cp->name_and_type_ref_index_at(idx);
         int signatureIdx      = cp->signature_ref_index_at(nameAndTypeIdx);
@@ -1356,8 +1356,8 @@
 
     case Bytecodes::_ldc2_w:            ppush(vvCTS);               break;
 
-    case Bytecodes::_ldc:               do_ldc(itr->get_index(), itr->bci());    break;
-    case Bytecodes::_ldc_w:             do_ldc(itr->get_index_big(), itr->bci());break;
+    case Bytecodes::_ldc:               do_ldc(itr->get_index(),    itr->bci()); break;
+    case Bytecodes::_ldc_w:             do_ldc(itr->get_index_u2(), itr->bci()); break;
 
     case Bytecodes::_iload:
     case Bytecodes::_fload:             ppload(vCTS, itr->get_index()); break;
@@ -1550,17 +1550,17 @@
     case Bytecodes::_jsr_w:             do_jsr(itr->dest_w());       break;
 
     case Bytecodes::_getstatic:         do_field(true,  true,
-                                                 itr->get_index_big(),
+                                                 itr->get_index_u2_cpcache(),
                                                  itr->bci()); break;
-    case Bytecodes::_putstatic:         do_field(false, true,  itr->get_index_big(), itr->bci()); break;
-    case Bytecodes::_getfield:          do_field(true,  false, itr->get_index_big(), itr->bci()); break;
-    case Bytecodes::_putfield:          do_field(false, false, itr->get_index_big(), itr->bci()); break;
+    case Bytecodes::_putstatic:         do_field(false, true,  itr->get_index_u2_cpcache(), itr->bci()); break;
+    case Bytecodes::_getfield:          do_field(true,  false, itr->get_index_u2_cpcache(), itr->bci()); break;
+    case Bytecodes::_putfield:          do_field(false, false, itr->get_index_u2_cpcache(), itr->bci()); break;
 
     case Bytecodes::_invokevirtual:
-    case Bytecodes::_invokespecial:     do_method(false, false, itr->get_index_big(), itr->bci()); break;
-    case Bytecodes::_invokestatic:      do_method(true,  false, itr->get_index_big(), itr->bci()); break;
-    case Bytecodes::_invokedynamic:     do_method(true,  false, itr->get_index_int(), itr->bci()); break;
-    case Bytecodes::_invokeinterface:   do_method(false, true,  itr->get_index_big(), itr->bci()); break;
+    case Bytecodes::_invokespecial:     do_method(false, false, itr->get_index_u2_cpcache(), itr->bci()); break;
+    case Bytecodes::_invokestatic:      do_method(true,  false, itr->get_index_u2_cpcache(), itr->bci()); break;
+    case Bytecodes::_invokedynamic:     do_method(true,  false, itr->get_index_u4(),         itr->bci()); break;
+    case Bytecodes::_invokeinterface:   do_method(false, true,  itr->get_index_u2_cpcache(), itr->bci()); break;
     case Bytecodes::_newarray:
     case Bytecodes::_anewarray:         pp_new_ref(vCTS, itr->bci()); break;
     case Bytecodes::_checkcast:         do_checkcast(); break;
--- a/src/share/vm/oops/methodKlass.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/oops/methodKlass.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -237,7 +237,7 @@
   Klass::oop_print_on(obj, st);
   methodOop m = methodOop(obj);
   // get the effect of PrintOopAddress, always, for methods:
-  st->print   (" - this oop:          "INTPTR_FORMAT, (intptr_t)m);
+  st->print_cr(" - this oop:          "INTPTR_FORMAT, (intptr_t)m);
   st->print   (" - method holder:     ");    m->method_holder()->print_value_on(st); st->cr();
   st->print   (" - constants:         "INTPTR_FORMAT" ", (address)m->constants());
   m->constants()->print_value_on(st); st->cr();
--- a/src/share/vm/oops/oop.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/oops/oop.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -149,10 +149,6 @@
   // Need this as public for garbage collection.
   template <class T> T* obj_field_addr(int offset) const;
 
-  // Oop encoding heap max
-  static const uint64_t OopEncodingHeapMax =
-              (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes;
-
   static bool is_null(oop obj);
   static bool is_null(narrowOop obj);
 
--- a/src/share/vm/oops/oop.inline.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/oops/oop.inline.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -146,8 +146,13 @@
 // offset from the heap base.  Saving the check for null can save instructions
 // in inner GC loops so these are separated.
 
+inline bool check_obj_alignment(oop obj) {
+  return (intptr_t)obj % MinObjAlignmentInBytes == 0;
+}
+
 inline narrowOop oopDesc::encode_heap_oop_not_null(oop v) {
   assert(!is_null(v), "oop value can never be zero");
+  assert(check_obj_alignment(v), "Address not aligned");
   assert(Universe::heap()->is_in_reserved(v), "Address not in heap");
   address base = Universe::narrow_oop_base();
   int    shift = Universe::narrow_oop_shift();
@@ -167,7 +172,9 @@
   assert(!is_null(v), "narrow oop value can never be zero");
   address base = Universe::narrow_oop_base();
   int    shift = Universe::narrow_oop_shift();
-  return (oop)(void*)((uintptr_t)base + ((uintptr_t)v << shift));
+  oop result = (oop)(void*)((uintptr_t)base + ((uintptr_t)v << shift));
+  assert(check_obj_alignment(result), "Address not aligned");
+  return result;
 }
 
 inline oop oopDesc::decode_heap_oop(narrowOop v) {
@@ -522,10 +529,6 @@
   return mark()->has_bias_pattern();
 }
 
-inline bool check_obj_alignment(oop obj) {
-  return (intptr_t)obj % MinObjAlignmentInBytes == 0;
-}
-
 
 // used only for asserts
 inline bool oopDesc::is_oop(bool ignore_mark_word) const {
@@ -600,6 +603,8 @@
 
 // Used by scavengers
 inline void oopDesc::forward_to(oop p) {
+  assert(check_obj_alignment(p),
+         "forwarding to something not aligned");
   assert(Universe::heap()->is_in_reserved(p),
          "forwarding to something not in heap");
   markOop m = markOopDesc::encode_pointer_as_mark(p);
@@ -609,6 +614,8 @@
 
 // Used by parallel scavengers
 inline bool oopDesc::cas_forward_to(oop p, markOop compare) {
+  assert(check_obj_alignment(p),
+         "forwarding to something not aligned");
   assert(Universe::heap()->is_in_reserved(p),
          "forwarding to something not in heap");
   markOop m = markOopDesc::encode_pointer_as_mark(p);
--- a/src/share/vm/opto/bytecodeInfo.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/opto/bytecodeInfo.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. 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
@@ -188,8 +188,8 @@
     return NULL;
   }
 
-  // Always inline MethodHandle methods.
-  if (callee_method->is_method_handle_invoke())
+  // Always inline MethodHandle methods and generated MethodHandle adapters.
+  if (callee_method->is_method_handle_invoke() || callee_method->is_method_handle_adapter())
     return NULL;
 
   // First check all inlining restrictions which are required for correctness
@@ -340,7 +340,7 @@
     Bytecodes::Code call_bc = iter.cur_bc();
     // An invokedynamic instruction does not have a klass.
     if (call_bc != Bytecodes::_invokedynamic) {
-      int index = iter.get_index_int();
+      int index = iter.get_index_u2_cpcache();
       if (!caller_method->is_klass_loaded(index, true)) {
         return false;
       }
--- a/src/share/vm/opto/compile.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/opto/compile.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -2176,14 +2176,14 @@
 
 #ifdef _LP64
   case Op_CastPP:
-    if (n->in(1)->is_DecodeN() && Universe::narrow_oop_use_implicit_null_checks()) {
+    if (n->in(1)->is_DecodeN() && Matcher::gen_narrow_oop_implicit_null_checks()) {
       Compile* C = Compile::current();
       Node* in1 = n->in(1);
       const Type* t = n->bottom_type();
       Node* new_in1 = in1->clone();
       new_in1->as_DecodeN()->set_type(t);
 
-      if (!Matcher::clone_shift_expressions) {
+      if (!Matcher::narrow_oop_use_complex_address()) {
         //
         // x86, ARM and friends can handle 2 adds in addressing mode
         // and Matcher can fold a DecodeN node into address by using
@@ -2231,8 +2231,12 @@
         new_in2 = in2->in(1);
       } else if (in2->Opcode() == Op_ConP) {
         const Type* t = in2->bottom_type();
-        if (t == TypePtr::NULL_PTR && Universe::narrow_oop_use_implicit_null_checks()) {
-          new_in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR);
+        if (t == TypePtr::NULL_PTR) {
+          // Don't convert CmpP null check into CmpN if compressed
+          // oops implicit null check is not generated.
+          // This will allow to generate normal oop implicit null check.
+          if (Matcher::gen_narrow_oop_implicit_null_checks())
+            new_in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR);
           //
           // This transformation together with CastPP transformation above
           // will generated code for implicit NULL checks for compressed oops.
@@ -2289,9 +2293,9 @@
 
   case Op_DecodeN:
     assert(!n->in(1)->is_EncodeP(), "should be optimized out");
-    // DecodeN could be pinned on Sparc where it can't be fold into
+    // DecodeN could be pinned when it can't be fold into
     // an address expression, see the code for Op_CastPP above.
-    assert(n->in(0) == NULL || !Matcher::clone_shift_expressions, "no control except on sparc");
+    assert(n->in(0) == NULL || !Matcher::narrow_oop_use_complex_address(), "no control");
     break;
 
   case Op_EncodeP: {
@@ -2496,6 +2500,10 @@
     }
   }
 
+  // Skip next transformation if compressed oops are not used.
+  if (!UseCompressedOops || !Matcher::gen_narrow_oop_implicit_null_checks())
+    return;
+
   // Go over safepoints nodes to skip DecodeN nodes for debug edges.
   // It could be done for an uncommon traps or any safepoints/calls
   // if the DecodeN node is referenced only in a debug info.
--- a/src/share/vm/opto/connode.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/opto/connode.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -437,7 +437,7 @@
 // If not converting int->oop, throw away cast after constant propagation
 Node *CastPPNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
   const Type *t = ccp->type(in(1));
-  if (!t->isa_oop_ptr() || (in(1)->is_DecodeN() && Universe::narrow_oop_use_implicit_null_checks())) {
+  if (!t->isa_oop_ptr() || (in(1)->is_DecodeN() && Matcher::gen_narrow_oop_implicit_null_checks())) {
     return NULL; // do not transform raw pointers or narrow oops
   }
   return ConstraintCastNode::Ideal_DU_postCCP(ccp);
--- a/src/share/vm/opto/lcm.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/opto/lcm.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -32,7 +32,8 @@
 // with suitable memory ops nearby.  Use the memory op to do the NULL check.
 // I can generate a memory op if there is not one nearby.
 // The proj is the control projection for the not-null case.
-// The val is the pointer being checked for nullness.
+// The val is the pointer being checked for nullness or
+// decodeHeapOop_not_null node if it did not fold into address.
 void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowed_reasons) {
   // Assume if null check need for 0 offset then always needed
   // Intel solaris doesn't support any null checks yet and no
@@ -96,6 +97,13 @@
     }
   }
 
+  // Check for decodeHeapOop_not_null node which did not fold into address
+  bool is_decoden = ((intptr_t)val) & 1;
+  val = (Node*)(((intptr_t)val) & ~1);
+
+  assert(!is_decoden || (val->in(0) == NULL) && val->is_Mach() &&
+         (val->as_Mach()->ideal_Opcode() == Op_DecodeN), "sanity");
+
   // Search the successor block for a load or store who's base value is also
   // the tested value.  There may be several.
   Node_List *out = new Node_List(Thread::current()->resource_area());
@@ -148,7 +156,8 @@
       if( !mach->needs_anti_dependence_check() )
         continue;               // Not an memory op; skip it
       {
-        // Check that value is used in memory address.
+        // Check that value is used in memory address in
+        // instructions with embedded load (CmpP val1,(val2+off)).
         Node* base;
         Node* index;
         const MachOper* oper = mach->memory_inputs(base, index);
@@ -213,7 +222,11 @@
     uint vidx = 0;              // Capture index of value into memop
     uint j;
     for( j = mach->req()-1; j > 0; j-- ) {
-      if( mach->in(j) == val ) vidx = j;
+      if( mach->in(j) == val ) {
+        vidx = j;
+        // Ignore DecodeN val which could be hoisted to where needed.
+        if( is_decoden ) continue;
+      }
       // Block of memory-op input
       Block *inb = cfg->_bbs[mach->in(j)->_idx];
       Block *b = this;          // Start from nul check
@@ -270,6 +283,26 @@
   extern int implicit_null_checks;
   implicit_null_checks++;
 
+  if( is_decoden ) {
+    // Check if we need to hoist decodeHeapOop_not_null first.
+    Block *valb = cfg->_bbs[val->_idx];
+    if( this != valb && this->_dom_depth < valb->_dom_depth ) {
+      // Hoist it up to the end of the test block.
+      valb->find_remove(val);
+      this->add_inst(val);
+      cfg->_bbs.map(val->_idx,this);
+      // DecodeN on x86 may kill flags. Check for flag-killing projections
+      // that also need to be hoisted.
+      for (DUIterator_Fast jmax, j = val->fast_outs(jmax); j < jmax; j++) {
+        Node* n = val->fast_out(j);
+        if( n->Opcode() == Op_MachProj ) {
+          cfg->_bbs[n->_idx]->find_remove(n);
+          this->add_inst(n);
+          cfg->_bbs.map(n->_idx,this);
+        }
+      }
+    }
+  }
   // Hoist the memory candidate up to the end of the test block.
   Block *old_block = cfg->_bbs[best->_idx];
   old_block->find_remove(best);
--- a/src/share/vm/opto/matcher.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/opto/matcher.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1334,7 +1334,7 @@
       if( j == max_scan )       // No post-domination before scan end?
         return true;            // Then break the match tree up
     }
-    if (m->is_DecodeN() && Matcher::clone_shift_expressions) {
+    if (m->is_DecodeN() && Matcher::narrow_oop_use_complex_address()) {
       // These are commonly used in address expressions and can
       // efficiently fold into them on X64 in some cases.
       return false;
@@ -2110,8 +2110,8 @@
         _null_check_tests.push(proj);
         Node* val = cmp->in(1);
 #ifdef _LP64
-        if (UseCompressedOops && !Matcher::clone_shift_expressions &&
-            val->bottom_type()->isa_narrowoop()) {
+        if (val->bottom_type()->isa_narrowoop() &&
+            !Matcher::narrow_oop_use_complex_address()) {
           //
           // Look for DecodeN node which should be pinned to orig_proj.
           // On platforms (Sparc) which can not handle 2 adds
@@ -2127,6 +2127,9 @@
             if (d->is_DecodeN() && d->in(1) == val) {
               val = d;
               val->set_req(0, NULL); // Unpin now.
+              // Mark this as special case to distinguish from
+              // a regular case: CmpP(DecodeN, NULL).
+              val = (Node*)(((intptr_t)val) | 1);
               break;
             }
           }
@@ -2146,9 +2149,21 @@
   for( uint i=0; i < cnt; i+=2 ) {
     Node *test = _null_check_tests[i];
     Node *val = _null_check_tests[i+1];
+    bool is_decoden = ((intptr_t)val) & 1;
+    val = (Node*)(((intptr_t)val) & ~1);
     if (has_new_node(val)) {
+      Node* new_val = new_node(val);
+      if (is_decoden) {
+        assert(val->is_DecodeN() && val->in(0) == NULL, "sanity");
+        // Note: new_val may have a control edge if
+        // the original ideal node DecodeN was matched before
+        // it was unpinned in Matcher::collect_null_checks().
+        // Unpin the mach node and mark it.
+        new_val->set_req(0, NULL);
+        new_val = (Node*)(((intptr_t)new_val) | 1);
+      }
       // Is a match-tree root, so replace with the matched value
-      _null_check_tests.map(i+1, new_node(val));
+      _null_check_tests.map(i+1, new_val);
     } else {
       // Yank from candidate list
       _null_check_tests.map(i+1,_null_check_tests[--cnt]);
--- a/src/share/vm/opto/matcher.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/opto/matcher.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -352,6 +352,38 @@
   // registers?  True for Intel but false for most RISCs
   static const bool clone_shift_expressions;
 
+  static bool narrow_oop_use_complex_address();
+
+  // Generate implicit null check for narrow oops if it can fold
+  // into address expression (x64).
+  //
+  // [R12 + narrow_oop_reg<<3 + offset] // fold into address expression
+  // NullCheck narrow_oop_reg
+  //
+  // When narrow oops can't fold into address expression (Sparc) and
+  // base is not null use decode_not_null and normal implicit null check.
+  // Note, decode_not_null node can be used here since it is referenced
+  // only on non null path but it requires special handling, see
+  // collect_null_checks():
+  //
+  // decode_not_null narrow_oop_reg, oop_reg // 'shift' and 'add base'
+  // [oop_reg + offset]
+  // NullCheck oop_reg
+  //
+  // With Zero base and when narrow oops can not fold into address
+  // expression use normal implicit null check since only shift
+  // is needed to decode narrow oop.
+  //
+  // decode narrow_oop_reg, oop_reg // only 'shift'
+  // [oop_reg + offset]
+  // NullCheck oop_reg
+  //
+  inline static bool gen_narrow_oop_implicit_null_checks() {
+    return Universe::narrow_oop_use_implicit_null_checks() &&
+           (narrow_oop_use_complex_address() ||
+            Universe::narrow_oop_base() != NULL);
+  }
+
   // Is it better to copy float constants, or load them directly from memory?
   // Intel can load a float constant from a direct address, requiring no
   // extra registers.  Most RISCs will have to materialize an address into a
--- a/src/share/vm/opto/parse2.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/opto/parse2.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1317,8 +1317,8 @@
   case Bytecodes::_iconst_3: push(intcon( 3)); break;
   case Bytecodes::_iconst_4: push(intcon( 4)); break;
   case Bytecodes::_iconst_5: push(intcon( 5)); break;
-  case Bytecodes::_bipush:   push(intcon( iter().get_byte())); break;
-  case Bytecodes::_sipush:   push(intcon( iter().get_short())); break;
+  case Bytecodes::_bipush:   push(intcon(iter().get_constant_u1())); break;
+  case Bytecodes::_sipush:   push(intcon(iter().get_constant_u2())); break;
   case Bytecodes::_aconst_null: push(null());  break;
   case Bytecodes::_ldc:
   case Bytecodes::_ldc_w:
--- a/src/share/vm/prims/jvmtiClassFileReconstituter.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/prims/jvmtiClassFileReconstituter.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. 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
@@ -638,7 +638,7 @@
 
     // length of bytecode (mnemonic + operands)
     address bcp = bs.bcp();
-    int len = bs.next_bcp() - bcp;
+    int     len = bs.instruction_size();
     assert(len > 0, "length must be > 0");
 
     // copy the bytecodes
--- a/src/share/vm/prims/jvmtiExport.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/prims/jvmtiExport.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -726,6 +726,32 @@
 GrowableArray<const void *>* JvmtiExport::_pending_compiled_method_unload_code_begins;
 JavaThread* JvmtiExport::_current_poster;
 
+void JvmtiExport::post_compiled_method_unload_internal(JavaThread* self, jmethodID method, const void *code_begin) {
+  EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
+                 ("JVMTI [%s] method compile unload event triggered",
+                  JvmtiTrace::safe_get_thread_name(self)));
+
+  // post the event for each environment that has this event enabled.
+  JvmtiEnvIterator it;
+  for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
+    if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_UNLOAD)) {
+
+      EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
+                ("JVMTI [%s] class compile method unload event sent jmethodID " PTR_FORMAT,
+                 JvmtiTrace::safe_get_thread_name(self), method));
+
+      ResourceMark rm(self);
+
+      JvmtiEventMark jem(self);
+      JvmtiJavaThreadEventTransition jet(self);
+      jvmtiEventCompiledMethodUnload callback = env->callbacks()->CompiledMethodUnload;
+      if (callback != NULL) {
+        (*callback)(env->jvmti_external(), method, code_begin);
+      }
+    }
+  }
+}
+
 // post any pending CompiledMethodUnload events
 
 void JvmtiExport::post_pending_compiled_method_unload_events() {
@@ -788,26 +814,7 @@
   // flag, cleanup _current_poster to indicate that no thread is now servicing the
   // pending events list, and finally notify any thread that might be waiting.
   for (;;) {
-    EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
-                   ("JVMTI [%s] method compile unload event triggered",
-                   JvmtiTrace::safe_get_thread_name(self)));
-
-    // post the event for each environment that has this event enabled.
-    JvmtiEnvIterator it;
-    for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
-      if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_UNLOAD)) {
-        EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
-                  ("JVMTI [%s] class compile method unload event sent jmethodID " PTR_FORMAT,
-                  JvmtiTrace::safe_get_thread_name(self), method));
-
-        JvmtiEventMark jem(self);
-        JvmtiJavaThreadEventTransition jet(self);
-        jvmtiEventCompiledMethodUnload callback = env->callbacks()->CompiledMethodUnload;
-        if (callback != NULL) {
-          (*callback)(env->jvmti_external(), method, code_begin);
-        }
-      }
-    }
+    post_compiled_method_unload_internal(self, method, code_begin);
 
     // event posted, now re-grab monitor and get the next event
     // If there's no next event then we are done. If this is the first
@@ -1864,17 +1871,25 @@
 }
 
 // used at a safepoint to post a CompiledMethodUnload event
-void JvmtiExport::post_compiled_method_unload_at_safepoint(jmethodID mid, const void *code_begin) {
-  assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
-
-  // create list lazily
-  if (_pending_compiled_method_unload_method_ids == NULL) {
-    _pending_compiled_method_unload_method_ids = new (ResourceObj::C_HEAP) GrowableArray<jmethodID>(10,true);
-    _pending_compiled_method_unload_code_begins = new (ResourceObj::C_HEAP) GrowableArray<const void *>(10,true);
+void JvmtiExport::post_compiled_method_unload(jmethodID mid, const void *code_begin) {
+  if (SafepointSynchronize::is_at_safepoint()) {
+    // Class unloading can cause nmethod unloading which is reported
+    // by the VMThread.  These must be batched to be processed later.
+    if (_pending_compiled_method_unload_method_ids == NULL) {
+      // create list lazily
+      _pending_compiled_method_unload_method_ids = new (ResourceObj::C_HEAP) GrowableArray<jmethodID>(10,true);
+      _pending_compiled_method_unload_code_begins = new (ResourceObj::C_HEAP) GrowableArray<const void *>(10,true);
+    }
+    _pending_compiled_method_unload_method_ids->append(mid);
+    _pending_compiled_method_unload_code_begins->append(code_begin);
+    _have_pending_compiled_method_unload_events = true;
+  } else {
+    // Unloading caused by the sweeper can be reported synchronously.
+    if (have_pending_compiled_method_unload_events()) {
+      post_pending_compiled_method_unload_events();
+    }
+    post_compiled_method_unload_internal(JavaThread::current(), mid, code_begin);
   }
-  _pending_compiled_method_unload_method_ids->append(mid);
-  _pending_compiled_method_unload_code_begins->append(code_begin);
-  _have_pending_compiled_method_unload_events = true;
 }
 
 void JvmtiExport::post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) {
--- a/src/share/vm/prims/jvmtiExport.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/prims/jvmtiExport.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -144,6 +144,9 @@
   // posts any pending CompiledMethodUnload events.
   static void post_pending_compiled_method_unload_events();
 
+  // Perform the actual notification to interested JvmtiEnvs.
+  static void post_compiled_method_unload_internal(JavaThread* self, jmethodID mid, const void* code_begin);
+
   // posts a DynamicCodeGenerated event (internal/private implementation).
   // The public post_dynamic_code_generated* functions make use of the
   // internal implementation.
@@ -299,8 +302,8 @@
   static void post_compiled_method_load(nmethod *nm) KERNEL_RETURN;
   static void post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) KERNEL_RETURN;
 
-  // used at a safepoint to post a CompiledMethodUnload event
-  static void post_compiled_method_unload_at_safepoint(jmethodID mid, const void *code_begin) KERNEL_RETURN;
+  // used to post a CompiledMethodUnload event
+  static void post_compiled_method_unload(jmethodID mid, const void *code_begin) KERNEL_RETURN;
 
   // similiar to post_dynamic_code_generated except that it can be used to
   // post a DynamicCodeGenerated event while holding locks in the VM. Any event
--- a/src/share/vm/prims/methodComparator.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/prims/methodComparator.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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,8 +130,8 @@
   case Bytecodes::_multianewarray : // fall through
   case Bytecodes::_checkcast      : // fall through
   case Bytecodes::_instanceof     : {
-    u2 cpi_old = _s_old->get_index_big();
-    u2 cpi_new = _s_new->get_index_big();
+    u2 cpi_old = _s_old->get_index_u2();
+    u2 cpi_new = _s_new->get_index_u2();
     if ((_old_cp->klass_at_noresolve(cpi_old) != _new_cp->klass_at_noresolve(cpi_new)))
         return false;
     if (c_old == Bytecodes::_multianewarray &&
@@ -147,9 +147,10 @@
   case Bytecodes::_invokevirtual   : // fall through
   case Bytecodes::_invokespecial   : // fall through
   case Bytecodes::_invokestatic    : // fall through
+  case Bytecodes::_invokedynamic   : // fall through
   case Bytecodes::_invokeinterface : {
-    u2 cpci_old = _s_old->get_index_int();
-    u2 cpci_new = _s_new->get_index_int();
+    int cpci_old = _s_old->has_index_u4() ? _s_old->get_index_u4() : _s_old->get_index_u2_cpcache();
+    int cpci_new = _s_new->has_index_u4() ? _s_new->get_index_u4() : _s_new->get_index_u2_cpcache();
     // Check if the names of classes, field/method names and signatures at these indexes
     // are the same. Indices which are really into constantpool cache (rather than constant
     // pool itself) are accepted by the constantpool query routines below.
@@ -162,14 +163,10 @@
 
   case Bytecodes::_ldc   : // fall through
   case Bytecodes::_ldc_w : {
-    u2 cpi_old, cpi_new;
-    if (c_old == Bytecodes::_ldc) {
-      cpi_old = _s_old->bcp()[1];
-      cpi_new = _s_new->bcp()[1];
-    } else {
-      cpi_old = _s_old->get_index_big();
-      cpi_new = _s_new->get_index_big();
-    }
+    Bytecode_loadconstant* ldc_old = Bytecode_loadconstant_at(_s_old->method()(), _s_old->bcp());
+    Bytecode_loadconstant* ldc_new = Bytecode_loadconstant_at(_s_new->method()(), _s_new->bcp());
+    int cpi_old = ldc_old->index();
+    int cpi_new = ldc_new->index();
     constantTag tag_old = _old_cp->tag_at(cpi_old);
     constantTag tag_new = _new_cp->tag_at(cpi_new);
     if (tag_old.is_int() || tag_old.is_float()) {
@@ -179,7 +176,9 @@
         if (_old_cp->int_at(cpi_old) != _new_cp->int_at(cpi_new))
           return false;
       } else {
-        if (_old_cp->float_at(cpi_old) != _new_cp->float_at(cpi_new))
+        // Use jint_cast to compare the bits rather than numerical values.
+        // This makes a difference for NaN constants.
+        if (jint_cast(_old_cp->float_at(cpi_old)) != jint_cast(_new_cp->float_at(cpi_new)))
           return false;
       }
     } else if (tag_old.is_string() || tag_old.is_unresolved_string()) {
@@ -199,8 +198,8 @@
   }
 
   case Bytecodes::_ldc2_w : {
-    u2 cpi_old = _s_old->get_index_big();
-    u2 cpi_new = _s_new->get_index_big();
+    u2 cpi_old = _s_old->get_index_u2();
+    u2 cpi_new = _s_new->get_index_u2();
     constantTag tag_old = _old_cp->tag_at(cpi_old);
     constantTag tag_new = _new_cp->tag_at(cpi_new);
     if (tag_old.value() != tag_new.value())
@@ -209,7 +208,9 @@
       if (_old_cp->long_at(cpi_old) != _new_cp->long_at(cpi_new))
         return false;
     } else {
-      if (_old_cp->double_at(cpi_old) != _new_cp->double_at(cpi_new))
+      // Use jlong_cast to compare the bits rather than numerical values.
+      // This makes a difference for NaN constants.
+      if (jlong_cast(_old_cp->double_at(cpi_old)) != jlong_cast(_new_cp->double_at(cpi_new)))
         return false;
     }
     break;
@@ -221,7 +222,7 @@
     break;
 
   case Bytecodes::_sipush    :
-    if (_s_old->get_index_big() != _s_new->get_index_big())
+    if (_s_old->get_index_u2() != _s_new->get_index_u2())
       return false;
     break;
 
@@ -260,8 +261,8 @@
   case Bytecodes::_ifnonnull : // fall through
   case Bytecodes::_ifnull    : // fall through
   case Bytecodes::_jsr       : {
-    short old_ofs = (short) _s_old->get_index_big();
-    short new_ofs = (short) _s_new->get_index_big();
+    int old_ofs = _s_old->bytecode()->get_offset_s2(c_old);
+    int new_ofs = _s_new->bytecode()->get_offset_s2(c_new);
     if (_switchable_test) {
       int old_dest = _s_old->bci() + old_ofs;
       int new_dest = _s_new->bci() + new_ofs;
@@ -285,9 +286,11 @@
     if (_s_old->is_wide() != _s_new->is_wide())
       return false;
     if (! _s_old->is_wide()) {
-      if (_s_old->get_index_big() != _s_new->get_index_big())
+      // We could use get_index_u1 and get_constant_u1, but it's simpler to grab both bytes at once:
+      if (Bytes::get_Java_u2(_s_old->bcp() + 1) != Bytes::get_Java_u2(_s_new->bcp() + 1))
         return false;
     } else {
+      // We could use get_index_u2 and get_constant_u2, but it's simpler to grab all four bytes at once:
       if (Bytes::get_Java_u4(_s_old->bcp() + 1) != Bytes::get_Java_u4(_s_new->bcp() + 1))
         return false;
     }
@@ -295,8 +298,8 @@
 
   case Bytecodes::_goto_w : // fall through
   case Bytecodes::_jsr_w  : {
-    int old_ofs = (int) Bytes::get_Java_u4(_s_old->bcp() + 1);
-    int new_ofs = (int) Bytes::get_Java_u4(_s_new->bcp() + 1);
+    int old_ofs = _s_old->bytecode()->get_offset_s4(c_old);
+    int new_ofs = _s_new->bytecode()->get_offset_s4(c_new);
     if (_switchable_test) {
       int old_dest = _s_old->bci() + old_ofs;
       int new_dest = _s_new->bci() + new_ofs;
@@ -357,8 +360,8 @@
         }
       }
     } else { // !_switchable_test, can use fast rough compare
-      int len_old = _s_old->next_bcp() - _s_old->bcp();
-      int len_new = _s_new->next_bcp() - _s_new->bcp();
+      int len_old = _s_old->instruction_size();
+      int len_new = _s_new->instruction_size();
       if (len_old != len_new)
         return false;
       if (memcmp(_s_old->bcp(), _s_new->bcp(), len_old) != 0)
--- a/src/share/vm/prims/methodHandleWalk.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/prims/methodHandleWalk.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -732,7 +732,7 @@
   case Bytecodes::_dreturn:
   case Bytecodes::_areturn:
   case Bytecodes::_return:
-    assert(strcmp(Bytecodes::format(op), "b") == 0, "wrong bytecode format");
+    assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_b, "wrong bytecode format");
     _bytecode.push(op);
     break;
 
@@ -748,7 +748,7 @@
   case Bytecodes::_fstore:
   case Bytecodes::_dstore:
   case Bytecodes::_astore:
-    assert(strcmp(Bytecodes::format(op), "bi") == 0, "wrong bytecode format");
+    assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bi, "wrong bytecode format");
     assert((char) index == index, "index does not fit in 8-bit");
     _bytecode.push(op);
     _bytecode.push(index);
@@ -757,18 +757,18 @@
   // bii
   case Bytecodes::_ldc2_w:
   case Bytecodes::_checkcast:
-    assert(strcmp(Bytecodes::format(op), "bii") == 0, "wrong bytecode format");
+    assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bkk, "wrong bytecode format");
     assert((short) index == index, "index does not fit in 16-bit");
     _bytecode.push(op);
     _bytecode.push(index >> 8);
     _bytecode.push(index);
     break;
 
-  // bjj
+  // bJJ
   case Bytecodes::_invokestatic:
   case Bytecodes::_invokespecial:
   case Bytecodes::_invokevirtual:
-    assert(strcmp(Bytecodes::format(op), "bjj") == 0, "wrong bytecode format");
+    assert(Bytecodes::format_bits(op, false) == Bytecodes::_fmt_bJJ, "wrong bytecode format");
     assert((short) index == index, "index does not fit in 16-bit");
     _bytecode.push(op);
     _bytecode.push(index >> 8);
--- a/src/share/vm/runtime/arguments.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/runtime/arguments.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1211,8 +1211,44 @@
 }
 #endif // KERNEL
 
+void set_object_alignment() {
+  // Object alignment.
+  assert(is_power_of_2(ObjectAlignmentInBytes), "ObjectAlignmentInBytes must be power of 2");
+  MinObjAlignmentInBytes     = ObjectAlignmentInBytes;
+  assert(MinObjAlignmentInBytes >= HeapWordsPerLong * HeapWordSize, "ObjectAlignmentInBytes value is too small");
+  MinObjAlignment            = MinObjAlignmentInBytes / HeapWordSize;
+  assert(MinObjAlignmentInBytes == MinObjAlignment * HeapWordSize, "ObjectAlignmentInBytes value is incorrect");
+  MinObjAlignmentInBytesMask = MinObjAlignmentInBytes - 1;
+
+  LogMinObjAlignmentInBytes  = exact_log2(ObjectAlignmentInBytes);
+  LogMinObjAlignment         = LogMinObjAlignmentInBytes - LogHeapWordSize;
+
+  // Oop encoding heap max
+  OopEncodingHeapMax = (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes;
+
+#ifndef KERNEL
+  // Set CMS global values
+  CompactibleFreeListSpace::set_cms_values();
+#endif // KERNEL
+}
+
+bool verify_object_alignment() {
+  // Object alignment.
+  if (!is_power_of_2(ObjectAlignmentInBytes)) {
+    jio_fprintf(defaultStream::error_stream(),
+                "error: ObjectAlignmentInBytes=%d must be power of 2", (int)ObjectAlignmentInBytes);
+    return false;
+  }
+  if ((int)ObjectAlignmentInBytes < BytesPerLong) {
+    jio_fprintf(defaultStream::error_stream(),
+                "error: ObjectAlignmentInBytes=%d must be greater or equal %d", (int)ObjectAlignmentInBytes, BytesPerLong);
+    return false;
+  }
+  return true;
+}
+
 inline uintx max_heap_for_compressed_oops() {
-  LP64_ONLY(return oopDesc::OopEncodingHeapMax - MaxPermSize - os::vm_page_size());
+  LP64_ONLY(return OopEncodingHeapMax - MaxPermSize - os::vm_page_size());
   NOT_LP64(ShouldNotReachHere(); return 0);
 }
 
@@ -1776,6 +1812,8 @@
   status = status && verify_interval(TLABWasteTargetPercent,
                                      1, 100, "TLABWasteTargetPercent");
 
+  status = status && verify_object_alignment();
+
   return status;
 }
 
@@ -2848,6 +2886,9 @@
   UseCompressedOops = false;
 #endif
 
+  // Set object alignment values.
+  set_object_alignment();
+
 #ifdef SERIALGC
   force_serial_gc();
 #endif // SERIALGC
--- a/src/share/vm/runtime/globals.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/runtime/globals.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -321,6 +321,9 @@
   diagnostic(bool, PrintCompressedOopsMode, false,                          \
             "Print compressed oops base address and encoding mode")         \
                                                                             \
+  lp64_product(intx, ObjectAlignmentInBytes, 8,                             \
+          "Default object alignment in bytes, 8 is minimum")                \
+                                                                            \
   /* UseMembar is theoretically a temp flag used for memory barrier         \
    * removal testing.  It was supposed to be removed before FCS but has     \
    * been re-added (see 6401008) */                                         \
@@ -1117,6 +1120,9 @@
   product(intx, TraceRedefineClasses, 0,                                    \
           "Trace level for JVMTI RedefineClasses")                          \
                                                                             \
+  develop(bool, StressMethodComparator, false,                              \
+          "run the MethodComparator on all loaded methods")                 \
+                                                                            \
   /* change to false by default sometime after Mustang */                   \
   product(bool, VerifyMergedCPBytecodes, true,                              \
           "Verify bytecodes after RedefineClasses constant pool merging")   \
--- a/src/share/vm/runtime/sharedRuntime.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Wed Jun 02 22:45:42 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();
@@ -2055,11 +2055,11 @@
   void scan() {
     while (_index < _table->table_size()) {
       AdapterHandlerEntry* a = _table->bucket(_index);
+      _index++;
       if (a != NULL) {
         _current = a;
         return;
       }
-      _index++;
     }
   }
 
--- a/src/share/vm/runtime/vmStructs.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/runtime/vmStructs.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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)                                   \
@@ -1328,14 +1328,6 @@
   declare_constant(LogBytesPerWord)                                       \
   declare_constant(BytesPerLong)                                          \
                                                                           \
-  /********************/                                                  \
-  /* Object alignment */                                                  \
-  /********************/                                                  \
-                                                                          \
-  declare_constant(MinObjAlignment)                                       \
-  declare_constant(MinObjAlignmentInBytes)                                \
-  declare_constant(LogMinObjAlignmentInBytes)                             \
-                                                                          \
   /********************************************/                          \
   /* Generation and Space Hierarchy Constants */                          \
   /********************************************/                          \
--- a/src/share/vm/utilities/copy.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/utilities/copy.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -51,7 +51,7 @@
 class Copy : AllStatic {
  public:
   // Block copy methods have four attributes.  We don't define all possibilities.
-  //   alignment: aligned according to minimum Java object alignment (MinObjAlignment)
+  //   alignment: aligned to BytesPerLong
   //   arrayof:   arraycopy operation with both operands aligned on the same
   //              boundary as the first element of an array of the copy unit.
   //              This is currently a HeapWord boundary on all platforms, except
@@ -70,7 +70,7 @@
   //     [ '_atomic' ]
   //
   // Except in the arrayof case, whatever the alignment is, we assume we can copy
-  // whole alignment units.  E.g., if MinObjAlignment is 2x word alignment, an odd
+  // whole alignment units.  E.g., if BytesPerLong is 2x word alignment, an odd
   // count may copy an extra word.  In the arrayof case, we are allowed to copy
   // only the number of copy units specified.
 
@@ -305,17 +305,17 @@
   }
   static void assert_params_aligned(HeapWord* from, HeapWord* to) {
 #ifdef ASSERT
-    if (mask_bits((uintptr_t)from, MinObjAlignmentInBytes-1) != 0)
-      basic_fatal("not object aligned");
-    if (mask_bits((uintptr_t)to, MinObjAlignmentInBytes-1) != 0)
-      basic_fatal("not object aligned");
+    if (mask_bits((uintptr_t)from, BytesPerLong-1) != 0)
+      basic_fatal("not long aligned");
+    if (mask_bits((uintptr_t)to, BytesPerLong-1) != 0)
+      basic_fatal("not long aligned");
 #endif
   }
 
   static void assert_params_aligned(HeapWord* to) {
 #ifdef ASSERT
-    if (mask_bits((uintptr_t)to, MinObjAlignmentInBytes-1) != 0)
-      basic_fatal("not object aligned");
+    if (mask_bits((uintptr_t)to, BytesPerLong-1) != 0)
+      basic_fatal("not long aligned");
 #endif
   }
 
--- a/src/share/vm/utilities/globalDefinitions.cpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/utilities/globalDefinitions.cpp	Wed Jun 02 22:45:42 2010 -0700
@@ -34,6 +34,18 @@
 int BytesPerHeapOop    = 0;
 int BitsPerHeapOop     = 0;
 
+// Object alignment, in units of HeapWords.
+// Defaults are -1 so things will break badly if incorrectly initialized.
+int MinObjAlignment            = -1;
+int MinObjAlignmentInBytes     = -1;
+int MinObjAlignmentInBytesMask = 0;
+
+int LogMinObjAlignment         = -1;
+int LogMinObjAlignmentInBytes  = -1;
+
+// Oop encoding heap max
+uint64_t OopEncodingHeapMax = 0;
+
 void basic_fatal(const char* msg) {
   fatal(msg);
 }
--- a/src/share/vm/utilities/globalDefinitions.hpp	Tue Jun 01 11:48:33 2010 -0700
+++ b/src/share/vm/utilities/globalDefinitions.hpp	Wed Jun 02 22:45:42 2010 -0700
@@ -73,6 +73,9 @@
 extern int BytesPerHeapOop;
 extern int BitsPerHeapOop;
 
+// Oop encoding heap max
+extern uint64_t OopEncodingHeapMax;
+
 const int BitsPerJavaInteger = 32;
 const int BitsPerJavaLong    = 64;
 const int BitsPerSize_t      = size_tSize * BitsPerByte;
@@ -292,12 +295,12 @@
 // Minimum is max(BytesPerLong, BytesPerDouble, BytesPerOop) / HeapWordSize, so jlong, jdouble and
 // reference fields can be naturally aligned.
 
-const int MinObjAlignment            = HeapWordsPerLong;
-const int MinObjAlignmentInBytes     = MinObjAlignment * HeapWordSize;
-const int MinObjAlignmentInBytesMask = MinObjAlignmentInBytes - 1;
+extern int MinObjAlignment;
+extern int MinObjAlignmentInBytes;
+extern int MinObjAlignmentInBytesMask;
 
-const int LogMinObjAlignment         = LogHeapWordsPerLong;
-const int LogMinObjAlignmentInBytes  = LogMinObjAlignment + LogHeapWordSize;
+extern int LogMinObjAlignment;
+extern int LogMinObjAlignmentInBytes;
 
 // Machine dependent stuff
 
@@ -332,18 +335,16 @@
   return align_size_up(size, MinObjAlignment);
 }
 
+inline bool is_object_aligned(intptr_t addr) {
+  return addr == align_object_size(addr);
+}
+
 // Pad out certain offsets to jlong alignment, in HeapWord units.
 
-#define align_object_offset_(offset) align_size_up_(offset, HeapWordsPerLong)
-
 inline intptr_t align_object_offset(intptr_t offset) {
   return align_size_up(offset, HeapWordsPerLong);
 }
 
-inline bool is_object_aligned(intptr_t offset) {
-  return offset == align_object_offset(offset);
-}
-
 
 //----------------------------------------------------------------------------------------------------
 // Utility macros for compilers