Merge
authoriveresov
Mon, 08 Nov 2010 14:33:48 -0800
changeset 7123 523bb0f29d61
parent 6989 ee71b41f53ff (current diff)
parent 7122 23b82ce71b4e (diff)
child 7124 7b83929ea9bb
Merge
hotspot/src/share/vm/classfile/classFileParser.cpp
hotspot/src/share/vm/includeDB_core
hotspot/src/share/vm/includeDB_features
hotspot/src/share/vm/includeDB_jvmti
hotspot/src/share/vm/prims/jvmtiImpl.cpp
hotspot/src/share/vm/runtime/thread.cpp
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java	Mon Nov 08 14:33:48 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2003, 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
@@ -188,7 +188,7 @@
        } else {
           throw new RuntimeException("should not reach here");
        }
-    } else if (ctag.isMethodHandle() || ctag.isMethodType()) {
+    } else if (ctag.isMethodHandle()) {
        Oop x = getCachedConstant();
        int refidx = cpool.getMethodHandleIndexAt(cpIndex);
        int refkind = cpool.getMethodHandleRefKindAt(cpIndex);
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java	Mon Nov 08 14:33:48 2010 -0800
@@ -53,11 +53,19 @@
   private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
     Type type   = db.lookupType("constantPoolOopDesc");
     tags        = new OopField(type.getOopField("_tags"), 0);
+    operands    = new OopField(type.getOopField("_operands"), 0);
     cache       = new OopField(type.getOopField("_cache"), 0);
     poolHolder  = new OopField(type.getOopField("_pool_holder"), 0);
     length      = new CIntField(type.getCIntegerField("_length"), 0);
     headerSize  = type.getSize();
     elementSize = 0;
+    // fetch constants:
+    MULTI_OPERAND_COUNT_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_multi_operand_count_offset").intValue();
+    MULTI_OPERAND_BASE_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_multi_operand_base_offset").intValue();
+    INDY_BSM_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_bsm_offset").intValue();
+    INDY_NT_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_nt_offset").intValue();
+    INDY_ARGC_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_argc_offset").intValue();
+    INDY_ARGV_OFFSET = db.lookupIntConstant("constantPoolOopDesc::_indy_argv_offset").intValue();
   }
 
   ConstantPool(OopHandle handle, ObjectHeap heap) {
@@ -67,6 +75,7 @@
   public boolean isConstantPool()      { return true; }
 
   private static OopField tags;
+  private static OopField operands;
   private static OopField cache;
   private static OopField poolHolder;
   private static CIntField length; // number of elements in oop
@@ -74,7 +83,15 @@
   private static long headerSize;
   private static long elementSize;
 
+  private static int MULTI_OPERAND_COUNT_OFFSET;
+  private static int MULTI_OPERAND_BASE_OFFSET;
+  private static int INDY_BSM_OFFSET;
+  private static int INDY_NT_OFFSET;
+  private static int INDY_ARGC_OFFSET;
+  private static int INDY_ARGV_OFFSET;
+
   public TypeArray         getTags()       { return (TypeArray)         tags.getValue(this); }
+  public TypeArray         getOperands()   { return (TypeArray)         operands.getValue(this); }
   public ConstantPoolCache getCache()      { return (ConstantPoolCache) cache.getValue(this); }
   public Klass             getPoolHolder() { return (Klass)             poolHolder.getValue(this); }
   public int               getLength()     { return (int)length.getValue(this); }
@@ -278,6 +295,25 @@
     return res;
   }
 
+  /** Lookup for multi-operand (InvokeDynamic) entries. */
+  public int[] getMultiOperandsAt(int i) {
+    if (Assert.ASSERTS_ENABLED) {
+      Assert.that(getTagAt(i).isInvokeDynamic(), "Corrupted constant pool");
+    }
+    int pos = this.getIntAt(i);
+    int countPos = pos + MULTI_OPERAND_COUNT_OFFSET;  // == pos-1
+    int basePos  = pos + MULTI_OPERAND_BASE_OFFSET;   // == pos
+    if (countPos < 0)  return null;  // safety first
+    TypeArray operands = getOperands();
+    if (operands == null)  return null;  // safety first
+    int length = operands.getIntAt(countPos);
+    int[] values = new int[length];
+    for (int j = 0; j < length; j++) {
+        values[j] = operands.getIntAt(basePos+j);
+    }
+    return values;
+  }
+
   final private static String[] nameForTag = new String[] {
   };
 
@@ -522,15 +558,20 @@
 
               case JVM_CONSTANT_InvokeDynamic: {
                   dos.writeByte(cpConstType);
-                  int value = getIntAt(ci);
-                  short bootstrapMethodIndex = (short) extractLowShortFromInt(value);
-                  short nameAndTypeIndex = (short) extractHighShortFromInt(value);
-                  dos.writeShort(bootstrapMethodIndex);
-                  dos.writeShort(nameAndTypeIndex);
+                  int[] values = getMultiOperandsAt(ci);
+                  for (int vn = 0; vn < values.length; vn++) {
+                      dos.writeShort(values[vn]);
+                  }
+                  int bootstrapMethodIndex = values[INDY_BSM_OFFSET];
+                  int nameAndTypeIndex = values[INDY_NT_OFFSET];
+                  int argumentCount = values[INDY_ARGC_OFFSET];
+                  assert(INDY_ARGV_OFFSET + argumentCount == values.length);
                   if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " + bootstrapMethodIndex
-                                          + ", N&T = " + nameAndTypeIndex);
+                                          + ", N&T = " + nameAndTypeIndex
+                                          + ", argc = " + argumentCount);
                   break;
               }
+
               default:
                   throw new InternalError("unknown tag: " + cpConstType);
           } // switch
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java	Mon Nov 08 14:33:48 2010 -0800
@@ -42,7 +42,8 @@
     public static final int JVM_CONSTANT_NameAndType        = 12;
     public static final int JVM_CONSTANT_MethodHandle       = 15;
     public static final int JVM_CONSTANT_MethodType         = 16;
-    public static final int JVM_CONSTANT_InvokeDynamic      = 17;
+    public static final int JVM_CONSTANT_InvokeDynamicTrans = 17;  // only occurs in old class files
+    public static final int JVM_CONSTANT_InvokeDynamic      = 18;
 
     // JVM_CONSTANT_MethodHandle subtypes
     public static final int JVM_REF_getField                = 1;
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java	Mon Nov 08 14:33:48 2010 -0800
@@ -303,12 +303,12 @@
                 case JVM_CONSTANT_MethodHandle: {
                      dos.writeByte(cpConstType);
                      int value = cpool.getIntAt(ci);
-                     short bootstrapMethodIndex = (short) extractLowShortFromInt(value);
-                     short nameAndTypeIndex = (short) extractHighShortFromInt(value);
-                     dos.writeShort(bootstrapMethodIndex);
-                     dos.writeShort(nameAndTypeIndex);
-                     if (DEBUG) debugMessage("CP[" + ci + "] = indy BSM = " +
-                           bootstrapMethodIndex + ", N&T = " + nameAndTypeIndex);
+                     byte refKind = (byte) extractLowShortFromInt(value);
+                     short memberIndex = (short) extractHighShortFromInt(value);
+                     dos.writeByte(refKind);
+                     dos.writeShort(memberIndex);
+                     if (DEBUG) debugMessage("CP[" + ci + "] = MH kind = " +
+                           refKind + ", mem = " + memberIndex);
                      break;
                 }
 
@@ -323,10 +323,11 @@
 
                 case JVM_CONSTANT_InvokeDynamic: {
                      dos.writeByte(cpConstType);
-                     int value = cpool.getIntAt(ci);
-                     short refIndex = (short) value;
-                     dos.writeShort(refIndex);
-                     if (DEBUG) debugMessage("CP[" + ci + "] = MT index = " + refIndex);
+                     int[] values = cpool.getMultiOperandsAt(ci);
+                     for (int vn = 0; vn < values.length; vn++) {
+                         dos.writeShort(values[vn]);
+                     }
+                     if (DEBUG) debugMessage("CP[" + ci + "] = INDY indexes = " + Arrays.toString(values));
                      break;
                 }
 
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Mon Nov 08 14:33:48 2010 -0800
@@ -460,6 +460,18 @@
       return buf.toString();
    }
 
+   private String genListOfShort(int[] values) {
+      Formatter buf = new Formatter(genHTML);
+      buf.append('[');
+      for (int i = 0; i < values.length; i++) {
+          if (i > 0)  buf.append(' ');
+          buf.append('#');
+          buf.append(Integer.toString(values[i]));
+      }
+      buf.append(']');
+      return buf.toString();
+   }
+
    protected String genHTMLTableForConstantPool(ConstantPool cpool) {
       Formatter buf = new Formatter(genHTML);
       buf.beginTable(1);
@@ -584,7 +596,7 @@
 
             case JVM_CONSTANT_InvokeDynamic:
                buf.cell("JVM_CONSTANT_InvokeDynamic");
-               buf.cell(genLowHighShort(cpool.getIntAt(index)));
+               buf.cell(genListOfShort(cpool.getMultiOperandsAt(index)));
                break;
 
             default:
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java	Mon Nov 08 14:33:48 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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,7 +40,8 @@
   private static int JVM_CONSTANT_NameAndType             = 12;
   private static int JVM_CONSTANT_MethodHandle            = 15;  // JSR 292
   private static int JVM_CONSTANT_MethodType              = 16;  // JSR 292
-  private static int JVM_CONSTANT_InvokeDynamic           = 17;  // JSR 292
+  //      static int JVM_CONSTANT_InvokeDynamicTrans      = 17;  // JSR 292, only occurs in old class files
+  private static int JVM_CONSTANT_InvokeDynamic           = 18;  // JSR 292
   private static int JVM_CONSTANT_Invalid                 = 0;   // For bad value initialization
   private static int JVM_CONSTANT_UnresolvedClass         = 100; // Temporary tag until actual use
   private static int JVM_CONSTANT_ClassIndex              = 101; // Temporary tag while constructing constant pool
--- a/hotspot/make/linux/Makefile	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/make/linux/Makefile	Mon Nov 08 14:33:48 2010 -0800
@@ -62,7 +62,9 @@
 include $(GAMMADIR)/make/$(OSNAME)/makefiles/rules.make
 
 ifndef CC_INTERP
-FORCE_TIERED=1
+  ifndef FORCE_TIERED
+    FORCE_TIERED=1
+  endif
 endif
 
 ifdef LP64
@@ -254,7 +256,7 @@
 	$(BUILDTREE) VARIANT=tiered
 
 $(SUBDIRS_C2): $(BUILDTREE_MAKE)
-ifdef FORCE_TIERED
+ifeq ($(FORCE_TIERED),1)
 	$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
 		$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
 else
--- a/hotspot/make/solaris/Makefile	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/make/solaris/Makefile	Mon Nov 08 14:33:48 2010 -0800
@@ -53,7 +53,9 @@
 include $(GAMMADIR)/make/$(OSNAME)/makefiles/rules.make
 
 ifndef CC_INTERP
-FORCE_TIERED=1
+  ifndef FORCE_TIERED
+    FORCE_TIERED=1
+  endif
 endif
 
 ifdef LP64
@@ -210,7 +212,7 @@
 	$(BUILDTREE) VARIANT=tiered
 
 $(SUBDIRS_C2): $(BUILDTREE_MAKE)
-ifdef FORCE_TIERED
+ifeq ($(FORCE_TIERED),1)
 	$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
 		$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
 else
--- a/hotspot/make/windows/build.make	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/make/windows/build.make	Mon Nov 08 14:33:48 2010 -0800
@@ -74,9 +74,11 @@
 
 !if "$(BUILDARCH)" != "ia64"
 !ifndef CC_INTERP
+!ifndef FORCE_TIERED
 FORCE_TIERED=1
 !endif
 !endif
+!endif
 
 !if "$(BUILDARCH)" == "amd64"
 Platform_arch=x86
@@ -100,7 +102,7 @@
 !if "$(Variant)" == "compiler1"
 VARIANT_TEXT=Client
 !elseif "$(Variant)" == "compiler2"
-!ifdef FORCE_TIERED
+!if "$(FORCE_TIERED)" == "1"
 VARIANT_TEXT=Server
 realVariant=tiered
 !else
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -1126,7 +1126,7 @@
   inline void add(Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none);
   inline void add(Register s1, int simm13a, Register d, RelocationHolder const& rspec);
   inline void add(Register s1, RegisterOrConstant s2, Register d, int offset = 0);
-  inline void add(const Address& a, Register d, int offset = 0) { add( a.base(), a.disp() + offset, d, a.rspec(offset)); }
+  inline void add(const Address& a, Register d, int offset = 0);
 
   void addcc(  Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3  | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
   void addcc(  Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3  | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -206,6 +206,11 @@
 inline void Assembler::ldd( Register s1, RegisterOrConstant s2, Register d) { ldd( Address(s1, s2), d); }
 
 // form effective addresses this way:
+inline void Assembler::add(const Address& a, Register d, int offset) {
+  if (a.has_index())   add(a.base(), a.index(),         d);
+  else               { add(a.base(), a.disp() + offset, d, a.rspec(offset)); offset = 0; }
+  if (offset != 0)     add(d,        offset,            d);
+}
 inline void Assembler::add(Register s1, RegisterOrConstant s2, Register d, int offset) {
   if (s2.is_register())  add(s1, s2.as_register(),          d);
   else                 { add(s1, s2.as_constant() + offset, d); offset = 0; }
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -70,17 +70,29 @@
 
 // Code generation
 address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
-  // I5_savedSP: sender SP (must preserve)
+  // I5_savedSP/O5_savedSP: sender SP (must preserve)
   // G4 (Gargs): incoming argument list (must preserve)
-  // G5_method:  invoke methodOop; becomes method type.
+  // G5_method:  invoke methodOop
   // G3_method_handle: receiver method handle (must load from sp[MethodTypeForm.vmslots])
-  // O0, O1: garbage temps, blown away
-  Register O0_argslot = O0;
+  // O0, O1, O2, O3, O4: garbage temps, blown away
+  Register O0_mtype   = O0;
   Register O1_scratch = O1;
+  Register O2_scratch = O2;
+  Register O3_scratch = O3;
+  Register O4_argslot = O4;
+  Register O4_argbase = O4;
 
   // emit WrongMethodType path first, to enable back-branch from main path
   Label wrong_method_type;
   __ bind(wrong_method_type);
+  Label invoke_generic_slow_path;
+  assert(methodOopDesc::intrinsic_id_size_in_bytes() == sizeof(u1), "");;
+  __ ldub(Address(G5_method, methodOopDesc::intrinsic_id_offset_in_bytes()), O1_scratch);
+  __ cmp(O1_scratch, (int) vmIntrinsics::_invokeExact);
+  __ brx(Assembler::notEqual, false, Assembler::pt, invoke_generic_slow_path);
+  __ delayed()->nop();
+  __ mov(O0_mtype, G5_method_type);  // required by throw_WrongMethodType
+  // mov(G3_method_handle, G3_method_handle);  // already in this register
   __ jump_to(AddressLiteral(Interpreter::throw_WrongMethodType_entry()), O1_scratch);
   __ delayed()->nop();
 
@@ -88,23 +100,74 @@
   __ align(CodeEntryAlignment);
   address entry_point = __ pc();
 
-  // fetch the MethodType from the method handle into G5_method_type
+  // fetch the MethodType from the method handle
   {
     Register tem = G5_method;
-    assert(tem == G5_method_type, "yes, it's the same register");
     for (jint* pchase = methodOopDesc::method_type_offsets_chain(); (*pchase) != -1; pchase++) {
-      __ ld_ptr(Address(tem, *pchase), G5_method_type);
+      __ ld_ptr(Address(tem, *pchase), O0_mtype);
+      tem = O0_mtype;          // in case there is another indirection
     }
   }
 
   // given the MethodType, find out where the MH argument is buried
-  __ load_heap_oop(Address(G5_method_type, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)),        O0_argslot);
-  __ ldsw(         Address(O0_argslot,     __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, O1_scratch)), O0_argslot);
-  __ ld_ptr(__ argument_address(O0_argslot), G3_method_handle);
+  __ load_heap_oop(Address(O0_mtype,   __ delayed_value(java_dyn_MethodType::form_offset_in_bytes,        O1_scratch)), O4_argslot);
+  __ ldsw(         Address(O4_argslot, __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, O1_scratch)), O4_argslot);
+  __ add(Gargs, __ argument_offset(O4_argslot, 1), O4_argbase);
+  // Note: argument_address uses its input as a scratch register!
+  __ ld_ptr(Address(O4_argbase, -Interpreter::stackElementSize), G3_method_handle);
+
+  trace_method_handle(_masm, "invokeExact");
+
+  __ check_method_handle_type(O0_mtype, G3_method_handle, O1_scratch, wrong_method_type);
+  __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
+
+  // for invokeGeneric (only), apply argument and result conversions on the fly
+  __ bind(invoke_generic_slow_path);
+#ifdef ASSERT
+  { Label L;
+    __ ldub(Address(G5_method, methodOopDesc::intrinsic_id_offset_in_bytes()), O1_scratch);
+    __ cmp(O1_scratch, (int) vmIntrinsics::_invokeGeneric);
+    __ brx(Assembler::equal, false, Assembler::pt, L);
+    __ delayed()->nop();
+    __ stop("bad methodOop::intrinsic_id");
+    __ bind(L);
+  }
+#endif //ASSERT
 
-  __ check_method_handle_type(G5_method_type, G3_method_handle, O1_scratch, wrong_method_type);
+  // make room on the stack for another pointer:
+  insert_arg_slots(_masm, 2 * stack_move_unit(), _INSERT_REF_MASK, O4_argbase, O1_scratch, O2_scratch, O3_scratch);
+  // load up an adapter from the calling type (Java weaves this)
+  Register O2_form    = O2_scratch;
+  Register O3_adapter = O3_scratch;
+  __ load_heap_oop(Address(O0_mtype, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes,               O1_scratch)), O2_form);
+  // load_heap_oop(Address(O2_form,  __ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter);
+  // deal with old JDK versions:
+  __ add(          Address(O2_form,  __ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter);
+  __ cmp(O3_adapter, O2_form);
+  Label sorry_no_invoke_generic;
+  __ brx(Assembler::lessUnsigned, false, Assembler::pn, sorry_no_invoke_generic);
+  __ delayed()->nop();
+
+  __ load_heap_oop(Address(O3_adapter, 0), O3_adapter);
+  __ tst(O3_adapter);
+  __ brx(Assembler::zero, false, Assembler::pn, sorry_no_invoke_generic);
+  __ delayed()->nop();
+  __ st_ptr(O3_adapter, Address(O4_argbase, 1 * Interpreter::stackElementSize));
+  // As a trusted first argument, pass the type being called, so the adapter knows
+  // the actual types of the arguments and return values.
+  // (Generic invokers are shared among form-families of method-type.)
+  __ st_ptr(O0_mtype,   Address(O4_argbase, 0 * Interpreter::stackElementSize));
+  // FIXME: assert that O3_adapter is of the right method-type.
+  __ mov(O3_adapter, G3_method_handle);
+  trace_method_handle(_masm, "invokeGeneric");
   __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
 
+  __ bind(sorry_no_invoke_generic); // no invokeGeneric implementation available!
+  __ mov(O0_mtype, G5_method_type);  // required by throw_WrongMethodType
+  // mov(G3_method_handle, G3_method_handle);  // already in this register
+  __ jump_to(AddressLiteral(Interpreter::throw_WrongMethodType_entry()), O1_scratch);
+  __ delayed()->nop();
+
   return entry_point;
 }
 
@@ -630,9 +693,15 @@
 
       switch (ek) {
       case _adapter_opt_i2i:
+        value = vmarg;
+        break;
       case _adapter_opt_l2i:
-        __ unimplemented(entry_name(ek));
-        value = vmarg;
+        {
+          // just delete the extra slot
+          __ add(Gargs, __ argument_offset(O0_argslot), O0_argslot);
+          remove_arg_slots(_masm, -stack_move_unit(), O0_argslot, O1_scratch, O2_scratch, O3_scratch);
+          value = vmarg = Address(O0_argslot, 0);
+        }
         break;
       case _adapter_opt_unboxi:
         {
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Mon Nov 08 14:33:48 2010 -0800
@@ -1843,6 +1843,12 @@
   return can_be_java_arg(reg);
 }
 
+bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) {
+  // Use hardware SDIVX instruction when it is
+  // faster than a code which use multiply.
+  return VM_Version::has_fast_idiv();
+}
+
 // Register for DIVI projection of divmodI
 RegMask Matcher::divI_proj_mask() {
   ShouldNotReachHere();
@@ -9510,16 +9516,16 @@
     Register Rdst = $dst$$Register;
     Register Rsrc = $src$$Register;
     Register Rtmp = $tmp$$Register;
-    __ srl(Rsrc, 1, Rtmp);
-    __ srl(Rsrc, 0, Rdst);
+    __ srl(Rsrc, 1,    Rtmp);
+    __ srl(Rsrc, 0,    Rdst);
     __ or3(Rdst, Rtmp, Rdst);
-    __ srl(Rdst, 2, Rtmp);
+    __ srl(Rdst, 2,    Rtmp);
     __ or3(Rdst, Rtmp, Rdst);
-    __ srl(Rdst, 4, Rtmp);
+    __ srl(Rdst, 4,    Rtmp);
     __ or3(Rdst, Rtmp, Rdst);
-    __ srl(Rdst, 8, Rtmp);
+    __ srl(Rdst, 8,    Rtmp);
     __ or3(Rdst, Rtmp, Rdst);
-    __ srl(Rdst, 16, Rtmp);
+    __ srl(Rdst, 16,   Rtmp);
     __ or3(Rdst, Rtmp, Rdst);
     __ popc(Rdst, Rdst);
     __ mov(BitsPerInt, Rtmp);
@@ -9528,7 +9534,7 @@
   ins_pipe(ialu_reg);
 %}
 
-instruct countLeadingZerosL(iRegI dst, iRegL src, iRegL tmp, flagsReg cr) %{
+instruct countLeadingZerosL(iRegIsafe dst, iRegL src, iRegL tmp, flagsReg cr) %{
   predicate(UsePopCountInstruction);  // See Matcher::match_rule_supported
   match(Set dst (CountLeadingZerosL src));
   effect(TEMP dst, TEMP tmp, KILL cr);
@@ -9559,18 +9565,18 @@
     Register Rdst = $dst$$Register;
     Register Rsrc = $src$$Register;
     Register Rtmp = $tmp$$Register;
-    __ srlx(Rsrc, 1, Rtmp);
-    __ or3(Rsrc, Rtmp, Rdst);
-    __ srlx(Rdst, 2, Rtmp);
-    __ or3(Rdst, Rtmp, Rdst);
-    __ srlx(Rdst, 4, Rtmp);
-    __ or3(Rdst, Rtmp, Rdst);
-    __ srlx(Rdst, 8, Rtmp);
-    __ or3(Rdst, Rtmp, Rdst);
-    __ srlx(Rdst, 16, Rtmp);
-    __ or3(Rdst, Rtmp, Rdst);
-    __ srlx(Rdst, 32, Rtmp);
-    __ or3(Rdst, Rtmp, Rdst);
+    __ srlx(Rsrc, 1,    Rtmp);
+    __ or3( Rsrc, Rtmp, Rdst);
+    __ srlx(Rdst, 2,    Rtmp);
+    __ or3( Rdst, Rtmp, Rdst);
+    __ srlx(Rdst, 4,    Rtmp);
+    __ or3( Rdst, Rtmp, Rdst);
+    __ srlx(Rdst, 8,    Rtmp);
+    __ or3( Rdst, Rtmp, Rdst);
+    __ srlx(Rdst, 16,   Rtmp);
+    __ or3( Rdst, Rtmp, Rdst);
+    __ srlx(Rdst, 32,   Rtmp);
+    __ or3( Rdst, Rtmp, Rdst);
     __ popc(Rdst, Rdst);
     __ mov(BitsPerLong, Rtmp);
     __ sub(Rtmp, Rdst, Rdst);
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -341,6 +341,26 @@
   resolve_cache_and_index(f1_oop, Otos_i, Rcache, Rscratch, wide ? sizeof(u2) : sizeof(u1));
 
   __ verify_oop(Otos_i);
+
+  Label L_done;
+  const Register Rcon_klass = G3_scratch;  // same as Rcache
+  const Register Rarray_klass = G4_scratch;  // same as Rscratch
+  __ load_klass(Otos_i, Rcon_klass);
+  AddressLiteral array_klass_addr((address)Universe::systemObjArrayKlassObj_addr());
+  __ load_contents(array_klass_addr, Rarray_klass);
+  __ cmp(Rarray_klass, Rcon_klass);
+  __ brx(Assembler::notEqual, false, Assembler::pt, L_done);
+  __ delayed()->nop();
+  __ ld(Address(Otos_i, arrayOopDesc::length_offset_in_bytes()), Rcon_klass);
+  __ tst(Rcon_klass);
+  __ brx(Assembler::zero, true, Assembler::pt, L_done);
+  __ delayed()->clr(Otos_i);    // executed only if branch is taken
+
+  // Load the exception from the system-array which wraps it:
+  __ load_heap_oop(Otos_i, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i);
+  __ throw_if_not_x(Assembler::never, Interpreter::throw_exception_entry(), G3_scratch);
+
+  __ bind(L_done);
 }
 
 void TemplateTable::ldc2_w() {
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -80,7 +80,8 @@
       FLAG_SET_DEFAULT(InteriorEntryAlignment, 4);
     }
     if (is_niagara1_plus()) {
-      if (AllocatePrefetchStyle > 0 && FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
+      if (has_blk_init() && AllocatePrefetchStyle > 0 &&
+          FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
         // Use BIS instruction for allocation prefetch.
         FLAG_SET_DEFAULT(AllocatePrefetchStyle, 3);
         if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) {
@@ -118,16 +119,18 @@
 #endif
 
   char buf[512];
-  jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s",
+  jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                (has_v8() ? ", has_v8" : ""),
                (has_v9() ? ", has_v9" : ""),
                (has_hardware_popc() ? ", popc" : ""),
                (has_vis1() ? ", has_vis1" : ""),
                (has_vis2() ? ", has_vis2" : ""),
+               (has_blk_init() ? ", has_blk_init" : ""),
                (is_ultra3() ? ", is_ultra3" : ""),
                (is_sun4v() ? ", is_sun4v" : ""),
                (is_niagara1() ? ", is_niagara1" : ""),
                (is_niagara1_plus() ? ", is_niagara1_plus" : ""),
+               (is_sparc64() ? ", is_sparc64" : ""),
                (!has_hardware_mul32() ? ", no-mul32" : ""),
                (!has_hardware_div32() ? ", no-div32" : ""),
                (!has_hardware_fsmuld() ? ", no-fsmuld" : ""));
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -33,7 +33,9 @@
     v9_instructions    = 5,
     vis1_instructions  = 6,
     vis2_instructions  = 7,
-    sun4v_instructions = 8
+    sun4v_instructions = 8,
+    blk_init_instructions = 9,
+    fmaf_instructions  = 10
   };
 
   enum Feature_Flag_Set {
@@ -49,6 +51,8 @@
     vis1_instructions_m = 1 << vis1_instructions,
     vis2_instructions_m = 1 << vis2_instructions,
     sun4v_m             = 1 << sun4v_instructions,
+    blk_init_instructions_m = 1 << blk_init_instructions,
+    fmaf_instructions_m = 1 << fmaf_instructions,
 
     generic_v8_m        = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m,
     generic_v9_m        = generic_v8_m | v9_instructions_m,
@@ -67,6 +71,7 @@
   static int  platform_features(int features);
 
   static bool is_niagara1(int features) { return (features & sun4v_m) != 0; }
+  static bool  is_sparc64(int features) { return (features & fmaf_instructions_m) != 0; }
 
   static int maximum_niagara1_processor_count() { return 32; }
   // Returns true if the platform is in the niagara line and
@@ -86,6 +91,7 @@
   static bool has_hardware_popc()       { return (_features & hardware_popc_m) != 0; }
   static bool has_vis1()                { return (_features & vis1_instructions_m) != 0; }
   static bool has_vis2()                { return (_features & vis2_instructions_m) != 0; }
+  static bool has_blk_init()            { return (_features & blk_init_instructions_m) != 0; }
 
   static bool supports_compare_and_exchange()
                                         { return has_v9(); }
@@ -93,8 +99,10 @@
   static bool is_ultra3()               { return (_features & ultra3_m) == ultra3_m; }
   static bool is_sun4v()                { return (_features & sun4v_m) != 0; }
   static bool is_niagara1()             { return is_niagara1(_features); }
+  static bool is_sparc64()              { return is_sparc64(_features); }
 
   static bool has_fast_fxtof()          { return has_v9() && !is_ultra3(); }
+  static bool has_fast_idiv()           { return is_niagara1_plus() || is_sparc64(); }
 
   static const char* cpu_features()     { return _features_str; }
 
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -1275,6 +1275,12 @@
   emit_byte(0xF8 | encode);
 }
 
+void Assembler::divl(Register src) { // Unsigned
+  int encode = prefix_and_encode(src->encoding());
+  emit_byte(0xF7);
+  emit_byte(0xF0 | encode);
+}
+
 void Assembler::imull(Register dst, Register src) {
   int encode = prefix_and_encode(dst->encoding(), src->encoding());
   emit_byte(0x0F);
@@ -1288,7 +1294,7 @@
   if (is8bit(value)) {
     emit_byte(0x6B);
     emit_byte(0xC0 | encode);
-    emit_byte(value);
+    emit_byte(value & 0xFF);
   } else {
     emit_byte(0x69);
     emit_byte(0xC0 | encode);
@@ -3903,7 +3909,7 @@
   if (is8bit(value)) {
     emit_byte(0x6B);
     emit_byte(0xC0 | encode);
-    emit_byte(value);
+    emit_byte(value & 0xFF);
   } else {
     emit_byte(0x69);
     emit_byte(0xC0 | encode);
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -1011,6 +1011,7 @@
   void hlt();
 
   void idivl(Register src);
+  void divl(Register src); // Unsigned division
 
   void idivq(Register src);
 
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -399,6 +399,23 @@
   if (VerifyOops) {
     __ verify_oop(rax);
   }
+
+  Label L_done, L_throw_exception;
+  const Register con_klass_temp = rcx;  // same as Rcache
+  __ movptr(con_klass_temp, Address(rax, oopDesc::klass_offset_in_bytes()));
+  __ cmpptr(con_klass_temp, ExternalAddress((address)Universe::systemObjArrayKlassObj_addr()));
+  __ jcc(Assembler::notEqual, L_done);
+  __ cmpl(Address(rax, arrayOopDesc::length_offset_in_bytes()), 0);
+  __ jcc(Assembler::notEqual, L_throw_exception);
+  __ xorptr(rax, rax);
+  __ jmp(L_done);
+
+  // Load the exception from the system-array which wraps it:
+  __ bind(L_throw_exception);
+  __ movptr(rax, Address(rax, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
+  __ jump(ExternalAddress(Interpreter::throw_exception_entry()));
+
+  __ bind(L_done);
 }
 
 void TemplateTable::ldc2_w() {
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -413,6 +413,25 @@
   if (VerifyOops) {
     __ verify_oop(rax);
   }
+
+  Label L_done, L_throw_exception;
+  const Register con_klass_temp = rcx;  // same as cache
+  const Register array_klass_temp = rdx;  // same as index
+  __ movptr(con_klass_temp, Address(rax, oopDesc::klass_offset_in_bytes()));
+  __ lea(array_klass_temp, ExternalAddress((address)Universe::systemObjArrayKlassObj_addr()));
+  __ cmpptr(con_klass_temp, Address(array_klass_temp, 0));
+  __ jcc(Assembler::notEqual, L_done);
+  __ cmpl(Address(rax, arrayOopDesc::length_offset_in_bytes()), 0);
+  __ jcc(Assembler::notEqual, L_throw_exception);
+  __ xorptr(rax, rax);
+  __ jmp(L_done);
+
+  // Load the exception from the system-array which wraps it:
+  __ bind(L_throw_exception);
+  __ movptr(rax, Address(rax, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
+  __ jump(ExternalAddress(Interpreter::throw_exception_entry()));
+
+  __ bind(L_done);
 }
 
 void TemplateTable::ldc2_w() {
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -446,6 +446,10 @@
   static bool supports_lzcnt()    { return (_cpuFeatures & CPU_LZCNT) != 0; }
   static bool supports_sse4a()    { return (_cpuFeatures & CPU_SSE4A) != 0; }
 
+  // Intel Core and newer cpus have fast IDIV instruction (excluding Atom).
+  static bool has_fast_idiv()     { return is_intel() && cpu_family() == 6 &&
+                                           supports_sse3() && _model != 0x1C; }
+
   static bool supports_compare_and_exchange() { return true; }
 
   static const char* cpu_features()           { return _features_str; }
--- a/hotspot/src/cpu/x86/vm/x86_32.ad	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad	Mon Nov 08 14:33:48 2010 -0800
@@ -1508,6 +1508,16 @@
   return can_be_java_arg(reg);
 }
 
+bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) {
+  // Use hardware integer DIV instruction when
+  // it is faster than a code which use multiply.
+  // Only when constant divisor fits into 32 bit
+  // (min_jint is excluded to get only correct
+  // positive 32 bit values from negative).
+  return VM_Version::has_fast_idiv() &&
+         (divisor == (int)divisor && divisor != min_jint);
+}
+
 // Register for DIVI projection of divmodI
 RegMask Matcher::divI_proj_mask() {
   return EAX_REG_mask;
@@ -1546,6 +1556,9 @@
       return true;
     }
   }
+  if (opc == Op_ConL && (n->get_long() & 0xFFFFFFFF00000000LL) == 0LL) {
+    return true;
+  }
   return false;
 }
 
@@ -2309,9 +2322,11 @@
   enc_class move_long_big_shift_sign( eRegL dst, immI_32_63 cnt ) %{
     emit_opcode( cbuf, 0x8B ); // Move
     emit_rm(cbuf, 0x3, $dst$$reg, HIGH_FROM_LOW($dst$$reg));
-    emit_d8(cbuf,$primary);
-    emit_rm(cbuf, 0x3, $secondary, $dst$$reg);
-    emit_d8(cbuf,$cnt$$constant-32);
+    if( $cnt$$constant > 32 ) { // Shift, if not by zero
+      emit_d8(cbuf,$primary);
+      emit_rm(cbuf, 0x3, $secondary, $dst$$reg);
+      emit_d8(cbuf,$cnt$$constant-32);
+    }
     emit_d8(cbuf,$primary);
     emit_rm(cbuf, 0x3, $secondary, HIGH_FROM_LOW($dst$$reg));
     emit_d8(cbuf,31);
@@ -8842,6 +8857,144 @@
   ins_pipe( pipe_slow );
 %}
 
+// Divide Register Long (no special case since divisor != -1)
+instruct divL_eReg_imm32( eADXRegL dst, immL32 imm, eRegI tmp, eRegI tmp2, eFlagsReg cr ) %{
+  match(Set dst (DivL dst imm));
+  effect( TEMP tmp, TEMP tmp2, KILL cr );
+  ins_cost(1000);
+  format %{ "MOV    $tmp,abs($imm) # ldiv EDX:EAX,$imm\n\t"
+            "XOR    $tmp2,$tmp2\n\t"
+            "CMP    $tmp,EDX\n\t"
+            "JA,s   fast\n\t"
+            "MOV    $tmp2,EAX\n\t"
+            "MOV    EAX,EDX\n\t"
+            "MOV    EDX,0\n\t"
+            "JLE,s  pos\n\t"
+            "LNEG   EAX : $tmp2\n\t"
+            "DIV    $tmp # unsigned division\n\t"
+            "XCHG   EAX,$tmp2\n\t"
+            "DIV    $tmp\n\t"
+            "LNEG   $tmp2 : EAX\n\t"
+            "JMP,s  done\n"
+    "pos:\n\t"
+            "DIV    $tmp\n\t"
+            "XCHG   EAX,$tmp2\n"
+    "fast:\n\t"
+            "DIV    $tmp\n"
+    "done:\n\t"
+            "MOV    EDX,$tmp2\n\t"
+            "NEG    EDX:EAX # if $imm < 0" %}
+  ins_encode %{
+    int con = (int)$imm$$constant;
+    assert(con != 0 && con != -1 && con != min_jint, "wrong divisor");
+    int pcon = (con > 0) ? con : -con;
+    Label Lfast, Lpos, Ldone;
+
+    __ movl($tmp$$Register, pcon);
+    __ xorl($tmp2$$Register,$tmp2$$Register);
+    __ cmpl($tmp$$Register, HIGH_FROM_LOW($dst$$Register));
+    __ jccb(Assembler::above, Lfast); // result fits into 32 bit
+
+    __ movl($tmp2$$Register, $dst$$Register); // save
+    __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register));
+    __ movl(HIGH_FROM_LOW($dst$$Register),0); // preserve flags
+    __ jccb(Assembler::lessEqual, Lpos); // result is positive
+
+    // Negative dividend.
+    // convert value to positive to use unsigned division
+    __ lneg($dst$$Register, $tmp2$$Register);
+    __ divl($tmp$$Register);
+    __ xchgl($dst$$Register, $tmp2$$Register);
+    __ divl($tmp$$Register);
+    // revert result back to negative
+    __ lneg($tmp2$$Register, $dst$$Register);
+    __ jmpb(Ldone);
+
+    __ bind(Lpos);
+    __ divl($tmp$$Register); // Use unsigned division
+    __ xchgl($dst$$Register, $tmp2$$Register);
+    // Fallthrow for final divide, tmp2 has 32 bit hi result
+
+    __ bind(Lfast);
+    // fast path: src is positive
+    __ divl($tmp$$Register); // Use unsigned division
+
+    __ bind(Ldone);
+    __ movl(HIGH_FROM_LOW($dst$$Register),$tmp2$$Register);
+    if (con < 0) {
+      __ lneg(HIGH_FROM_LOW($dst$$Register), $dst$$Register);
+    }
+  %}
+  ins_pipe( pipe_slow );
+%}
+
+// Remainder Register Long (remainder fit into 32 bits)
+instruct modL_eReg_imm32( eADXRegL dst, immL32 imm, eRegI tmp, eRegI tmp2, eFlagsReg cr ) %{
+  match(Set dst (ModL dst imm));
+  effect( TEMP tmp, TEMP tmp2, KILL cr );
+  ins_cost(1000);
+  format %{ "MOV    $tmp,abs($imm) # lrem EDX:EAX,$imm\n\t"
+            "CMP    $tmp,EDX\n\t"
+            "JA,s   fast\n\t"
+            "MOV    $tmp2,EAX\n\t"
+            "MOV    EAX,EDX\n\t"
+            "MOV    EDX,0\n\t"
+            "JLE,s  pos\n\t"
+            "LNEG   EAX : $tmp2\n\t"
+            "DIV    $tmp # unsigned division\n\t"
+            "MOV    EAX,$tmp2\n\t"
+            "DIV    $tmp\n\t"
+            "NEG    EDX\n\t"
+            "JMP,s  done\n"
+    "pos:\n\t"
+            "DIV    $tmp\n\t"
+            "MOV    EAX,$tmp2\n"
+    "fast:\n\t"
+            "DIV    $tmp\n"
+    "done:\n\t"
+            "MOV    EAX,EDX\n\t"
+            "SAR    EDX,31\n\t" %}
+  ins_encode %{
+    int con = (int)$imm$$constant;
+    assert(con != 0 && con != -1 && con != min_jint, "wrong divisor");
+    int pcon = (con > 0) ? con : -con;
+    Label  Lfast, Lpos, Ldone;
+
+    __ movl($tmp$$Register, pcon);
+    __ cmpl($tmp$$Register, HIGH_FROM_LOW($dst$$Register));
+    __ jccb(Assembler::above, Lfast); // src is positive and result fits into 32 bit
+
+    __ movl($tmp2$$Register, $dst$$Register); // save
+    __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register));
+    __ movl(HIGH_FROM_LOW($dst$$Register),0); // preserve flags
+    __ jccb(Assembler::lessEqual, Lpos); // result is positive
+
+    // Negative dividend.
+    // convert value to positive to use unsigned division
+    __ lneg($dst$$Register, $tmp2$$Register);
+    __ divl($tmp$$Register);
+    __ movl($dst$$Register, $tmp2$$Register);
+    __ divl($tmp$$Register);
+    // revert remainder back to negative
+    __ negl(HIGH_FROM_LOW($dst$$Register));
+    __ jmpb(Ldone);
+
+    __ bind(Lpos);
+    __ divl($tmp$$Register);
+    __ movl($dst$$Register, $tmp2$$Register);
+
+    __ bind(Lfast);
+    // fast path: src is positive
+    __ divl($tmp$$Register);
+
+    __ bind(Ldone);
+    __ movl($dst$$Register, HIGH_FROM_LOW($dst$$Register));
+    __ sarl(HIGH_FROM_LOW($dst$$Register), 31); // result sign
+
+  %}
+  ins_pipe( pipe_slow );
+%}
+
 // Integer Shift Instructions
 // Shift Left by one
 instruct shlI_eReg_1(eRegI dst, immI1 shift, eFlagsReg cr) %{
--- a/hotspot/src/cpu/x86/vm/x86_64.ad	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad	Mon Nov 08 14:33:48 2010 -0800
@@ -2065,6 +2065,13 @@
   return can_be_java_arg(reg);
 }
 
+bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) {
+  // In 64 bit mode a code which use multiply when
+  // devisor is constant is faster than hardware
+  // DIV instruction (it uses MulHiL).
+  return false;
+}
+
 // Register for DIVI projection of divmodI
 RegMask Matcher::divI_proj_mask() {
   return INT_RAX_REG_mask;
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -200,6 +200,18 @@
   sigcontext* sc = (sigcontext*)context;
   st->print_cr("Registers:");
 
+  st->print_cr(" G1=" INTPTR_FORMAT " G2=" INTPTR_FORMAT
+               " G3=" INTPTR_FORMAT " G4=" INTPTR_FORMAT,
+               SIG_REGS(sc).u_regs[CON_G1],
+               SIG_REGS(sc).u_regs[CON_G2],
+               SIG_REGS(sc).u_regs[CON_G3],
+               SIG_REGS(sc).u_regs[CON_G4]);
+  st->print_cr(" G5=" INTPTR_FORMAT " G6=" INTPTR_FORMAT
+               " G7=" INTPTR_FORMAT " Y=" INTPTR_FORMAT,
+               SIG_REGS(sc).u_regs[CON_G5],
+               SIG_REGS(sc).u_regs[CON_G6],
+               SIG_REGS(sc).u_regs[CON_G7],
+               SIG_REGS(sc).y);
   st->print_cr(" O0=" INTPTR_FORMAT " O1=" INTPTR_FORMAT
                " O2=" INTPTR_FORMAT " O3=" INTPTR_FORMAT,
                SIG_REGS(sc).u_regs[CON_O0],
@@ -213,18 +225,32 @@
                SIG_REGS(sc).u_regs[CON_O6],
                SIG_REGS(sc).u_regs[CON_O7]);
 
-  st->print_cr(" G1=" INTPTR_FORMAT " G2=" INTPTR_FORMAT
-               " G3=" INTPTR_FORMAT " G4=" INTPTR_FORMAT,
-               SIG_REGS(sc).u_regs[CON_G1],
-               SIG_REGS(sc).u_regs[CON_G2],
-               SIG_REGS(sc).u_regs[CON_G3],
-               SIG_REGS(sc).u_regs[CON_G4]);
-  st->print_cr(" G5=" INTPTR_FORMAT " G6=" INTPTR_FORMAT
-               " G7=" INTPTR_FORMAT " Y=" INTPTR_FORMAT,
-               SIG_REGS(sc).u_regs[CON_G5],
-               SIG_REGS(sc).u_regs[CON_G6],
-               SIG_REGS(sc).u_regs[CON_G7],
-               SIG_REGS(sc).y);
+
+  intptr_t *sp = (intptr_t *)os::Linux::ucontext_get_sp(uc);
+  st->print_cr(" L0=" INTPTR_FORMAT " L1=" INTPTR_FORMAT
+               " L2=" INTPTR_FORMAT " L3=" INTPTR_FORMAT,
+               sp[L0->sp_offset_in_saved_window()],
+               sp[L1->sp_offset_in_saved_window()],
+               sp[L2->sp_offset_in_saved_window()],
+               sp[L3->sp_offset_in_saved_window()]);
+  st->print_cr(" L4=" INTPTR_FORMAT " L5=" INTPTR_FORMAT
+               " L6=" INTPTR_FORMAT " L7=" INTPTR_FORMAT,
+               sp[L4->sp_offset_in_saved_window()],
+               sp[L5->sp_offset_in_saved_window()],
+               sp[L6->sp_offset_in_saved_window()],
+               sp[L7->sp_offset_in_saved_window()]);
+  st->print_cr(" I0=" INTPTR_FORMAT " I1=" INTPTR_FORMAT
+               " I2=" INTPTR_FORMAT " I3=" INTPTR_FORMAT,
+               sp[I0->sp_offset_in_saved_window()],
+               sp[I1->sp_offset_in_saved_window()],
+               sp[I2->sp_offset_in_saved_window()],
+               sp[I3->sp_offset_in_saved_window()]);
+  st->print_cr(" I4=" INTPTR_FORMAT " I5=" INTPTR_FORMAT
+               " I6=" INTPTR_FORMAT " I7=" INTPTR_FORMAT,
+               sp[I4->sp_offset_in_saved_window()],
+               sp[I5->sp_offset_in_saved_window()],
+               sp[I6->sp_offset_in_saved_window()],
+               sp[I7->sp_offset_in_saved_window()]);
 
   st->print_cr(" PC=" INTPTR_FORMAT " nPC=" INTPTR_FORMAT,
                SIG_PC(sc),
@@ -232,7 +258,6 @@
   st->cr();
   st->cr();
 
-  intptr_t *sp = (intptr_t *)os::Linux::ucontext_get_sp(uc);
   st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp);
   print_hex_dump(st, (address)sp, (address)(sp + 32), sizeof(intptr_t));
   st->cr();
@@ -242,7 +267,58 @@
   // this at the end, and hope for the best.
   address pc = os::Linux::ucontext_get_pc(uc);
   st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
-  print_hex_dump(st, pc - 16, pc + 16, sizeof(char));
+  print_hex_dump(st, pc - 32, pc + 32, sizeof(char));
+}
+
+
+void os::print_register_info(outputStream *st, void *context) {
+  if (context == NULL) return;
+
+  ucontext_t *uc = (ucontext_t*)context;
+  intptr_t *sp = (intptr_t *)os::Linux::ucontext_get_sp(uc);
+
+  st->print_cr("Register to memory mapping:");
+  st->cr();
+
+  // this is only for the "general purpose" registers
+  st->print("G1="); print_location(st, SIG_REGS(sc).u_regs[CON__G1]);
+  st->print("G2="); print_location(st, SIG_REGS(sc).u_regs[CON__G2]);
+  st->print("G3="); print_location(st, SIG_REGS(sc).u_regs[CON__G3]);
+  st->print("G4="); print_location(st, SIG_REGS(sc).u_regs[CON__G4]);
+  st->print("G5="); print_location(st, SIG_REGS(sc).u_regs[CON__G5]);
+  st->print("G6="); print_location(st, SIG_REGS(sc).u_regs[CON__G6]);
+  st->print("G7="); print_location(st, SIG_REGS(sc).u_regs[CON__G7]);
+  st->cr();
+
+  st->print("O0="); print_location(st, SIG_REGS(sc).u_regs[CON__O0]);
+  st->print("O1="); print_location(st, SIG_REGS(sc).u_regs[CON__O1]);
+  st->print("O2="); print_location(st, SIG_REGS(sc).u_regs[CON__O2]);
+  st->print("O3="); print_location(st, SIG_REGS(sc).u_regs[CON__O3]);
+  st->print("O4="); print_location(st, SIG_REGS(sc).u_regs[CON__O4]);
+  st->print("O5="); print_location(st, SIG_REGS(sc).u_regs[CON__O5]);
+  st->print("O6="); print_location(st, SIG_REGS(sc).u_regs[CON__O6]);
+  st->print("O7="); print_location(st, SIG_REGS(sc).u_regs[CON__O7]);
+  st->cr();
+
+  st->print("L0="); print_location(st, sp[L0->sp_offset_in_saved_window()]);
+  st->print("L1="); print_location(st, sp[L1->sp_offset_in_saved_window()]);
+  st->print("L2="); print_location(st, sp[L2->sp_offset_in_saved_window()]);
+  st->print("L3="); print_location(st, sp[L3->sp_offset_in_saved_window()]);
+  st->print("L4="); print_location(st, sp[L4->sp_offset_in_saved_window()]);
+  st->print("L5="); print_location(st, sp[L5->sp_offset_in_saved_window()]);
+  st->print("L6="); print_location(st, sp[L6->sp_offset_in_saved_window()]);
+  st->print("L7="); print_location(st, sp[L7->sp_offset_in_saved_window()]);
+  st->cr();
+
+  st->print("I0="); print_location(st, sp[I0->sp_offset_in_saved_window()]);
+  st->print("I1="); print_location(st, sp[I1->sp_offset_in_saved_window()]);
+  st->print("I2="); print_location(st, sp[I2->sp_offset_in_saved_window()]);
+  st->print("I3="); print_location(st, sp[I3->sp_offset_in_saved_window()]);
+  st->print("I4="); print_location(st, sp[I4->sp_offset_in_saved_window()]);
+  st->print("I5="); print_location(st, sp[I5->sp_offset_in_saved_window()]);
+  st->print("I6="); print_location(st, sp[I6->sp_offset_in_saved_window()]);
+  st->print("I7="); print_location(st, sp[I7->sp_offset_in_saved_window()]);
+  st->cr();
 }
 
 
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -718,11 +718,6 @@
 
   ucontext_t *uc = (ucontext_t*)context;
   st->print_cr("Registers:");
-
-  // this is horrendously verbose but the layout of the registers in the
-  // context does not match how we defined our abstract Register set, so
-  // we can't just iterate through the gregs area
-
 #ifdef AMD64
   st->print(  "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]);
   st->print(", RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]);
@@ -745,68 +740,11 @@
   st->print(", R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]);
   st->cr();
   st->print(  "RIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RIP]);
-  st->print(", EFL=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EFL]);
+  st->print(", EFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EFL]);
   st->print(", CSGSFS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_CSGSFS]);
   st->print(", ERR=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ERR]);
   st->cr();
   st->print("  TRAPNO=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_TRAPNO]);
-
-  st->cr();
-  st->cr();
-
-  st->print_cr("Register to memory mapping:");
-  st->cr();
-
-  // this is only for the "general purpose" registers
-
-  st->print_cr("RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RAX]);
-  st->cr();
-  st->print_cr("RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RBX]);
-  st->cr();
-  st->print_cr("RCX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RCX]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RCX]);
-  st->cr();
-  st->print_cr("RDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDX]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RDX]);
-  st->cr();
-  st->print_cr("RSP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSP]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RSP]);
-  st->cr();
-  st->print_cr("RBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBP]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RBP]);
-  st->cr();
-  st->print_cr("RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RSI]);
-  st->cr();
-  st->print_cr("RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RDI]);
-  st->cr();
-  st->print_cr("R8 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R8]);
-  st->cr();
-  st->print_cr("R9 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R9]);
-  st->cr();
-  st->print_cr("R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R10]);
-  st->cr();
-  st->print_cr("R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R11]);
-  st->cr();
-  st->print_cr("R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R12]);
-  st->cr();
-  st->print_cr("R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R13]);
-  st->cr();
-  st->print_cr("R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R14]);
-  st->cr();
-  st->print_cr("R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R15]);
-
 #else
   st->print(  "EAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EAX]);
   st->print(", EBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EBX]);
@@ -819,41 +757,8 @@
   st->print(", EDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EDI]);
   st->cr();
   st->print(  "EIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EIP]);
+  st->print(", EFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EFL]);
   st->print(", CR2=" INTPTR_FORMAT, uc->uc_mcontext.cr2);
-  st->print(", EFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EFL]);
-
-  st->cr();
-  st->cr();
-
-  st->print_cr("Register to memory mapping:");
-  st->cr();
-
-  // this is only for the "general purpose" registers
-
-  st->print_cr("EAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EAX]);
-  print_location(st, uc->uc_mcontext.gregs[REG_EAX]);
-  st->cr();
-  st->print_cr("EBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EBX]);
-  print_location(st, uc->uc_mcontext.gregs[REG_EBX]);
-  st->cr();
-  st->print_cr("ECX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ECX]);
-  print_location(st, uc->uc_mcontext.gregs[REG_ECX]);
-  st->cr();
-  st->print_cr("EDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EDX]);
-  print_location(st, uc->uc_mcontext.gregs[REG_EDX]);
-  st->cr();
-  st->print_cr("ESP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ESP]);
-  print_location(st, uc->uc_mcontext.gregs[REG_ESP]);
-  st->cr();
-  st->print_cr("EBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EBP]);
-  print_location(st, uc->uc_mcontext.gregs[REG_EBP]);
-  st->cr();
-  st->print_cr("ESI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_ESI]);
-  print_location(st, uc->uc_mcontext.gregs[REG_ESI]);
-  st->cr();
-  st->print_cr("EDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_EDI]);
-  print_location(st, uc->uc_mcontext.gregs[REG_EDI]);
-
 #endif // AMD64
   st->cr();
   st->cr();
@@ -868,7 +773,52 @@
   // this at the end, and hope for the best.
   address pc = os::Linux::ucontext_get_pc(uc);
   st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
-  print_hex_dump(st, pc - 16, pc + 16, sizeof(char));
+  print_hex_dump(st, pc - 32, pc + 32, sizeof(char));
+}
+
+void os::print_register_info(outputStream *st, void *context) {
+  if (context == NULL) return;
+
+  ucontext_t *uc = (ucontext_t*)context;
+
+  st->print_cr("Register to memory mapping:");
+  st->cr();
+
+  // this is horrendously verbose but the layout of the registers in the
+  // context does not match how we defined our abstract Register set, so
+  // we can't just iterate through the gregs area
+
+  // this is only for the "general purpose" registers
+
+#ifdef AMD64
+  st->print("RAX="); print_location(st, uc->uc_mcontext.gregs[REG_RAX]);
+  st->print("RBX="); print_location(st, uc->uc_mcontext.gregs[REG_RBX]);
+  st->print("RCX="); print_location(st, uc->uc_mcontext.gregs[REG_RCX]);
+  st->print("RDX="); print_location(st, uc->uc_mcontext.gregs[REG_RDX]);
+  st->print("RSP="); print_location(st, uc->uc_mcontext.gregs[REG_RSP]);
+  st->print("RBP="); print_location(st, uc->uc_mcontext.gregs[REG_RBP]);
+  st->print("RSI="); print_location(st, uc->uc_mcontext.gregs[REG_RSI]);
+  st->print("RDI="); print_location(st, uc->uc_mcontext.gregs[REG_RDI]);
+  st->print("R8 ="); print_location(st, uc->uc_mcontext.gregs[REG_R8]);
+  st->print("R9 ="); print_location(st, uc->uc_mcontext.gregs[REG_R9]);
+  st->print("R10="); print_location(st, uc->uc_mcontext.gregs[REG_R10]);
+  st->print("R11="); print_location(st, uc->uc_mcontext.gregs[REG_R11]);
+  st->print("R12="); print_location(st, uc->uc_mcontext.gregs[REG_R12]);
+  st->print("R13="); print_location(st, uc->uc_mcontext.gregs[REG_R13]);
+  st->print("R14="); print_location(st, uc->uc_mcontext.gregs[REG_R14]);
+  st->print("R15="); print_location(st, uc->uc_mcontext.gregs[REG_R15]);
+#else
+  st->print("EAX="); print_location(st, uc->uc_mcontext.gregs[REG_EAX]);
+  st->print("EBX="); print_location(st, uc->uc_mcontext.gregs[REG_EBX]);
+  st->print("ECX="); print_location(st, uc->uc_mcontext.gregs[REG_ECX]);
+  st->print("EDX="); print_location(st, uc->uc_mcontext.gregs[REG_EDX]);
+  st->print("ESP="); print_location(st, uc->uc_mcontext.gregs[REG_ESP]);
+  st->print("EBP="); print_location(st, uc->uc_mcontext.gregs[REG_EBP]);
+  st->print("ESI="); print_location(st, uc->uc_mcontext.gregs[REG_ESI]);
+  st->print("EDI="); print_location(st, uc->uc_mcontext.gregs[REG_EDI]);
+#endif // AMD64
+
+  st->cr();
 }
 
 void os::setup_fpu() {
--- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -540,6 +540,11 @@
     pc = (address) uc->uc_mcontext.gregs[REG_PC];
   }
 
+  // Sometimes the register windows are not properly flushed.
+  if(uc->uc_mcontext.gwins != NULL) {
+    ::handle_unflushed_register_windows(uc->uc_mcontext.gwins);
+  }
+
   // unmask current signal
   sigset_t newset;
   sigemptyset(&newset);
@@ -558,6 +563,18 @@
   ucontext_t *uc = (ucontext_t*)context;
   st->print_cr("Registers:");
 
+  st->print_cr(" G1=" INTPTR_FORMAT " G2=" INTPTR_FORMAT
+               " G3=" INTPTR_FORMAT " G4=" INTPTR_FORMAT,
+            uc->uc_mcontext.gregs[REG_G1],
+            uc->uc_mcontext.gregs[REG_G2],
+            uc->uc_mcontext.gregs[REG_G3],
+            uc->uc_mcontext.gregs[REG_G4]);
+  st->print_cr(" G5=" INTPTR_FORMAT " G6=" INTPTR_FORMAT
+               " G7=" INTPTR_FORMAT " Y=" INTPTR_FORMAT,
+            uc->uc_mcontext.gregs[REG_G5],
+            uc->uc_mcontext.gregs[REG_G6],
+            uc->uc_mcontext.gregs[REG_G7],
+            uc->uc_mcontext.gregs[REG_Y]);
   st->print_cr(" O0=" INTPTR_FORMAT " O1=" INTPTR_FORMAT
                " O2=" INTPTR_FORMAT " O3=" INTPTR_FORMAT,
                  uc->uc_mcontext.gregs[REG_O0],
@@ -571,81 +588,39 @@
             uc->uc_mcontext.gregs[REG_O6],
             uc->uc_mcontext.gregs[REG_O7]);
 
-  st->print_cr(" G1=" INTPTR_FORMAT " G2=" INTPTR_FORMAT
-               " G3=" INTPTR_FORMAT " G4=" INTPTR_FORMAT,
-            uc->uc_mcontext.gregs[REG_G1],
-            uc->uc_mcontext.gregs[REG_G2],
-            uc->uc_mcontext.gregs[REG_G3],
-            uc->uc_mcontext.gregs[REG_G4]);
-  st->print_cr(" G5=" INTPTR_FORMAT " G6=" INTPTR_FORMAT
-               " G7=" INTPTR_FORMAT " Y=" INTPTR_FORMAT,
-            uc->uc_mcontext.gregs[REG_G5],
-            uc->uc_mcontext.gregs[REG_G6],
-            uc->uc_mcontext.gregs[REG_G7],
-            uc->uc_mcontext.gregs[REG_Y]);
+
+  intptr_t *sp = (intptr_t *)os::Solaris::ucontext_get_sp(uc);
+  st->print_cr(" L0=" INTPTR_FORMAT " L1=" INTPTR_FORMAT
+               " L2=" INTPTR_FORMAT " L3=" INTPTR_FORMAT,
+               sp[L0->sp_offset_in_saved_window()],
+               sp[L1->sp_offset_in_saved_window()],
+               sp[L2->sp_offset_in_saved_window()],
+               sp[L3->sp_offset_in_saved_window()]);
+  st->print_cr(" L4=" INTPTR_FORMAT " L5=" INTPTR_FORMAT
+               " L6=" INTPTR_FORMAT " L7=" INTPTR_FORMAT,
+               sp[L4->sp_offset_in_saved_window()],
+               sp[L5->sp_offset_in_saved_window()],
+               sp[L6->sp_offset_in_saved_window()],
+               sp[L7->sp_offset_in_saved_window()]);
+  st->print_cr(" I0=" INTPTR_FORMAT " I1=" INTPTR_FORMAT
+               " I2=" INTPTR_FORMAT " I3=" INTPTR_FORMAT,
+               sp[I0->sp_offset_in_saved_window()],
+               sp[I1->sp_offset_in_saved_window()],
+               sp[I2->sp_offset_in_saved_window()],
+               sp[I3->sp_offset_in_saved_window()]);
+  st->print_cr(" I4=" INTPTR_FORMAT " I5=" INTPTR_FORMAT
+               " I6=" INTPTR_FORMAT " I7=" INTPTR_FORMAT,
+               sp[I4->sp_offset_in_saved_window()],
+               sp[I5->sp_offset_in_saved_window()],
+               sp[I6->sp_offset_in_saved_window()],
+               sp[I7->sp_offset_in_saved_window()]);
 
   st->print_cr(" PC=" INTPTR_FORMAT " nPC=" INTPTR_FORMAT,
             uc->uc_mcontext.gregs[REG_PC],
             uc->uc_mcontext.gregs[REG_nPC]);
-
   st->cr();
   st->cr();
 
-  st->print_cr("Register to memory mapping:");
-  st->cr();
-
-  // this is only for the "general purpose" registers
-
-  st->print_cr("O0=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_O0]);
-  print_location(st, uc->uc_mcontext.gregs[REG_O0]);
-  st->cr();
-  st->print_cr("O1=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_O1]);
-  print_location(st, uc->uc_mcontext.gregs[REG_O1]);
-  st->cr();
-  st->print_cr("O2=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_O2]);
-  print_location(st, uc->uc_mcontext.gregs[REG_O2]);
-  st->cr();
-  st->print_cr("O3=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_O3]);
-  print_location(st, uc->uc_mcontext.gregs[REG_O3]);
-  st->cr();
-  st->print_cr("O4=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_O4]);
-  print_location(st, uc->uc_mcontext.gregs[REG_O4]);
-  st->cr();
-  st->print_cr("O5=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_O5]);
-  print_location(st, uc->uc_mcontext.gregs[REG_O5]);
-  st->cr();
-  st->print_cr("O6=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_O6]);
-  print_location(st, uc->uc_mcontext.gregs[REG_O6]);
-  st->cr();
-  st->print_cr("O7=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_O7]);
-  print_location(st, uc->uc_mcontext.gregs[REG_O7]);
-  st->cr();
-
-  st->print_cr("G1=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_G1]);
-  print_location(st, uc->uc_mcontext.gregs[REG_G1]);
-  st->cr();
-  st->print_cr("G2=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_G2]);
-  print_location(st, uc->uc_mcontext.gregs[REG_G2]);
-  st->cr();
-  st->print_cr("G3=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_G3]);
-  print_location(st, uc->uc_mcontext.gregs[REG_G3]);
-  st->cr();
-  st->print_cr("G4=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_G4]);
-  print_location(st, uc->uc_mcontext.gregs[REG_G4]);
-  st->cr();
-  st->print_cr("G5=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_G5]);
-  print_location(st, uc->uc_mcontext.gregs[REG_G5]);
-  st->cr();
-  st->print_cr("G6=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_G6]);
-  print_location(st, uc->uc_mcontext.gregs[REG_G6]);
-  st->cr();
-  st->print_cr("G7=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_G7]);
-  print_location(st, uc->uc_mcontext.gregs[REG_G7]);
-
-  st->cr();
-  st->cr();
-
-  intptr_t *sp = (intptr_t *)os::Solaris::ucontext_get_sp(uc);
   st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp);
   print_hex_dump(st, (address)sp, (address)(sp + 32), sizeof(intptr_t));
   st->cr();
@@ -656,7 +631,57 @@
   ExtendedPC epc = os::Solaris::ucontext_get_ExtendedPC(uc);
   address pc = epc.pc();
   st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
-  print_hex_dump(st, pc - 16, pc + 16, sizeof(char));
+  print_hex_dump(st, pc - 32, pc + 32, sizeof(char));
+}
+
+void os::print_register_info(outputStream *st, void *context) {
+  if (context == NULL) return;
+
+  ucontext_t *uc = (ucontext_t*)context;
+  intptr_t *sp = (intptr_t *)os::Solaris::ucontext_get_sp(uc);
+
+  st->print_cr("Register to memory mapping:");
+  st->cr();
+
+  // this is only for the "general purpose" registers
+  st->print("G1="); print_location(st, uc->uc_mcontext.gregs[REG_G1]);
+  st->print("G2="); print_location(st, uc->uc_mcontext.gregs[REG_G2]);
+  st->print("G3="); print_location(st, uc->uc_mcontext.gregs[REG_G3]);
+  st->print("G4="); print_location(st, uc->uc_mcontext.gregs[REG_G4]);
+  st->print("G5="); print_location(st, uc->uc_mcontext.gregs[REG_G5]);
+  st->print("G6="); print_location(st, uc->uc_mcontext.gregs[REG_G6]);
+  st->print("G7="); print_location(st, uc->uc_mcontext.gregs[REG_G7]);
+  st->cr();
+
+  st->print("O0="); print_location(st, uc->uc_mcontext.gregs[REG_O0]);
+  st->print("O1="); print_location(st, uc->uc_mcontext.gregs[REG_O1]);
+  st->print("O2="); print_location(st, uc->uc_mcontext.gregs[REG_O2]);
+  st->print("O3="); print_location(st, uc->uc_mcontext.gregs[REG_O3]);
+  st->print("O4="); print_location(st, uc->uc_mcontext.gregs[REG_O4]);
+  st->print("O5="); print_location(st, uc->uc_mcontext.gregs[REG_O5]);
+  st->print("O6="); print_location(st, uc->uc_mcontext.gregs[REG_O6]);
+  st->print("O7="); print_location(st, uc->uc_mcontext.gregs[REG_O7]);
+  st->cr();
+
+  st->print("L0="); print_location(st, sp[L0->sp_offset_in_saved_window()]);
+  st->print("L1="); print_location(st, sp[L1->sp_offset_in_saved_window()]);
+  st->print("L2="); print_location(st, sp[L2->sp_offset_in_saved_window()]);
+  st->print("L3="); print_location(st, sp[L3->sp_offset_in_saved_window()]);
+  st->print("L4="); print_location(st, sp[L4->sp_offset_in_saved_window()]);
+  st->print("L5="); print_location(st, sp[L5->sp_offset_in_saved_window()]);
+  st->print("L6="); print_location(st, sp[L6->sp_offset_in_saved_window()]);
+  st->print("L7="); print_location(st, sp[L7->sp_offset_in_saved_window()]);
+  st->cr();
+
+  st->print("I0="); print_location(st, sp[I0->sp_offset_in_saved_window()]);
+  st->print("I1="); print_location(st, sp[I1->sp_offset_in_saved_window()]);
+  st->print("I2="); print_location(st, sp[I2->sp_offset_in_saved_window()]);
+  st->print("I3="); print_location(st, sp[I3->sp_offset_in_saved_window()]);
+  st->print("I4="); print_location(st, sp[I4->sp_offset_in_saved_window()]);
+  st->print("I5="); print_location(st, sp[I5->sp_offset_in_saved_window()]);
+  st->print("I6="); print_location(st, sp[I6->sp_offset_in_saved_window()]);
+  st->print("I7="); print_location(st, sp[I7->sp_offset_in_saved_window()]);
+  st->cr();
 }
 
 void os::Solaris::init_thread_fpu_state(void) {
--- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -65,10 +65,6 @@
   // getisax(2), SI_ARCHITECTURE_32, and SI_ARCHITECTURE_64 are
   // supported on Solaris 10 and later.
   if (os::Solaris::supports_getisax()) {
-#ifndef PRODUCT
-    if (PrintMiscellaneous && Verbose)
-      tty->print_cr("getisax(2) supported.");
-#endif
 
     // Check 32-bit architecture.
     do_sysinfo(SI_ARCHITECTURE_32, "sparc", &features, v8_instructions_m);
@@ -81,6 +77,11 @@
     uint_t avn = os::Solaris::getisax(&av, 1);
     assert(avn == 1, "should only return one av");
 
+#ifndef PRODUCT
+    if (PrintMiscellaneous && Verbose)
+      tty->print_cr("getisax(2) returned: " PTR32_FORMAT, av);
+#endif
+
     if (av & AV_SPARC_MUL32)  features |= hardware_mul32_m;
     if (av & AV_SPARC_DIV32)  features |= hardware_div32_m;
     if (av & AV_SPARC_FSMULD) features |= hardware_fsmuld_m;
@@ -88,11 +89,22 @@
     if (av & AV_SPARC_POPC)   features |= hardware_popc_m;
     if (av & AV_SPARC_VIS)    features |= vis1_instructions_m;
     if (av & AV_SPARC_VIS2)   features |= vis2_instructions_m;
+
+    // Next values are not defined before Solaris 10
+    // but Solaris 8 is used for jdk6 update builds.
+#ifndef AV_SPARC_ASI_BLK_INIT
+#define AV_SPARC_ASI_BLK_INIT 0x0080  /* ASI_BLK_INIT_xxx ASI */
+#endif
+#ifndef AV_SPARC_FMAF
+#define AV_SPARC_FMAF 0x0100  /* Sparc64 Fused Multiply-Add */
+#endif
+    if (av & AV_SPARC_ASI_BLK_INIT) features |= blk_init_instructions_m;
+    if (av & AV_SPARC_FMAF)         features |= fmaf_instructions_m;
   } else {
     // getisax(2) failed, use the old legacy code.
 #ifndef PRODUCT
     if (PrintMiscellaneous && Verbose)
-      tty->print_cr("getisax(2) not supported.");
+      tty->print_cr("getisax(2) is not supported.");
 #endif
 
     char   tmp;
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -719,11 +719,6 @@
 
   ucontext_t *uc = (ucontext_t*)context;
   st->print_cr("Registers:");
-
-  // this is horrendously verbose but the layout of the registers in the
-  // context does not match how we defined our abstract Register set, so
-  // we can't just iterate through the gregs area
-
 #ifdef AMD64
   st->print(  "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]);
   st->print(", RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]);
@@ -735,8 +730,8 @@
   st->print(", RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]);
   st->print(", RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]);
   st->cr();
-  st->print(  "R8=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]);
-  st->print(", R9=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]);
+  st->print(  "R8 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]);
+  st->print(", R9 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]);
   st->print(", R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]);
   st->print(", R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]);
   st->cr();
@@ -747,63 +742,6 @@
   st->cr();
   st->print(  "RIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RIP]);
   st->print(", RFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RFL]);
-
-  st->cr();
-  st->cr();
-
-  st->print_cr("Register to memory mapping:");
-  st->cr();
-
-  // this is only for the "general purpose" registers
-
-  st->print_cr("RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RAX]);
-  st->cr();
-  st->print_cr("RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RBX]);
-  st->cr();
-  st->print_cr("RCX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RCX]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RCX]);
-  st->cr();
-  st->print_cr("RDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDX]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RDX]);
-  st->cr();
-  st->print_cr("RSP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSP]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RSP]);
-  st->cr();
-  st->print_cr("RBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBP]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RSP]);
-  st->cr();
-  st->print_cr("RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RSI]);
-  st->cr();
-  st->print_cr("RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]);
-  print_location(st, uc->uc_mcontext.gregs[REG_RDI]);
-  st->cr();
-  st->print_cr("R8 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R8]);
-  st->cr();
-  st->print_cr("R9 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R9]);
-  st->cr();
-  st->print_cr("R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R10]);
-  st->cr();
-  st->print_cr("R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R11]);
-  st->cr();
-  st->print_cr("R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R12]);
-  st->cr();
-  st->print_cr("R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R13]);
-  st->cr();
-  st->print_cr("R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R14]);
-  st->cr();
-  st->print_cr("R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]);
-  print_location(st, uc->uc_mcontext.gregs[REG_R15]);
-
 #else
   st->print(  "EAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EAX]);
   st->print(", EBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EBX]);
@@ -817,39 +755,6 @@
   st->cr();
   st->print(  "EIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EIP]);
   st->print(", EFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EFL]);
-
-  st->cr();
-  st->cr();
-
-  st->print_cr("Register to memory mapping:");
-  st->cr();
-
-  // this is only for the "general purpose" registers
-
-  st->print_cr("EAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EAX]);
-  print_location(st, uc->uc_mcontext.gregs[EAX]);
-  st->cr();
-  st->print_cr("EBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EBX]);
-  print_location(st, uc->uc_mcontext.gregs[EBX]);
-  st->cr();
-  st->print_cr("ECX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[ECX]);
-  print_location(st, uc->uc_mcontext.gregs[ECX]);
-  st->cr();
-  st->print_cr("EDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EDX]);
-  print_location(st, uc->uc_mcontext.gregs[EDX]);
-  st->cr();
-  st->print_cr("ESP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[UESP]);
-  print_location(st, uc->uc_mcontext.gregs[UESP]);
-  st->cr();
-  st->print_cr("EBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EBP]);
-  print_location(st, uc->uc_mcontext.gregs[EBP]);
-  st->cr();
-  st->print_cr("ESI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[ESI]);
-  print_location(st, uc->uc_mcontext.gregs[ESI]);
-  st->cr();
-  st->print_cr("EDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EDI]);
-  print_location(st, uc->uc_mcontext.gregs[EDI]);
-
 #endif // AMD64
   st->cr();
   st->cr();
@@ -865,7 +770,52 @@
   ExtendedPC epc = os::Solaris::ucontext_get_ExtendedPC(uc);
   address pc = epc.pc();
   st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
-  print_hex_dump(st, pc - 16, pc + 16, sizeof(char));
+  print_hex_dump(st, pc - 32, pc + 32, sizeof(char));
+}
+
+void os::print_register_info(outputStream *st, void *context) {
+  if (context == NULL) return;
+
+  ucontext_t *uc = (ucontext_t*)context;
+
+  st->print_cr("Register to memory mapping:");
+  st->cr();
+
+  // this is horrendously verbose but the layout of the registers in the
+  // context does not match how we defined our abstract Register set, so
+  // we can't just iterate through the gregs area
+
+  // this is only for the "general purpose" registers
+
+#ifdef AMD64
+  st->print("RAX="); print_location(st, uc->uc_mcontext.gregs[REG_RAX]);
+  st->print("RBX="); print_location(st, uc->uc_mcontext.gregs[REG_RBX]);
+  st->print("RCX="); print_location(st, uc->uc_mcontext.gregs[REG_RCX]);
+  st->print("RDX="); print_location(st, uc->uc_mcontext.gregs[REG_RDX]);
+  st->print("RSP="); print_location(st, uc->uc_mcontext.gregs[REG_RSP]);
+  st->print("RBP="); print_location(st, uc->uc_mcontext.gregs[REG_RBP]);
+  st->print("RSI="); print_location(st, uc->uc_mcontext.gregs[REG_RSI]);
+  st->print("RDI="); print_location(st, uc->uc_mcontext.gregs[REG_RDI]);
+  st->print("R8 ="); print_location(st, uc->uc_mcontext.gregs[REG_R8]);
+  st->print("R9 ="); print_location(st, uc->uc_mcontext.gregs[REG_R9]);
+  st->print("R10="); print_location(st, uc->uc_mcontext.gregs[REG_R10]);
+  st->print("R11="); print_location(st, uc->uc_mcontext.gregs[REG_R11]);
+  st->print("R12="); print_location(st, uc->uc_mcontext.gregs[REG_R12]);
+  st->print("R13="); print_location(st, uc->uc_mcontext.gregs[REG_R13]);
+  st->print("R14="); print_location(st, uc->uc_mcontext.gregs[REG_R14]);
+  st->print("R15="); print_location(st, uc->uc_mcontext.gregs[REG_R15]);
+#else
+  st->print("EAX="); print_location(st, uc->uc_mcontext.gregs[EAX]);
+  st->print("EBX="); print_location(st, uc->uc_mcontext.gregs[EBX]);
+  st->print("ECX="); print_location(st, uc->uc_mcontext.gregs[ECX]);
+  st->print("EDX="); print_location(st, uc->uc_mcontext.gregs[EDX]);
+  st->print("ESP="); print_location(st, uc->uc_mcontext.gregs[UESP]);
+  st->print("EBP="); print_location(st, uc->uc_mcontext.gregs[EBP]);
+  st->print("ESI="); print_location(st, uc->uc_mcontext.gregs[ESI]);
+  st->print("EDI="); print_location(st, uc->uc_mcontext.gregs[EDI]);
+#endif
+
+  st->cr();
 }
 
 
--- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -387,8 +387,8 @@
   st->print(", RSI=" INTPTR_FORMAT, uc->Rsi);
   st->print(", RDI=" INTPTR_FORMAT, uc->Rdi);
   st->cr();
-  st->print(  "R8=" INTPTR_FORMAT,  uc->R8);
-  st->print(", R9=" INTPTR_FORMAT,  uc->R9);
+  st->print(  "R8 =" INTPTR_FORMAT, uc->R8);
+  st->print(", R9 =" INTPTR_FORMAT, uc->R9);
   st->print(", R10=" INTPTR_FORMAT, uc->R10);
   st->print(", R11=" INTPTR_FORMAT, uc->R11);
   st->cr();
@@ -399,62 +399,6 @@
   st->cr();
   st->print(  "RIP=" INTPTR_FORMAT, uc->Rip);
   st->print(", EFLAGS=" INTPTR_FORMAT, uc->EFlags);
-
-  st->cr();
-  st->cr();
-
-  st->print_cr("Register to memory mapping:");
-  st->cr();
-
-  // this is only for the "general purpose" registers
-
-  st->print_cr("RAX=" INTPTR_FORMAT, uc->Rax);
-  print_location(st, uc->Rax);
-  st->cr();
-  st->print_cr("RBX=" INTPTR_FORMAT, uc->Rbx);
-  print_location(st, uc->Rbx);
-  st->cr();
-  st->print_cr("RCX=" INTPTR_FORMAT, uc->Rcx);
-  print_location(st, uc->Rcx);
-  st->cr();
-  st->print_cr("RDX=" INTPTR_FORMAT, uc->Rdx);
-  print_location(st, uc->Rdx);
-  st->cr();
-  st->print_cr("RSP=" INTPTR_FORMAT, uc->Rsp);
-  print_location(st, uc->Rsp);
-  st->cr();
-  st->print_cr("RBP=" INTPTR_FORMAT, uc->Rbp);
-  print_location(st, uc->Rbp);
-  st->cr();
-  st->print_cr("RSI=" INTPTR_FORMAT, uc->Rsi);
-  print_location(st, uc->Rsi);
-  st->cr();
-  st->print_cr("RDI=" INTPTR_FORMAT, uc->Rdi);
-  print_location(st, uc->Rdi);
-  st->cr();
-  st->print_cr("R8 =" INTPTR_FORMAT, uc->R8);
-  print_location(st, uc->R8);
-  st->cr();
-  st->print_cr("R9 =" INTPTR_FORMAT, uc->R9);
-  print_location(st, uc->R9);
-  st->cr();
-  st->print_cr("R10=" INTPTR_FORMAT, uc->R10);
-  print_location(st, uc->R10);
-  st->cr();
-  st->print_cr("R11=" INTPTR_FORMAT, uc->R11);
-  print_location(st, uc->R11);
-  st->cr();
-  st->print_cr("R12=" INTPTR_FORMAT, uc->R12);
-  print_location(st, uc->R12);
-  st->cr();
-  st->print_cr("R13=" INTPTR_FORMAT, uc->R13);
-  print_location(st, uc->R13);
-  st->cr();
-  st->print_cr("R14=" INTPTR_FORMAT, uc->R14);
-  print_location(st, uc->R14);
-  st->cr();
-  st->print_cr("R15=" INTPTR_FORMAT, uc->R15);
-  print_location(st, uc->R15);
 #else
   st->print(  "EAX=" INTPTR_FORMAT, uc->Eax);
   st->print(", EBX=" INTPTR_FORMAT, uc->Ebx);
@@ -468,38 +412,6 @@
   st->cr();
   st->print(  "EIP=" INTPTR_FORMAT, uc->Eip);
   st->print(", EFLAGS=" INTPTR_FORMAT, uc->EFlags);
-
-  st->cr();
-  st->cr();
-
-  st->print_cr("Register to memory mapping:");
-  st->cr();
-
-  // this is only for the "general purpose" registers
-
-  st->print_cr("EAX=" INTPTR_FORMAT, uc->Eax);
-  print_location(st, uc->Eax);
-  st->cr();
-  st->print_cr("EBX=" INTPTR_FORMAT, uc->Ebx);
-  print_location(st, uc->Ebx);
-  st->cr();
-  st->print_cr("ECX=" INTPTR_FORMAT, uc->Ecx);
-  print_location(st, uc->Ecx);
-  st->cr();
-  st->print_cr("EDX=" INTPTR_FORMAT, uc->Edx);
-  print_location(st, uc->Edx);
-  st->cr();
-  st->print_cr("ESP=" INTPTR_FORMAT, uc->Esp);
-  print_location(st, uc->Esp);
-  st->cr();
-  st->print_cr("EBP=" INTPTR_FORMAT, uc->Ebp);
-  print_location(st, uc->Ebp);
-  st->cr();
-  st->print_cr("ESI=" INTPTR_FORMAT, uc->Esi);
-  print_location(st, uc->Esi);
-  st->cr();
-  st->print_cr("EDI=" INTPTR_FORMAT, uc->Edi);
-  print_location(st, uc->Edi);
 #endif // AMD64
   st->cr();
   st->cr();
@@ -514,7 +426,49 @@
   // this at the end, and hope for the best.
   address pc = (address)uc->REG_PC;
   st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
-  print_hex_dump(st, pc - 16, pc + 16, sizeof(char));
+  print_hex_dump(st, pc - 32, pc + 32, sizeof(char));
+  st->cr();
+}
+
+
+void os::print_register_info(outputStream *st, void *context) {
+  if (context == NULL) return;
+
+  CONTEXT* uc = (CONTEXT*)context;
+
+  st->print_cr("Register to memory mapping:");
+  st->cr();
+
+  // this is only for the "general purpose" registers
+
+#ifdef AMD64
+  st->print("RAX="); print_location(st, uc->Rax);
+  st->print("RBX="); print_location(st, uc->Rbx);
+  st->print("RCX="); print_location(st, uc->Rcx);
+  st->print("RDX="); print_location(st, uc->Rdx);
+  st->print("RSP="); print_location(st, uc->Rsp);
+  st->print("RBP="); print_location(st, uc->Rbp);
+  st->print("RSI="); print_location(st, uc->Rsi);
+  st->print("RDI="); print_location(st, uc->Rdi);
+  st->print("R8 ="); print_location(st, uc->R8);
+  st->print("R9 ="); print_location(st, uc->R9);
+  st->print("R10="); print_location(st, uc->R10);
+  st->print("R11="); print_location(st, uc->R11);
+  st->print("R12="); print_location(st, uc->R12);
+  st->print("R13="); print_location(st, uc->R13);
+  st->print("R14="); print_location(st, uc->R14);
+  st->print("R15="); print_location(st, uc->R15);
+#else
+  st->print("EAX="); print_location(st, uc->Eax);
+  st->print("EBX="); print_location(st, uc->Ebx);
+  st->print("ECX="); print_location(st, uc->Ecx);
+  st->print("EDX="); print_location(st, uc->Edx);
+  st->print("ESP="); print_location(st, uc->Esp);
+  st->print("EBP="); print_location(st, uc->Ebp);
+  st->print("ESI="); print_location(st, uc->Esi);
+  st->print("EDI="); print_location(st, uc->Edi);
+#endif
+
   st->cr();
 }
 
--- a/hotspot/src/share/vm/c1/c1_Compilation.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compilation.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -178,15 +178,11 @@
     return (int) NMethodSizeLimit;  // default 256K or 512K
 #else
     // conditional branches on PPC are restricted to 16 bit signed
-    return MAX2((unsigned int)NMethodSizeLimit,32*K);
+    return MIN2((unsigned int)NMethodSizeLimit,32*K);
 #endif
   }
   static int desired_max_constant_size() {
-#ifndef PPC
-    return (int) NMethodSizeLimit / 10;  // about 25K
-#else
-    return (MAX2((unsigned int)NMethodSizeLimit, 32*K)) / 10;
-#endif
+    return desired_max_code_buffer_size() / 10;
   }
 
   static void setup_code_buffer(CodeBuffer* cb, int call_stub_estimate);
--- a/hotspot/src/share/vm/c1/c1_IR.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_IR.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -321,7 +321,7 @@
   void visit(Value* n) {
     // Local instructions and Phis for expression stack values at the
     // start of basic blocks are not added to the instruction list
-    if (!(*n)->is_linked()&& (*n)->can_be_linked()) {
+    if (!(*n)->is_linked() && (*n)->can_be_linked()) {
       assert(false, "a node was not appended to the graph");
       Compilation::current()->bailout("a node was not appended to the graph");
     }
--- a/hotspot/src/share/vm/c1/c1_Instruction.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Instruction.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -415,28 +415,26 @@
   return false;
 }
 
-
-BlockBegin* Constant::compare(Instruction::Condition cond, Value right,
-                              BlockBegin* true_sux, BlockBegin* false_sux) {
+Constant::CompareResult Constant::compare(Instruction::Condition cond, Value right) const {
   Constant* rc = right->as_Constant();
   // other is not a constant
-  if (rc == NULL) return NULL;
+  if (rc == NULL) return not_comparable;
 
   ValueType* lt = type();
   ValueType* rt = rc->type();
   // different types
-  if (lt->base() != rt->base()) return NULL;
+  if (lt->base() != rt->base()) return not_comparable;
   switch (lt->tag()) {
   case intTag: {
     int x = lt->as_IntConstant()->value();
     int y = rt->as_IntConstant()->value();
     switch (cond) {
-    case If::eql: return x == y ? true_sux : false_sux;
-    case If::neq: return x != y ? true_sux : false_sux;
-    case If::lss: return x <  y ? true_sux : false_sux;
-    case If::leq: return x <= y ? true_sux : false_sux;
-    case If::gtr: return x >  y ? true_sux : false_sux;
-    case If::geq: return x >= y ? true_sux : false_sux;
+    case If::eql: return x == y ? cond_true : cond_false;
+    case If::neq: return x != y ? cond_true : cond_false;
+    case If::lss: return x <  y ? cond_true : cond_false;
+    case If::leq: return x <= y ? cond_true : cond_false;
+    case If::gtr: return x >  y ? cond_true : cond_false;
+    case If::geq: return x >= y ? cond_true : cond_false;
     }
     break;
   }
@@ -444,12 +442,12 @@
     jlong x = lt->as_LongConstant()->value();
     jlong y = rt->as_LongConstant()->value();
     switch (cond) {
-    case If::eql: return x == y ? true_sux : false_sux;
-    case If::neq: return x != y ? true_sux : false_sux;
-    case If::lss: return x <  y ? true_sux : false_sux;
-    case If::leq: return x <= y ? true_sux : false_sux;
-    case If::gtr: return x >  y ? true_sux : false_sux;
-    case If::geq: return x >= y ? true_sux : false_sux;
+    case If::eql: return x == y ? cond_true : cond_false;
+    case If::neq: return x != y ? cond_true : cond_false;
+    case If::lss: return x <  y ? cond_true : cond_false;
+    case If::leq: return x <= y ? cond_true : cond_false;
+    case If::gtr: return x >  y ? cond_true : cond_false;
+    case If::geq: return x >= y ? cond_true : cond_false;
     }
     break;
   }
@@ -459,14 +457,14 @@
     assert(xvalue != NULL && yvalue != NULL, "not constants");
     if (xvalue->is_loaded() && yvalue->is_loaded()) {
       switch (cond) {
-      case If::eql: return xvalue == yvalue ? true_sux : false_sux;
-      case If::neq: return xvalue != yvalue ? true_sux : false_sux;
+      case If::eql: return xvalue == yvalue ? cond_true : cond_false;
+      case If::neq: return xvalue != yvalue ? cond_true : cond_false;
       }
     }
     break;
   }
   }
-  return NULL;
+  return not_comparable;
 }
 
 
--- a/hotspot/src/share/vm/c1/c1_Instruction.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -443,7 +443,7 @@
 
   // generic
   virtual Instruction*      as_Instruction()     { return this; } // to satisfy HASHING1 macro
-  virtual Phi*           as_Phi()          { return NULL; }
+  virtual Phi*              as_Phi()             { return NULL; }
   virtual Local*            as_Local()           { return NULL; }
   virtual Constant*         as_Constant()        { return NULL; }
   virtual AccessField*      as_AccessField()     { return NULL; }
@@ -650,8 +650,24 @@
   virtual intx hash() const;
   virtual bool is_equal(Value v) const;
 
-  virtual BlockBegin* compare(Instruction::Condition condition, Value right,
-                              BlockBegin* true_sux, BlockBegin* false_sux);
+
+  enum CompareResult { not_comparable = -1, cond_false, cond_true };
+
+  virtual CompareResult compare(Instruction::Condition condition, Value right) const;
+  BlockBegin* compare(Instruction::Condition cond, Value right,
+                      BlockBegin* true_sux, BlockBegin* false_sux) const {
+    switch (compare(cond, right)) {
+    case not_comparable:
+      return NULL;
+    case cond_false:
+      return false_sux;
+    case cond_true:
+      return true_sux;
+    default:
+      ShouldNotReachHere();
+      return NULL;
+    }
+  }
 };
 
 
--- a/hotspot/src/share/vm/c1/c1_Optimizer.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Optimizer.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -38,18 +38,20 @@
  private:
   IR* _hir;
   int _cee_count;                                // the number of CEs successfully eliminated
+  int _ifop_count;                               // the number of IfOps successfully simplified
   int _has_substitution;
 
  public:
-  CE_Eliminator(IR* hir) : _cee_count(0), _hir(hir) {
+  CE_Eliminator(IR* hir) : _cee_count(0), _ifop_count(0), _hir(hir) {
     _has_substitution = false;
     _hir->iterate_preorder(this);
     if (_has_substitution) {
-      // substituted some phis so resolve the substitution
+      // substituted some ifops/phis, so resolve the substitution
       SubstitutionResolver sr(_hir);
     }
   }
   int cee_count() const                          { return _cee_count; }
+  int ifop_count() const                         { return _ifop_count; }
 
   void adjust_exception_edges(BlockBegin* block, BlockBegin* sux) {
     int e = sux->number_of_exception_handlers();
@@ -68,156 +70,214 @@
     }
   }
 
-  virtual void block_do(BlockBegin* block) {
-    // 1) find conditional expression
-    // check if block ends with an If
-    If* if_ = block->end()->as_If();
-    if (if_ == NULL) return;
+  virtual void block_do(BlockBegin* block);
+
+ private:
+  Value make_ifop(Value x, Instruction::Condition cond, Value y, Value tval, Value fval);
+};
 
-    // check if If works on int or object types
-    // (we cannot handle If's working on long, float or doubles yet,
-    // since IfOp doesn't support them - these If's show up if cmp
-    // operations followed by If's are eliminated)
-    ValueType* if_type = if_->x()->type();
-    if (!if_type->is_int() && !if_type->is_object()) return;
+void CE_Eliminator::block_do(BlockBegin* block) {
+  // 1) find conditional expression
+  // check if block ends with an If
+  If* if_ = block->end()->as_If();
+  if (if_ == NULL) return;
 
-    BlockBegin* t_block = if_->tsux();
-    BlockBegin* f_block = if_->fsux();
-    Instruction* t_cur = t_block->next();
-    Instruction* f_cur = f_block->next();
+  // check if If works on int or object types
+  // (we cannot handle If's working on long, float or doubles yet,
+  // since IfOp doesn't support them - these If's show up if cmp
+  // operations followed by If's are eliminated)
+  ValueType* if_type = if_->x()->type();
+  if (!if_type->is_int() && !if_type->is_object()) return;
 
-    // one Constant may be present between BlockBegin and BlockEnd
-    Value t_const = NULL;
-    Value f_const = NULL;
-    if (t_cur->as_Constant() != NULL && !t_cur->can_trap()) {
-      t_const = t_cur;
-      t_cur = t_cur->next();
-    }
-    if (f_cur->as_Constant() != NULL && !f_cur->can_trap()) {
-      f_const = f_cur;
-      f_cur = f_cur->next();
-    }
+  BlockBegin* t_block = if_->tsux();
+  BlockBegin* f_block = if_->fsux();
+  Instruction* t_cur = t_block->next();
+  Instruction* f_cur = f_block->next();
 
-    // check if both branches end with a goto
-    Goto* t_goto = t_cur->as_Goto();
-    if (t_goto == NULL) return;
-    Goto* f_goto = f_cur->as_Goto();
-    if (f_goto == NULL) return;
+  // one Constant may be present between BlockBegin and BlockEnd
+  Value t_const = NULL;
+  Value f_const = NULL;
+  if (t_cur->as_Constant() != NULL && !t_cur->can_trap()) {
+    t_const = t_cur;
+    t_cur = t_cur->next();
+  }
+  if (f_cur->as_Constant() != NULL && !f_cur->can_trap()) {
+    f_const = f_cur;
+    f_cur = f_cur->next();
+  }
 
-    // check if both gotos merge into the same block
-    BlockBegin* sux = t_goto->default_sux();
-    if (sux != f_goto->default_sux()) return;
+  // check if both branches end with a goto
+  Goto* t_goto = t_cur->as_Goto();
+  if (t_goto == NULL) return;
+  Goto* f_goto = f_cur->as_Goto();
+  if (f_goto == NULL) return;
 
-    // check if at least one word was pushed on sux_state
-    ValueStack* sux_state = sux->state();
-    if (sux_state->stack_size() <= if_->state()->stack_size()) return;
+  // check if both gotos merge into the same block
+  BlockBegin* sux = t_goto->default_sux();
+  if (sux != f_goto->default_sux()) return;
 
-    // check if phi function is present at end of successor stack and that
-    // only this phi was pushed on the stack
-    Value sux_phi = sux_state->stack_at(if_->state()->stack_size());
-    if (sux_phi == NULL || sux_phi->as_Phi() == NULL || sux_phi->as_Phi()->block() != sux) return;
-    if (sux_phi->type()->size() != sux_state->stack_size() - if_->state()->stack_size()) return;
-
-    // get the values that were pushed in the true- and false-branch
-    Value t_value = t_goto->state()->stack_at(if_->state()->stack_size());
-    Value f_value = f_goto->state()->stack_at(if_->state()->stack_size());
+  // check if at least one word was pushed on sux_state
+  ValueStack* sux_state = sux->state();
+  if (sux_state->stack_size() <= if_->state()->stack_size()) return;
 
-    // backend does not support floats
-    assert(t_value->type()->base() == f_value->type()->base(), "incompatible types");
-    if (t_value->type()->is_float_kind()) return;
+  // check if phi function is present at end of successor stack and that
+  // only this phi was pushed on the stack
+  Value sux_phi = sux_state->stack_at(if_->state()->stack_size());
+  if (sux_phi == NULL || sux_phi->as_Phi() == NULL || sux_phi->as_Phi()->block() != sux) return;
+  if (sux_phi->type()->size() != sux_state->stack_size() - if_->state()->stack_size()) return;
 
-    // check that successor has no other phi functions but sux_phi
-    // this can happen when t_block or f_block contained additonal stores to local variables
-    // that are no longer represented by explicit instructions
-    for_each_phi_fun(sux, phi,
-                     if (phi != sux_phi) return;
-                     );
-    // true and false blocks can't have phis
-    for_each_phi_fun(t_block, phi, return; );
-    for_each_phi_fun(f_block, phi, return; );
+  // get the values that were pushed in the true- and false-branch
+  Value t_value = t_goto->state()->stack_at(if_->state()->stack_size());
+  Value f_value = f_goto->state()->stack_at(if_->state()->stack_size());
+
+  // backend does not support floats
+  assert(t_value->type()->base() == f_value->type()->base(), "incompatible types");
+  if (t_value->type()->is_float_kind()) return;
 
-    // 2) substitute conditional expression
-    //    with an IfOp followed by a Goto
-    // cut if_ away and get node before
-    Instruction* cur_end = if_->prev(block);
+  // check that successor has no other phi functions but sux_phi
+  // this can happen when t_block or f_block contained additonal stores to local variables
+  // that are no longer represented by explicit instructions
+  for_each_phi_fun(sux, phi,
+                   if (phi != sux_phi) return;
+                   );
+  // true and false blocks can't have phis
+  for_each_phi_fun(t_block, phi, return; );
+  for_each_phi_fun(f_block, phi, return; );
+
+  // 2) substitute conditional expression
+  //    with an IfOp followed by a Goto
+  // cut if_ away and get node before
+  Instruction* cur_end = if_->prev(block);
 
-    // append constants of true- and false-block if necessary
-    // clone constants because original block must not be destroyed
-    assert((t_value != f_const && f_value != t_const) || t_const == f_const, "mismatch");
-    if (t_value == t_const) {
-      t_value = new Constant(t_const->type());
-      NOT_PRODUCT(t_value->set_printable_bci(if_->printable_bci()));
-      cur_end = cur_end->set_next(t_value);
-    }
-    if (f_value == f_const) {
-      f_value = new Constant(f_const->type());
-      NOT_PRODUCT(f_value->set_printable_bci(if_->printable_bci()));
-      cur_end = cur_end->set_next(f_value);
-    }
+  // append constants of true- and false-block if necessary
+  // clone constants because original block must not be destroyed
+  assert((t_value != f_const && f_value != t_const) || t_const == f_const, "mismatch");
+  if (t_value == t_const) {
+    t_value = new Constant(t_const->type());
+    NOT_PRODUCT(t_value->set_printable_bci(if_->printable_bci()));
+    cur_end = cur_end->set_next(t_value);
+  }
+  if (f_value == f_const) {
+    f_value = new Constant(f_const->type());
+    NOT_PRODUCT(f_value->set_printable_bci(if_->printable_bci()));
+    cur_end = cur_end->set_next(f_value);
+  }
 
-    // it is very unlikely that the condition can be statically decided
-    // (this was checked previously by the Canonicalizer), so always
-    // append IfOp
-    Value result = new IfOp(if_->x(), if_->cond(), if_->y(), t_value, f_value);
+  Value result = make_ifop(if_->x(), if_->cond(), if_->y(), t_value, f_value);
+  assert(result != NULL, "make_ifop must return a non-null instruction");
+  if (!result->is_linked() && result->can_be_linked()) {
     NOT_PRODUCT(result->set_printable_bci(if_->printable_bci()));
     cur_end = cur_end->set_next(result);
+  }
 
-    // append Goto to successor
-    ValueStack* state_before = if_->is_safepoint() ? if_->state_before() : NULL;
-    Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint());
+  // append Goto to successor
+  ValueStack* state_before = if_->is_safepoint() ? if_->state_before() : NULL;
+  Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint());
+
+  // prepare state for Goto
+  ValueStack* goto_state = if_->state();
+  while (sux_state->scope() != goto_state->scope()) {
+    goto_state = goto_state->caller_state();
+    assert(goto_state != NULL, "states do not match up");
+  }
+  goto_state = goto_state->copy(ValueStack::StateAfter, goto_state->bci());
+  goto_state->push(result->type(), result);
+  assert(goto_state->is_same(sux_state), "states must match now");
+  goto_->set_state(goto_state);
+
+  cur_end = cur_end->set_next(goto_, goto_state->bci());
+
+  // Adjust control flow graph
+  BlockBegin::disconnect_edge(block, t_block);
+  BlockBegin::disconnect_edge(block, f_block);
+  if (t_block->number_of_preds() == 0) {
+    BlockBegin::disconnect_edge(t_block, sux);
+  }
+  adjust_exception_edges(block, t_block);
+  if (f_block->number_of_preds() == 0) {
+    BlockBegin::disconnect_edge(f_block, sux);
+  }
+  adjust_exception_edges(block, f_block);
+
+  // update block end
+  block->set_end(goto_);
+
+  // substitute the phi if possible
+  if (sux_phi->as_Phi()->operand_count() == 1) {
+    assert(sux_phi->as_Phi()->operand_at(0) == result, "screwed up phi");
+    sux_phi->set_subst(result);
+    _has_substitution = true;
+  }
+
+  // 3) successfully eliminated a conditional expression
+  _cee_count++;
+  if (PrintCEE) {
+    tty->print_cr("%d. CEE in B%d (B%d B%d)", cee_count(), block->block_id(), t_block->block_id(), f_block->block_id());
+    tty->print_cr("%d. IfOp in B%d", ifop_count(), block->block_id());
+  }
 
-    // prepare state for Goto
-    ValueStack* goto_state = if_->state();
-    while (sux_state->scope() != goto_state->scope()) {
-      goto_state = goto_state->caller_state();
-      assert(goto_state != NULL, "states do not match up");
-    }
-    goto_state = goto_state->copy(ValueStack::StateAfter, goto_state->bci());
-    goto_state->push(result->type(), result);
-    assert(goto_state->is_same(sux_state), "states must match now");
-    goto_->set_state(goto_state);
+  _hir->verify();
+}
+
+Value CE_Eliminator::make_ifop(Value x, Instruction::Condition cond, Value y, Value tval, Value fval) {
+  if (!OptimizeIfOps) {
+    return new IfOp(x, cond, y, tval, fval);
+  }
+
+  tval = tval->subst();
+  fval = fval->subst();
+  if (tval == fval) {
+    _ifop_count++;
+    return tval;
+  }
+
+  x = x->subst();
+  y = y->subst();
+
+  Constant* y_const = y->as_Constant();
+  if (y_const != NULL) {
+    IfOp* x_ifop = x->as_IfOp();
+    if (x_ifop != NULL) {                 // x is an ifop, y is a constant
+      Constant* x_tval_const = x_ifop->tval()->subst()->as_Constant();
+      Constant* x_fval_const = x_ifop->fval()->subst()->as_Constant();
 
-    cur_end = cur_end->set_next(goto_, goto_state->bci());
+      if (x_tval_const != NULL && x_fval_const != NULL) {
+        Instruction::Condition x_ifop_cond = x_ifop->cond();
+
+        Constant::CompareResult t_compare_res = x_tval_const->compare(cond, y_const);
+        Constant::CompareResult f_compare_res = x_fval_const->compare(cond, y_const);
+
+        guarantee(t_compare_res != Constant::not_comparable && f_compare_res != Constant::not_comparable, "incomparable constants in IfOp");
+
+        Value new_tval = t_compare_res == Constant::cond_true ? tval : fval;
+        Value new_fval = f_compare_res == Constant::cond_true ? tval : fval;
 
-    // Adjust control flow graph
-    BlockBegin::disconnect_edge(block, t_block);
-    BlockBegin::disconnect_edge(block, f_block);
-    if (t_block->number_of_preds() == 0) {
-      BlockBegin::disconnect_edge(t_block, sux);
+        _ifop_count++;
+        if (new_tval == new_fval) {
+          return new_tval;
+        } else {
+          return new IfOp(x_ifop->x(), x_ifop_cond, x_ifop->y(), new_tval, new_fval);
+        }
+      }
+    } else {
+      Constant* x_const = x->as_Constant();
+      if (x_const != NULL) {         // x and y are constants
+        Constant::CompareResult x_compare_res = x_const->compare(cond, y_const);
+        guarantee(x_compare_res != Constant::not_comparable, "incomparable constants in IfOp");
+
+        _ifop_count++;
+        return x_compare_res == Constant::cond_true ? tval : fval;
+      }
     }
-    adjust_exception_edges(block, t_block);
-    if (f_block->number_of_preds() == 0) {
-      BlockBegin::disconnect_edge(f_block, sux);
-    }
-    adjust_exception_edges(block, f_block);
-
-    // update block end
-    block->set_end(goto_);
-
-    // substitute the phi if possible
-    if (sux_phi->as_Phi()->operand_count() == 1) {
-      assert(sux_phi->as_Phi()->operand_at(0) == result, "screwed up phi");
-      sux_phi->set_subst(result);
-      _has_substitution = true;
-    }
-
-    // 3) successfully eliminated a conditional expression
-    _cee_count++;
-    if (PrintCEE) {
-      tty->print_cr("%d. CEE in B%d (B%d B%d)", cee_count(), block->block_id(), t_block->block_id(), f_block->block_id());
-    }
-
-    _hir->verify();
   }
-};
-
+  return new IfOp(x, cond, y, tval, fval);
+}
 
 void Optimizer::eliminate_conditional_expressions() {
   // find conditional expressions & replace them with IfOps
   CE_Eliminator ce(ir());
 }
 
-
 class BlockMerger: public BlockClosure {
  private:
   IR* _hir;
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -107,7 +107,6 @@
     RegisterMap reg_map(thread, false);
     frame runtime_frame = thread->last_frame();
     frame caller_frame = runtime_frame.sender(&reg_map);
-    // bypass VM_DeoptimizeFrame and deoptimize the frame directly
     Deoptimization::deoptimize_frame(thread, caller_frame.id());
     assert(caller_is_deopted(), "Must be deoptimized");
   }
@@ -368,8 +367,7 @@
     if (osr_nm != NULL) {
       RegisterMap map(thread, false);
       frame fr =  thread->last_frame().sender(&map);
-      VM_DeoptimizeFrame deopt(thread, fr.id());
-      VMThread::execute(&deopt);
+      Deoptimization::deoptimize_frame(thread, fr.id());
     }
   JRT_BLOCK_END
   return NULL;
@@ -441,8 +439,8 @@
     // We don't really want to deoptimize the nmethod itself since we
     // can actually continue in the exception handler ourselves but I
     // don't see an easy way to have the desired effect.
-    VM_DeoptimizeFrame deopt(thread, caller_frame.id());
-    VMThread::execute(&deopt);
+    Deoptimization::deoptimize_frame(thread, caller_frame.id());
+    assert(caller_is_deopted(), "Must be deoptimized");
 
     return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls();
   }
@@ -835,8 +833,7 @@
       nm->make_not_entrant();
     }
 
-    VM_DeoptimizeFrame deopt(thread, caller_frame.id());
-    VMThread::execute(&deopt);
+    Deoptimization::deoptimize_frame(thread, caller_frame.id());
 
     // Return to the now deoptimized frame.
   }
--- a/hotspot/src/share/vm/c1/c1_globals.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_globals.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -75,6 +75,9 @@
   develop(bool, SelectivePhiFunctions, true,                                \
           "create phi functions at loop headers only when necessary")       \
                                                                             \
+  develop(bool, OptimizeIfOps, true,                                        \
+          "Optimize multiple IfOps")                                        \
+                                                                            \
   develop(bool, DoCEE, true,                                                \
           "Do Conditional Expression Elimination to simplify CFG")          \
                                                                             \
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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,12 @@
   unsigned int hashValues[SymbolTable::symbol_alloc_batch_size];
   int names_count = 0;
 
+  // Side buffer for operands of variable-sized (InvokeDynamic) entries.
+  GrowableArray<int>* operands = NULL;
+#ifdef ASSERT
+  GrowableArray<int>* indy_instructions = new GrowableArray<int>(THREAD, 10);
+#endif
+
   // parsing  Index 0 is unused
   for (int index = 1; index < length; index++) {
     // Each of the following case guarantees one more byte in the stream
@@ -141,6 +147,7 @@
           ShouldNotReachHere();
         }
         break;
+      case JVM_CONSTANT_InvokeDynamicTrans :  // this tag appears only in old classfiles
       case JVM_CONSTANT_InvokeDynamic :
         {
           if (!EnableInvokeDynamic ||
@@ -151,10 +158,36 @@
                "Class file version does not support constant tag %u in class file %s"),
               tag, CHECK);
           }
-          cfs->guarantee_more(5, CHECK);  // bsm_index, name_and_type_index, tag/access_flags
+          if (!AllowTransitionalJSR292 && tag == JVM_CONSTANT_InvokeDynamicTrans) {
+            classfile_parse_error(
+                "This JVM does not support transitional InvokeDynamic tag %u in class file %s",
+                tag, CHECK);
+          }
+          bool trans_no_argc = AllowTransitionalJSR292 && (tag == JVM_CONSTANT_InvokeDynamicTrans);
+          cfs->guarantee_more(7, CHECK);  // bsm_index, nt, argc, ..., tag/access_flags
           u2 bootstrap_method_index = cfs->get_u2_fast();
           u2 name_and_type_index = cfs->get_u2_fast();
-          cp->invoke_dynamic_at_put(index, bootstrap_method_index, name_and_type_index);
+          int argument_count = trans_no_argc ? 0 : cfs->get_u2_fast();
+          cfs->guarantee_more(2*argument_count + 1, CHECK);  // argv[argc]..., tag/access_flags
+          int argv_offset = constantPoolOopDesc::_indy_argv_offset;
+          int op_count = argv_offset + argument_count;  // bsm, nt, argc, argv[]...
+          int op_base = start_operand_group(operands, op_count, CHECK);
+          assert(argv_offset == 3, "else adjust next 3 assignments");
+          operands->at_put(op_base + constantPoolOopDesc::_indy_bsm_offset, bootstrap_method_index);
+          operands->at_put(op_base + constantPoolOopDesc::_indy_nt_offset, name_and_type_index);
+          operands->at_put(op_base + constantPoolOopDesc::_indy_argc_offset, argument_count);
+          for (int arg_i = 0; arg_i < argument_count; arg_i++) {
+            int arg = cfs->get_u2_fast();
+            operands->at_put(op_base + constantPoolOopDesc::_indy_argv_offset + arg_i, arg);
+          }
+          cp->invoke_dynamic_at_put(index, op_base, op_count);
+#ifdef ASSERT
+          // Record the steps just taken for later checking.
+          indy_instructions->append(index);
+          indy_instructions->append(bootstrap_method_index);
+          indy_instructions->append(name_and_type_index);
+          indy_instructions->append(argument_count);
+#endif //ASSERT
         }
         break;
       case JVM_CONSTANT_Integer :
@@ -257,6 +290,23 @@
     oopFactory::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK);
   }
 
+  if (operands != NULL && operands->length() > 0) {
+    store_operand_array(operands, cp, CHECK);
+  }
+#ifdef ASSERT
+  // Re-assert the indy structures, now that assertion checking can work.
+  for (int indy_i = 0; indy_i < indy_instructions->length(); ) {
+    int index                  = indy_instructions->at(indy_i++);
+    int bootstrap_method_index = indy_instructions->at(indy_i++);
+    int name_and_type_index    = indy_instructions->at(indy_i++);
+    int argument_count         = indy_instructions->at(indy_i++);
+    assert(cp->check_invoke_dynamic_at(index,
+                                       bootstrap_method_index, name_and_type_index,
+                                       argument_count),
+           "indy structure is OK");
+  }
+#endif //ASSERT
+
   // Copy _current pointer of local copy back to stream().
 #ifdef ASSERT
   assert(cfs0->current() == old_current, "non-exclusive use of stream()");
@@ -264,6 +314,41 @@
   cfs0->set_current(cfs1.current());
 }
 
+int ClassFileParser::start_operand_group(GrowableArray<int>* &operands, int op_count, TRAPS) {
+  if (operands == NULL) {
+    operands = new GrowableArray<int>(THREAD, 100);
+    int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset;
+    while (operands->length() <= fillp_offset)
+      operands->append(0);  // force op_base > 0, for an error check
+    DEBUG_ONLY(operands->at_put(fillp_offset, (int)badHeapWordVal));
+  }
+  int cnt_pos = operands->append(op_count);
+  int arg_pos = operands->length();
+  operands->at_grow(arg_pos + op_count - 1);  // grow to include the operands
+  assert(operands->length() == arg_pos + op_count, "");
+  int op_base = cnt_pos - constantPoolOopDesc::_multi_operand_count_offset;
+  return op_base;
+}
+
+void ClassFileParser::store_operand_array(GrowableArray<int>* operands, constantPoolHandle cp, TRAPS) {
+  // Collect the buffer of operands from variable-sized entries into a permanent array.
+  int arraylen = operands->length();
+  int fillp_offset = constantPoolOopDesc::_multi_operand_buffer_fill_pointer_offset;
+  assert(operands->at(fillp_offset) == (int)badHeapWordVal, "value unused so far");
+  operands->at_put(fillp_offset, arraylen);
+  cp->multi_operand_buffer_grow(arraylen, CHECK);
+  typeArrayOop operands_oop = cp->operands();
+  assert(operands_oop->length() == arraylen, "");
+  for (int i = 0; i < arraylen; i++) {
+    operands_oop->int_at_put(i, operands->at(i));
+  }
+  cp->set_operands(operands_oop);
+  // The fill_pointer is used only by constantPoolOop::copy_entry_to and friends,
+  // when constant pools need to be merged.  Make sure it is sane now.
+  assert(cp->multi_operand_buffer_fill_pointer() == arraylen, "");
+}
+
+
 bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); }
 
 constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
@@ -431,6 +516,8 @@
               ref_index, CHECK_(nullHandle));
         }
         break;
+      case JVM_CONSTANT_InvokeDynamicTrans :
+        ShouldNotReachHere();  // this tag does not appear in the heap
       case JVM_CONSTANT_InvokeDynamic :
         {
           int bootstrap_method_ref_index = cp->invoke_dynamic_bootstrap_method_ref_index_at(index);
@@ -438,7 +525,7 @@
           check_property((bootstrap_method_ref_index == 0 && AllowTransitionalJSR292)
                          ||
                          (valid_cp_range(bootstrap_method_ref_index, length) &&
-                          cp->tag_at(bootstrap_method_ref_index).is_method_handle()),
+                          (cp->tag_at(bootstrap_method_ref_index).is_method_handle())),
                          "Invalid constant pool index %u in class file %s",
                          bootstrap_method_ref_index,
                          CHECK_(nullHandle));
@@ -447,6 +534,18 @@
                          "Invalid constant pool index %u in class file %s",
                          name_and_type_ref_index,
                          CHECK_(nullHandle));
+          int argc = cp->invoke_dynamic_argument_count_at(index);
+          for (int arg_i = 0; arg_i < argc; arg_i++) {
+            int arg = cp->invoke_dynamic_argument_index_at(index, arg_i);
+            check_property(valid_cp_range(arg, length) &&
+                           cp->tag_at(arg).is_loadable_constant() ||
+                           // temporary early forms of string and class:
+                           cp->tag_at(arg).is_klass_index() ||
+                           cp->tag_at(arg).is_string_index(),
+                           "Invalid constant pool index %u in class file %s",
+                           arg,
+                           CHECK_(nullHandle));
+          }
           break;
         }
       default:
@@ -2516,18 +2615,6 @@
   // field.  If it is not present, artifically create a field for it.
   // This allows this VM to run on early JDK where the field is not
   // present.
-
-  //
-  // Increment fac.nonstatic_oop_count so that the start of the
-  // next type of non-static oops leaves room for the fake oop.
-  // Do not increment next_nonstatic_oop_offset so that the
-  // fake oop is place after the java.lang.ref.Reference oop
-  // fields.
-  //
-  // Check the fields in java.lang.ref.Reference for the "discovered"
-  // field.  If it is not present, artifically create a field for it.
-  // This allows this VM to run on early JDK where the field is not
-  // present.
   int reference_sig_index = 0;
   int reference_name_index = 0;
   int reference_index = 0;
@@ -2663,7 +2750,7 @@
 // Force MethodHandle.vmentry to be an unmanaged pointer.
 // There is no way for a classfile to express this, so we must help it.
 void ClassFileParser::java_dyn_MethodHandle_fix_pre(constantPoolHandle cp,
-                                                    typeArrayHandle* fields_ptr,
+                                                    typeArrayHandle fields,
                                                     FieldAllocationCount *fac_ptr,
                                                     TRAPS) {
   // Add fake fields for java.dyn.MethodHandle instances
@@ -2687,41 +2774,45 @@
     THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
               "missing I or J signature (for vmentry) in java.dyn.MethodHandle");
 
+  // Find vmentry field and change the signature.
   bool found_vmentry = false;
-
-  const int n = (*fields_ptr)()->length();
-  for (int i = 0; i < n; i += instanceKlass::next_offset) {
-    int name_index = (*fields_ptr)->ushort_at(i + instanceKlass::name_index_offset);
-    int sig_index  = (*fields_ptr)->ushort_at(i + instanceKlass::signature_index_offset);
-    int acc_flags  = (*fields_ptr)->ushort_at(i + instanceKlass::access_flags_offset);
+  for (int i = 0; i < fields->length(); i += instanceKlass::next_offset) {
+    int name_index = fields->ushort_at(i + instanceKlass::name_index_offset);
+    int sig_index  = fields->ushort_at(i + instanceKlass::signature_index_offset);
+    int acc_flags  = fields->ushort_at(i + instanceKlass::access_flags_offset);
     symbolOop f_name = cp->symbol_at(name_index);
     symbolOop f_sig  = cp->symbol_at(sig_index);
-    if (f_sig == vmSymbols::byte_signature() &&
-        f_name == vmSymbols::vmentry_name() &&
-        (acc_flags & JVM_ACC_STATIC) == 0) {
-      // Adjust the field type from byte to an unmanaged pointer.
-      assert(fac_ptr->nonstatic_byte_count > 0, "");
-      fac_ptr->nonstatic_byte_count -= 1;
-
-      (*fields_ptr)->ushort_at_put(i + instanceKlass::signature_index_offset, word_sig_index);
-      assert(wordSize == longSize || wordSize == jintSize, "ILP32 or LP64");
-      if (wordSize == longSize)  fac_ptr->nonstatic_double_count += 1;
-      else                       fac_ptr->nonstatic_word_count   += 1;
-
-      FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i + instanceKlass::low_offset);
-      assert(atype == NONSTATIC_BYTE, "");
-      FieldAllocationType new_atype = (wordSize == longSize) ? NONSTATIC_DOUBLE : NONSTATIC_WORD;
-      (*fields_ptr)->ushort_at_put(i + instanceKlass::low_offset, new_atype);
-
-      found_vmentry = true;
-      break;
+
+    if (f_name == vmSymbols::vmentry_name() && (acc_flags & JVM_ACC_STATIC) == 0) {
+      if (f_sig == vmSymbols::machine_word_signature()) {
+        // If the signature of vmentry is already changed, we're done.
+        found_vmentry = true;
+        break;
+      }
+      else if (f_sig == vmSymbols::byte_signature()) {
+        // Adjust the field type from byte to an unmanaged pointer.
+        assert(fac_ptr->nonstatic_byte_count > 0, "");
+        fac_ptr->nonstatic_byte_count -= 1;
+
+        fields->ushort_at_put(i + instanceKlass::signature_index_offset, word_sig_index);
+        assert(wordSize == longSize || wordSize == jintSize, "ILP32 or LP64");
+        if (wordSize == longSize)  fac_ptr->nonstatic_double_count += 1;
+        else                       fac_ptr->nonstatic_word_count   += 1;
+
+        FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset);
+        assert(atype == NONSTATIC_BYTE, "");
+        FieldAllocationType new_atype = (wordSize == longSize) ? NONSTATIC_DOUBLE : NONSTATIC_WORD;
+        fields->ushort_at_put(i + instanceKlass::low_offset, new_atype);
+
+        found_vmentry = true;
+        break;
+      }
     }
   }
 
   if (!found_vmentry)
     THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
               "missing vmentry byte field in java.dyn.MethodHandle");
-
 }
 
 
@@ -3082,7 +3173,7 @@
 
     // adjust the vmentry field declaration in java.dyn.MethodHandle
     if (EnableMethodHandles && class_name() == vmSymbols::sun_dyn_MethodHandleImpl() && class_loader.is_null()) {
-      java_dyn_MethodHandle_fix_pre(cp, &fields, &fac, CHECK_(nullHandle));
+      java_dyn_MethodHandle_fix_pre(cp, fields, &fac, CHECK_(nullHandle));
     }
 
     // Add a fake "discovered" field if it is not present
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -56,6 +56,9 @@
 
   constantPoolHandle parse_constant_pool(TRAPS);
 
+  static int start_operand_group(GrowableArray<int>* &operands, int op_count, TRAPS);
+  static void store_operand_array(GrowableArray<int>* operands, constantPoolHandle cp, TRAPS);
+
   // Interface parsing
   objArrayHandle parse_interfaces(constantPoolHandle cp,
                                   int length,
@@ -151,7 +154,7 @@
   // Adjust the field allocation counts for java.dyn.MethodHandle to add
   // a fake address (void*) field.
   void java_dyn_MethodHandle_fix_pre(constantPoolHandle cp,
-                                     typeArrayHandle* fields_ptr,
+                                     typeArrayHandle fields,
                                      FieldAllocationCount *fac_ptr, TRAPS);
 
   // Format checker methods
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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,12 +26,12 @@
 # include "incls/_systemDictionary.cpp.incl"
 
 
-Dictionary*       SystemDictionary::_dictionary = NULL;
-PlaceholderTable* SystemDictionary::_placeholders = NULL;
-Dictionary*       SystemDictionary::_shared_dictionary = NULL;
-LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL;
-ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL;
-SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL;
+Dictionary*            SystemDictionary::_dictionary          = NULL;
+PlaceholderTable*      SystemDictionary::_placeholders        = NULL;
+Dictionary*            SystemDictionary::_shared_dictionary   = NULL;
+LoaderConstraintTable* SystemDictionary::_loader_constraints  = NULL;
+ResolutionErrorTable*  SystemDictionary::_resolution_errors   = NULL;
+SymbolPropertyTable*   SystemDictionary::_invoke_method_table = NULL;
 
 
 int         SystemDictionary::_number_of_modifications = 0;
@@ -1727,8 +1727,7 @@
   placeholders_do(blk);
 
   // Visit extra methods
-  if (invoke_method_table() != NULL)
-    invoke_method_table()->oops_do(blk);
+  invoke_method_table()->oops_do(blk);
 
   // Loader constraints. We must keep the symbolOop used in the name alive.
   constraints()->always_strong_classes_do(blk);
@@ -1766,8 +1765,7 @@
   dictionary()->oops_do(f);
 
   // Visit extra methods
-  if (invoke_method_table() != NULL)
-    invoke_method_table()->oops_do(f);
+  invoke_method_table()->oops_do(f);
 
   // Partially loaded classes
   placeholders()->oops_do(f);
@@ -1841,8 +1839,7 @@
 
 void SystemDictionary::methods_do(void f(methodOop)) {
   dictionary()->methods_do(f);
-  if (invoke_method_table() != NULL)
-    invoke_method_table()->methods_do(f);
+  invoke_method_table()->methods_do(f);
 }
 
 // ----------------------------------------------------------------------------
@@ -1870,12 +1867,12 @@
   // Allocate arrays
   assert(dictionary() == NULL,
          "SystemDictionary should only be initialized once");
-  _dictionary = new Dictionary(_nof_buckets);
-  _placeholders = new PlaceholderTable(_nof_buckets);
+  _dictionary          = new Dictionary(_nof_buckets);
+  _placeholders        = new PlaceholderTable(_nof_buckets);
   _number_of_modifications = 0;
-  _loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
-  _resolution_errors = new ResolutionErrorTable(_resolution_error_size);
-  // _invoke_method_table is allocated lazily in find_method_handle_invoke()
+  _loader_constraints  = new LoaderConstraintTable(_loader_constraint_size);
+  _resolution_errors   = new ResolutionErrorTable(_resolution_error_size);
+  _invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
 
   // Allocate private object used as system class loader lock
   _system_loader_lock_obj = oopFactory::new_system_objArray(0, CHECK);
@@ -2346,10 +2343,6 @@
                                                       KlassHandle accessing_klass,
                                                       TRAPS) {
   if (!EnableMethodHandles)  return NULL;
-  if (invoke_method_table() == NULL) {
-    // create this side table lazily
-    _invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
-  }
   vmSymbols::SID name_id = vmSymbols::find_sid(name());
   assert(name_id != vmSymbols::NO_SID, "must be a known name");
   unsigned int hash  = invoke_method_table()->compute_hash(signature, name_id);
@@ -2562,7 +2555,9 @@
 }
 
 Handle SystemDictionary::find_bootstrap_method(methodHandle caller_method, int caller_bci,
-                                               int cache_index, TRAPS) {
+                                               int cache_index,
+                                               Handle& argument_info_result,
+                                               TRAPS) {
   Handle empty;
 
   constantPoolHandle pool;
@@ -2576,7 +2571,7 @@
   constantTag tag = pool->tag_at(constant_pool_index);
 
   if (tag.is_invoke_dynamic()) {
-    // JVM_CONSTANT_InvokeDynamic is an ordered pair of [bootm, name&type]
+    // JVM_CONSTANT_InvokeDynamic is an ordered pair of [bootm, name&type], plus optional arguments
     // The bootm, being a JVM_CONSTANT_MethodHandle, has its own cache entry.
     int bsm_index = pool->invoke_dynamic_bootstrap_method_ref_index_at(constant_pool_index);
     if (bsm_index != 0) {
@@ -2592,9 +2587,38 @@
         tty->print_cr("bootstrap method for "PTR_FORMAT" at %d retrieved as "PTR_FORMAT":",
                       (intptr_t) caller_method(), caller_bci, (intptr_t) bsm_oop);
       }
-      assert(bsm_oop->is_oop()
-             && java_dyn_MethodHandle::is_instance(bsm_oop), "must be sane");
-      return Handle(THREAD, bsm_oop);
+      assert(bsm_oop->is_oop(), "must be sane");
+      // caller must verify that it is of type MethodHandle
+      Handle bsm(THREAD, bsm_oop);
+      bsm_oop = NULL;  // safety
+
+      // Extract the optional static arguments.
+      Handle argument_info;  // either null, or one arg, or Object[]{arg...}
+      int argc = pool->invoke_dynamic_argument_count_at(constant_pool_index);
+      if (TraceInvokeDynamic) {
+        tty->print_cr("find_bootstrap_method: [%d/%d] CONSTANT_InvokeDynamic: %d[%d]",
+                      constant_pool_index, cache_index, bsm_index, argc);
+      }
+      if (argc > 0) {
+        objArrayHandle arg_array;
+        if (argc > 1) {
+          objArrayOop arg_array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), argc, CHECK_(empty));
+          arg_array = objArrayHandle(THREAD, arg_array_oop);
+          argument_info = arg_array;
+        }
+        for (int arg_i = 0; arg_i < argc; arg_i++) {
+          int arg_index = pool->invoke_dynamic_argument_index_at(constant_pool_index, arg_i);
+          oop arg_oop = pool->resolve_possibly_cached_constant_at(arg_index, CHECK_(empty));
+          if (arg_array.is_null()) {
+            argument_info = Handle(THREAD, arg_oop);
+          } else {
+            arg_array->obj_at_put(arg_i, arg_oop);
+          }
+        }
+      }
+
+      argument_info_result = argument_info;  // return argument_info to caller
+      return bsm;
     }
     // else null BSM; fall through
   } else if (tag.is_name_and_type()) {
@@ -2607,14 +2631,14 @@
   // Fall through to pick up the per-class bootstrap method.
   // This mechanism may go away in the PFD.
   assert(AllowTransitionalJSR292, "else the verifier should have stopped us already");
+  argument_info_result = empty;  // return no argument_info to caller
   oop bsm_oop = instanceKlass::cast(caller_method->method_holder())->bootstrap_method();
   if (bsm_oop != NULL) {
     if (TraceMethodHandles) {
       tty->print_cr("bootstrap method for "PTR_FORMAT" registered as "PTR_FORMAT":",
                     (intptr_t) caller_method(), (intptr_t) bsm_oop);
     }
-    assert(bsm_oop->is_oop()
-           && java_dyn_MethodHandle::is_instance(bsm_oop), "must be sane");
+    assert(bsm_oop->is_oop(), "must be sane");
     return Handle(THREAD, bsm_oop);
   }
 
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -496,6 +496,7 @@
   static Handle    find_bootstrap_method(methodHandle caller_method,
                                          int caller_bci,  // N.B. must be an invokedynamic
                                          int cache_index, // must be corresponding main_entry
+                                         Handle &argument_info_result, // static BSM arguments, if any
                                          TRAPS);
 
   // Utility for printing loader "name" as part of tracing constraints
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -1909,7 +1909,7 @@
   unsigned int types = (opcode == Bytecodes::_invokeinterface
                                 ? 1 << JVM_CONSTANT_InterfaceMethodref
                       : opcode == Bytecodes::_invokedynamic
-                                ? (1 << JVM_CONSTANT_NameAndType
+                                ? ((AllowTransitionalJSR292 ? 1 << JVM_CONSTANT_NameAndType : 0)
                                   |1 << JVM_CONSTANT_InvokeDynamic)
                                 : 1 << JVM_CONSTANT_Methodref);
   verify_cp_type(index, cp, types, CHECK_VERIFY(this));
--- a/hotspot/src/share/vm/code/codeCache.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/code/codeCache.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -914,3 +914,14 @@
 }
 
 #endif // PRODUCT
+
+void CodeCache::print_bounds(outputStream* st) {
+  st->print_cr("Code Cache  [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT ")",
+               _heap->low_boundary(),
+               _heap->high(),
+               _heap->high_boundary());
+  st->print_cr(" total_blobs=" UINT32_FORMAT " nmethods=" UINT32_FORMAT
+               " adapters=" UINT32_FORMAT " free_code_cache=" SIZE_FORMAT,
+               CodeCache::nof_blobs(), CodeCache::nof_nmethods(),
+               CodeCache::nof_adapters(), CodeCache::unallocated_capacity());
+}
--- a/hotspot/src/share/vm/code/codeCache.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/code/codeCache.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -137,6 +137,7 @@
   static void print_internals();
   static void verify();                          // verifies the code cache
   static void print_trace(const char* event, CodeBlob* cb, int size = 0) PRODUCT_RETURN;
+  static void print_bounds(outputStream* st);    // Prints a summary of the bounds of the code cache
 
   // The full limits of the codeCache
   static address  low_bound()                    { return (address) _heap->low_boundary(); }
--- a/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/includeDB_gc_parallelScavenge	Mon Nov 08 14:33:48 2010 -0800
@@ -133,6 +133,7 @@
 parallelScavengeHeap.cpp                psParallelCompact.hpp
 parallelScavengeHeap.cpp                psPromotionManager.hpp
 parallelScavengeHeap.cpp                psScavenge.hpp
+parallelScavengeHeap.cpp                vmError.hpp
 parallelScavengeHeap.cpp                vmThread.hpp
 parallelScavengeHeap.cpp                vmPSOperations.hpp
 
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -805,7 +805,8 @@
   if (young_gen()->is_in_reserved(addr)) {
     assert(young_gen()->is_in(addr),
            "addr should be in allocated part of young gen");
-    if (Debugging)  return NULL;  // called from find() in debug.cpp
+    // called from os::print_location by find or VMError
+    if (Debugging || VMError::fatal_error_in_progress())  return NULL;
     Unimplemented();
   } else if (old_gen()->is_in_reserved(addr)) {
     assert(old_gen()->is_in(addr),
--- a/hotspot/src/share/vm/includeDB_core	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/includeDB_core	Mon Nov 08 14:33:48 2010 -0800
@@ -1272,6 +1272,7 @@
 constantPoolOop.cpp                     linkResolver.hpp
 constantPoolOop.cpp                     objArrayKlass.hpp
 constantPoolOop.cpp                     oop.inline.hpp
+constantPoolOop.cpp                     oopFactory.hpp
 constantPoolOop.cpp                     signature.hpp
 constantPoolOop.cpp                     symbolTable.hpp
 constantPoolOop.cpp                     systemDictionary.hpp
--- a/hotspot/src/share/vm/includeDB_features	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/includeDB_features	Mon Nov 08 14:33:48 2010 -0800
@@ -154,6 +154,7 @@
 jvmtiExtensions.hpp                     jvmti.h
 jvmtiExtensions.hpp                     jvmtiEnv.hpp
 
+jvmtiImpl.cpp                           deoptimization.hpp
 jvmtiImpl.cpp                           exceptions.hpp
 jvmtiImpl.cpp                           handles.hpp
 jvmtiImpl.cpp                           handles.inline.hpp
--- a/hotspot/src/share/vm/includeDB_jvmti	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/includeDB_jvmti	Mon Nov 08 14:33:48 2010 -0800
@@ -89,6 +89,7 @@
 jvmtiEnv.hpp                            jvmtiEnvBase.hpp
 
 jvmtiEnvBase.cpp                        biasedLocking.hpp
+jvmtiEnvBase.cpp                        deoptimization.hpp
 jvmtiEnvBase.cpp                        interfaceSupport.hpp
 jvmtiEnvBase.cpp                        jfieldIDWorkaround.hpp
 jvmtiEnvBase.cpp                        jvmtiEnv.hpp
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -716,12 +716,13 @@
   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();
+  int pool_index = pool->cache()->entry_at(main_index)->constant_pool_index();
 
   // first resolve the signature to a MH.invoke methodOop
   if (!pool->cache()->entry_at(main_index)->is_resolved(bytecode)) {
     JvmtiHideSingleStepping jhss(thread);
-    CallInfo info;
-    LinkResolver::resolve_invoke(info, Handle(), pool,
+    CallInfo callinfo;
+    LinkResolver::resolve_invoke(callinfo, Handle(), pool,
                                  site_index, bytecode, CHECK);
     // The main entry corresponds to a JVM_CONSTANT_InvokeDynamic, and serves
     // as a common reference point for all invokedynamic call sites with
@@ -729,8 +730,8 @@
     // as if it were an invokevirtual of MethodHandle.invoke.
     pool->cache()->entry_at(main_index)->set_method(
       bytecode,
-      info.resolved_method(),
-      info.vtable_index());
+      callinfo.resolved_method(),
+      callinfo.vtable_index());
   }
 
   // The method (f2 entry) of the main entry is the MH.invoke for the
@@ -740,9 +741,10 @@
   assert(signature_invoker.not_null() && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(),
          "correct result from LinkResolver::resolve_invokedynamic");
 
+  Handle info;  // optional argument(s) in JVM_CONSTANT_InvokeDynamic
   Handle bootm = SystemDictionary::find_bootstrap_method(caller_method, caller_bci,
-                                                         main_index, CHECK);
-  if (bootm.is_null()) {
+                                                         main_index, info, CHECK);
+  if (!java_dyn_MethodHandle::is_instance(bootm())) {
     THROW_MSG(vmSymbols::java_lang_IllegalStateException(),
               "no bootstrap method found for invokedynamic");
   }
@@ -753,8 +755,6 @@
 
   symbolHandle call_site_name(THREAD, pool->name_ref_at(site_index));
 
-  Handle info;  // NYI: Other metadata from a new kind of CP entry.  (Annotations?)
-
   Handle call_site
     = SystemDictionary::make_dynamic_call_site(bootm,
                                                // Callee information:
--- a/hotspot/src/share/vm/memory/heap.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/memory/heap.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -140,6 +140,7 @@
 
   // Returns reserved area high and low addresses
   char *low_boundary() const                     { return _memory.low_boundary (); }
+  char *high() const                             { return _memory.high(); }
   char *high_boundary() const                    { return _memory.high_boundary(); }
 
   // Iteration
--- a/hotspot/src/share/vm/memory/universe.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/memory/universe.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -340,6 +340,7 @@
   static klassOop* longArrayKlassObj_addr()           { return &_longArrayKlassObj;   }
   static klassOop* singleArrayKlassObj_addr()         { return &_singleArrayKlassObj; }
   static klassOop* doubleArrayKlassObj_addr()         { return &_doubleArrayKlassObj; }
+  static klassOop* systemObjArrayKlassObj_addr()      { return &_systemObjArrayKlassObj; }
 
   // The particular choice of collected heap.
   static CollectedHeap* heap() { return _collectedHeap; }
--- a/hotspot/src/share/vm/oops/constantPoolKlass.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolKlass.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -34,6 +34,7 @@
   c->set_length(length);
   c->set_tags(NULL);
   c->set_cache(NULL);
+  c->set_operands(NULL);
   c->set_pool_holder(NULL);
   c->set_flags(0);
   // only set to non-zero if constant pool is merged by RedefineClasses
@@ -92,6 +93,7 @@
     // gc of constant pool instance variables
     MarkSweep::mark_and_push(cp->tags_addr());
     MarkSweep::mark_and_push(cp->cache_addr());
+    MarkSweep::mark_and_push(cp->operands_addr());
     MarkSweep::mark_and_push(cp->pool_holder_addr());
   }
 }
@@ -118,6 +120,7 @@
     // gc of constant pool instance variables
     PSParallelCompact::mark_and_push(cm, cp->tags_addr());
     PSParallelCompact::mark_and_push(cm, cp->cache_addr());
+    PSParallelCompact::mark_and_push(cm, cp->operands_addr());
     PSParallelCompact::mark_and_push(cm, cp->pool_holder_addr());
   }
 }
@@ -146,6 +149,7 @@
   }
   MarkSweep::adjust_pointer(cp->tags_addr());
   MarkSweep::adjust_pointer(cp->cache_addr());
+  MarkSweep::adjust_pointer(cp->operands_addr());
   MarkSweep::adjust_pointer(cp->pool_holder_addr());
   return size;
 }
@@ -173,6 +177,7 @@
   }
   blk->do_oop(cp->tags_addr());
   blk->do_oop(cp->cache_addr());
+  blk->do_oop(cp->operands_addr());
   blk->do_oop(cp->pool_holder_addr());
   return size;
 }
@@ -205,6 +210,8 @@
   blk->do_oop(addr);
   addr = cp->cache_addr();
   blk->do_oop(addr);
+  addr = cp->operands_addr();
+  blk->do_oop(addr);
   addr = cp->pool_holder_addr();
   blk->do_oop(addr);
   return size;
@@ -232,6 +239,7 @@
   }
   PSParallelCompact::adjust_pointer(cp->tags_addr());
   PSParallelCompact::adjust_pointer(cp->cache_addr());
+  PSParallelCompact::adjust_pointer(cp->operands_addr());
   PSParallelCompact::adjust_pointer(cp->pool_holder_addr());
   return cp->object_size();
 }
@@ -262,6 +270,8 @@
   PSParallelCompact::adjust_pointer(p, beg_addr, end_addr);
   p = cp->cache_addr();
   PSParallelCompact::adjust_pointer(p, beg_addr, end_addr);
+  p = cp->operands_addr();
+  PSParallelCompact::adjust_pointer(p, beg_addr, end_addr);
   p = cp->pool_holder_addr();
   PSParallelCompact::adjust_pointer(p, beg_addr, end_addr);
 
@@ -363,8 +373,18 @@
         st->print("signature_index=%d", cp->method_type_index_at(index));
         break;
       case JVM_CONSTANT_InvokeDynamic :
-        st->print("bootstrap_method_index=%d", cp->invoke_dynamic_bootstrap_method_ref_index_at(index));
-        st->print(" name_and_type_index=%d", cp->invoke_dynamic_name_and_type_ref_index_at(index));
+        {
+          st->print("bootstrap_method_index=%d", cp->invoke_dynamic_bootstrap_method_ref_index_at(index));
+          st->print(" name_and_type_index=%d", cp->invoke_dynamic_name_and_type_ref_index_at(index));
+          int argc = cp->invoke_dynamic_argument_count_at(index);
+          if (argc > 0) {
+            for (int arg_i = 0; arg_i < argc; arg_i++) {
+              int arg = cp->invoke_dynamic_argument_index_at(index, arg_i);
+              st->print((arg_i == 0 ? " arguments={%d" : ", %d"), arg);
+            }
+            st->print("}");
+          }
+        }
         break;
       default:
         ShouldNotReachHere();
@@ -381,6 +401,7 @@
   st->print("constant pool [%d]", cp->length());
   if (cp->has_pseudo_string()) st->print("/pseudo_string");
   if (cp->has_invokedynamic()) st->print("/invokedynamic");
+  if (cp->operands() != NULL)  st->print("/operands[%d]", cp->operands()->length());
   cp->print_address_on(st);
   st->print(" for ");
   cp->pool_holder()->print_value_on(st);
@@ -440,6 +461,10 @@
       guarantee(cp->cache()->is_perm(),              "should be in permspace");
       guarantee(cp->cache()->is_constantPoolCache(), "should be constant pool cache");
     }
+    if (cp->operands() != NULL) {
+      guarantee(cp->operands()->is_perm(),  "should be in permspace");
+      guarantee(cp->operands()->is_typeArray(), "should be type array");
+    }
     if (cp->pool_holder() != NULL) {
       // Note: pool_holder() can be NULL in temporary constant pools
       // used during constant pool merging
--- a/hotspot/src/share/vm/oops/constantPoolOop.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolOop.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -265,10 +265,9 @@
   int i = which;
   if (!uncached && cache() != NULL) {
     if (constantPoolCacheOopDesc::is_secondary_index(which)) {
-      // Invokedynamic indexes are always processed in native order
-      // so there is no question of reading a native u2 in Java order here.
+      // Invokedynamic index.
       int pool_index = cache()->main_entry_at(which)->constant_pool_index();
-      if (tag_at(pool_index).is_invoke_dynamic())
+      if (!AllowTransitionalJSR292 || tag_at(pool_index).is_invoke_dynamic())
         pool_index = invoke_dynamic_name_and_type_ref_index_at(pool_index);
       assert(tag_at(pool_index).is_name_and_type(), "");
       return pool_index;
@@ -276,11 +275,17 @@
     // change byte-ordering and go via cache
     i = remap_instruction_operand_from_cache(which);
   } else {
-    if (tag_at(which).is_name_and_type())
+    if (AllowTransitionalJSR292 && tag_at(which).is_name_and_type())
       // invokedynamic index is a simple name-and-type
       return which;
+    if (tag_at(which).is_invoke_dynamic()) {
+      int pool_index = invoke_dynamic_name_and_type_ref_index_at(which);
+      assert(tag_at(pool_index).is_name_and_type(), "");
+      return pool_index;
+    }
   }
   assert(tag_at(i).is_field_or_method(), "Corrupted constant pool");
+  assert(!tag_at(i).is_invoke_dynamic(), "Must be handled above");
   jint ref_index = *int_at_addr(i);
   return extract_high_short_from_int(ref_index);
 }
@@ -394,18 +399,61 @@
   }
 }
 
+// A resolved constant value in the CP cache is represented as a non-null
+// value.  As a special case, this value can be a 'systemObjArray'
+// which masks an exception object to throw.
+// This allows a MethodHandle constant reference to throw a consistent
+// exception every time, if it fails to resolve.
+static oop decode_exception_from_f1(oop result_oop, TRAPS) {
+  if (result_oop->klass() != Universe::systemObjArrayKlassObj())
+    return result_oop;
+
+  // Special cases here:  Masked null, saved exception.
+  objArrayOop sys_array = (objArrayOop) result_oop;
+  assert(sys_array->length() == 1, "bad system array");
+  if (sys_array->length() == 1) {
+    THROW_OOP_(sys_array->obj_at(0), NULL);
+  }
+  return NULL;
+}
+
 oop constantPoolOopDesc::resolve_constant_at_impl(constantPoolHandle this_oop, int index, int cache_index, TRAPS) {
   oop result_oop = NULL;
+  Handle throw_exception;
+
+  if (cache_index == _possible_index_sentinel) {
+    // It is possible that this constant is one which is cached in the CP cache.
+    // We'll do a linear search.  This should be OK because this usage is rare.
+    assert(index > 0, "valid index");
+    constantPoolCacheOop cache = this_oop()->cache();
+    for (int i = 0, len = cache->length(); i < len; i++) {
+      ConstantPoolCacheEntry* cpc_entry = cache->entry_at(i);
+      if (!cpc_entry->is_secondary_entry() && cpc_entry->constant_pool_index() == index) {
+        // Switch the query to use this CPC entry.
+        cache_index = i;
+        index = _no_index_sentinel;
+        break;
+      }
+    }
+    if (cache_index == _possible_index_sentinel)
+      cache_index = _no_index_sentinel;  // not found
+  }
+  assert(cache_index == _no_index_sentinel || cache_index >= 0, "");
+  assert(index == _no_index_sentinel || index >= 0, "");
+
   if (cache_index >= 0) {
-    assert(index < 0, "only one kind of index at a time");
+    assert(index == _no_index_sentinel, "only one kind of index at a time");
     ConstantPoolCacheEntry* cpc_entry = this_oop->cache()->entry_at(cache_index);
     result_oop = cpc_entry->f1();
     if (result_oop != NULL) {
-      return result_oop;  // that was easy...
+      return decode_exception_from_f1(result_oop, THREAD);
+      // That was easy...
     }
     index = cpc_entry->constant_pool_index();
   }
 
+  jvalue prim_value;  // temp used only in a few cases below
+
   int tag_value = this_oop->tag_at(index).value();
   switch (tag_value) {
 
@@ -449,9 +497,14 @@
       KlassHandle klass(THREAD, this_oop->pool_holder());
       Handle value = SystemDictionary::link_method_handle_constant(klass, ref_kind,
                                                                    callee, name, signature,
-                                                                   CHECK_NULL);
+                                                                   THREAD);
+      if (HAS_PENDING_EXCEPTION) {
+        throw_exception = Handle(THREAD, PENDING_EXCEPTION);
+        CLEAR_PENDING_EXCEPTION;
+        break;
+      }
       result_oop = value();
-      // FIXME: Uniquify errors, using SystemDictionary::find_resolution_error.
+      assert(result_oop != NULL, "");
       break;
     }
 
@@ -468,20 +521,36 @@
                                                                klass,
                                                                false,
                                                                ignore_is_on_bcp,
-                                                               CHECK_NULL);
+                                                               THREAD);
+      if (HAS_PENDING_EXCEPTION) {
+        throw_exception = Handle(THREAD, PENDING_EXCEPTION);
+        CLEAR_PENDING_EXCEPTION;
+        break;
+      }
       result_oop = value();
-      // FIXME: Uniquify errors, using SystemDictionary::find_resolution_error.
+      assert(result_oop != NULL, "");
       break;
     }
 
-    /* maybe some day
   case JVM_CONSTANT_Integer:
+    prim_value.i = this_oop->int_at(index);
+    result_oop = java_lang_boxing_object::create(T_INT, &prim_value, CHECK_NULL);
+    break;
+
   case JVM_CONSTANT_Float:
+    prim_value.f = this_oop->float_at(index);
+    result_oop = java_lang_boxing_object::create(T_FLOAT, &prim_value, CHECK_NULL);
+    break;
+
   case JVM_CONSTANT_Long:
+    prim_value.j = this_oop->long_at(index);
+    result_oop = java_lang_boxing_object::create(T_LONG, &prim_value, CHECK_NULL);
+    break;
+
   case JVM_CONSTANT_Double:
-    result_oop = java_lang_boxing_object::create(...);
+    prim_value.d = this_oop->double_at(index);
+    result_oop = java_lang_boxing_object::create(T_DOUBLE, &prim_value, CHECK_NULL);
     break;
-    */
 
   default:
     DEBUG_ONLY( tty->print_cr("*** %p: tag at CP[%d/%d] = %d",
@@ -492,18 +561,31 @@
 
   if (cache_index >= 0) {
     // Cache the oop here also.
-    Handle result(THREAD, result_oop);
+    if (throw_exception.not_null()) {
+      objArrayOop sys_array = oopFactory::new_system_objArray(1, CHECK_NULL);
+      sys_array->obj_at_put(0, throw_exception());
+      result_oop = sys_array;
+      throw_exception = Handle();  // be tidy
+    }
+    Handle result_handle(THREAD, result_oop);
     result_oop = NULL;  // safety
     ObjectLocker ol(this_oop, THREAD);
     ConstantPoolCacheEntry* cpc_entry = this_oop->cache()->entry_at(cache_index);
-    oop result_oop2 = cpc_entry->f1();
-    if (result_oop2 != NULL) {
-      // Race condition:  May already be filled in while we were trying to lock.
-      return result_oop2;
+    result_oop = cpc_entry->f1();
+    // Benign race condition:  f1 may already be filled in while we were trying to lock.
+    // The important thing here is that all threads pick up the same result.
+    // It doesn't matter which racing thread wins, as long as only one
+    // result is used by all threads, and all future queries.
+    // That result may be either a resolved constant or a failure exception.
+    if (result_oop == NULL) {
+      result_oop = result_handle();
+      cpc_entry->set_f1(result_oop);
     }
-    cpc_entry->set_f1(result());
-    return result();
+    return decode_exception_from_f1(result_oop, THREAD);
   } else {
+    if (throw_exception.not_null()) {
+      THROW_HANDLE_(throw_exception, NULL);
+    }
     return result_oop;
   }
 }
@@ -621,6 +703,7 @@
 
 void constantPoolOopDesc::shared_tags_iterate(OopClosure* closure) {
   closure->do_oop(tags_addr());
+  closure->do_oop(operands_addr());
 }
 
 
@@ -838,13 +921,19 @@
 
   case JVM_CONSTANT_InvokeDynamic:
   {
-    int k1 = invoke_dynamic_bootstrap_method_ref_index_at(index1);
-    int k2 = cp2->invoke_dynamic_bootstrap_method_ref_index_at(index2);
-    if (k1 == k2) {
-      int i1 = invoke_dynamic_name_and_type_ref_index_at(index1);
-      int i2 = cp2->invoke_dynamic_name_and_type_ref_index_at(index2);
-      if (i1 == i2) {
-        return true;
+    int op_count = multi_operand_count_at(index1);
+    if (op_count == cp2->multi_operand_count_at(index2)) {
+      bool all_equal = true;
+      for (int op_i = 0; op_i < op_count; op_i++) {
+        int k1 = multi_operand_ref_at(index1, op_i);
+        int k2 = cp2->multi_operand_ref_at(index2, op_i);
+        if (k1 != k2) {
+          all_equal = false;
+          break;
+        }
+      }
+      if (all_equal) {
+        return true;           // got through loop; all elements equal
       }
     }
   } break;
@@ -881,6 +970,25 @@
 } // end compare_entry_to()
 
 
+// Grow this->operands() to the indicated length, unless it is already at least that long.
+void constantPoolOopDesc::multi_operand_buffer_grow(int min_length, TRAPS) {
+  int old_length = multi_operand_buffer_fill_pointer();
+  if (old_length >= min_length)  return;
+  int new_length = min_length;
+  assert(new_length > _multi_operand_buffer_fill_pointer_offset, "");
+  typeArrayHandle new_operands = oopFactory::new_permanent_intArray(new_length, CHECK);
+  if (operands() == NULL) {
+    new_operands->int_at_put(_multi_operand_buffer_fill_pointer_offset, old_length);
+  } else {
+    // copy fill pointer and everything else
+    for (int i = 0; i < old_length; i++) {
+      new_operands->int_at_put(i, operands()->int_at(i));
+    }
+  }
+  set_operands(new_operands());
+}
+
+
 // Copy this constant pool's entries at start_i to end_i (inclusive)
 // to the constant pool to_cp's entries starting at to_i. A total of
 // (end_i - start_i) + 1 entries are copied.
@@ -889,6 +997,13 @@
 
   int dest_i = to_i;  // leave original alone for debug purposes
 
+  if (operands() != NULL) {
+    // pre-grow the target CP's operand buffer
+    int nops = this->multi_operand_buffer_fill_pointer();
+    nops   += to_cp->multi_operand_buffer_fill_pointer();
+    to_cp->multi_operand_buffer_grow(nops, CHECK);
+  }
+
   for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) {
     copy_entry_to(src_i, to_cp, dest_i, CHECK);
 
@@ -1037,9 +1152,26 @@
 
   case JVM_CONSTANT_InvokeDynamic:
   {
+    int op_count = multi_operand_count_at(from_i);
+    int fillp = to_cp->multi_operand_buffer_fill_pointer();
+    int to_op_base = fillp - _multi_operand_count_offset;  // fillp is count offset; get to base
+    to_cp->multi_operand_buffer_grow(to_op_base + op_count, CHECK);
+    to_cp->operands()->int_at_put(fillp++, op_count);
+    assert(fillp == to_op_base + _multi_operand_base_offset, "just wrote count, will now write args");
+    for (int op_i = 0; op_i < op_count; op_i++) {
+      int op = multi_operand_ref_at(from_i, op_i);
+      to_cp->operands()->int_at_put(fillp++, op);
+    }
+    assert(fillp <= to_cp->operands()->length(), "oob");
+    to_cp->set_multi_operand_buffer_fill_pointer(fillp);
+    to_cp->invoke_dynamic_at_put(to_i, to_op_base, op_count);
+#ifdef ASSERT
     int k1 = invoke_dynamic_bootstrap_method_ref_index_at(from_i);
     int k2 = invoke_dynamic_name_and_type_ref_index_at(from_i);
-    to_cp->invoke_dynamic_at_put(to_i, k1, k2);
+    int k3 = invoke_dynamic_argument_count_at(from_i);
+    assert(to_cp->check_invoke_dynamic_at(to_i, k1, k2, k3),
+           "indy structure is OK");
+#endif //ASSERT
   } break;
 
   // Invalid is used as the tag for the second constant pool entry
@@ -1257,8 +1389,11 @@
     case JVM_CONSTANT_Methodref:
     case JVM_CONSTANT_InterfaceMethodref:
     case JVM_CONSTANT_NameAndType:
+      return 5;
+
     case JVM_CONSTANT_InvokeDynamic:
-      return 5;
+      // u1 tag, u2 bsm, u2 nt, u2 argc, u2 argv[argc]
+      return 7 + 2 * invoke_dynamic_argument_count_at(idx);
 
     case JVM_CONSTANT_Long:
     case JVM_CONSTANT_Double:
@@ -1475,9 +1610,15 @@
         *bytes = JVM_CONSTANT_InvokeDynamic;
         idx1 = invoke_dynamic_bootstrap_method_ref_index_at(idx);
         idx2 = invoke_dynamic_name_and_type_ref_index_at(idx);
+        int argc = invoke_dynamic_argument_count_at(idx);
         Bytes::put_Java_u2((address) (bytes+1), idx1);
         Bytes::put_Java_u2((address) (bytes+3), idx2);
-        DBG(printf("JVM_CONSTANT_InvokeDynamic: %hd %hd", idx1, idx2));
+        Bytes::put_Java_u2((address) (bytes+5), argc);
+        for (int arg_i = 0; arg_i < argc; arg_i++) {
+          int arg = invoke_dynamic_argument_index_at(idx, arg_i);
+          Bytes::put_Java_u2((address) (bytes+7+2*arg_i), arg);
+        }
+        DBG(printf("JVM_CONSTANT_InvokeDynamic: %hd %hd [%d]", idx1, idx2, argc));
         break;
       }
     }
--- a/hotspot/src/share/vm/oops/constantPoolOop.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -41,6 +41,7 @@
   typeArrayOop         _tags; // the tag array describing the constant pool's contents
   constantPoolCacheOop _cache;         // the cache holding interpreter runtime information
   klassOop             _pool_holder;   // the corresponding class
+  typeArrayOop         _operands;      // for variable-sized (InvokeDynamic) nodes, usually empty
   int                  _flags;         // a few header bits to describe contents for GC
   int                  _length; // number of elements in the array
   volatile bool        _is_conc_safe; // if true, safe for concurrent
@@ -52,6 +53,8 @@
   void tag_at_put(int which, jbyte t)          { tags()->byte_at_put(which, t); }
   void release_tag_at_put(int which, jbyte t)  { tags()->release_byte_at_put(which, t); }
 
+  void set_operands(typeArrayOop operands)     { oop_store_without_check((oop*)&_operands, operands); }
+
   enum FlagBit {
     FB_has_invokedynamic = 1,
     FB_has_pseudo_string = 2
@@ -67,6 +70,7 @@
   intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(constantPoolOopDesc)); }
   oop* tags_addr()       { return (oop*)&_tags; }
   oop* cache_addr()      { return (oop*)&_cache; }
+  oop* operands_addr()   { return (oop*)&_operands; }
 
   oop* obj_at_addr(int which) const {
     assert(is_within_bounds(which), "index out of bounds");
@@ -95,6 +99,7 @@
 
  public:
   typeArrayOop tags() const                 { return _tags; }
+  typeArrayOop operands() const             { return _operands; }
 
   bool has_pseudo_string() const            { return flag_at(FB_has_pseudo_string); }
   bool has_invokedynamic() const            { return flag_at(FB_has_invokedynamic); }
@@ -113,6 +118,7 @@
   // Assembly code support
   static int tags_offset_in_bytes()         { return offset_of(constantPoolOopDesc, _tags); }
   static int cache_offset_in_bytes()        { return offset_of(constantPoolOopDesc, _cache); }
+  static int operands_offset_in_bytes()     { return offset_of(constantPoolOopDesc, _operands); }
   static int pool_holder_offset_in_bytes()  { return offset_of(constantPoolOopDesc, _pool_holder); }
 
   // Storing constants
@@ -156,10 +162,28 @@
     *int_at_addr(which) = ref_index;
   }
 
-  void invoke_dynamic_at_put(int which, int bootstrap_method_index, int name_and_type_index) {
+  void invoke_dynamic_at_put(int which, int operand_base, int operand_count) {
     tag_at_put(which, JVM_CONSTANT_InvokeDynamic);
-    *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_method_index;
+    *int_at_addr(which) = operand_base;  // this is the real information
   }
+#ifdef ASSERT
+  bool check_invoke_dynamic_at(int which,
+                               int bootstrap_method_index,
+                               int name_and_type_index,
+                               int argument_count) {
+    assert(invoke_dynamic_bootstrap_method_ref_index_at(which) == bootstrap_method_index,
+           "already stored by caller");
+    assert(invoke_dynamic_name_and_type_ref_index_at(which) == name_and_type_index,
+           "already stored by caller");
+    assert(invoke_dynamic_argument_count_at(which) == argument_count,
+           "consistent argument count");
+    if (argument_count != 0) {
+      invoke_dynamic_argument_index_at(which, 0);
+      invoke_dynamic_argument_index_at(which, argument_count - 1);
+    }
+    return true;
+  }
+#endif //ASSERT
 
   // Temporary until actual use
   void unresolved_string_at_put(int which, symbolOop s) {
@@ -401,27 +425,93 @@
     int sym = method_type_index_at(which);
     return symbol_at(sym);
   }
+
+ private:
+  // some nodes (InvokeDynamic) have a variable number of operands, each a u2 value
+  enum { _multi_operand_count_offset = -1,
+         _multi_operand_base_offset  = 0,
+         _multi_operand_buffer_fill_pointer_offset = 0  // shared at front of operands array
+  };
+  int multi_operand_buffer_length() {
+    return operands() == NULL ? 0 : operands()->length();
+  }
+  int multi_operand_buffer_fill_pointer() {
+    return operands() == NULL
+      ? _multi_operand_buffer_fill_pointer_offset + 1
+      : operands()->int_at(_multi_operand_buffer_fill_pointer_offset);
+  }
+  void multi_operand_buffer_grow(int min_length, TRAPS);
+  void set_multi_operand_buffer_fill_pointer(int fillp) {
+    assert(operands() != NULL, "");
+    operands()->int_at_put(_multi_operand_buffer_fill_pointer_offset, fillp);
+  }
+  int multi_operand_base_at(int which) {
+    assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
+    int op_base = *int_at_addr(which);
+    assert(op_base > _multi_operand_buffer_fill_pointer_offset, "Corrupted operand base");
+    return op_base;
+  }
+  int multi_operand_count_at(int which) {
+    int op_base = multi_operand_base_at(which);
+    assert((uint)(op_base + _multi_operand_count_offset) < (uint)operands()->length(), "oob");
+    int count = operands()->int_at(op_base + _multi_operand_count_offset);
+    return count;
+  }
+  int multi_operand_ref_at(int which, int i) {
+    int op_base = multi_operand_base_at(which);
+    assert((uint)i < (uint)multi_operand_count_at(which), "oob");
+    assert((uint)(op_base + _multi_operand_base_offset + i) < (uint)operands()->length(), "oob");
+    return operands()->int_at(op_base + _multi_operand_base_offset + i);
+  }
+  void set_multi_operand_ref_at(int which, int i, int ref) {
+    DEBUG_ONLY(multi_operand_ref_at(which, i));  // trigger asserts
+    int op_base = multi_operand_base_at(which);
+    operands()->int_at_put(op_base + _multi_operand_base_offset + i, ref);
+  }
+
+ public:
+  // layout of InvokeDynamic:
+  enum {
+         _indy_bsm_offset  = 0,  // CONSTANT_MethodHandle bsm
+         _indy_nt_offset   = 1,  // CONSTANT_NameAndType descr
+         _indy_argc_offset = 2,  // u2 argc
+         _indy_argv_offset = 3   // u2 argv[argc]
+  };
   int invoke_dynamic_bootstrap_method_ref_index_at(int which) {
     assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
-    jint ref_index = *int_at_addr(which);
-    return extract_low_short_from_int(ref_index);
+    return multi_operand_ref_at(which, _indy_bsm_offset);
   }
   int invoke_dynamic_name_and_type_ref_index_at(int which) {
     assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
-    jint ref_index = *int_at_addr(which);
-    return extract_high_short_from_int(ref_index);
+    return multi_operand_ref_at(which, _indy_nt_offset);
+  }
+  int invoke_dynamic_argument_count_at(int which) {
+    assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
+    int argc = multi_operand_ref_at(which, _indy_argc_offset);
+    DEBUG_ONLY(int op_count = multi_operand_count_at(which));
+    assert(_indy_argv_offset + argc == op_count, "consistent inner and outer counts");
+    return argc;
+  }
+  int invoke_dynamic_argument_index_at(int which, int j) {
+    assert((uint)j < (uint)invoke_dynamic_argument_count_at(which), "oob");
+    return multi_operand_ref_at(which, _indy_argv_offset + j);
   }
 
   // The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve,
   // name_and_type_ref_index_at) all expect to be passed indices obtained
-  // directly from the bytecode, and extracted according to java byte order.
+  // directly from the bytecode.
   // If the indices are meant to refer to fields or methods, they are
-  // actually potentially byte-swapped, rewritten constant pool cache indices.
+  // actually rewritten constant pool cache indices.
   // The routine remap_instruction_operand_from_cache manages the adjustment
   // of these values back to constant pool indices.
 
   // There are also "uncached" versions which do not adjust the operand index; see below.
 
+  // FIXME: Consider renaming these with a prefix "cached_" to make the distinction clear.
+  // In a few cases (the verifier) there are uses before a cpcache has been built,
+  // which are handled by a dynamic check in remap_instruction_operand_from_cache.
+  // FIXME: Remove the dynamic check, and adjust all callers to specify the correct mode.
+
   // Lookup for entries consisting of (klass_index, name_and_type index)
   klassOop klass_ref_at(int which, TRAPS);
   symbolOop klass_ref_at_noresolve(int which);
@@ -443,15 +533,24 @@
     resolve_string_constants_impl(h_this, CHECK);
   }
 
+ private:
+  enum { _no_index_sentinel = -1, _possible_index_sentinel = -2 };
+ public:
+
   // Resolve late bound constants.
   oop resolve_constant_at(int index, TRAPS) {
     constantPoolHandle h_this(THREAD, this);
-    return resolve_constant_at_impl(h_this, index, -1, THREAD);
+    return resolve_constant_at_impl(h_this, index, _no_index_sentinel, THREAD);
   }
 
   oop resolve_cached_constant_at(int cache_index, TRAPS) {
     constantPoolHandle h_this(THREAD, this);
-    return resolve_constant_at_impl(h_this, -1, cache_index, THREAD);
+    return resolve_constant_at_impl(h_this, _no_index_sentinel, cache_index, THREAD);
+  }
+
+  oop resolve_possibly_cached_constant_at(int pool_index, TRAPS) {
+    constantPoolHandle h_this(THREAD, this);
+    return resolve_constant_at_impl(h_this, pool_index, _possible_index_sentinel, THREAD);
   }
 
   // Klass name matches name at offset
@@ -484,7 +583,7 @@
   static klassOop klass_ref_at_if_loaded_check(constantPoolHandle this_oop, int which, TRAPS);
 
   // Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
-  // future by other Java code. These take constant pool indices rather than possibly-byte-swapped
+  // future by other Java code. These take constant pool indices rather than
   // constant pool cache indices as do the peer methods above.
   symbolOop uncached_klass_ref_at_noresolve(int which);
   symbolOop uncached_name_ref_at(int which)                 { return impl_name_ref_at(which, true); }
--- a/hotspot/src/share/vm/oops/cpCacheOop.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/oops/cpCacheOop.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -87,6 +87,19 @@
   OrderAccess::release_store_ptr(&_indices, _indices | ((u_char)code << 24));
 }
 
+// Atomically sets f1 if it is still NULL, otherwise it keeps the
+// current value.
+void ConstantPoolCacheEntry::set_f1_if_null_atomic(oop f1) {
+    // Use barriers as in oop_store
+    HeapWord* f1_addr = (HeapWord*) &_f1;
+    update_barrier_set_pre(f1_addr, f1);
+    void* result = Atomic::cmpxchg_ptr(f1, f1_addr, NULL);
+    bool success = (result == NULL);
+    if (success) {
+      update_barrier_set((void*) f1_addr, f1);
+    }
+  }
+
 #ifdef ASSERT
 // It is possible to have two different dummy methodOops created
 // when the resolve code for invoke interface executes concurrently
@@ -165,7 +178,12 @@
       }
       assert(method->can_be_statically_bound(), "must be a MH invoker method");
       assert(AllowTransitionalJSR292 || _f2 >= constantPoolOopDesc::CPCACHE_INDEX_TAG, "BSM index initialized");
-      set_f1(method());
+      // SystemDictionary::find_method_handle_invoke only caches
+      // methods which signature classes are on the boot classpath,
+      // otherwise the newly created method is returned.  To avoid
+      // races in that case we store the first one coming in into the
+      // cp-cache atomically if it's still unset.
+      set_f1_if_null_atomic(method());
       needs_vfinal_flag = false;  // _f2 is not an oop
       assert(!is_vfinal(), "f2 not an oop");
       byte_no = 1;  // coordinate this with bytecode_number & is_resolved
--- a/hotspot/src/share/vm/oops/cpCacheOop.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -130,6 +130,7 @@
     assert(existing_f1 == NULL || existing_f1 == f1, "illegal field change");
     oop_store(&_f1, f1);
   }
+  void set_f1_if_null_atomic(oop f1);
   void set_f2(intx f2)                           { assert(_f2 == 0    || _f2 == f2, "illegal field change"); _f2 = f2; }
   int as_flags(TosState state, bool is_final, bool is_vfinal, bool is_volatile,
                bool is_method_interface, bool is_method);
@@ -318,7 +319,9 @@
 
   // Sizing
   debug_only(friend class ClassVerifier;)
+ public:
   int length() const                             { return _length; }
+ private:
   void set_length(int length)                    { _length = length; }
 
   static int header_size()                       { return sizeof(constantPoolCacheOopDesc) / HeapWordSize; }
--- a/hotspot/src/share/vm/oops/generateOopMap.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/oops/generateOopMap.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -1254,7 +1254,7 @@
       case Bytecodes::_invokestatic:
       case Bytecodes::_invokedynamic:
       case Bytecodes::_invokeinterface:
-        int idx = currentBC->has_index_u4() ? currentBC->get_index_u4() : currentBC->get_index_u2();
+        int idx = currentBC->has_index_u4() ? currentBC->get_index_u4() : currentBC->get_index_u2_cpcache();
         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->has_index_u4() ? currentBC->get_index_u4() : currentBC->get_index_u2();
+        int idx = currentBC->has_index_u4() ? currentBC->get_index_u4() : currentBC->get_index_u2_cpcache();
         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_u2(), itr->bci()); break;
+    case Bytecodes::_ldc:               // fall through:
+    case Bytecodes::_ldc_w:             do_ldc(itr->bci());         break;
 
     case Bytecodes::_iload:
     case Bytecodes::_fload:             ppload(vCTS, itr->get_index()); break;
@@ -1829,9 +1829,16 @@
 
 
 
-void GenerateOopMap::do_ldc(int idx, int bci) {
+void GenerateOopMap::do_ldc(int bci) {
+  Bytecode_loadconstant* ldc = Bytecode_loadconstant_at(method(), bci);
   constantPoolOop cp  = method()->constants();
-  CellTypeState   cts = cp->is_pointer_entry(idx) ? CellTypeState::make_line_ref(bci) : valCTS;
+  BasicType       bt  = ldc->result_type();
+  CellTypeState   cts = (bt == T_OBJECT) ? CellTypeState::make_line_ref(bci) : valCTS;
+  // Make sure bt==T_OBJECT is the same as old code (is_pointer_entry).
+  // Note that CONSTANT_MethodHandle entries are u2 index pairs, not pointer-entries,
+  // and they are processed by _fast_aldc and the CP cache.
+  assert((ldc->has_cache_index() || cp->is_pointer_entry(ldc->pool_index()))
+         ? (bt == T_OBJECT) : true, "expected object type");
   ppush1(cts);
 }
 
--- a/hotspot/src/share/vm/oops/generateOopMap.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/oops/generateOopMap.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -389,7 +389,7 @@
   void  pp                                  (CellTypeState *in, CellTypeState *out);
   void  pp_new_ref                          (CellTypeState *in, int bci);
   void  ppdupswap                           (int poplen, const char *out);
-  void  do_ldc                              (int idx, int bci);
+  void  do_ldc                              (int bci);
   void  do_astore                           (int idx);
   void  do_jsr                              (int delta);
   void  do_field                            (int is_get, int is_static, int idx, int bci);
--- a/hotspot/src/share/vm/opto/divnode.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/opto/divnode.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -388,7 +388,8 @@
     if (!d_pos) {
       q = new (phase->C, 3) SubLNode(phase->longcon(0), phase->transform(q));
     }
-  } else {
+  } else if ( !Matcher::use_asm_for_ldiv_by_con(d) ) { // Use hardware DIV instruction when
+                                                       // it is faster than code generated below.
     // Attempt the jlong constant divide -> multiply transform found in
     //   "Division by Invariant Integers using Multiplication"
     //     by Granlund and Montgomery
@@ -558,7 +559,7 @@
 
   set_req(0,NULL);              // Dividing by a not-zero constant; no faulting
 
-  // Dividing by MININT does not optimize as a power-of-2 shift.
+  // Dividing by MINLONG does not optimize as a power-of-2 shift.
   if( l == min_jlong ) return NULL;
 
   return transform_long_divide( phase, in(1), l );
@@ -1062,7 +1063,7 @@
   // Fell thru, the unroll case is not appropriate. Transform the modulo
   // into a long multiply/int multiply/subtract case
 
-  // Cannot handle mod 0, and min_jint isn't handled by the transform
+  // Cannot handle mod 0, and min_jlong isn't handled by the transform
   if( con == 0 || con == min_jlong ) return NULL;
 
   // Get the absolute value of the constant; at this point, we can use this
@@ -1075,7 +1076,7 @@
 
   // If this is a power of two, then maybe we can mask it
   if( is_power_of_2_long(pos_con) ) {
-    log2_con = log2_long(pos_con);
+    log2_con = exact_log2_long(pos_con);
 
     const Type *dt = phase->type(in(1));
     const TypeLong *dtl = dt->isa_long();
@@ -1088,7 +1089,7 @@
   // Save in(1) so that it cannot be changed or deleted
   hook->init_req(0, in(1));
 
-  // Divide using the transform from DivI to MulL
+  // Divide using the transform from DivL to MulL
   Node *result = transform_long_divide( phase, in(1), pos_con );
   if (result != NULL) {
     Node *divide = phase->transform(result);
--- a/hotspot/src/share/vm/opto/escape.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/opto/escape.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -85,6 +85,7 @@
   _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()),
   _processed(C->comp_arena()),
   _collecting(true),
+  _progress(false),
   _compile(C),
   _igvn(igvn),
   _node_map(C->comp_arena()) {
@@ -113,7 +114,7 @@
   assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set");
   assert(f->node_type() == PointsToNode::LocalVar || f->node_type() == PointsToNode::Field, "invalid source of PointsTo edge");
   assert(t->node_type() == PointsToNode::JavaObject, "invalid destination of PointsTo edge");
-  f->add_edge(to_i, PointsToNode::PointsToEdge);
+  add_edge(f, to_i, PointsToNode::PointsToEdge);
 }
 
 void ConnectionGraph::add_deferred_edge(uint from_i, uint to_i) {
@@ -126,7 +127,7 @@
   // don't add a self-referential edge, this can occur during removal of
   // deferred edges
   if (from_i != to_i)
-    f->add_edge(to_i, PointsToNode::DeferredEdge);
+    add_edge(f, to_i, PointsToNode::DeferredEdge);
 }
 
 int ConnectionGraph::address_offset(Node* adr, PhaseTransform *phase) {
@@ -157,7 +158,7 @@
   assert (t->offset() == -1 || t->offset() == offset, "conflicting field offsets");
   t->set_offset(offset);
 
-  f->add_edge(to_i, PointsToNode::FieldEdge);
+  add_edge(f, to_i, PointsToNode::FieldEdge);
 }
 
 void ConnectionGraph::set_escape_state(uint ni, PointsToNode::EscapeState es) {
@@ -995,7 +996,7 @@
   GrowableArray<Node *>  memnode_worklist;
   GrowableArray<PhiNode *>  orig_phis;
 
-  PhaseGVN  *igvn = _igvn;
+  PhaseIterGVN  *igvn = _igvn;
   uint new_index_start = (uint) _compile->num_alias_types();
   Arena* arena = Thread::current()->resource_area();
   VectorSet visited(arena);
@@ -1531,14 +1532,9 @@
       has_allocations = true;
     }
     if(n->is_AddP()) {
-      // Collect address nodes which directly reference an allocation.
-      // Use them during stage 3 below to build initial connection graph
-      // field edges. Other field edges could be added after StoreP/LoadP
-      // nodes are processed during stage 4 below.
-      Node* base = get_addp_base(n);
-      if(base->is_Proj() && base->in(0)->is_Allocate()) {
-        cg_worklist.append(n->_idx);
-      }
+      // Collect address nodes. Use them during stage 3 below
+      // to build initial connection graph field edges.
+      cg_worklist.append(n->_idx);
     } else if (n->is_MergeMem()) {
       // Collect all MergeMem nodes to add memory slices for
       // scalar replaceable objects in split_unique_types().
@@ -1562,18 +1558,28 @@
     build_connection_graph(n, igvn);
   }
 
-  // 3. Pass to create fields edges (Allocate -F-> AddP).
+  // 3. Pass to create initial fields edges (JavaObject -F-> AddP)
+  //    to reduce number of iterations during stage 4 below.
   uint cg_length = cg_worklist.length();
   for( uint next = 0; next < cg_length; ++next ) {
     int ni = cg_worklist.at(next);
-    build_connection_graph(ptnode_adr(ni)->_node, igvn);
+    Node* n = ptnode_adr(ni)->_node;
+    Node* base = get_addp_base(n);
+    if (base->is_Proj())
+      base = base->in(0);
+    PointsToNode::NodeType nt = ptnode_adr(base->_idx)->node_type();
+    if (nt == PointsToNode::JavaObject) {
+      build_connection_graph(n, igvn);
+    }
   }
 
   cg_worklist.clear();
   cg_worklist.append(_phantom_object);
+  GrowableArray<uint>  worklist;
 
   // 4. Build Connection Graph which need
   //    to walk the connection graph.
+  _progress = false;
   for (uint ni = 0; ni < nodes_size(); ni++) {
     PointsToNode* ptn = ptnode_adr(ni);
     Node *n = ptn->_node;
@@ -1581,13 +1587,52 @@
       build_connection_graph(n, igvn);
       if (ptn->node_type() != PointsToNode::UnknownType)
         cg_worklist.append(n->_idx); // Collect CG nodes
+      if (!_processed.test(n->_idx))
+        worklist.append(n->_idx); // Collect C/A/L/S nodes
     }
   }
 
+  // After IGVN user nodes may have smaller _idx than
+  // their inputs so they will be processed first in
+  // previous loop. Because of that not all Graph
+  // edges will be created. Walk over interesting
+  // nodes again until no new edges are created.
+  //
+  // Normally only 1-3 passes needed to build
+  // Connection Graph depending on graph complexity.
+  // Set limit to 10 to catch situation when something
+  // did go wrong and recompile the method without EA.
+
+#define CG_BUILD_ITER_LIMIT 10
+
+  uint length = worklist.length();
+  int iterations = 0;
+  while(_progress && (iterations++ < CG_BUILD_ITER_LIMIT)) {
+    _progress = false;
+    for( uint next = 0; next < length; ++next ) {
+      int ni = worklist.at(next);
+      PointsToNode* ptn = ptnode_adr(ni);
+      Node* n = ptn->_node;
+      assert(n != NULL, "should be known node");
+      build_connection_graph(n, igvn);
+    }
+  }
+  if (iterations >= CG_BUILD_ITER_LIMIT) {
+    assert(iterations < CG_BUILD_ITER_LIMIT,
+           err_msg("infinite EA connection graph build with %d nodes and worklist size %d",
+           nodes_size(), length));
+    // Possible infinite build_connection_graph loop,
+    // retry compilation without escape analysis.
+    C->record_failure(C2Compiler::retry_no_escape_analysis());
+    _collecting = false;
+    return false;
+  }
+#undef CG_BUILD_ITER_LIMIT
+
   Arena* arena = Thread::current()->resource_area();
   VectorSet ptset(arena);
-  GrowableArray<uint>  deferred_edges;
   VectorSet visited(arena);
+  worklist.clear();
 
   // 5. Remove deferred edges from the graph and adjust
   //    escape state of nonescaping objects.
@@ -1597,7 +1642,7 @@
     PointsToNode* ptn = ptnode_adr(ni);
     PointsToNode::NodeType nt = ptn->node_type();
     if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) {
-      remove_deferred(ni, &deferred_edges, &visited);
+      remove_deferred(ni, &worklist, &visited);
       Node *n = ptn->_node;
       if (n->is_AddP()) {
         // Search for objects which are not scalar replaceable
@@ -1608,7 +1653,7 @@
   }
 
   // 6. Propagate escape states.
-  GrowableArray<int>  worklist;
+  worklist.clear();
   bool has_non_escaping_obj = false;
 
   // push all GlobalEscape nodes on the worklist
@@ -2444,13 +2489,14 @@
 
   // Don't set processed bit for AddP, LoadP, StoreP since
   // they may need more then one pass to process.
+  // Also don't mark as processed Call nodes since their
+  // arguments may need more then one pass to process.
   if (_processed.test(n_idx))
     return; // No need to redefine node's state.
 
   if (n->is_Call()) {
     CallNode *call = n->as_Call();
     process_call_arguments(call, phase);
-    _processed.set(n_idx);
     return;
   }
 
--- a/hotspot/src/share/vm/opto/escape.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/opto/escape.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -219,6 +219,9 @@
                                        // is still being collected. If false,
                                        // no new nodes will be processed.
 
+  bool                    _progress;   // Indicates whether new Graph's edges
+                                       // were created.
+
   uint                _phantom_object; // Index of globally escaping object
                                        // that pointer values loaded from
                                        // a field which has not been set
@@ -266,6 +269,13 @@
   void add_deferred_edge(uint from_i, uint to_i);
   void add_field_edge(uint from_i, uint to_i, int offs);
 
+  // Add an edge of the specified type pointing to the specified target.
+  // Set _progress if new edge is added.
+  void add_edge(PointsToNode *f, uint to_i, PointsToNode::EdgeType et) {
+    uint e_cnt = f->edge_count();
+    f->add_edge(to_i, et);
+    _progress |= (f->edge_count() != e_cnt);
+  }
 
   // Add an edge to node given by "to_i" from any field of adr_i whose offset
   // matches "offset"  A deferred edge is added if to_i is a LocalVar, and
--- a/hotspot/src/share/vm/opto/matcher.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/opto/matcher.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -298,6 +298,10 @@
   // Register for MODL projection of divmodL
   static RegMask modL_proj_mask();
 
+  // Use hardware DIV instruction when it is faster than
+  // a code which use multiply for division by constant.
+  static bool use_asm_for_ldiv_by_con( jlong divisor );
+
   static const RegMask method_handle_invoke_SP_save_mask();
 
   // Java-Interpreter calling convention
--- a/hotspot/src/share/vm/prims/jvm.h	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/prims/jvm.h	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -1047,7 +1047,8 @@
     JVM_CONSTANT_NameAndType,
     JVM_CONSTANT_MethodHandle           = 15,  // JSR 292
     JVM_CONSTANT_MethodType             = 16,  // JSR 292
-    JVM_CONSTANT_InvokeDynamic          = 17  // JSR 292
+    JVM_CONSTANT_InvokeDynamicTrans     = 17,  // JSR 292, only occurs in old class files
+    JVM_CONSTANT_InvokeDynamic          = 18   // JSR 292
 };
 
 /* JVM_CONSTANT_MethodHandle subtypes */
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -1407,8 +1407,7 @@
     // If any of the top 2 frames is a compiled one, need to deoptimize it
     for (int i = 0; i < 2; i++) {
       if (!is_interpreted[i]) {
-        VM_DeoptimizeFrame op(java_thread, frame_sp[i]);
-        VMThread::execute(&op);
+        Deoptimization::deoptimize_frame(java_thread, frame_sp[i]);
       }
     }
 
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -1322,8 +1322,7 @@
     if (!vf->fr().can_be_deoptimized()) {
       return JVMTI_ERROR_OPAQUE_FRAME;
     }
-    VM_DeoptimizeFrame deopt(java_thread, jvf->fr().id());
-    VMThread::execute(&deopt);
+    Deoptimization::deoptimize_frame(java_thread, jvf->fr().id());
   }
 
   // Get information about method return type
--- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -728,8 +728,7 @@
 
       // Schedule deoptimization so that eventually the local
       // update will be written to an interpreter frame.
-      VM_DeoptimizeFrame deopt(_jvf->thread(), _jvf->fr().id());
-      VMThread::execute(&deopt);
+      Deoptimization::deoptimize_frame(_jvf->thread(), _jvf->fr().id());
 
       // Now store a new value for the local which will be applied
       // once deoptimization occurs. Note however that while this
--- a/hotspot/src/share/vm/prims/methodComparator.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/prims/methodComparator.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -147,10 +147,9 @@
   case Bytecodes::_invokevirtual   : // fall through
   case Bytecodes::_invokespecial   : // fall through
   case Bytecodes::_invokestatic    : // fall through
-  case Bytecodes::_invokedynamic   : // fall through
   case Bytecodes::_invokeinterface : {
-    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();
+    int cpci_old = _s_old->get_index_u2_cpcache();
+    int cpci_new = _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.
@@ -160,6 +159,33 @@
       return false;
     break;
   }
+  case Bytecodes::_invokedynamic: {
+    int cpci_old = _s_old->get_index_u4();
+    int cpci_new = _s_new->get_index_u4();
+    // 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.
+    if ((_old_cp->name_ref_at(cpci_old) != _new_cp->name_ref_at(cpci_new)) ||
+        (_old_cp->signature_ref_at(cpci_old) != _new_cp->signature_ref_at(cpci_new)))
+      return false;
+    int cpi_old = _old_cp->cache()->main_entry_at(cpci_old)->constant_pool_index();
+    int cpi_new = _new_cp->cache()->main_entry_at(cpci_new)->constant_pool_index();
+    int bsm_old = _old_cp->invoke_dynamic_bootstrap_method_ref_index_at(cpi_old);
+    int bsm_new = _new_cp->invoke_dynamic_bootstrap_method_ref_index_at(cpi_new);
+    if (!pool_constants_same(bsm_old, bsm_new))
+      return false;
+    int cnt_old = _old_cp->invoke_dynamic_argument_count_at(cpi_old);
+    int cnt_new = _new_cp->invoke_dynamic_argument_count_at(cpi_new);
+    if (cnt_old != cnt_new)
+      return false;
+    for (int arg_i = 0; arg_i < cnt_old; arg_i++) {
+      int idx_old = _old_cp->invoke_dynamic_argument_index_at(cpi_old, arg_i);
+      int idx_new = _new_cp->invoke_dynamic_argument_index_at(cpi_new, arg_i);
+      if (!pool_constants_same(idx_old, idx_new))
+        return false;
+    }
+    break;
+  }
 
   case Bytecodes::_ldc   : // fall through
   case Bytecodes::_ldc_w : {
@@ -167,51 +193,8 @@
     Bytecode_loadconstant* ldc_new = Bytecode_loadconstant_at(_s_new->method(), _s_new->bci());
     int cpi_old = ldc_old->pool_index();
     int cpi_new = ldc_new->pool_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()) {
-      if (tag_old.value() != tag_new.value())
-        return false;
-      if (tag_old.is_int()) {
-        if (_old_cp->int_at(cpi_old) != _new_cp->int_at(cpi_new))
-          return false;
-      } else {
-        // 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()) {
-      if (! (tag_new.is_unresolved_string() || tag_new.is_string()))
-        return false;
-      if (strcmp(_old_cp->string_at_noresolve(cpi_old),
-                 _new_cp->string_at_noresolve(cpi_new)) != 0)
-        return false;
-    } else if (tag_old.is_klass() || tag_old.is_unresolved_klass()) {
-      // tag_old should be klass - 4881222
-      if (! (tag_new.is_unresolved_klass() || tag_new.is_klass()))
-        return false;
-      if (_old_cp->klass_at_noresolve(cpi_old) !=
-          _new_cp->klass_at_noresolve(cpi_new))
-        return false;
-    } else if (tag_old.is_method_type() && tag_new.is_method_type()) {
-      int mti_old = _old_cp->method_type_index_at(cpi_old);
-      int mti_new = _new_cp->method_type_index_at(cpi_new);
-      if ((_old_cp->symbol_at(mti_old) != _new_cp->symbol_at(mti_new)))
-        return false;
-    } else if (tag_old.is_method_handle() && tag_new.is_method_handle()) {
-      if (_old_cp->method_handle_ref_kind_at(cpi_old) !=
-          _new_cp->method_handle_ref_kind_at(cpi_new))
-        return false;
-      int mhi_old = _old_cp->method_handle_index_at(cpi_old);
-      int mhi_new = _new_cp->method_handle_index_at(cpi_new);
-      if ((_old_cp->uncached_klass_ref_at_noresolve(mhi_old) != _new_cp->uncached_klass_ref_at_noresolve(mhi_new)) ||
-          (_old_cp->uncached_name_ref_at(mhi_old) != _new_cp->uncached_name_ref_at(mhi_new)) ||
-          (_old_cp->uncached_signature_ref_at(mhi_old) != _new_cp->uncached_signature_ref_at(mhi_new)))
-        return false;
-    } else {
-      return false;  // unknown tag
-    }
+    if (!pool_constants_same(cpi_old, cpi_new))
+      return false;
     break;
   }
 
@@ -392,6 +375,55 @@
   return true;
 }
 
+bool MethodComparator::pool_constants_same(int cpi_old, int cpi_new) {
+  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()) {
+    if (tag_old.value() != tag_new.value())
+      return false;
+    if (tag_old.is_int()) {
+      if (_old_cp->int_at(cpi_old) != _new_cp->int_at(cpi_new))
+        return false;
+    } else {
+      // 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()) {
+    if (! (tag_new.is_unresolved_string() || tag_new.is_string()))
+      return false;
+    if (strcmp(_old_cp->string_at_noresolve(cpi_old),
+               _new_cp->string_at_noresolve(cpi_new)) != 0)
+      return false;
+  } else if (tag_old.is_klass() || tag_old.is_unresolved_klass()) {
+    // tag_old should be klass - 4881222
+    if (! (tag_new.is_unresolved_klass() || tag_new.is_klass()))
+      return false;
+    if (_old_cp->klass_at_noresolve(cpi_old) !=
+        _new_cp->klass_at_noresolve(cpi_new))
+      return false;
+  } else if (tag_old.is_method_type() && tag_new.is_method_type()) {
+    int mti_old = _old_cp->method_type_index_at(cpi_old);
+    int mti_new = _new_cp->method_type_index_at(cpi_new);
+    if ((_old_cp->symbol_at(mti_old) != _new_cp->symbol_at(mti_new)))
+      return false;
+  } else if (tag_old.is_method_handle() && tag_new.is_method_handle()) {
+    if (_old_cp->method_handle_ref_kind_at(cpi_old) !=
+        _new_cp->method_handle_ref_kind_at(cpi_new))
+      return false;
+    int mhi_old = _old_cp->method_handle_index_at(cpi_old);
+    int mhi_new = _new_cp->method_handle_index_at(cpi_new);
+    if ((_old_cp->uncached_klass_ref_at_noresolve(mhi_old) != _new_cp->uncached_klass_ref_at_noresolve(mhi_new)) ||
+        (_old_cp->uncached_name_ref_at(mhi_old) != _new_cp->uncached_name_ref_at(mhi_new)) ||
+        (_old_cp->uncached_signature_ref_at(mhi_old) != _new_cp->uncached_signature_ref_at(mhi_new)))
+      return false;
+  } else {
+    return false;  // unknown tag
+  }
+  return true;
+}
+
 
 int MethodComparator::check_stack_and_locals_size(methodOop old_method, methodOop new_method) {
   if (old_method->max_stack() != new_method->max_stack()) {
--- a/hotspot/src/share/vm/prims/methodComparator.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/prims/methodComparator.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2005, 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
@@ -36,6 +36,7 @@
   static GrowableArray<int> *_fwd_jmps;
 
   static bool args_same(Bytecodes::Code c_old, Bytecodes::Code c_new);
+  static bool pool_constants_same(int cpi_old, int cpi_new);
   static int check_stack_and_locals_size(methodOop old_method, methodOop new_method);
 
  public:
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -974,6 +974,8 @@
   assert(src != T_VOID && dst != T_VOID, "should not be here");
   if (src == dst)  return true;
   if (type2size[src] != type2size[dst])  return false;
+  if (src == T_OBJECT || dst == T_OBJECT)  return false;
+  if (raw)  return true;  // bitwise reinterpretation; caller guarantees safety
   // allow reinterpretation casts for integral widening
   if (is_subword_type(src)) { // subwords can fit in int or other subwords
     if (dst == T_INT)         // any subword fits in an int
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -1065,7 +1065,9 @@
 }
 
 
-void Deoptimization::deoptimize_frame(JavaThread* thread, intptr_t* id) {
+void Deoptimization::deoptimize_frame_internal(JavaThread* thread, intptr_t* id) {
+  assert(thread == Thread::current() || SafepointSynchronize::is_at_safepoint(),
+         "can only deoptimize other thread at a safepoint");
   // Compute frame and register map based on thread and sp.
   RegisterMap reg_map(thread, UseBiasedLocking);
   frame fr = thread->last_frame();
@@ -1076,6 +1078,16 @@
 }
 
 
+void Deoptimization::deoptimize_frame(JavaThread* thread, intptr_t* id) {
+  if (thread == Thread::current()) {
+    Deoptimization::deoptimize_frame_internal(thread, id);
+  } else {
+    VM_DeoptimizeFrame deopt(thread, id);
+    VMThread::execute(&deopt);
+  }
+}
+
+
 // JVMTI PopFrame support
 JRT_LEAF(void, Deoptimization::popframe_preserve_args(JavaThread* thread, int bytes_to_save, void* start_address))
 {
--- a/hotspot/src/share/vm/runtime/deoptimization.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/runtime/deoptimization.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -216,6 +216,10 @@
   // Only called from VMDeoptimizeFrame
   // @argument thread.     Thread where stub_frame resides.
   // @argument id.         id of frame that should be deoptimized.
+  static void deoptimize_frame_internal(JavaThread* thread, intptr_t* id);
+
+  // If thread is not the current thread then execute
+  // VM_DeoptimizeFrame otherwise deoptimize directly.
   static void deoptimize_frame(JavaThread* thread, intptr_t* id);
 
   // Statistics
--- a/hotspot/src/share/vm/runtime/frame.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/runtime/frame.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -878,7 +878,7 @@
 
 #endif /* CC_INTERP */
 
-#ifndef PPC
+#if !defined(PPC) || defined(ZERO)
   if (m->is_native()) {
 #ifdef CC_INTERP
     f->do_oop((oop*)&istate->_oop_temp);
--- a/hotspot/src/share/vm/runtime/java.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/runtime/java.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -198,7 +198,7 @@
   if (CountCompiledCalls) {
     print_method_invocation_histogram();
   }
-  if (ProfileInterpreter || C1UpdateMethodData) {
+  if (ProfileInterpreter COMPILER1_PRESENT(|| C1UpdateMethodData)) {
     print_method_profiling_data();
   }
   if (TimeCompiler) {
--- a/hotspot/src/share/vm/runtime/os.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -736,8 +736,8 @@
 }
 
 // moved from debug.cpp (used to be find()) but still called from there
-// The print_pc parameter is only set by the debug code in one case
-void os::print_location(outputStream* st, intptr_t x, bool print_pc) {
+// The verbose parameter is only set by the debug code in one case
+void os::print_location(outputStream* st, intptr_t x, bool verbose) {
   address addr = (address)x;
   CodeBlob* b = CodeCache::find_blob_unsafe(addr);
   if (b != NULL) {
@@ -745,6 +745,7 @@
       // the interpreter is generated into a buffer blob
       InterpreterCodelet* i = Interpreter::codelet_containing(addr);
       if (i != NULL) {
+        st->print_cr(INTPTR_FORMAT " is an Interpreter codelet", addr);
         i->print_on(st);
         return;
       }
@@ -755,14 +756,14 @@
       }
       //
       if (AdapterHandlerLibrary::contains(b)) {
-        st->print_cr("Printing AdapterHandler");
+        st->print_cr(INTPTR_FORMAT " is an AdapterHandler", addr);
         AdapterHandlerLibrary::print_handler_on(st, b);
       }
       // the stubroutines are generated into a buffer blob
       StubCodeDesc* d = StubCodeDesc::desc_for(addr);
       if (d != NULL) {
         d->print_on(st);
-        if (print_pc) st->cr();
+        if (verbose) st->cr();
         return;
       }
       if (StubRoutines::contains(addr)) {
@@ -781,7 +782,7 @@
         return;
       }
     }
-    if (print_pc && b->is_nmethod()) {
+    if (verbose && b->is_nmethod()) {
       ResourceMark rm;
       st->print("%#p: Compiled ", addr);
       ((nmethod*)b)->method()->print_value_on(st);
@@ -789,11 +790,12 @@
       st->cr();
       return;
     }
+    st->print(INTPTR_FORMAT " ", b);
     if ( b->is_nmethod()) {
       if (b->is_zombie()) {
-        st->print_cr(INTPTR_FORMAT " is zombie nmethod", b);
+        st->print_cr("is zombie nmethod");
       } else if (b->is_not_entrant()) {
-        st->print_cr(INTPTR_FORMAT " is non-entrant nmethod", b);
+        st->print_cr("is non-entrant nmethod");
       }
     }
     b->print_on(st);
@@ -812,6 +814,7 @@
       print = true;
     }
     if (print) {
+      st->print_cr(INTPTR_FORMAT " is an oop", addr);
       oop(p)->print_on(st);
       if (p != (HeapWord*)x && oop(p)->is_constMethod() &&
           constMethodOop(p)->contains(addr)) {
@@ -855,12 +858,16 @@
         thread->privileged_stack_top()->contains(addr)) {
       st->print_cr(INTPTR_FORMAT " is pointing into the privilege stack "
                    "for thread: " INTPTR_FORMAT, addr, thread);
-      thread->print_on(st);
+      if (verbose) thread->print_on(st);
       return;
     }
     // If the addr is a java thread print information about that.
     if (addr == (address)thread) {
-      thread->print_on(st);
+      if (verbose) {
+        thread->print_on(st);
+      } else {
+        st->print_cr(INTPTR_FORMAT " is a thread", addr);
+      }
       return;
     }
     // If the addr is in the stack region for this thread then report that
@@ -869,7 +876,7 @@
         addr > (thread->stack_base() - thread->stack_size())) {
       st->print_cr(INTPTR_FORMAT " is pointing into the stack for thread: "
                    INTPTR_FORMAT, addr, thread);
-      thread->print_on(st);
+      if (verbose) thread->print_on(st);
       return;
     }
 
@@ -879,7 +886,7 @@
     return;
   }
 
-  st->print_cr(INTPTR_FORMAT " is pointing to unknown location", addr);
+  st->print_cr(INTPTR_FORMAT " is an unknown value", addr);
 }
 
 // Looks like all platforms except IA64 can use the same function to check
--- a/hotspot/src/share/vm/runtime/os.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/runtime/os.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -450,11 +450,12 @@
   static void print_dll_info(outputStream* st);
   static void print_environment_variables(outputStream* st, const char** env_list, char* buffer, int len);
   static void print_context(outputStream* st, void* context);
+  static void print_register_info(outputStream* st, void* context);
   static void print_siginfo(outputStream* st, void* siginfo);
   static void print_signal_handlers(outputStream* st, char* buf, size_t buflen);
   static void print_date_and_time(outputStream* st);
 
-  static void print_location(outputStream* st, intptr_t x, bool print_pc = false);
+  static void print_location(outputStream* st, intptr_t x, bool verbose = false);
 
   // The following two functions are used by fatal error handler to trace
   // native (C) frames. They are not part of frame.hpp/frame.cpp because
--- a/hotspot/src/share/vm/runtime/safepoint.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -940,8 +940,7 @@
     // as otherwise we may never deliver it.
     if (thread()->has_async_condition()) {
       ThreadInVMfromJavaNoAsyncException __tiv(thread());
-      VM_DeoptimizeFrame deopt(thread(), caller_fr.id());
-      VMThread::execute(&deopt);
+      Deoptimization::deoptimize_frame(thread(), caller_fr.id());
     }
 
     // If an exception has been installed we must check for a pending deoptimization
--- a/hotspot/src/share/vm/runtime/thread.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -1199,6 +1199,7 @@
   _exception_pc  = 0;
   _exception_handler_pc = 0;
   _exception_stack_size = 0;
+  _is_method_handle_return = 0;
   _jvmti_thread_state= NULL;
   _should_post_on_exceptions_flag = JNI_FALSE;
   _jvmti_get_loaded_classes_closure = NULL;
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -86,6 +86,7 @@
   nonstatic_field(constantPoolOopDesc,         _tags,                                         typeArrayOop)                          \
   nonstatic_field(constantPoolOopDesc,         _cache,                                        constantPoolCacheOop)                  \
   nonstatic_field(constantPoolOopDesc,         _pool_holder,                                  klassOop)                              \
+  nonstatic_field(constantPoolOopDesc,         _operands,                                     typeArrayOop)                          \
   nonstatic_field(constantPoolOopDesc,         _length,                                       int)                                   \
   nonstatic_field(constantPoolCacheOopDesc,    _length,                                       int)                                   \
   nonstatic_field(constantPoolCacheOopDesc,    _constant_pool,                                constantPoolOop)                       \
@@ -1527,6 +1528,17 @@
                                                                           \
   declare_constant(symbolOopDesc::max_symbol_length)                      \
                                                                           \
+  /*************************************************/                     \
+  /* constantPoolOop layout enum for InvokeDynamic */                     \
+  /*************************************************/                     \
+                                                                          \
+  declare_constant(constantPoolOopDesc::_multi_operand_count_offset)      \
+  declare_constant(constantPoolOopDesc::_multi_operand_base_offset)       \
+  declare_constant(constantPoolOopDesc::_indy_bsm_offset)                 \
+  declare_constant(constantPoolOopDesc::_indy_nt_offset)                  \
+  declare_constant(constantPoolOopDesc::_indy_argc_offset)                \
+  declare_constant(constantPoolOopDesc::_indy_argv_offset)                \
+                                                                          \
   /*********************************************/                         \
   /* ConstantPoolCacheEntry FlagBitValues enum */                         \
   /*********************************************/                         \
--- a/hotspot/src/share/vm/runtime/vm_operations.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/runtime/vm_operations.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -100,7 +100,7 @@
 
 
 void VM_DeoptimizeFrame::doit() {
-  Deoptimization::deoptimize_frame(_thread, _id);
+  Deoptimization::deoptimize_frame_internal(_thread, _id);
 }
 
 
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -231,12 +231,18 @@
   bool allow_nested_vm_operations() const        { return true; }
 };
 
+
+// Deopt helper that can deoptimize frames in threads other than the
+// current thread.  Only used through Deoptimization::deoptimize_frame.
 class VM_DeoptimizeFrame: public VM_Operation {
+  friend class Deoptimization;
+
  private:
   JavaThread* _thread;
   intptr_t*   _id;
+  VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id);
+
  public:
-  VM_DeoptimizeFrame(JavaThread* thread, intptr_t* id);
   VMOp_Type type() const                         { return VMOp_DeoptimizeFrame; }
   void doit();
   bool allow_nested_vm_operations() const        { return true;  }
--- a/hotspot/src/share/vm/utilities/constantTag.hpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/utilities/constantTag.hpp	Mon Nov 08 14:33:48 2010 -0800
@@ -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
@@ -82,6 +82,13 @@
   bool is_method_handle() const            { return _tag == JVM_CONSTANT_MethodHandle; }
   bool is_invoke_dynamic() const           { return _tag == JVM_CONSTANT_InvokeDynamic; }
 
+  bool is_loadable_constant() const {
+    return ((_tag >= JVM_CONSTANT_Integer && _tag <= JVM_CONSTANT_String) ||
+            is_method_type() || is_method_handle() ||
+            is_unresolved_klass() || is_unresolved_string() ||
+            is_object());
+  }
+
   constantTag() {
     _tag = JVM_CONSTANT_Invalid;
   }
--- a/hotspot/src/share/vm/utilities/vmError.cpp	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/src/share/vm/utilities/vmError.cpp	Mon Nov 08 14:33:48 2010 -0800
@@ -455,6 +455,14 @@
        st->cr();
      }
 
+  STEP(105, "(printing register info)")
+
+     // decode register contents if possible
+     if (_verbose && _context && Universe::is_fully_initialized()) {
+       os::print_register_info(st, _context);
+       st->cr();
+     }
+
   STEP(110, "(printing stack bounds)" )
 
      if (_verbose) {
@@ -522,7 +530,7 @@
   STEP(135, "(printing target Java thread stack)" )
 
      // printing Java thread stack trace if it is involved in GC crash
-     if (_verbose && (_thread->is_Named_thread())) {
+     if (_verbose && _thread && (_thread->is_Named_thread())) {
        JavaThread*  jt = ((NamedThread *)_thread)->processed_thread();
        if (jt != NULL) {
          st->print_cr("JavaThread " PTR_FORMAT " (nid = " UINTX_FORMAT ") was being processed", jt, jt->osthread()->thread_id());
@@ -608,6 +616,14 @@
        st->cr();
      }
 
+  STEP(195, "(printing code cache information)" )
+
+     if (_verbose && Universe::is_fully_initialized()) {
+       // print code cache information before vm abort
+       CodeCache::print_bounds(st);
+       st->cr();
+     }
+
   STEP(200, "(printing dynamic libraries)" )
 
      if (_verbose) {
--- a/hotspot/test/Makefile	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/test/Makefile	Mon Nov 08 14:33:48 2010 -0800
@@ -78,7 +78,11 @@
 TEST_ROOT := $(shell pwd)
 
 # Root of all test results
-ABS_BUILD_ROOT = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH)
+ifdef ALT_OUTPUTDIR
+  ABS_BUILD_ROOT = $(ALT_OUTPUTDIR)/$(PLATFORM)-$(ARCH)
+else
+  ABS_BUILD_ROOT = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH)
+endif
 ABS_TEST_OUTPUT_DIR = $(ABS_BUILD_ROOT)/testoutput
 
 # Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test)
--- a/hotspot/test/compiler/6603011/Test.java	Thu Nov 04 16:17:54 2010 -0700
+++ b/hotspot/test/compiler/6603011/Test.java	Mon Nov 08 14:33:48 2010 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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
@@ -108,8 +108,10 @@
 
     if (quo != quo0 || rem != rem0) {
       if (VERBOSE) {
-        System.out.println("  " + dividend + " / " + divisor() + " = " +
-                           quo + ", " + dividend + " % " + divisor() + " = " + rem);
+        System.out.println("Computed: " + dividend + " / " + divisor() + " = " +
+                           quo  + ", " + dividend + " % " + divisor() + " = " + rem );
+        System.out.println("expected: " + dividend + " / " + divisor() + " = " +
+                           quo0 + ", " + dividend + " % " + divisor() + " = " + rem0);
         // Report sign of rem failure
         if (rem != 0 && (rem ^ dividend) < 0) {
           System.out.println("  rem & dividend have different signs");
@@ -168,7 +170,7 @@
     for (int i = start; i <= end; i++) {
       for (int s = 0; s < 64; s += 4) {
         total++;
-        long dividend = i << s;
+        long dividend = ((long)i) << s;
         if (!checkL(dividend)) {
           wrong++;
           // Stop on the first failure
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6991596/Test6991596.java	Mon Nov 08 14:33:48 2010 -0800
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6991596
+ * @summary JSR 292 unimplemented adapter_opt_i2i and adapter_opt_l2i on SPARC
+ *
+ * @run main/othervm -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6991596
+ */
+
+import java.dyn.*;
+
+public class Test6991596 {
+    private static final Class   CLASS = Test6991596.class;
+    private static final String  NAME  = "foo";
+    private static final boolean DEBUG = false;
+
+    public static void main(String[] args) throws Throwable {
+        testboolean();
+        testbyte();
+        testchar();
+        testshort();
+        testint();
+        testlong();
+    }
+
+    // Helpers to get various methods.
+    static MethodHandle getmh1(Class ret, Class arg) {
+        return MethodHandles.lookup().findStatic(CLASS, NAME, MethodType.methodType(ret, arg));
+    }
+    static MethodHandle getmh2(MethodHandle mh1, Class ret, Class arg) {
+        return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
+    }
+    static MethodHandle getmh3(MethodHandle mh1, Class ret, Class arg) {
+        return MethodHandles.convertArguments(mh1, MethodType.methodType(ret, arg));
+    }
+
+    // test adapter_opt_i2i
+    static void testboolean() throws Throwable {
+        boolean[] a = new boolean[] {
+            true,
+            false
+        };
+        for (int i = 0; i < a.length; i++) {
+            doboolean(a[i]);
+        }
+    }
+    static void doboolean(boolean x) throws Throwable {
+        if (DEBUG)  System.out.println("boolean=" + x);
+
+        // boolean
+        {
+            MethodHandle mh1 = getmh1(     boolean.class, boolean.class);
+            MethodHandle mh2 = getmh2(mh1, boolean.class, boolean.class);
+            // TODO add this for all cases when the bugs are fixed.
+            //MethodHandle mh3 = getmh3(mh1, boolean.class, boolean.class);
+            boolean a = mh1.<boolean>invokeExact((boolean) x);
+            boolean b = mh2.<boolean>invokeExact(x);
+            //boolean c = mh3.<boolean>invokeExact((boolean) x);
+            assert a == b : a + " != " + b;
+            //assert c == x : c + " != " + x;
+        }
+
+        // byte
+        {
+            MethodHandle mh1 = getmh1(     byte.class,    byte.class   );
+            MethodHandle mh2 = getmh2(mh1, byte.class,    boolean.class);
+            byte    a = mh1.<byte>invokeExact((byte) (x ? 1 : 0));
+            byte    b = mh2.<byte>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // char
+        {
+            MethodHandle mh1 = getmh1(     char.class, char.class);
+            MethodHandle mh2 = getmh2(mh1, char.class, boolean.class);
+            char a = mh1.<char>invokeExact((char) (x ? 1 : 0));
+            char b = mh2.<char>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // short
+        {
+            MethodHandle mh1 = getmh1(     short.class, short.class);
+            MethodHandle mh2 = getmh2(mh1, short.class, boolean.class);
+            short a = mh1.<short>invokeExact((short) (x ? 1 : 0));
+            short b = mh2.<short>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+    }
+
+    static void testbyte() throws Throwable {
+        byte[] a = new byte[] {
+            Byte.MIN_VALUE,
+            Byte.MIN_VALUE + 1,
+            -0x0F,
+            -1,
+            0,
+            1,
+            0x0F,
+            Byte.MAX_VALUE - 1,
+            Byte.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            dobyte(a[i]);
+        }
+    }
+    static void dobyte(byte x) throws Throwable {
+        if (DEBUG)  System.out.println("byte=" + x);
+
+        // boolean
+        {
+            MethodHandle mh1 = getmh1(     boolean.class, boolean.class);
+            MethodHandle mh2 = getmh2(mh1, boolean.class, byte.class);
+            boolean a = mh1.<boolean>invokeExact((x & 1) == 1);
+            boolean b = mh2.<boolean>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // byte
+        {
+            MethodHandle mh1 = getmh1(     byte.class, byte.class);
+            MethodHandle mh2 = getmh2(mh1, byte.class, byte.class);
+            byte a = mh1.<byte>invokeExact((byte) x);
+            byte b = mh2.<byte>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // char
+        {
+            MethodHandle mh1 = getmh1(     char.class, char.class);
+            MethodHandle mh2 = getmh2(mh1, char.class, byte.class);
+            char a = mh1.<char>invokeExact((char) x);
+            char b = mh2.<char>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // short
+        {
+            MethodHandle mh1 = getmh1(     short.class, short.class);
+            MethodHandle mh2 = getmh2(mh1, short.class, byte.class);
+            short a = mh1.<short>invokeExact((short) x);
+            short b = mh2.<short>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+    }
+
+    static void testchar() throws Throwable {
+        char[] a = new char[] {
+            Character.MIN_VALUE,
+            Character.MIN_VALUE + 1,
+            0x000F,
+            0x00FF,
+            0x0FFF,
+            Character.MAX_VALUE - 1,
+            Character.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            dochar(a[i]);
+        }
+    }
+    static void dochar(char x) throws Throwable {
+        if (DEBUG)  System.out.println("char=" + x);
+
+        // boolean
+        {
+            MethodHandle mh1 = getmh1(     boolean.class, boolean.class);
+            MethodHandle mh2 = getmh2(mh1, boolean.class, char.class);
+            boolean a = mh1.<boolean>invokeExact((x & 1) == 1);
+            boolean b = mh2.<boolean>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // byte
+        {
+            MethodHandle mh1 = getmh1(     byte.class, byte.class);
+            MethodHandle mh2 = getmh2(mh1, byte.class, char.class);
+            byte a = mh1.<byte>invokeExact((byte) x);
+            byte b = mh2.<byte>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // char
+        {
+            MethodHandle mh1 = getmh1(     char.class, char.class);
+            MethodHandle mh2 = getmh2(mh1, char.class, char.class);
+            char a = mh1.<char>invokeExact((char) x);
+            char b = mh2.<char>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // short
+        {
+            MethodHandle mh1 = getmh1(     short.class, short.class);
+            MethodHandle mh2 = getmh2(mh1, short.class, char.class);
+            short a = mh1.<short>invokeExact((short) x);
+            short b = mh2.<short>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+    }
+
+    static void testshort() throws Throwable {
+        short[] a = new short[] {
+            Short.MIN_VALUE,
+            Short.MIN_VALUE + 1,
+            -0x0FFF,
+            -0x00FF,
+            -0x000F,
+            -1,
+            0,
+            1,
+            0x000F,
+            0x00FF,
+            0x0FFF,
+            Short.MAX_VALUE - 1,
+            Short.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            doshort(a[i]);
+        }
+    }
+    static void doshort(short x) throws Throwable {
+        if (DEBUG)  System.out.println("short=" + x);
+
+        // boolean
+        {
+            MethodHandle mh1 = getmh1(     boolean.class, boolean.class);
+            MethodHandle mh2 = getmh2(mh1, boolean.class, short.class);
+            boolean a = mh1.<boolean>invokeExact((x & 1) == 1);
+            boolean b = mh2.<boolean>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // byte
+        {
+            MethodHandle mh1 = getmh1(     byte.class, byte.class);
+            MethodHandle mh2 = getmh2(mh1, byte.class, short.class);
+            byte a = mh1.<byte>invokeExact((byte) x);
+            byte b = mh2.<byte>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // char
+        {
+            MethodHandle mh1 = getmh1(     char.class, char.class);
+            MethodHandle mh2 = getmh2(mh1, char.class, short.class);
+            char a = mh1.<char>invokeExact((char) x);
+            char b = mh2.<char>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // short
+        {
+            MethodHandle mh1 = getmh1(     short.class, short.class);
+            MethodHandle mh2 = getmh2(mh1, short.class, short.class);
+            short a = mh1.<short>invokeExact((short) x);
+            short b = mh2.<short>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+    }
+
+    static void testint() throws Throwable {
+        int[] a = new int[] {
+            Integer.MIN_VALUE,
+            Integer.MIN_VALUE + 1,
+            -0x0FFFFFFF,
+            -0x00FFFFFF,
+            -0x000FFFFF,
+            -0x0000FFFF,
+            -0x00000FFF,
+            -0x000000FF,
+            -0x0000000F,
+            -1,
+            0,
+            1,
+            0x0000000F,
+            0x000000FF,
+            0x00000FFF,
+            0x0000FFFF,
+            0x000FFFFF,
+            0x00FFFFFF,
+            0x0FFFFFFF,
+            Integer.MAX_VALUE - 1,
+            Integer.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            doint(a[i]);
+        }
+    }
+    static void doint(int x) throws Throwable {
+        if (DEBUG)  System.out.println("int=" + x);
+
+        // boolean
+        {
+            MethodHandle mh1 = getmh1(     boolean.class, boolean.class);
+            MethodHandle mh2 = getmh2(mh1, boolean.class, int.class);
+            boolean a = mh1.<boolean>invokeExact((x & 1) == 1);
+            boolean b = mh2.<boolean>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // byte
+        {
+            MethodHandle mh1 = getmh1(     byte.class, byte.class);
+            MethodHandle mh2 = getmh2(mh1, byte.class, int.class);
+            byte a = mh1.<byte>invokeExact((byte) x);
+            byte b = mh2.<byte>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // char
+        {
+            MethodHandle mh1 = getmh1(     char.class, char.class);
+            MethodHandle mh2 = getmh2(mh1, char.class, int.class);
+            char a = mh1.<char>invokeExact((char) x);
+            char b = mh2.<char>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // short
+        {
+            MethodHandle mh1 = getmh1(     short.class, short.class);
+            MethodHandle mh2 = getmh2(mh1, short.class, int.class);
+            short a = mh1.<short>invokeExact((short) x);
+            short b = mh2.<short>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // int
+        {
+            MethodHandle mh1 = getmh1(     int.class, int.class);
+            MethodHandle mh2 = getmh2(mh1, int.class, int.class);
+            int a = mh1.<int>invokeExact((int) x);
+            int b = mh2.<int>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+    }
+
+    // test adapter_opt_l2i
+    static void testlong() throws Throwable {
+        long[] a = new long[] {
+            Long.MIN_VALUE,
+            Long.MIN_VALUE + 1,
+            -0x000000000FFFFFFFL,
+            -0x0000000000FFFFFFL,
+            -0x00000000000FFFFFL,
+            -0x000000000000FFFFL,
+            -0x0000000000000FFFL,
+            -0x00000000000000FFL,
+            -0x000000000000000FL,
+            -1L,
+            0L,
+            1L,
+            0x000000000000000FL,
+            0x00000000000000FFL,
+            0x0000000000000FFFL,
+            0x0000000000000FFFL,
+            0x000000000000FFFFL,
+            0x00000000000FFFFFL,
+            0x0000000000FFFFFFL,
+            0x000000000FFFFFFFL,
+            Long.MAX_VALUE - 1,
+            Long.MAX_VALUE
+        };
+        for (int i = 0; i < a.length; i++) {
+            dolong(a[i]);
+        }
+    }
+    static void dolong(long x) throws Throwable {
+        if (DEBUG)  System.out.println("long=" + x);
+
+        // boolean
+        {
+            MethodHandle mh1 = getmh1(     boolean.class, boolean.class);
+            MethodHandle mh2 = getmh2(mh1, boolean.class, long.class);
+            boolean a = mh1.<boolean>invokeExact((x & 1L) == 1L);
+            boolean b = mh2.<boolean>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // byte
+        {
+            MethodHandle mh1 = getmh1(     byte.class, byte.class);
+            MethodHandle mh2 = getmh2(mh1, byte.class, long.class);
+            byte a = mh1.<byte>invokeExact((byte) x);
+            byte b = mh2.<byte>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // char
+        {
+            MethodHandle mh1 = getmh1(     char.class, char.class);
+            MethodHandle mh2 = getmh2(mh1, char.class, long.class);
+            char a = mh1.<char>invokeExact((char) x);
+            char b = mh2.<char>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // short
+        {
+            MethodHandle mh1 = getmh1(     short.class, short.class);
+            MethodHandle mh2 = getmh2(mh1, short.class, long.class);
+            short a = mh1.<short>invokeExact((short) x);
+            short b = mh2.<short>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+        // int
+        {
+            MethodHandle mh1 = getmh1(     int.class, int.class);
+            MethodHandle mh2 = getmh2(mh1, int.class, long.class);
+            int a = mh1.<int>invokeExact((int) x);
+            int b = mh2.<int>invokeExact(x);
+            assert a == b : a + " != " + b;
+        }
+
+    }
+
+    // to int
+    public static boolean foo(boolean i) { return i; }
+    public static byte    foo(byte    i) { return i; }
+    public static char    foo(char    i) { return i; }
+    public static short   foo(short   i) { return i; }
+    public static int     foo(int     i) { return i; }
+}