changeset 6012:f3f101a5e59b

Merge
author johnc
date Fri, 20 Apr 2012 11:41:49 -0700
parents 0105f367a14c (diff) f7a8920427a6 (current diff)
children dff6e3459210
files
diffstat 34 files changed, 836 insertions(+), 275 deletions(-) [+]
line wrap: on
line diff
--- a/agent/src/os/linux/ps_core.c	Wed Apr 18 13:39:55 2012 -0400
+++ b/agent/src/os/linux/ps_core.c	Fri Apr 20 11:41:49 2012 -0700
@@ -440,7 +440,7 @@
       int j = 0;
       print_debug("---- sorted virtual address map ----\n");
       for (j = 0; j < ph->core->num_maps; j++) {
-        print_debug("base = 0x%lx\tsize = %d\n", ph->core->map_array[j]->vaddr,
+        print_debug("base = 0x%lx\tsize = %zd\n", ph->core->map_array[j]->vaddr,
                                          ph->core->map_array[j]->memsz);
       }
    }
--- a/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java	Wed Apr 18 13:39:55 2012 -0400
+++ b/agent/src/share/classes/sun/jvm/hotspot/jdi/VirtualMachineImpl.java	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, 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
@@ -889,15 +889,9 @@
         Klass kls = ((ReferenceTypeImpl)type).ref();
         if (kls instanceof InstanceKlass) {
             InstanceKlass ik = (InstanceKlass) kls;
-            if (ik.isInterface()) {
-                if (ik.nofImplementors() == 0L) {
-                    return new ArrayList(0);
-                }
-            } else {
-                // if the Klass is final or if there are no subklasses loaded yet
-                if (ik.getAccessFlagsObj().isFinal() || ik.getSubklassKlass() == null) {
-                    includeSubtypes = false;
-                }
+            // if the Klass is final or if there are no subklasses loaded yet
+            if (ik.getAccessFlagsObj().isFinal() || ik.getSubklassKlass() == null) {
+                includeSubtypes = false;
             }
         } else {
             // no subtypes for primitive array types
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java	Wed Apr 18 13:39:55 2012 -0400
+++ b/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -52,7 +52,6 @@
   private static int HIGH_OFFSET;
   private static int GENERIC_SIGNATURE_INDEX_OFFSET;
   private static int FIELD_SLOTS;
-  public static int IMPLEMENTORS_LIMIT;
 
   // ClassState constants
   private static int CLASS_STATE_UNPARSABLE_BY_GC;
@@ -70,13 +69,6 @@
     methodOrdering       = new OopField(type.getOopField("_method_ordering"), Oop.getHeaderSize());
     localInterfaces      = new OopField(type.getOopField("_local_interfaces"), Oop.getHeaderSize());
     transitiveInterfaces = new OopField(type.getOopField("_transitive_interfaces"), Oop.getHeaderSize());
-    nofImplementors      = new CIntField(type.getCIntegerField("_nof_implementors"), Oop.getHeaderSize());
-    IMPLEMENTORS_LIMIT   = db.lookupIntConstant("instanceKlass::implementors_limit").intValue();
-    implementors         = new OopField[IMPLEMENTORS_LIMIT];
-    for (int i = 0; i < IMPLEMENTORS_LIMIT; i++) {
-      long arrayOffset = Oop.getHeaderSize() + (i * db.getAddressSize());
-      implementors[i]    = new OopField(type.getOopField("_implementors[0]"), arrayOffset);
-    }
     fields               = new OopField(type.getOopField("_fields"), Oop.getHeaderSize());
     javaFieldsCount      = new CIntField(type.getCIntegerField("_java_fields_count"), Oop.getHeaderSize());
     constants            = new OopField(type.getOopField("_constants"), Oop.getHeaderSize());
@@ -136,8 +128,6 @@
   private static OopField  methodOrdering;
   private static OopField  localInterfaces;
   private static OopField  transitiveInterfaces;
-  private static CIntField nofImplementors;
-  private static OopField[] implementors;
   private static OopField  fields;
   private static CIntField javaFieldsCount;
   private static OopField  constants;
@@ -317,9 +307,6 @@
   public TypeArray getMethodOrdering()      { return (TypeArray)    methodOrdering.getValue(this); }
   public ObjArray  getLocalInterfaces()     { return (ObjArray)     localInterfaces.getValue(this); }
   public ObjArray  getTransitiveInterfaces() { return (ObjArray)     transitiveInterfaces.getValue(this); }
-  public long      nofImplementors()        { return                nofImplementors.getValue(this); }
-  public Klass     getImplementor()         { return (Klass)        implementors[0].getValue(this); }
-  public Klass     getImplementor(int i)    { return (Klass)        implementors[i].getValue(this); }
   public TypeArray getFields()              { return (TypeArray)    fields.getValue(this); }
   public int       getJavaFieldsCount()     { return                (int) javaFieldsCount.getValue(this); }
   public int       getAllFieldsCount()      { return                (int)getFields().getLength() / FIELD_SLOTS; }
@@ -527,9 +514,6 @@
       visitor.doOop(methodOrdering, true);
       visitor.doOop(localInterfaces, true);
       visitor.doOop(transitiveInterfaces, true);
-      visitor.doCInt(nofImplementors, true);
-      for (int i = 0; i < IMPLEMENTORS_LIMIT; i++)
-        visitor.doOop(implementors[i], true);
       visitor.doOop(fields, true);
       visitor.doOop(constants, true);
       visitor.doOop(classLoader, true);
--- a/src/cpu/x86/vm/templateTable_x86_32.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/cpu/x86/vm/templateTable_x86_32.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -2651,56 +2651,49 @@
     // Check to see if a field modification watch has been set before we take
     // the time to call into the VM.
     Label L2;
-    __ mov32(rcx, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr()));
-    __ testl(rcx,rcx);
-    __ jcc(Assembler::zero, L2);
-    __ pop_ptr(rbx);               // copy the object pointer from tos
-    __ verify_oop(rbx);
-    __ push_ptr(rbx);              // put the object pointer back on tos
-    __ subptr(rsp, sizeof(jvalue));  // add space for a jvalue object
-    __ mov(rcx, rsp);
-    __ push_ptr(rbx);                 // save object pointer so we can steal rbx,
-    __ xorptr(rbx, rbx);
-    const Address lo_value(rcx, rbx, Address::times_1, 0*wordSize);
-    const Address hi_value(rcx, rbx, Address::times_1, 1*wordSize);
-    switch (bytecode()) {          // load values into the jvalue object
-    case Bytecodes::_fast_bputfield: __ movb(lo_value, rax); break;
-    case Bytecodes::_fast_sputfield: __ movw(lo_value, rax); break;
-    case Bytecodes::_fast_cputfield: __ movw(lo_value, rax); break;
-    case Bytecodes::_fast_iputfield: __ movl(lo_value, rax);                         break;
-    case Bytecodes::_fast_lputfield:
-      NOT_LP64(__ movptr(hi_value, rdx));
-      __ movptr(lo_value, rax);
-      break;
-
-    // need to call fld_s() after fstp_s() to restore the value for below
-    case Bytecodes::_fast_fputfield: __ fstp_s(lo_value); __ fld_s(lo_value);        break;
-
-    // need to call fld_d() after fstp_d() to restore the value for below
-    case Bytecodes::_fast_dputfield: __ fstp_d(lo_value); __ fld_d(lo_value);        break;
-
-    // since rcx is not an object we don't call store_check() here
-    case Bytecodes::_fast_aputfield: __ movptr(lo_value, rax);                       break;
-
-    default:  ShouldNotReachHere();
-    }
-    __ pop_ptr(rbx);  // restore copy of object pointer
-
-    // Save rax, and sometimes rdx because call_VM() will clobber them,
-    // then use them for JVM/DI purposes
-    __ push(rax);
-    if (bytecode() == Bytecodes::_fast_lputfield) __ push(rdx);
-    // access constant pool cache entry
-    __ get_cache_entry_pointer_at_bcp(rax, rdx, 1);
-    __ verify_oop(rbx);
-    // rbx,: object pointer copied above
-    // rax,: cache entry pointer
-    // rcx: jvalue object on the stack
-    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, rax, rcx);
-    if (bytecode() == Bytecodes::_fast_lputfield) __ pop(rdx);  // restore high value
-    __ pop(rax);     // restore lower value
-    __ addptr(rsp, sizeof(jvalue));  // release jvalue object space
-    __ bind(L2);
+     __ mov32(rcx, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr()));
+     __ testl(rcx,rcx);
+     __ jcc(Assembler::zero, L2);
+     __ pop_ptr(rbx);               // copy the object pointer from tos
+     __ verify_oop(rbx);
+     __ push_ptr(rbx);              // put the object pointer back on tos
+
+     // Save tos values before call_VM() clobbers them. Since we have
+     // to do it for every data type, we use the saved values as the
+     // jvalue object.
+     switch (bytecode()) {          // load values into the jvalue object
+     case Bytecodes::_fast_aputfield: __ push_ptr(rax); break;
+     case Bytecodes::_fast_bputfield: // fall through
+     case Bytecodes::_fast_sputfield: // fall through
+     case Bytecodes::_fast_cputfield: // fall through
+     case Bytecodes::_fast_iputfield: __ push_i(rax); break;
+     case Bytecodes::_fast_dputfield: __ push_d(); break;
+     case Bytecodes::_fast_fputfield: __ push_f(); break;
+     case Bytecodes::_fast_lputfield: __ push_l(rax); break;
+
+     default:
+       ShouldNotReachHere();
+     }
+     __ mov(rcx, rsp);              // points to jvalue on the stack
+     // access constant pool cache entry
+     __ get_cache_entry_pointer_at_bcp(rax, rdx, 1);
+     __ verify_oop(rbx);
+     // rbx,: object pointer copied above
+     // rax,: cache entry pointer
+     // rcx: jvalue object on the stack
+     __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, rax, rcx);
+
+     switch (bytecode()) {             // restore tos values
+     case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break;
+     case Bytecodes::_fast_bputfield: // fall through
+     case Bytecodes::_fast_sputfield: // fall through
+     case Bytecodes::_fast_cputfield: // fall through
+     case Bytecodes::_fast_iputfield: __ pop_i(rax); break;
+     case Bytecodes::_fast_dputfield: __ pop_d(); break;
+     case Bytecodes::_fast_fputfield: __ pop_f(); break;
+     case Bytecodes::_fast_lputfield: __ pop_l(rax); break;
+     }
+     __ bind(L2);
   }
 }
 
--- a/src/cpu/x86/vm/templateTable_x86_64.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/cpu/x86/vm/templateTable_x86_64.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -2685,26 +2685,23 @@
     __ pop_ptr(rbx);                  // copy the object pointer from tos
     __ verify_oop(rbx);
     __ push_ptr(rbx);                 // put the object pointer back on tos
-    __ subptr(rsp, sizeof(jvalue));  // add space for a jvalue object
-    __ mov(c_rarg3, rsp);
-    const Address field(c_rarg3, 0);
-
+    // Save tos values before call_VM() clobbers them. Since we have
+    // to do it for every data type, we use the saved values as the
+    // jvalue object.
     switch (bytecode()) {          // load values into the jvalue object
-    case Bytecodes::_fast_aputfield: __ movq(field, rax); break;
-    case Bytecodes::_fast_lputfield: __ movq(field, rax); break;
-    case Bytecodes::_fast_iputfield: __ movl(field, rax); break;
-    case Bytecodes::_fast_bputfield: __ movb(field, rax); break;
+    case Bytecodes::_fast_aputfield: __ push_ptr(rax); break;
+    case Bytecodes::_fast_bputfield: // fall through
     case Bytecodes::_fast_sputfield: // fall through
-    case Bytecodes::_fast_cputfield: __ movw(field, rax); break;
-    case Bytecodes::_fast_fputfield: __ movflt(field, xmm0); break;
-    case Bytecodes::_fast_dputfield: __ movdbl(field, xmm0); break;
+    case Bytecodes::_fast_cputfield: // fall through
+    case Bytecodes::_fast_iputfield: __ push_i(rax); break;
+    case Bytecodes::_fast_dputfield: __ push_d(); break;
+    case Bytecodes::_fast_fputfield: __ push_f(); break;
+    case Bytecodes::_fast_lputfield: __ push_l(rax); break;
+
     default:
       ShouldNotReachHere();
     }
-
-    // Save rax because call_VM() will clobber it, then use it for
-    // JVMTI purposes
-    __ push(rax);
+    __ mov(c_rarg3, rsp);             // points to jvalue on the stack
     // access constant pool cache entry
     __ get_cache_entry_pointer_at_bcp(c_rarg2, rax, 1);
     __ verify_oop(rbx);
@@ -2715,8 +2712,17 @@
                CAST_FROM_FN_PTR(address,
                                 InterpreterRuntime::post_field_modification),
                rbx, c_rarg2, c_rarg3);
-    __ pop(rax);     // restore lower value
-    __ addptr(rsp, sizeof(jvalue));  // release jvalue object space
+
+    switch (bytecode()) {             // restore tos values
+    case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break;
+    case Bytecodes::_fast_bputfield: // fall through
+    case Bytecodes::_fast_sputfield: // fall through
+    case Bytecodes::_fast_cputfield: // fall through
+    case Bytecodes::_fast_iputfield: __ pop_i(rax); break;
+    case Bytecodes::_fast_dputfield: __ pop_d(); break;
+    case Bytecodes::_fast_fputfield: __ pop_f(); break;
+    case Bytecodes::_fast_lputfield: __ pop_l(rax); break;
+    }
     __ bind(L2);
   }
 }
--- a/src/os/bsd/vm/osThread_bsd.hpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/os/bsd/vm/osThread_bsd.hpp	Fri Apr 20 11:41:49 2012 -0700
@@ -72,15 +72,18 @@
 
 #ifdef _ALLBSD_SOURCE
 #ifdef __APPLE__
+  static size_t thread_id_size()         { return sizeof(thread_t); }
   thread_t thread_id() const {
     return _thread_id;
   }
 #else
+  static size_t thread_id_size()         { return sizeof(pthread_t); }
   pthread_t thread_id() const {
     return _thread_id;
   }
 #endif
 #else
+  static size_t thread_id_size()         { return sizeof(pid_t); }
   pid_t thread_id() const {
     return _thread_id;
   }
--- a/src/os/linux/vm/osThread_linux.hpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/os/linux/vm/osThread_linux.hpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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,8 @@
   sigset_t  caller_sigmask() const       { return _caller_sigmask; }
   void    set_caller_sigmask(sigset_t sigmask)  { _caller_sigmask = sigmask; }
 
+  static size_t thread_id_size()         { return sizeof(pid_t); }
+
   pid_t thread_id() const {
     return _thread_id;
   }
--- a/src/os/solaris/vm/osThread_solaris.hpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/os/solaris/vm/osThread_solaris.hpp	Fri Apr 20 11:41:49 2012 -0700
@@ -36,6 +36,7 @@
   bool     _vm_created_thread; // true if the VM created this thread,
                                // false if primary thread or attached thread
  public:
+  static size_t thread_id_size()   { return sizeof(thread_t); }
   thread_t thread_id() const       { return _thread_id; }
   uint     lwp_id() const          { return _lwp_id; }
   int      native_priority() const { return _native_priority; }
--- a/src/os/windows/vm/osThread_windows.hpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/os/windows/vm/osThread_windows.hpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -42,6 +42,8 @@
   HANDLE interrupt_event() const                   { return _interrupt_event; }
   void set_interrupt_event(HANDLE interrupt_event) { _interrupt_event = interrupt_event; }
 
+
+  static size_t thread_id_size()                   { return sizeof(unsigned long); }
   unsigned long thread_id() const                  { return _thread_id; }
 #ifndef PRODUCT
   // Used for debugging, return a unique integer for each thread.
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1694,7 +1694,9 @@
       // they are roughly equivalent to Object.
       ciInstanceKlass* singleton = NULL;
       if (target->holder()->nof_implementors() == 1) {
-        singleton = target->holder()->implementor(0);
+        singleton = target->holder()->implementor();
+        assert(singleton != NULL && singleton != target->holder(),
+               "just checking");
 
         assert(holder->is_interface(), "invokeinterface to non interface?");
         ciInstanceKlass* decl_interface = (ciInstanceKlass*)holder;
@@ -3130,10 +3132,23 @@
   bool cantrap = true;
   vmIntrinsics::ID id = callee->intrinsic_id();
   switch (id) {
-    case vmIntrinsics::_arraycopy     :
+    case vmIntrinsics::_arraycopy:
       if (!InlineArrayCopy) return false;
       break;
 
+#ifdef TRACE_HAVE_INTRINSICS
+    case vmIntrinsics::_classID:
+    case vmIntrinsics::_threadID:
+      preserves_state = true;
+      cantrap = true;
+      break;
+
+    case vmIntrinsics::_counterTime:
+      preserves_state = true;
+      cantrap = false;
+      break;
+#endif
+
     case vmIntrinsics::_currentTimeMillis:
     case vmIntrinsics::_nanoTime:
       preserves_state = true;
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, 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
@@ -2879,6 +2879,50 @@
   __ cmove(lir_cond(x->cond()), t_val.result(), f_val.result(), reg, as_BasicType(x->x()->type()));
 }
 
+void LIRGenerator::do_RuntimeCall(address routine, int expected_arguments, Intrinsic* x) {
+    assert(x->number_of_arguments() == expected_arguments, "wrong type");
+    LIR_Opr reg = result_register_for(x->type());
+    __ call_runtime_leaf(routine, getThreadTemp(),
+                         reg, new LIR_OprList());
+    LIR_Opr result = rlock_result(x);
+    __ move(reg, result);
+}
+
+#ifdef TRACE_HAVE_INTRINSICS
+void LIRGenerator::do_ThreadIDIntrinsic(Intrinsic* x) {
+    LIR_Opr thread = getThreadPointer();
+    LIR_Opr osthread = new_pointer_register();
+    __ move(new LIR_Address(thread, in_bytes(JavaThread::osthread_offset()), osthread->type()), osthread);
+    size_t thread_id_size = OSThread::thread_id_size();
+    if (thread_id_size == (size_t) BytesPerLong) {
+      LIR_Opr id = new_register(T_LONG);
+      __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_LONG), id);
+      __ convert(Bytecodes::_l2i, id, rlock_result(x));
+    } else if (thread_id_size == (size_t) BytesPerInt) {
+      __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_INT), rlock_result(x));
+    } else {
+      ShouldNotReachHere();
+    }
+}
+
+void LIRGenerator::do_ClassIDIntrinsic(Intrinsic* x) {
+    CodeEmitInfo* info = state_for(x);
+    CodeEmitInfo* info2 = new CodeEmitInfo(info); // Clone for the second null check
+    assert(info != NULL, "must have info");
+    LIRItem arg(x->argument_at(1), this);
+    arg.load_item();
+    LIR_Opr klass = new_register(T_OBJECT);
+    __ move(new LIR_Address(arg.result(), java_lang_Class::klass_offset_in_bytes(), T_OBJECT), klass, info);
+    LIR_Opr id = new_register(T_LONG);
+    ByteSize offset = TRACE_ID_OFFSET;
+    LIR_Address* trace_id_addr = new LIR_Address(klass, in_bytes(offset), T_LONG);
+    __ move(trace_id_addr, id);
+    __ logical_or(id, LIR_OprFact::longConst(0x01l), id);
+    __ store(id, trace_id_addr);
+    __ logical_and(id, LIR_OprFact::longConst(~0x3l), id);
+    __ move(id, rlock_result(x));
+}
+#endif
 
 void LIRGenerator::do_Intrinsic(Intrinsic* x) {
   switch (x->id()) {
@@ -2890,25 +2934,21 @@
     break;
   }
 
-  case vmIntrinsics::_currentTimeMillis: {
-    assert(x->number_of_arguments() == 0, "wrong type");
-    LIR_Opr reg = result_register_for(x->type());
-    __ call_runtime_leaf(CAST_FROM_FN_PTR(address, os::javaTimeMillis), getThreadTemp(),
-                         reg, new LIR_OprList());
-    LIR_Opr result = rlock_result(x);
-    __ move(reg, result);
+#ifdef TRACE_HAVE_INTRINSICS
+  case vmIntrinsics::_threadID: do_ThreadIDIntrinsic(x); break;
+  case vmIntrinsics::_classID: do_ClassIDIntrinsic(x); break;
+  case vmIntrinsics::_counterTime:
+    do_RuntimeCall(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), 0, x);
     break;
-  }
-
-  case vmIntrinsics::_nanoTime: {
-    assert(x->number_of_arguments() == 0, "wrong type");
-    LIR_Opr reg = result_register_for(x->type());
-    __ call_runtime_leaf(CAST_FROM_FN_PTR(address, os::javaTimeNanos), getThreadTemp(),
-                         reg, new LIR_OprList());
-    LIR_Opr result = rlock_result(x);
-    __ move(reg, result);
+#endif
+
+  case vmIntrinsics::_currentTimeMillis:
+    do_RuntimeCall(CAST_FROM_FN_PTR(address, os::javaTimeMillis), 0, x);
     break;
-  }
+
+  case vmIntrinsics::_nanoTime:
+    do_RuntimeCall(CAST_FROM_FN_PTR(address, os::javaTimeNanos), 0, x);
+    break;
 
   case vmIntrinsics::_Object_init:    do_RegisterFinalizer(x); break;
   case vmIntrinsics::_getClass:       do_getClass(x);      break;
--- a/src/share/vm/c1/c1_LIRGenerator.hpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/c1/c1_LIRGenerator.hpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, 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
@@ -426,6 +426,12 @@
   SwitchRangeArray* create_lookup_ranges(LookupSwitch* x);
   void do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux);
 
+  void do_RuntimeCall(address routine, int expected_arguments, Intrinsic* x);
+#ifdef TRACE_HAVE_INTRINSICS
+  void do_ThreadIDIntrinsic(Intrinsic* x);
+  void do_ClassIDIntrinsic(Intrinsic* x);
+#endif
+
  public:
   Compilation*  compilation() const              { return _compilation; }
   FrameMap*     frame_map() const                { return _compilation->frame_map(); }
--- a/src/share/vm/c1/c1_Runtime1.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -295,6 +295,9 @@
   FUNCTION_CASE(entry, SharedRuntime::dtrace_method_entry);
   FUNCTION_CASE(entry, SharedRuntime::dtrace_method_exit);
   FUNCTION_CASE(entry, trace_block_entry);
+#ifdef TRACE_HAVE_INTRINSICS
+  FUNCTION_CASE(entry, TRACE_TIME_METHOD);
+#endif
 
 #undef FUNCTION_CASE
 
--- a/src/share/vm/ci/ciInstanceKlass.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/ci/ciInstanceKlass.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -59,10 +59,7 @@
   _has_nonstatic_fields = ik->has_nonstatic_fields();
   _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields:
 
-  _nof_implementors = ik->nof_implementors();
-  for (int i = 0; i < implementors_limit; i++) {
-    _implementors[i] = NULL;  // we will fill these lazily
-  }
+  _implementor = NULL; // we will fill these lazily
 
   Thread *thread = Thread::current();
   if (ciObjectFactory::is_initialized()) {
@@ -102,7 +99,6 @@
   _nonstatic_field_size = -1;
   _has_nonstatic_fields = false;
   _nonstatic_fields = NULL;
-  _nof_implementors = -1;
   _loader = loader;
   _protection_domain = protection_domain;
   _is_shared = false;
@@ -133,17 +129,6 @@
 }
 
 // ------------------------------------------------------------------
-// ciInstanceKlass::compute_shared_nof_implementors
-int ciInstanceKlass::compute_shared_nof_implementors() {
-  // We requery this property, since it is a very old ciObject.
-  GUARDED_VM_ENTRY(
-    instanceKlass* ik = get_instanceKlass();
-    _nof_implementors = ik->nof_implementors();
-    return _nof_implementors;
-  )
-}
-
-// ------------------------------------------------------------------
 // ciInstanceKlass::loader
 oop ciInstanceKlass::loader() {
   ASSERT_IN_VM;
@@ -540,7 +525,7 @@
   if (is_shared()) {
     return is_final();  // approximately correct
   } else {
-    return !_has_subklass && (_nof_implementors == 0);
+    return !_has_subklass && (nof_implementors() == 0);
   }
 }
 
@@ -548,35 +533,31 @@
 // ciInstanceKlass::implementor
 //
 // Report an implementor of this interface.
-// Returns NULL if exact information is not available.
 // Note that there are various races here, since my copy
 // of _nof_implementors might be out of date with respect
 // to results returned by instanceKlass::implementor.
 // This is OK, since any dependencies we decide to assert
 // will be checked later under the Compile_lock.
-ciInstanceKlass* ciInstanceKlass::implementor(int n) {
-  if (n >= implementors_limit) {
-    return NULL;
-  }
-  ciInstanceKlass* impl = _implementors[n];
+ciInstanceKlass* ciInstanceKlass::implementor() {
+  ciInstanceKlass* impl = _implementor;
   if (impl == NULL) {
-    if (_nof_implementors > implementors_limit) {
-      return NULL;
-    }
     // Go into the VM to fetch the implementor.
     {
       VM_ENTRY_MARK;
-      klassOop k = get_instanceKlass()->implementor(n);
+      klassOop k = get_instanceKlass()->implementor();
       if (k != NULL) {
-        impl = CURRENT_THREAD_ENV->get_object(k)->as_instance_klass();
+        if (k == get_instanceKlass()->as_klassOop()) {
+          // More than one implementors. Use 'this' in this case.
+          impl = this;
+        } else {
+          impl = CURRENT_THREAD_ENV->get_object(k)->as_instance_klass();
+        }
       }
     }
     // Memoize this result.
     if (!is_shared()) {
-      _implementors[n] = (impl == NULL)? this: impl;
+      _implementor = impl;
     }
-  } else if (impl == this) {
-    impl = NULL;  // memoized null result from a VM query
   }
   return impl;
 }
--- a/src/share/vm/ci/ciInstanceKlass.hpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/ci/ciInstanceKlass.hpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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,9 +65,11 @@
   ciConstantPoolCache*   _field_cache;  // cached map index->field
   GrowableArray<ciField*>* _nonstatic_fields;
 
-  enum { implementors_limit = instanceKlass::implementors_limit };
-  ciInstanceKlass*       _implementors[implementors_limit];
-  jint                   _nof_implementors;
+  // The possible values of the _implementor fall into following three cases:
+  //   NULL: no implementor.
+  //   A ciInstanceKlass that's not itself: one implementor.
+  //   Itsef: more than one implementors.
+  ciInstanceKlass*       _implementor;
 
   GrowableArray<ciField*>* _non_static_fields;
 
@@ -97,7 +99,6 @@
 
   void compute_shared_init_state();
   bool compute_shared_has_subklass();
-  int  compute_shared_nof_implementors();
   int  compute_nonstatic_fields();
   GrowableArray<ciField*>* compute_nonstatic_fields_impl(GrowableArray<ciField*>* super_fields);
 
@@ -158,10 +159,17 @@
     assert(is_loaded(), "must be loaded");
     return _nonstatic_oop_map_size; }
   ciInstanceKlass*       super();
-  jint                   nof_implementors()  {
+  jint                   nof_implementors() {
+    ciInstanceKlass* impl;
     assert(is_loaded(), "must be loaded");
-    if (_is_shared)  return compute_shared_nof_implementors();
-    return _nof_implementors;
+    impl = implementor();
+    if (impl == NULL) {
+      return 0;
+    } else if (impl != this) {
+      return 1;
+    } else {
+      return 2;
+    }
   }
 
   ciInstanceKlass* get_canonical_holder(int offset);
@@ -207,7 +215,7 @@
   // but consider adding to vmSymbols.hpp instead.
 
   bool is_leaf_type();
-  ciInstanceKlass* implementor(int n);
+  ciInstanceKlass* implementor();
 
   // Is the defining class loader of this class the default loader?
   bool uses_default_loader();
--- a/src/share/vm/classfile/classFileParser.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/classfile/classFileParser.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -3354,6 +3354,7 @@
     klassOop ik = oopFactory::new_instanceKlass(name, vtable_size, itable_size,
                                                 static_field_size,
                                                 total_oop_map_count,
+                                                access_flags,
                                                 rt, CHECK_(nullHandle));
     instanceKlassHandle this_klass (THREAD, ik);
 
@@ -3362,7 +3363,6 @@
            "sanity");
 
     // Fill in information already parsed
-    this_klass->set_access_flags(access_flags);
     this_klass->set_should_verify_class(verify);
     jint lh = Klass::instance_layout_helper(instance_size, false);
     this_klass->set_layout_helper(lh);
--- a/src/share/vm/classfile/vmSymbols.hpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/classfile/vmSymbols.hpp	Fri Apr 20 11:41:49 2012 -0700
@@ -27,6 +27,7 @@
 
 #include "oops/symbol.hpp"
 #include "memory/iterator.hpp"
+#include "trace/traceMacros.hpp"
 
 // The class vmSymbols is a name space for fast lookup of
 // symbols commonly used in the VM.
@@ -424,6 +425,7 @@
   template(throwable_throwable_signature,             "(Ljava/lang/Throwable;)Ljava/lang/Throwable;")             \
   template(class_void_signature,                      "(Ljava/lang/Class;)V")                     \
   template(class_int_signature,                       "(Ljava/lang/Class;)I")                     \
+  template(class_long_signature,                      "(Ljava/lang/Class;)J")                     \
   template(class_boolean_signature,                   "(Ljava/lang/Class;)Z")                     \
   template(throwable_string_void_signature,           "(Ljava/lang/Throwable;Ljava/lang/String;)V")               \
   template(string_array_void_signature,               "([Ljava/lang/String;)V")                                   \
@@ -539,10 +541,12 @@
   template(serializePropertiesToByteArray_signature,   "()[B")                                                    \
   template(serializeAgentPropertiesToByteArray_name,   "serializeAgentPropertiesToByteArray")                     \
   template(classRedefinedCount_name,                   "classRedefinedCount")                                     \
+                                                                                                                  \
+  /* trace signatures */                                                                                          \
+  TRACE_TEMPLATES(template)                                                                                       \
+                                                                                                                  \
   /*end*/
 
-
-
 // Here are all the intrinsics known to the runtime and the CI.
 // Each intrinsic consists of a public enum name (like _hashCode),
 // followed by a specification of its klass, name, and signature:
@@ -648,6 +652,8 @@
   do_intrinsic(_nanoTime,                 java_lang_System,       nanoTime_name,          void_long_signature,   F_S)   \
    do_name(     nanoTime_name,                                   "nanoTime")                                            \
                                                                                                                         \
+  TRACE_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias)                                             \
+                                                                                                                        \
   do_intrinsic(_arraycopy,                java_lang_System,       arraycopy_name, arraycopy_signature,           F_S)   \
    do_name(     arraycopy_name,                                  "arraycopy")                                           \
    do_signature(arraycopy_signature,                             "(Ljava/lang/Object;ILjava/lang/Object;II)V")          \
--- a/src/share/vm/code/dependencies.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/code/dependencies.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, 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
@@ -1033,21 +1033,25 @@
     // (Old CHA had the same limitation.)
     return context_type;
   }
-  for (int i = 0; i < nof_impls; i++) {
-    klassOop impl = instanceKlass::cast(context_type)->implementor(i);
-    if (impl == NULL) {
-      // implementors array overflowed => no exact info.
+  if (nof_impls > 0) {
+    klassOop impl = instanceKlass::cast(context_type)->implementor();
+    assert(impl != NULL, "just checking");
+    // If impl is the same as the context_type, then more than one
+    // implementor has seen. No exact info in this case.
+    if (impl == context_type) {
       return context_type;  // report an inexact witness to this sad affair
     }
     if (do_counts)
       { NOT_PRODUCT(deps_find_witness_steps++); }
     if (is_participant(impl)) {
-      if (participants_hide_witnesses)  continue;
-      // else fall through to process this guy's subclasses
+      if (!participants_hide_witnesses) {
+        ADD_SUBCLASS_CHAIN(impl);
+      }
     } else if (is_witness(impl) && !ignore_witness(impl)) {
       return impl;
+    } else {
+      ADD_SUBCLASS_CHAIN(impl);
     }
-    ADD_SUBCLASS_CHAIN(impl);
   }
 
   // Recursively process each non-trivial sibling chain.
@@ -1174,8 +1178,9 @@
   } else if (ctx->nof_implementors() != 0) {
     // if it is an interface, it must be unimplemented
     // (if it is not an interface, nof_implementors is always zero)
-    klassOop impl = ctx->implementor(0);
-    return (impl != NULL)? impl: ctxk;
+    klassOop impl = ctx->implementor();
+    assert(impl != NULL, "must be set");
+    return impl;
   } else {
     return NULL;
   }
--- a/src/share/vm/memory/oopFactory.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/memory/oopFactory.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -127,9 +127,12 @@
 klassOop oopFactory::new_instanceKlass(Symbol* name, int vtable_len, int itable_len,
                                        int static_field_size,
                                        unsigned int nonstatic_oop_map_count,
+                                       AccessFlags access_flags,
                                        ReferenceType rt, TRAPS) {
   instanceKlassKlass* ikk = instanceKlassKlass::cast(Universe::instanceKlassKlassObj());
-  return ikk->allocate_instance_klass(name, vtable_len, itable_len, static_field_size, nonstatic_oop_map_count, rt, CHECK_NULL);
+  return ikk->allocate_instance_klass(name, vtable_len, itable_len,
+                                      static_field_size, nonstatic_oop_map_count,
+                                      access_flags, rt, CHECK_NULL);
 }
 
 
--- a/src/share/vm/memory/oopFactory.hpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/memory/oopFactory.hpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -77,6 +77,7 @@
                                            int vtable_len, int itable_len,
                                            int static_field_size,
                                            unsigned int nonstatic_oop_map_count,
+                                           AccessFlags access_flags,
                                            ReferenceType rt, TRAPS);
 
   // Methods
--- a/src/share/vm/oops/instanceKlass.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/oops/instanceKlass.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -567,8 +567,18 @@
   ol.notify_all(CHECK);
 }
 
+// The embedded _implementor field can only record one implementor.
+// When there are more than one implementors, the _implementor field
+// is set to the interface klassOop itself. Following are the possible
+// values for the _implementor field:
+//   NULL                  - no implementor
+//   implementor klassOop  - one implementor
+//   self                  - more than one implementor
+//
+// The _implementor field only exists for interfaces.
 void instanceKlass::add_implementor(klassOop k) {
   assert(Compile_lock->owned_by_self(), "");
+  assert(is_interface(), "not interface");
   // Filter out my subinterfaces.
   // (Note: Interfaces are never on the subklass list.)
   if (instanceKlass::cast(k)->is_interface()) return;
@@ -583,17 +593,13 @@
     // Any supers of the super have the same (or fewer) transitive_interfaces.
     return;
 
-  // Update number of implementors
-  int i = _nof_implementors++;
-
-  // Record this implementor, if there are not too many already
-  if (i < implementors_limit) {
-    assert(_implementors[i] == NULL, "should be exactly one implementor");
-    oop_store_without_check((oop*)&_implementors[i], k);
-  } else if (i == implementors_limit) {
-    // clear out the list on first overflow
-    for (int i2 = 0; i2 < implementors_limit; i2++)
-      oop_store_without_check((oop*)&_implementors[i2], NULL);
+  klassOop ik = implementor();
+  if (ik == NULL) {
+    set_implementor(k);
+  } else if (ik != this->as_klassOop()) {
+    // There is already an implementor. Use itself as an indicator of
+    // more than one implementors.
+    set_implementor(this->as_klassOop());
   }
 
   // The implementor also implements the transitive_interfaces
@@ -603,9 +609,9 @@
 }
 
 void instanceKlass::init_implementor() {
-  for (int i = 0; i < implementors_limit; i++)
-    oop_store_without_check((oop*)&_implementors[i], NULL);
-  _nof_implementors = 0;
+  if (is_interface()) {
+    set_implementor(NULL);
+  }
 }
 
 
@@ -1849,24 +1855,22 @@
 void instanceKlass::follow_weak_klass_links(
   BoolObjectClosure* is_alive, OopClosure* keep_alive) {
   assert(is_alive->do_object_b(as_klassOop()), "this oop should be live");
-  if (ClassUnloading) {
-    for (int i = 0; i < implementors_limit; i++) {
-      klassOop impl = _implementors[i];
-      if (impl == NULL)  break;  // no more in the list
-      if (!is_alive->do_object_b(impl)) {
-        // remove this guy from the list by overwriting him with the tail
-        int lasti = --_nof_implementors;
-        assert(lasti >= i && lasti < implementors_limit, "just checking");
-        _implementors[i] = _implementors[lasti];
-        _implementors[lasti] = NULL;
-        --i; // rerun the loop at this index
+
+  if (is_interface()) {
+    if (ClassUnloading) {
+      klassOop impl = implementor();
+      if (impl != NULL) {
+        if (!is_alive->do_object_b(impl)) {
+          // remove this guy
+          *start_of_implementor() = NULL;
+        }
       }
-    }
-  } else {
-    for (int i = 0; i < implementors_limit; i++) {
-      keep_alive->do_oop(&adr_implementors()[i]);
+    } else {
+      assert(adr_implementor() != NULL, "just checking");
+      keep_alive->do_oop(adr_implementor());
     }
   }
+
   Klass::follow_weak_klass_links(is_alive, keep_alive);
 }
 
--- a/src/share/vm/oops/instanceKlass.hpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/oops/instanceKlass.hpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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,8 +56,6 @@
 //    [methods                    ]
 //    [local interfaces           ]
 //    [transitive interfaces      ]
-//    [number of implementors     ]
-//    [implementors               ] klassOop[2]
 //    [fields                     ]
 //    [constants                  ]
 //    [class loader               ]
@@ -77,9 +75,9 @@
 //    [oop map cache (stack maps) ]
 //    [EMBEDDED Java vtable             ] size in words = vtable_len
 //    [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size
-//
-//    The embedded nonstatic oop-map blocks are short pairs (offset, length) indicating
-//    where oops are located in instances of this klass.
+//      The embedded nonstatic oop-map blocks are short pairs (offset, length)
+//      indicating where oops are located in instances of this klass.
+//    [EMBEDDED implementor of the interface] only exist for interface
 
 
 // forward declaration for class -- see below for definition
@@ -153,10 +151,6 @@
   oop* oop_block_beg() const { return adr_array_klasses(); }
   oop* oop_block_end() const { return adr_methods_default_annotations() + 1; }
 
-  enum {
-    implementors_limit = 2              // how many implems can we track?
-  };
-
  protected:
   //
   // The oop block.  See comment in klass.hpp before making changes.
@@ -200,8 +194,6 @@
   // and EnclosingMethod attributes the _inner_classes array length is
   // number_of_inner_classes * 4 + enclosing_method_attribute_size.
   typeArrayOop    _inner_classes;
-  // Implementors of this interface (not valid if it overflows)
-  klassOop        _implementors[implementors_limit];
   // Annotations for this class, or null if none.
   typeArrayOop    _class_annotations;
   // Annotation objects (byte arrays) for fields, or null if no annotations.
@@ -257,7 +249,6 @@
   nmethodBucket*  _dependencies;         // list of dependent nmethods
   nmethod*        _osr_nmethods_head;    // Head of list of on-stack replacement nmethods for this class
   BreakpointInfo* _breakpoints;          // bpt lists, managed by methodOop
-  int             _nof_implementors;     // No of implementors of this interface (zero if not an interface)
   // Array of interesting part(s) of the previous version(s) of this
   // instanceKlass. See PreviousVersionWalker below.
   GrowableArray<PreviousVersionNode *>* _previous_versions;
@@ -278,6 +269,13 @@
   // embedded Java itables follows here
   // embedded static fields follows here
   // embedded nonstatic oop-map blocks follows here
+  // embedded implementor of this interface follows here
+  //   The embedded implementor only exists if the current klass is an
+  //   iterface. The possible values of the implementor fall into following
+  //   three cases:
+  //     NULL: no implementor.
+  //     A klassOop that's not itself: one implementor.
+  //     Itsef: more than one implementors.
 
   friend class instanceKlassKlass;
   friend class SystemDictionary;
@@ -644,19 +642,40 @@
 
   // support for stub routines
   static ByteSize init_state_offset()  { return in_ByteSize(sizeof(klassOopDesc) + offset_of(instanceKlass, _init_state)); }
+  TRACE_DEFINE_OFFSET;
   static ByteSize init_thread_offset() { return in_ByteSize(sizeof(klassOopDesc) + offset_of(instanceKlass, _init_thread)); }
 
   // subclass/subinterface checks
   bool implements_interface(klassOop k) const;
 
-  // Access to implementors of an interface. We only store the count
-  // of implementors, and in case, there are only a few
-  // implementors, we store them in a short list.
-  // This accessor returns NULL if we walk off the end of the list.
-  klassOop implementor(int i) const {
-    return (i < implementors_limit)? _implementors[i]: (klassOop) NULL;
+  // Access to the implementor of an interface.
+  klassOop implementor() const
+  {
+    klassOop* k = start_of_implementor();
+    if (k == NULL) {
+      return NULL;
+    } else {
+      return *k;
+    }
   }
-  int  nof_implementors() const       { return _nof_implementors; }
+
+  void set_implementor(klassOop k) {
+    assert(is_interface(), "not interface");
+    oop* addr = (oop*)start_of_implementor();
+    oop_store_without_check(addr, k);
+  }
+
+  int  nof_implementors() const       {
+    klassOop k = implementor();
+    if (k == NULL) {
+      return 0;
+    } else if (k != this->as_klassOop()) {
+      return 1;
+    } else {
+      return 2;
+    }
+  }
+
   void add_implementor(klassOop k);  // k is a new class that implements this interface
   void init_implementor();           // initialize
 
@@ -693,7 +712,15 @@
 
   // Sizing (in words)
   static int header_size()            { return align_object_offset(oopDesc::header_size() + sizeof(instanceKlass)/HeapWordSize); }
-  int object_size() const             { return object_size(align_object_offset(vtable_length()) + align_object_offset(itable_length()) + nonstatic_oop_map_size()); }
+
+  int object_size() const
+  {
+    return object_size(align_object_offset(vtable_length()) +
+                       align_object_offset(itable_length()) +
+                       (is_interface() ?
+                        (align_object_offset(nonstatic_oop_map_size()) + (int)sizeof(klassOop)/HeapWordSize) :
+                        nonstatic_oop_map_size()));
+  }
   static int vtable_start_offset()    { return header_size(); }
   static int vtable_length_offset()   { return oopDesc::header_size() + offset_of(instanceKlass, _vtable_len) / HeapWordSize; }
   static int object_size(int extra)   { return align_object_size(header_size() + extra); }
@@ -710,6 +737,15 @@
     return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length()));
   }
 
+  klassOop* start_of_implementor() const {
+    if (is_interface()) {
+      return (klassOop*)(start_of_nonstatic_oop_maps() +
+                         nonstatic_oop_map_count());
+    } else {
+      return NULL;
+    }
+  };
+
   // Allocation profiling support
   juint alloc_size() const            { return _alloc_count * size_helper(); }
   void set_alloc_size(juint n)        {}
@@ -819,7 +855,7 @@
   oop* adr_host_klass() const        { return (oop*)&this->_host_klass;}
   oop* adr_signers() const           { return (oop*)&this->_signers;}
   oop* adr_inner_classes() const     { return (oop*)&this->_inner_classes;}
-  oop* adr_implementors() const      { return (oop*)&this->_implementors[0];}
+  oop* adr_implementor() const       { return (oop*)start_of_implementor(); }
   oop* adr_methods_jmethod_ids() const             { return (oop*)&this->_methods_jmethod_ids;}
   oop* adr_methods_cached_itable_indices() const   { return (oop*)&this->_methods_cached_itable_indices;}
   oop* adr_class_annotations() const   { return (oop*)&this->_class_annotations;}
--- a/src/share/vm/oops/instanceKlassKlass.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/oops/instanceKlassKlass.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -111,7 +111,7 @@
   MarkSweep::mark_and_push(ik->adr_methods_parameter_annotations());
   MarkSweep::mark_and_push(ik->adr_methods_default_annotations());
 
-  // We do not follow adr_implementors() here. It is followed later
+  // We do not follow adr_implementor() here. It is followed later
   // in instanceKlass::follow_weak_klass_links()
 
   klassKlass::oop_follow_contents(obj);
@@ -180,8 +180,8 @@
   blk->do_oop(ik->adr_host_klass());
   blk->do_oop(ik->adr_signers());
   blk->do_oop(ik->adr_inner_classes());
-  for (int i = 0; i < instanceKlass::implementors_limit; i++) {
-    blk->do_oop(&ik->adr_implementors()[i]);
+  if (ik->is_interface()) {
+    blk->do_oop(ik->adr_implementor());
   }
   blk->do_oop(ik->adr_class_annotations());
   blk->do_oop(ik->adr_fields_annotations());
@@ -232,9 +232,9 @@
   if (mr.contains(adr)) blk->do_oop(adr);
   adr = ik->adr_inner_classes();
   if (mr.contains(adr)) blk->do_oop(adr);
-  adr = ik->adr_implementors();
-  for (int i = 0; i < instanceKlass::implementors_limit; i++) {
-    if (mr.contains(&adr[i])) blk->do_oop(&adr[i]);
+  if (ik->is_interface()) {
+    adr = ik->adr_implementor();
+    if (mr.contains(adr)) blk->do_oop(adr);
   }
   adr = ik->adr_class_annotations();
   if (mr.contains(adr)) blk->do_oop(adr);
@@ -273,8 +273,8 @@
   MarkSweep::adjust_pointer(ik->adr_host_klass());
   MarkSweep::adjust_pointer(ik->adr_signers());
   MarkSweep::adjust_pointer(ik->adr_inner_classes());
-  for (int i = 0; i < instanceKlass::implementors_limit; i++) {
-    MarkSweep::adjust_pointer(&ik->adr_implementors()[i]);
+  if (ik->is_interface()) {
+    MarkSweep::adjust_pointer(ik->adr_implementor());
   }
   MarkSweep::adjust_pointer(ik->adr_class_annotations());
   MarkSweep::adjust_pointer(ik->adr_fields_annotations());
@@ -328,6 +328,9 @@
   for (oop* cur_oop = beg_oop; cur_oop < end_oop; ++cur_oop) {
     PSParallelCompact::adjust_pointer(cur_oop);
   }
+  if (ik->is_interface()) {
+    PSParallelCompact::adjust_pointer(ik->adr_implementor());
+  }
 
   OopClosure* closure = PSParallelCompact::adjust_root_pointer_closure();
   iterate_c_heap_oops(ik, closure);
@@ -342,11 +345,18 @@
 instanceKlassKlass::allocate_instance_klass(Symbol* name, int vtable_len, int itable_len,
                                             int static_field_size,
                                             unsigned nonstatic_oop_map_count,
+                                            AccessFlags access_flags,
                                             ReferenceType rt, TRAPS) {
 
   const int nonstatic_oop_map_size =
     instanceKlass::nonstatic_oop_map_size(nonstatic_oop_map_count);
-  int size = instanceKlass::object_size(align_object_offset(vtable_len) + align_object_offset(itable_len) + nonstatic_oop_map_size);
+  int size = align_object_offset(vtable_len) + align_object_offset(itable_len);
+  if (access_flags.is_interface()) {
+    size += align_object_offset(nonstatic_oop_map_size) + (int)sizeof(klassOop)/HeapWordSize;
+  } else {
+    size += nonstatic_oop_map_size;
+  }
+  size = instanceKlass::object_size(size);
 
   // Allocation
   KlassHandle h_this_klass(THREAD, as_klassOop());
@@ -378,6 +388,7 @@
     ik->set_itable_length(itable_len);
     ik->set_static_field_size(static_field_size);
     ik->set_nonstatic_oop_map_size(nonstatic_oop_map_size);
+    ik->set_access_flags(access_flags);
     assert(k()->size() == size, "wrong size for object");
 
     ik->set_array_klasses(NULL);
@@ -470,16 +481,12 @@
 
   if (ik->is_interface()) {
     st->print_cr(BULLET"nof implementors:  %d", ik->nof_implementors());
-    int print_impl = 0;
-    for (int i = 0; i < instanceKlass::implementors_limit; i++) {
-      if (ik->implementor(i) != NULL) {
-        if (++print_impl == 1)
-          st->print_cr(BULLET"implementor:    ");
-        st->print("   ");
-        ik->implementor(i)->print_value_on(st);
-      }
+    if (ik->nof_implementors() == 1) {
+      st->print_cr(BULLET"implementor:    ");
+      st->print("   ");
+      ik->implementor()->print_value_on(st);
+      st->cr();
     }
-    if (print_impl > 0)  st->cr();
   }
 
   st->print(BULLET"arrays:            "); ik->array_klasses()->print_value_on(st);     st->cr();
@@ -640,16 +647,12 @@
     }
 
     // Verify implementor fields
-    bool saw_null_impl = false;
-    for (int i = 0; i < instanceKlass::implementors_limit; i++) {
-      klassOop im = ik->implementor(i);
-      if (im == NULL) { saw_null_impl = true; continue; }
-      guarantee(!saw_null_impl, "non-nulls must preceded all nulls");
+    klassOop im = ik->implementor();
+    if (im != NULL) {
       guarantee(ik->is_interface(), "only interfaces should have implementor set");
-      guarantee(i < ik->nof_implementors(), "should only have one implementor");
       guarantee(im->is_perm(),  "should be in permspace");
       guarantee(im->is_klass(), "should be klass");
-      guarantee(!Klass::cast(klassOop(im))->is_interface(), "implementors cannot be interfaces");
+      guarantee(!Klass::cast(klassOop(im))->is_interface() || im == ik->as_klassOop(), "implementors cannot be interfaces");
     }
 
     // Verify local interfaces
--- a/src/share/vm/oops/instanceKlassKlass.hpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/oops/instanceKlassKlass.hpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -46,6 +46,7 @@
                                    int itable_len,
                                    int static_field_size,
                                    unsigned int nonstatic_oop_map_count,
+                                   AccessFlags access_flags,
                                    ReferenceType rt,
                                    TRAPS);
 
--- a/src/share/vm/opto/library_call.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/opto/library_call.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, 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
@@ -175,7 +175,11 @@
   bool inline_unsafe_allocate();
   bool inline_unsafe_copyMemory();
   bool inline_native_currentThread();
-  bool inline_native_time_funcs(bool isNano);
+#ifdef TRACE_HAVE_INTRINSICS
+  bool inline_native_classID();
+  bool inline_native_threadID();
+#endif
+  bool inline_native_time_funcs(address method, const char* funcName);
   bool inline_native_isInterrupted();
   bool inline_native_Class_query(vmIntrinsics::ID id);
   bool inline_native_subtype_check();
@@ -638,10 +642,18 @@
   case vmIntrinsics::_isInterrupted:
     return inline_native_isInterrupted();
 
+#ifdef TRACE_HAVE_INTRINSICS
+  case vmIntrinsics::_classID:
+    return inline_native_classID();
+  case vmIntrinsics::_threadID:
+    return inline_native_threadID();
+  case vmIntrinsics::_counterTime:
+    return inline_native_time_funcs(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), "counterTime");
+#endif
   case vmIntrinsics::_currentTimeMillis:
-    return inline_native_time_funcs(false);
+    return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeMillis), "currentTimeMillis");
   case vmIntrinsics::_nanoTime:
-    return inline_native_time_funcs(true);
+    return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeNanos), "nanoTime");
   case vmIntrinsics::_allocateInstance:
     return inline_unsafe_allocate();
   case vmIntrinsics::_copyMemory:
@@ -2840,14 +2852,63 @@
   return true;
 }
 
+#ifdef TRACE_HAVE_INTRINSICS
+/*
+ * oop -> myklass
+ * myklass->trace_id |= USED
+ * return myklass->trace_id & ~0x3
+ */
+bool LibraryCallKit::inline_native_classID() {
+  int nargs = 1 + 1;
+  null_check_receiver(callee());  // check then ignore argument(0)
+  _sp += nargs;
+  Node* cls = do_null_check(argument(1), T_OBJECT);
+  _sp -= nargs;
+  Node* kls = load_klass_from_mirror(cls, false, nargs, NULL, 0);
+  _sp += nargs;
+  kls = do_null_check(kls, T_OBJECT);
+  _sp -= nargs;
+  ByteSize offset = TRACE_ID_OFFSET;
+  Node* insp = basic_plus_adr(kls, in_bytes(offset));
+  Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG);
+  Node* bits = longcon(~0x03l); // ignore bit 0 & 1
+  Node* andl = _gvn.transform(new (C, 3) AndLNode(tvalue, bits));
+  Node* clsused = longcon(0x01l); // set the class bit
+  Node* orl = _gvn.transform(new (C, 3) OrLNode(tvalue, clsused));
+
+  const TypePtr *adr_type = _gvn.type(insp)->isa_ptr();
+  store_to_memory(control(), insp, orl, T_LONG, adr_type);
+  push_pair(andl);
+  return true;
+}
+
+bool LibraryCallKit::inline_native_threadID() {
+  Node* tls_ptr = NULL;
+  Node* cur_thr = generate_current_thread(tls_ptr);
+  Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset()));
+  Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS);
+  p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::thread_id_offset()));
+
+  Node* threadid = NULL;
+  size_t thread_id_size = OSThread::thread_id_size();
+  if (thread_id_size == (size_t) BytesPerLong) {
+    threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG));
+    push(threadid);
+  } else if (thread_id_size == (size_t) BytesPerInt) {
+    threadid = make_load(control(), p, TypeInt::INT, T_INT);
+    push(threadid);
+  } else {
+    ShouldNotReachHere();
+  }
+  return true;
+}
+#endif
+
 //------------------------inline_native_time_funcs--------------
 // inline code for System.currentTimeMillis() and System.nanoTime()
 // these have the same type and signature
-bool LibraryCallKit::inline_native_time_funcs(bool isNano) {
-  address funcAddr = isNano ? CAST_FROM_FN_PTR(address, os::javaTimeNanos) :
-                              CAST_FROM_FN_PTR(address, os::javaTimeMillis);
-  const char * funcName = isNano ? "nanoTime" : "currentTimeMillis";
-  const TypeFunc *tf = OptoRuntime::current_time_millis_Type();
+bool LibraryCallKit::inline_native_time_funcs(address funcAddr, const char* funcName) {
+  const TypeFunc *tf = OptoRuntime::void_long_Type();
   const TypePtr* no_memory_effects = NULL;
   Node* time = make_runtime_call(RC_LEAF, tf, funcAddr, funcName, no_memory_effects);
   Node* value = _gvn.transform(new (C, 1) ProjNode(time, TypeFunc::Parms+0));
--- a/src/share/vm/opto/runtime.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/opto/runtime.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, 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
@@ -709,9 +709,9 @@
   return TypeFunc::make(domain, range);
 }
 
-//-------------- currentTimeMillis
+//-------------- currentTimeMillis, currentTimeNanos, etc
 
-const TypeFunc* OptoRuntime::current_time_millis_Type() {
+const TypeFunc* OptoRuntime::void_long_Type() {
   // create input type (domain)
   const Type **fields = TypeTuple::fields(0);
   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+0, fields);
--- a/src/share/vm/opto/runtime.hpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/opto/runtime.hpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, 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
@@ -268,7 +268,7 @@
   static const TypeFunc* Math_DD_D_Type(); // mod,pow & friends
   static const TypeFunc* modf_Type();
   static const TypeFunc* l2f_Type();
-  static const TypeFunc* current_time_millis_Type();
+  static const TypeFunc* void_long_Type();
 
   static const TypeFunc* flush_windows_Type();
 
--- a/src/share/vm/runtime/osThread.hpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/runtime/osThread.hpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -98,6 +98,7 @@
 
   // For java intrinsics:
   static ByteSize interrupted_offset()            { return byte_offset_of(OSThread, _interrupted); }
+  static ByteSize thread_id_offset()              { return byte_offset_of(OSThread, _thread_id); }
 
   // Platform dependent stuff
 #ifdef TARGET_OS_FAMILY_linux
--- a/src/share/vm/runtime/thread.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/runtime/thread.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -3468,13 +3468,13 @@
     create_vm_init_libraries();
   }
 
+  // Notify JVMTI agents that VM initialization is complete - nop if no agents.
+  JvmtiExport::post_vm_initialized();
+
   if (!TRACE_START()) {
     vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION));
   }
 
-  // Notify JVMTI agents that VM initialization is complete - nop if no agents.
-  JvmtiExport::post_vm_initialized();
-
   if (CleanChunkPoolAsync) {
     Chunk::start_chunk_pool_cleaner_task();
   }
--- a/src/share/vm/runtime/vmStructs.cpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/runtime/vmStructs.cpp	Fri Apr 20 11:41:49 2012 -0700
@@ -292,8 +292,6 @@
   nonstatic_field(instanceKlass,               _method_ordering,                              typeArrayOop)                          \
   nonstatic_field(instanceKlass,               _local_interfaces,                             objArrayOop)                           \
   nonstatic_field(instanceKlass,               _transitive_interfaces,                        objArrayOop)                           \
-  nonstatic_field(instanceKlass,               _nof_implementors,                             int)                                   \
-  nonstatic_field(instanceKlass,               _implementors[0],                              klassOop)                              \
   nonstatic_field(instanceKlass,               _fields,                                       typeArrayOop)                          \
   nonstatic_field(instanceKlass,               _java_fields_count,                            u2)                                    \
   nonstatic_field(instanceKlass,               _constants,                                    constantPoolOop)                       \
@@ -2343,7 +2341,6 @@
   /* instanceKlass enum                */                                 \
   /*************************************/                                 \
                                                                           \
-  declare_constant(instanceKlass::implementors_limit)                     \
                                                                           \
   /*************************************/                                 \
   /* FieldInfo FieldOffset enum        */                                 \
--- a/src/share/vm/trace/traceMacros.hpp	Wed Apr 18 13:39:55 2012 -0400
+++ b/src/share/vm/trace/traceMacros.hpp	Fri Apr 20 11:41:49 2012 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -43,5 +43,9 @@
 #define TRACE_SET_KLASS_TRACE_ID(x1, x2) do { } while (0)
 #define TRACE_DEFINE_KLASS_METHODS typedef int ___IGNORED_hs_trace_type1
 #define TRACE_DEFINE_KLASS_TRACE_ID typedef int ___IGNORED_hs_trace_type2
+#define TRACE_DEFINE_OFFSET typedef int ___IGNORED_hs_trace_type3
+#define TRACE_ID_OFFSET in_ByteSize(0); ShouldNotReachHere()
+#define TRACE_TEMPLATES(template)
+#define TRACE_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias)
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/7158988/FieldMonitor.java	Fri Apr 20 11:41:49 2012 -0700
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2012 SAP AG.  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 FieldMonitor.java
+ * @bug 7158988
+ * @summary verify jvm does not crash while debugging
+ * @run shell TestFieldMonitor.sh
+ * @author axel.siebenborn@sap.com
+ */
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import com.sun.jdi.Bootstrap;
+import com.sun.jdi.Field;
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.VirtualMachine;
+import com.sun.jdi.connect.Connector;
+import com.sun.jdi.connect.IllegalConnectorArgumentsException;
+import com.sun.jdi.connect.LaunchingConnector;
+import com.sun.jdi.connect.VMStartException;
+import com.sun.jdi.event.ClassPrepareEvent;
+import com.sun.jdi.event.Event;
+import com.sun.jdi.event.EventQueue;
+import com.sun.jdi.event.EventSet;
+import com.sun.jdi.event.ModificationWatchpointEvent;
+import com.sun.jdi.event.VMDeathEvent;
+import com.sun.jdi.event.VMDisconnectEvent;
+import com.sun.jdi.request.ClassPrepareRequest;
+import com.sun.jdi.request.EventRequest;
+import com.sun.jdi.request.EventRequestManager;
+import com.sun.jdi.request.ModificationWatchpointRequest;
+
+public class FieldMonitor {
+
+  public static final String CLASS_NAME = "TestPostFieldModification";
+  public static final String FIELD_NAME = "value";
+  public static final String ARGUMENTS = "-Xshare:off -XX:+PrintGC";
+
+  public static void main(String[] args)
+      throws IOException, InterruptedException {
+
+    StringBuffer sb = new StringBuffer();
+
+    for (int i=0; i < args.length; i++) {
+        sb.append(' ');
+        sb.append(args[i]);
+    }
+    //VirtualMachine vm = launchTarget(sb.toString());
+    VirtualMachine vm = launchTarget(CLASS_NAME);
+
+    System.out.println("Vm launched");
+    // set watch field on already loaded classes
+    List<ReferenceType> referenceTypes = vm
+        .classesByName(CLASS_NAME);
+    for (ReferenceType refType : referenceTypes) {
+      addFieldWatch(vm, refType);
+    }
+    // watch for loaded classes
+    addClassWatch(vm);
+
+    // process events
+    EventQueue eventQueue = vm.eventQueue();
+    // resume the vm
+
+    Process process = vm.process();
+
+
+    // Copy target's output and error to our output and error.
+    Thread outThread = new StreamRedirectThread("out reader", process.getInputStream());
+    Thread errThread = new StreamRedirectThread("error reader", process.getErrorStream());
+
+    errThread.start();
+    outThread.start();
+
+
+    vm.resume();
+    boolean connected = true;
+    while (connected) {
+      EventSet eventSet = eventQueue.remove();
+      for (Event event : eventSet) {
+        if (event instanceof VMDeathEvent
+            || event instanceof VMDisconnectEvent) {
+          // exit
+          connected = false;
+        } else if (event instanceof ClassPrepareEvent) {
+          // watch field on loaded class
+          System.out.println("ClassPrepareEvent");
+          ClassPrepareEvent classPrepEvent = (ClassPrepareEvent) event;
+          ReferenceType refType = classPrepEvent
+              .referenceType();
+          addFieldWatch(vm, refType);
+        } else if (event instanceof ModificationWatchpointEvent) {
+          System.out.println("sleep for 500 ms");
+          Thread.sleep(500);
+          System.out.println("resume...");
+
+          ModificationWatchpointEvent modEvent = (ModificationWatchpointEvent) event;
+          System.out.println("old="
+              + modEvent.valueCurrent());
+          System.out.println("new=" + modEvent.valueToBe());
+          System.out.println();
+        }
+      }
+      eventSet.resume();
+    }
+    // Shutdown begins when event thread terminates
+    try {
+        errThread.join(); // Make sure output is forwarded
+        outThread.join();
+    } catch (InterruptedException exc) {
+        // we don't interrupt
+    }
+  }
+
+  /**
+   * Find a com.sun.jdi.CommandLineLaunch connector
+   */
+  static LaunchingConnector findLaunchingConnector() {
+    List <Connector> connectors = Bootstrap.virtualMachineManager().allConnectors();
+    Iterator <Connector> iter = connectors.iterator();
+    while (iter.hasNext()) {
+      Connector connector = iter.next();
+      if (connector.name().equals("com.sun.jdi.CommandLineLaunch")) {
+        return (LaunchingConnector)connector;
+      }
+    }
+    throw new Error("No launching connector");
+  }
+  /**
+   * Return the launching connector's arguments.
+   */
+ static Map <String,Connector.Argument> connectorArguments(LaunchingConnector connector, String mainArgs) {
+      Map<String,Connector.Argument> arguments = connector.defaultArguments();
+      for (String key : arguments.keySet()) {
+        System.out.println(key);
+      }
+
+      Connector.Argument mainArg = (Connector.Argument)arguments.get("main");
+      if (mainArg == null) {
+          throw new Error("Bad launching connector");
+      }
+      mainArg.setValue(mainArgs);
+
+      Connector.Argument optionsArg = (Connector.Argument)arguments.get("options");
+      if (optionsArg == null) {
+        throw new Error("Bad launching connector");
+      }
+      optionsArg.setValue(ARGUMENTS);
+      return arguments;
+  }
+
+ static VirtualMachine launchTarget(String mainArgs) {
+    LaunchingConnector connector = findLaunchingConnector();
+    Map  arguments = connectorArguments(connector, mainArgs);
+    try {
+        return (VirtualMachine) connector.launch(arguments);
+    } catch (IOException exc) {
+        throw new Error("Unable to launch target VM: " + exc);
+    } catch (IllegalConnectorArgumentsException exc) {
+        throw new Error("Internal error: " + exc);
+    } catch (VMStartException exc) {
+        throw new Error("Target VM failed to initialize: " +
+                        exc.getMessage());
+    }
+}
+
+
+  private static void addClassWatch(VirtualMachine vm) {
+    EventRequestManager erm = vm.eventRequestManager();
+    ClassPrepareRequest classPrepareRequest = erm
+        .createClassPrepareRequest();
+    classPrepareRequest.addClassFilter(CLASS_NAME);
+    classPrepareRequest.setEnabled(true);
+  }
+
+
+  private static void addFieldWatch(VirtualMachine vm,
+      ReferenceType refType) {
+    EventRequestManager erm = vm.eventRequestManager();
+    Field field = refType.fieldByName(FIELD_NAME);
+    ModificationWatchpointRequest modificationWatchpointRequest = erm
+        .createModificationWatchpointRequest(field);
+    modificationWatchpointRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
+    modificationWatchpointRequest.setEnabled(true);
+  }
+}
+
+class StreamRedirectThread extends Thread {
+
+  private final BufferedReader in;
+
+  private static final int BUFFER_SIZE = 2048;
+
+  /**
+   * Set up for copy.
+   * @param name  Name of the thread
+   * @param in    Stream to copy from
+   * @param out   Stream to copy to
+   */
+  StreamRedirectThread(String name, InputStream in) {
+    super(name);
+    this.in = new BufferedReader(new InputStreamReader(in));
+  }
+
+  /**
+   * Copy.
+   */
+  public void run() {
+    try {
+      String line;
+        while ((line = in.readLine ()) != null) {
+          System.out.println ("testvm: " + line);
+      }
+     System.out.flush();
+    } catch(IOException exc) {
+      System.err.println("Child I/O Transfer - " + exc);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/7158988/TestFieldMonitor.sh	Fri Apr 20 11:41:49 2012 -0700
@@ -0,0 +1,94 @@
+#!/bin/sh
+
+if [ "${TESTSRC}" = "" ]
+then TESTSRC=.
+fi
+
+if [ "${TESTJAVA}" = "" ]
+then
+  PARENT=`dirname \`which java\``
+  TESTJAVA=`dirname ${PARENT}`
+  echo "TESTJAVA not set, selecting " ${TESTJAVA}
+  echo "If this is incorrect, try setting the variable manually."
+fi
+
+if [ "${TESTCLASSES}" = "" ]
+then
+  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
+  exit 1
+fi
+
+BIT_FLAG=""
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+  SunOS | Linux )
+    NULL=/dev/null
+    PS=":"
+    FS="/"
+    ## for solaris, linux it's HOME
+    FILE_LOCATION=$HOME
+    if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" -a `uname -p`='sparc' ]
+    then
+        BIT_FLAG="-d64"
+    fi
+    ;;
+  Windows_95 | Windows_98 | Windows_ME )
+    NULL=NUL
+    PS=";"
+    FS="\\"
+    echo "Test skipped, only for WinNT"
+    exit 0
+    ;;
+  Windows_NT )
+    NULL=NUL
+    PS=";"
+    FS="\\"
+    ;;
+  * )
+    echo "Unrecognized system!"
+    exit 1;
+    ;;
+esac
+
+#CLASSPATH=.${PS}${TESTCLASSES} ; export CLASSPATH
+
+cp ${TESTSRC}${FS}*.java .
+
+${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -fullversion
+
+${TESTJAVA}${FS}bin${FS}javac -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar *.java
+
+${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar FieldMonitor > test.out 2>&1 &
+
+P_PID=$!
+
+sleep 60
+STATUS=0
+
+case "$OS" in
+    SunOS | Linux )
+        ps -ef | grep $P_PID | grep -v grep > ${NULL}
+        if [ $? = 0 ]; then
+            kill -9 $P_PID
+            STATUS=1
+        fi
+        ;;
+      * )
+        ps | grep -i "FieldMonitor" | grep -v grep > ${NULL}
+        if [ $? = 0 ]; then
+            C_PID=`ps | grep -i "FieldMonitor" | awk '{print $1}'`
+            kill -s 9 $C_PID
+            STATUS=1
+        fi
+        ;;
+esac
+
+grep "A fatal error has been detected" test.out > ${NULL}
+if [ $? = 0 ]; then
+    cat test.out
+    STATUS=1
+fi
+
+exit $STATUS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/runtime/7158988/TestPostFieldModification.java	Fri Apr 20 11:41:49 2012 -0700
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012 SAP AG.  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.
+ */
+
+public class TestPostFieldModification {
+
+  public String value;  // watch modification of value
+
+  public static void main(String[] args){
+
+    System.out.println("Start threads");
+    // this thread modifies the field 'value'
+    new Thread() {
+      TestPostFieldModification test = new TestPostFieldModification();
+      public void run() {
+        test.value="test";
+        for(int i = 0; i < 10; i++) {
+          test.value += new String("_test");
+        }
+      }
+    }.start();
+
+    // this thread is used to trigger a gc
+    Thread d = new Thread() {
+      public void run() {
+        while(true) {
+          try {
+            Thread.sleep(100);
+          } catch (InterruptedException e) {
+
+          }
+          System.gc();
+        }
+      }
+    };
+    d.setDaemon(true);
+    d.start();
+  }
+}