hotspot/src/share/vm/oops/instanceKlass.cpp
changeset 6453 970dc585ab63
parent 6421 7c02a5af38e7
child 7397 5b173b4ca846
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Sep 02 11:40:02 2010 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Fri Sep 03 17:51:07 2010 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2200,8 +2200,23 @@
   assert(n->is_osr_method(), "wrong kind of nmethod");
   n->set_osr_link(osr_nmethods_head());
   set_osr_nmethods_head(n);
+  // Raise the highest osr level if necessary
+  if (TieredCompilation) {
+    methodOop m = n->method();
+    m->set_highest_osr_comp_level(MAX2(m->highest_osr_comp_level(), n->comp_level()));
+  }
   // Remember to unlock again
   OsrList_lock->unlock();
+
+  // Get rid of the osr methods for the same bci that have lower levels.
+  if (TieredCompilation) {
+    for (int l = CompLevel_limited_profile; l < n->comp_level(); l++) {
+      nmethod *inv = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), l, true);
+      if (inv != NULL && inv->is_in_use()) {
+        inv->make_not_entrant();
+      }
+    }
+  }
 }
 
 
@@ -2211,39 +2226,79 @@
   assert(n->is_osr_method(), "wrong kind of nmethod");
   nmethod* last = NULL;
   nmethod* cur  = osr_nmethods_head();
+  int max_level = CompLevel_none;  // Find the max comp level excluding n
+  methodOop m = n->method();
   // Search for match
   while(cur != NULL && cur != n) {
+    if (TieredCompilation) {
+      // Find max level before n
+      max_level = MAX2(max_level, cur->comp_level());
+    }
     last = cur;
     cur = cur->osr_link();
   }
+  nmethod* next = NULL;
   if (cur == n) {
+    next = cur->osr_link();
     if (last == NULL) {
       // Remove first element
-      set_osr_nmethods_head(osr_nmethods_head()->osr_link());
+      set_osr_nmethods_head(next);
     } else {
-      last->set_osr_link(cur->osr_link());
+      last->set_osr_link(next);
     }
   }
   n->set_osr_link(NULL);
+  if (TieredCompilation) {
+    cur = next;
+    while (cur != NULL) {
+      // Find max level after n
+      max_level = MAX2(max_level, cur->comp_level());
+      cur = cur->osr_link();
+    }
+    m->set_highest_osr_comp_level(max_level);
+  }
   // Remember to unlock again
   OsrList_lock->unlock();
 }
 
-nmethod* instanceKlass::lookup_osr_nmethod(const methodOop m, int bci) const {
+nmethod* instanceKlass::lookup_osr_nmethod(const methodOop m, int bci, int comp_level, bool match_level) const {
   // This is a short non-blocking critical region, so the no safepoint check is ok.
   OsrList_lock->lock_without_safepoint_check();
   nmethod* osr = osr_nmethods_head();
+  nmethod* best = NULL;
   while (osr != NULL) {
     assert(osr->is_osr_method(), "wrong kind of nmethod found in chain");
+    // There can be a time when a c1 osr method exists but we are waiting
+    // for a c2 version. When c2 completes its osr nmethod we will trash
+    // the c1 version and only be able to find the c2 version. However
+    // while we overflow in the c1 code at back branches we don't want to
+    // try and switch to the same code as we are already running
+
     if (osr->method() == m &&
         (bci == InvocationEntryBci || osr->osr_entry_bci() == bci)) {
-      // Found a match - return it.
-      OsrList_lock->unlock();
-      return osr;
+      if (match_level) {
+        if (osr->comp_level() == comp_level) {
+          // Found a match - return it.
+          OsrList_lock->unlock();
+          return osr;
+        }
+      } else {
+        if (best == NULL || (osr->comp_level() > best->comp_level())) {
+          if (osr->comp_level() == CompLevel_highest_tier) {
+            // Found the best possible - return it.
+            OsrList_lock->unlock();
+            return osr;
+          }
+          best = osr;
+        }
+      }
     }
     osr = osr->osr_link();
   }
   OsrList_lock->unlock();
+  if (best != NULL && best->comp_level() >= comp_level && match_level == false) {
+    return best;
+  }
   return NULL;
 }