Merge
authormorris
Thu, 07 Mar 2013 14:46:20 -0800
changeset 15876 affbcaf73c57
parent 15863 7234fc6fbe90 (current diff)
parent 15875 638b3e8fbe5e (diff)
child 15877 9dc93ed54d35
Merge
hotspot/src/os/bsd/vm/os_bsd.cpp
--- a/hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m	Thu Mar 07 14:29:02 2013 +0100
+++ b/hotspot/agent/src/os/bsd/MacosxDebuggerLocal.m	Thu Mar 07 14:46:20 2013 -0800
@@ -160,7 +160,7 @@
   CHECK_EXCEPTION_(0);
 
   unsigned long alignedAddress;
-  unsigned long alignedLength;
+  unsigned long alignedLength = 0;
   kern_return_t result;
   vm_offset_t *pages;
   int *mapped;
@@ -630,7 +630,7 @@
     /* Couldn't find entry point.  error_message should contain some
      * platform dependent error message.
      */
-    THROW_NEW_DEBUGGER_EXCEPTION(error_message);
+    THROW_NEW_DEBUGGER_EXCEPTION_(error_message, (jlong)func);
   }
   return (jlong)func;
 }
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp	Thu Mar 07 14:29:02 2013 +0100
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp	Thu Mar 07 14:46:20 2013 -0800
@@ -3903,15 +3903,27 @@
 jlong os::current_thread_cpu_time() {
 #ifdef __APPLE__
   return os::thread_cpu_time(Thread::current(), true /* user + sys */);
+#else
+  Unimplemented();
+  return 0;
 #endif
 }
 
 jlong os::thread_cpu_time(Thread* thread) {
+#ifdef __APPLE__
+  return os::thread_cpu_time(thread, true /* user + sys */);
+#else
+  Unimplemented();
+  return 0;
+#endif
 }
 
 jlong os::current_thread_cpu_time(bool user_sys_cpu_time) {
 #ifdef __APPLE__
   return os::thread_cpu_time(Thread::current(), user_sys_cpu_time);
+#else
+  Unimplemented();
+  return 0;
 #endif
 }
 
@@ -3935,6 +3947,9 @@
   } else {
     return ((jlong)tinfo.user_time.seconds * 1000000000) + ((jlong)tinfo.user_time.microseconds * (jlong)1000);
   }
+#else
+  Unimplemented();
+  return 0;
 #endif
 }
 
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Mar 07 14:29:02 2013 +0100
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Mar 07 14:46:20 2013 -0800
@@ -2170,7 +2170,11 @@
       if (impl != NULL) {
         if (!impl->is_loader_alive(is_alive)) {
           // remove this guy
-          *adr_implementor() = NULL;
+          Klass** klass = adr_implementor();
+          assert(klass != NULL, "null klass");
+          if (klass != NULL) {
+            *klass = NULL;
+          }
         }
       }
     }
@@ -3151,9 +3155,10 @@
   if (protection_domain() != NULL) {
     guarantee(protection_domain()->is_oop(), "should be oop");
   }
-  if (host_klass() != NULL) {
-    guarantee(host_klass()->is_metadata(), "should be in metaspace");
-    guarantee(host_klass()->is_klass(), "should be klass");
+  const Klass* host = host_klass();
+  if (host != NULL) {
+    guarantee(host->is_metadata(), "should be in metaspace");
+    guarantee(host->is_klass(), "should be klass");
   }
   if (signers() != NULL) {
     guarantee(signers()->is_objArray(), "should be obj array");
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Thu Mar 07 14:29:02 2013 +0100
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Thu Mar 07 14:46:20 2013 -0800
@@ -536,7 +536,9 @@
     assert(is_anonymous(), "not anonymous");
     Klass** addr = (Klass**)adr_host_klass();
     assert(addr != NULL, "no reversed space");
-    *addr = host;
+    if (addr != NULL) {
+      *addr = host;
+    }
   }
   bool is_anonymous() const                {
     return (_misc_flags & _misc_is_anonymous) != 0;
@@ -758,7 +760,10 @@
   void set_implementor(Klass* k) {
     assert(is_interface(), "not interface");
     Klass** addr = adr_implementor();
-    *addr = k;
+    assert(addr != NULL, "null addr");
+    if (addr != NULL) {
+      *addr = k;
+    }
   }
 
   int  nof_implementors() const       {
--- a/hotspot/src/share/vm/opto/c2_globals.hpp	Thu Mar 07 14:29:02 2013 +0100
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp	Thu Mar 07 14:46:20 2013 -0800
@@ -54,6 +54,12 @@
 
 #define C2_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct) \
                                                                             \
+  develop(bool, StressLCM, false,                                           \
+          "Randomize instruction scheduling in LCM")                        \
+                                                                            \
+  develop(bool, StressGCM, false,                                           \
+          "Randomize instruction scheduling in GCM")                        \
+                                                                            \
   notproduct(intx, CompileZapFirst, 0,                                      \
           "If +ZapDeadCompiledLocals, "                                     \
           "skip this many before compiling in zap calls")                   \
--- a/hotspot/src/share/vm/opto/compile.cpp	Thu Mar 07 14:29:02 2013 +0100
+++ b/hotspot/src/share/vm/opto/compile.cpp	Thu Mar 07 14:46:20 2013 -0800
@@ -2899,6 +2899,13 @@
       }
     }
     break;
+  case Op_MemBarStoreStore:
+    // Break the link with AllocateNode: it is no longer useful and
+    // confuses register allocation.
+    if (n->req() > MemBarNode::Precedent) {
+      n->set_req(MemBarNode::Precedent, top());
+    }
+    break;
   default:
     assert( !n->is_Call(), "" );
     assert( !n->is_Mem(), "" );
@@ -3669,3 +3676,38 @@
     n->set_req(0, NULL);
   }
 }
+
+// Auxiliary method to support randomized stressing/fuzzing.
+//
+// This method can be called the arbitrary number of times, with current count
+// as the argument. The logic allows selecting a single candidate from the
+// running list of candidates as follows:
+//    int count = 0;
+//    Cand* selected = null;
+//    while(cand = cand->next()) {
+//      if (randomized_select(++count)) {
+//        selected = cand;
+//      }
+//    }
+//
+// Including count equalizes the chances any candidate is "selected".
+// This is useful when we don't have the complete list of candidates to choose
+// from uniformly. In this case, we need to adjust the randomicity of the
+// selection, or else we will end up biasing the selection towards the latter
+// candidates.
+//
+// Quick back-envelope calculation shows that for the list of n candidates
+// the equal probability for the candidate to persist as "best" can be
+// achieved by replacing it with "next" k-th candidate with the probability
+// of 1/k. It can be easily shown that by the end of the run, the
+// probability for any candidate is converged to 1/n, thus giving the
+// uniform distribution among all the candidates.
+//
+// We don't care about the domain size as long as (RANDOMIZED_DOMAIN / count) is large.
+#define RANDOMIZED_DOMAIN_POW 29
+#define RANDOMIZED_DOMAIN (1 << RANDOMIZED_DOMAIN_POW)
+#define RANDOMIZED_DOMAIN_MASK ((1 << (RANDOMIZED_DOMAIN_POW + 1)) - 1)
+bool Compile::randomized_select(int count) {
+  assert(count > 0, "only positive");
+  return (os::random() & RANDOMIZED_DOMAIN_MASK) < (RANDOMIZED_DOMAIN / count);
+}
--- a/hotspot/src/share/vm/opto/compile.hpp	Thu Mar 07 14:29:02 2013 +0100
+++ b/hotspot/src/share/vm/opto/compile.hpp	Thu Mar 07 14:46:20 2013 -0800
@@ -678,6 +678,7 @@
   void         record_dead_node(uint idx)  { if (_dead_node_list.test_set(idx)) return;
                                              _dead_node_count++;
                                            }
+  bool         is_dead_node(uint idx)      { return _dead_node_list.test(idx) != 0; }
   uint         dead_node_count()           { return _dead_node_count; }
   void         reset_dead_node_list()      { _dead_node_list.Reset();
                                              _dead_node_count = 0;
@@ -1086,6 +1087,9 @@
 
   // Definitions of pd methods
   static void pd_compiler2_init();
+
+  // Auxiliary method for randomized fuzzing/stressing
+  static bool randomized_select(int count);
 };
 
 #endif // SHARE_VM_OPTO_COMPILE_HPP
--- a/hotspot/src/share/vm/opto/gcm.cpp	Thu Mar 07 14:29:02 2013 +0100
+++ b/hotspot/src/share/vm/opto/gcm.cpp	Thu Mar 07 14:46:20 2013 -0800
@@ -1046,6 +1046,8 @@
   }
 #endif
 
+  int cand_cnt = 0;  // number of candidates tried
+
   // Walk up the dominator tree from LCA (Lowest common ancestor) to
   // the earliest legal location.  Capture the least execution frequency.
   while (LCA != early) {
@@ -1071,8 +1073,11 @@
         LCA->_pre_order, LCA->_nodes[0]->_idx, start_lat, end_idx, end_lat, LCA_freq);
     }
 #endif
+    cand_cnt++;
     if (LCA_freq < least_freq              || // Better Frequency
-        ( !in_latency                   &&    // No block containing latency
+        (StressGCM && Compile::randomized_select(cand_cnt)) || // Should be randomly accepted in stress mode
+         (!StressGCM                    &&    // Otherwise, choose with latency
+          !in_latency                   &&    // No block containing latency
           LCA_freq < least_freq * delta &&    // No worse frequency
           target >= end_lat             &&    // within latency range
           !self->is_iteratively_computed() )  // But don't hoist IV increments
@@ -1210,7 +1215,8 @@
     }
 
     // If there is no opportunity to hoist, then we're done.
-    bool try_to_hoist = (LCA != early);
+    // In stress mode, try to hoist even the single operations.
+    bool try_to_hoist = StressGCM || (LCA != early);
 
     // Must clone guys stay next to use; no hoisting allowed.
     // Also cannot hoist guys that alter memory or are otherwise not
--- a/hotspot/src/share/vm/opto/lcm.cpp	Thu Mar 07 14:29:02 2013 +0100
+++ b/hotspot/src/share/vm/opto/lcm.cpp	Thu Mar 07 14:46:20 2013 -0800
@@ -421,6 +421,7 @@
   uint latency = 0; // Bigger is scheduled first
   uint score   = 0; // Bigger is better
   int idx = -1;     // Index in worklist
+  int cand_cnt = 0; // Candidate count
 
   for( uint i=0; i<cnt; i++ ) { // Inspect entire worklist
     // Order in worklist is used to break ties.
@@ -503,11 +504,14 @@
     uint n_score   = n->req();   // Many inputs get high score to break ties
 
     // Keep best latency found
-    if( choice < n_choice ||
-        ( choice == n_choice &&
-          ( latency < n_latency ||
-            ( latency == n_latency &&
-              ( score < n_score ))))) {
+    cand_cnt++;
+    if (choice < n_choice ||
+        (choice == n_choice &&
+         ((StressLCM && Compile::randomized_select(cand_cnt)) ||
+          (!StressLCM &&
+           (latency < n_latency ||
+            (latency == n_latency &&
+             (score < n_score))))))) {
       choice  = n_choice;
       latency = n_latency;
       score   = n_score;
--- a/hotspot/src/share/vm/opto/macro.cpp	Thu Mar 07 14:29:02 2013 +0100
+++ b/hotspot/src/share/vm/opto/macro.cpp	Thu Mar 07 14:46:20 2013 -0800
@@ -1101,12 +1101,6 @@
   Node* klass_node        = alloc->in(AllocateNode::KlassNode);
   Node* initial_slow_test = alloc->in(AllocateNode::InitialTest);
 
-  Node* storestore = alloc->storestore();
-  if (storestore != NULL) {
-    // Break this link that is no longer useful and confuses register allocation
-    storestore->set_req(MemBarNode::Precedent, top());
-  }
-
   assert(ctrl != NULL, "must have control");
   // We need a Region and corresponding Phi's to merge the slow-path and fast-path results.
   // they will not be used if "always_slow" is set
@@ -1324,7 +1318,7 @@
         // No InitializeNode or no stores captured by zeroing
         // elimination. Simply add the MemBarStoreStore after object
         // initialization.
-        MemBarNode* mb = MemBarNode::make(C, Op_MemBarStoreStore, Compile::AliasIdxBot, fast_oop_rawmem);
+        MemBarNode* mb = MemBarNode::make(C, Op_MemBarStoreStore, Compile::AliasIdxBot);
         transform_later(mb);
 
         mb->init_req(TypeFunc::Memory, fast_oop_rawmem);
--- a/hotspot/src/share/vm/opto/memnode.cpp	Thu Mar 07 14:29:02 2013 +0100
+++ b/hotspot/src/share/vm/opto/memnode.cpp	Thu Mar 07 14:46:20 2013 -0800
@@ -238,7 +238,7 @@
     return this;
   ctl = in(MemNode::Control);
   // Don't bother trying to transform a dead node
-  if( ctl && ctl->is_top() )  return NodeSentinel;
+  if (ctl && ctl->is_top())  return NodeSentinel;
 
   PhaseIterGVN *igvn = phase->is_IterGVN();
   // Wait if control on the worklist.
@@ -262,8 +262,8 @@
   }
   // Ignore if memory is dead, or self-loop
   Node *mem = in(MemNode::Memory);
-  if( phase->type( mem ) == Type::TOP ) return NodeSentinel; // caller will return NULL
-  assert( mem != this, "dead loop in MemNode::Ideal" );
+  if (phase->type( mem ) == Type::TOP) return NodeSentinel; // caller will return NULL
+  assert(mem != this, "dead loop in MemNode::Ideal");
 
   if (can_reshape && igvn != NULL && igvn->_worklist.member(mem)) {
     // This memory slice may be dead.
@@ -273,12 +273,12 @@
   }
 
   Node *address = in(MemNode::Address);
-  const Type *t_adr = phase->type( address );
-  if( t_adr == Type::TOP )              return NodeSentinel; // caller will return NULL
-
-  if( can_reshape && igvn != NULL &&
+  const Type *t_adr = phase->type(address);
+  if (t_adr == Type::TOP)              return NodeSentinel; // caller will return NULL
+
+  if (can_reshape && igvn != NULL &&
       (igvn->_worklist.member(address) ||
-       igvn->_worklist.size() > 0 && (phase->type(address) != adr_type())) ) {
+       igvn->_worklist.size() > 0 && (t_adr != adr_type())) ) {
     // The address's base and type may change when the address is processed.
     // Delay this mem node transformation until the address is processed.
     phase->is_IterGVN()->_worklist.push(this);
@@ -288,7 +288,7 @@
   // Do NOT remove or optimize the next lines: ensure a new alias index
   // is allocated for an oop pointer type before Escape Analysis.
   // Note: C++ will not remove it since the call has side effect.
-  if ( t_adr->isa_oopptr() ) {
+  if (t_adr->isa_oopptr()) {
     int alias_idx = phase->C->get_alias_index(t_adr->is_ptr());
   }
 
@@ -296,6 +296,26 @@
   Node* base = NULL;
   if (address->is_AddP())
     base = address->in(AddPNode::Base);
+  if (base != NULL && phase->type(base)->higher_equal(TypePtr::NULL_PTR) &&
+      !t_adr->isa_rawptr()) {
+    // Note: raw address has TOP base and top->higher_equal(TypePtr::NULL_PTR) is true.
+    Compile* C = phase->C;
+    tty->cr();
+    tty->print_cr("===== NULL+offs not RAW address =====");
+    if (C->is_dead_node(this->_idx))    tty->print_cr("'this' is dead");
+    if ((ctl != NULL) && C->is_dead_node(ctl->_idx)) tty->print_cr("'ctl' is dead");
+    if (C->is_dead_node(mem->_idx))     tty->print_cr("'mem' is dead");
+    if (C->is_dead_node(address->_idx)) tty->print_cr("'address' is dead");
+    if (C->is_dead_node(base->_idx))    tty->print_cr("'base' is dead");
+    tty->cr();
+    base->dump(1);
+    tty->cr();
+    this->dump(2);
+    tty->print("this->adr_type():     "); adr_type()->dump(); tty->cr();
+    tty->print("phase->type(address): "); t_adr->dump(); tty->cr();
+    tty->print("phase->type(base):    "); phase->type(address)->dump(); tty->cr();
+    tty->cr();
+  }
   assert(base == NULL || t_adr->isa_rawptr() ||
         !phase->type(base)->higher_equal(TypePtr::NULL_PTR), "NULL+offs not RAW address?");
 #endif
--- a/hotspot/src/share/vm/runtime/frame.cpp	Thu Mar 07 14:29:02 2013 +0100
+++ b/hotspot/src/share/vm/runtime/frame.cpp	Thu Mar 07 14:46:20 2013 -0800
@@ -1070,7 +1070,12 @@
 
   // First consult the ADLC on where it puts parameter 0 for this signature.
   VMReg reg = SharedRuntime::name_for_receiver();
-  oop r = *caller.oopmapreg_to_location(reg, reg_map);
+  oop* oop_adr = caller.oopmapreg_to_location(reg, reg_map);
+  if (oop_adr == NULL) {
+    guarantee(oop_adr != NULL, "bad register save location");
+    return NULL;
+  }
+  oop r = *oop_adr;
   assert(Universe::heap()->is_in_or_null(r), err_msg("bad receiver: " INTPTR_FORMAT " (" INTX_FORMAT ")", (intptr_t) r, (intptr_t) r));
   return r;
 }