--- 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;
}