--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Mon Jun 16 13:38:17 2008 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Tue Jun 17 09:33:34 2008 -0700
@@ -283,6 +283,7 @@
template(cache_field_name, "cache") \
template(value_name, "value") \
template(frontCacheEnabled_name, "frontCacheEnabled") \
+ template(stringCacheEnabled_name, "stringCacheEnabled") \
\
/* non-intrinsic name/signature pairs: */ \
template(register_method_name, "register") \
--- a/hotspot/src/share/vm/opto/memnode.cpp Mon Jun 16 13:38:17 2008 -0700
+++ b/hotspot/src/share/vm/opto/memnode.cpp Tue Jun 17 09:33:34 2008 -0700
@@ -253,11 +253,17 @@
if (dom == NULL || dom->is_top() || sub == NULL || sub->is_top())
return false; // Conservative answer for dead code
- // Check 'dom'.
+ // Check 'dom'. Skip Proj and CatchProj nodes.
dom = dom->find_exact_control(dom);
if (dom == NULL || dom->is_top())
return false; // Conservative answer for dead code
+ if (dom == sub) {
+ // For the case when, for example, 'sub' is Initialize and the original
+ // 'dom' is Proj node of the 'sub'.
+ return false;
+ }
+
if (dom->is_Con() || dom->is_Start() || dom->is_Root() || dom == sub)
return true;
@@ -271,6 +277,7 @@
sub->is_Region(), "expecting only these nodes");
// Get control edge of 'sub'.
+ Node* orig_sub = sub;
sub = sub->find_exact_control(sub->in(0));
if (sub == NULL || sub->is_top())
return false; // Conservative answer for dead code
@@ -296,14 +303,16 @@
for (uint next = 0; next < dom_list.size(); next++) {
Node* n = dom_list.at(next);
+ if (n == orig_sub)
+ return false; // One of dom's inputs dominated by sub.
if (!n->is_CFG() && n->pinned()) {
// Check only own control edge for pinned non-control nodes.
n = n->find_exact_control(n->in(0));
if (n == NULL || n->is_top())
return false; // Conservative answer for dead code
assert(n->is_CFG(), "expecting control");
- }
- if (n->is_Con() || n->is_Start() || n->is_Root()) {
+ dom_list.push(n);
+ } else if (n->is_Con() || n->is_Start() || n->is_Root()) {
only_dominating_controls = true;
} else if (n->is_CFG()) {
if (n->dominates(sub, nlist))
--- a/hotspot/src/share/vm/opto/node.cpp Mon Jun 16 13:38:17 2008 -0700
+++ b/hotspot/src/share/vm/opto/node.cpp Tue Jun 17 09:33:34 2008 -0700
@@ -1039,6 +1039,9 @@
//--------------------------dominates------------------------------------------
// Helper function for MemNode::all_controls_dominate().
// Check if 'this' control node dominates or equal to 'sub' control node.
+// We already know that if any path back to Root or Start reaches 'this',
+// then all paths so, so this is a simple search for one example,
+// not an exhaustive search for a counterexample.
bool Node::dominates(Node* sub, Node_List &nlist) {
assert(this->is_CFG(), "expecting control");
assert(sub != NULL && sub->is_CFG(), "expecting control");
@@ -1047,110 +1050,115 @@
int iterations_without_region_limit = DominatorSearchLimit;
Node* orig_sub = sub;
+ Node* dom = this;
+ bool met_dom = false;
nlist.clear();
- bool this_dominates = false;
- bool result = false; // Conservative answer
- while (sub != NULL) { // walk 'sub' up the chain to 'this'
- if (sub == this) {
+ // Walk 'sub' backward up the chain to 'dom', watching for regions.
+ // After seeing 'dom', continue up to Root or Start.
+ // If we hit a region (backward split point), it may be a loop head.
+ // Keep going through one of the region's inputs. If we reach the
+ // same region again, go through a different input. Eventually we
+ // will either exit through the loop head, or give up.
+ // (If we get confused, break out and return a conservative 'false'.)
+ while (sub != NULL) {
+ if (sub->is_top()) break; // Conservative answer for dead code.
+ if (sub == dom) {
if (nlist.size() == 0) {
// No Region nodes except loops were visited before and the EntryControl
// path was taken for loops: it did not walk in a cycle.
- result = true;
- break;
- } else if (this_dominates) {
- result = false; // already met before: walk in a cycle
- break;
+ return true;
+ } else if (met_dom) {
+ break; // already met before: walk in a cycle
} else {
// Region nodes were visited. Continue walk up to Start or Root
// to make sure that it did not walk in a cycle.
- this_dominates = true; // first time meet
+ met_dom = true; // first time meet
iterations_without_region_limit = DominatorSearchLimit; // Reset
}
}
if (sub->is_Start() || sub->is_Root()) {
- result = this_dominates;
- break;
+ // Success if we met 'dom' along a path to Start or Root.
+ // We assume there are no alternative paths that avoid 'dom'.
+ // (This assumption is up to the caller to ensure!)
+ return met_dom;
}
- Node* up = sub->find_exact_control(sub->in(0));
- if (up == NULL || up->is_top()) {
- result = false; // Conservative answer for dead code
- break;
- }
- if (sub == up && (sub->is_Loop() || sub->is_Region() && sub->req() != 3)) {
- // Take first valid path on the way up to 'this'.
+ Node* up = sub->in(0);
+ // Normalize simple pass-through regions and projections:
+ up = sub->find_exact_control(up);
+ // If sub == up, we found a self-loop. Try to push past it.
+ if (sub == up && sub->is_Loop()) {
+ // Take loop entry path on the way up to 'dom'.
up = sub->in(1); // in(LoopNode::EntryControl);
+ } else if (sub == up && sub->is_Region() && sub->req() != 3) {
+ // Always take in(1) path on the way up to 'dom' for clone regions
+ // (with only one input) or regions which merge > 2 paths
+ // (usually used to merge fast/slow paths).
+ up = sub->in(1);
} else if (sub == up && sub->is_Region()) {
- assert(sub->req() == 3, "sanity");
+ // Try both paths for Regions with 2 input paths (it may be a loop head).
+ // It could give conservative 'false' answer without information
+ // which region's input is the entry path.
iterations_without_region_limit = DominatorSearchLimit; // Reset
- // Try both paths for such Regions.
- // It is not accurate without regions dominating information.
- // With such information the other path should be checked for
- // the most dominating Region which was visited before.
bool region_was_visited_before = false;
- uint i = 1;
- uint size = nlist.size();
- if (size == 0) {
- // No such Region nodes were visited before.
- // Take first valid path on the way up to 'this'.
- } else {
- // Was this Region node visited before?
- intptr_t ni;
- int j = size - 1;
- for (; j >= 0; j--) {
- ni = (intptr_t)nlist.at(j);
- if ((Node*)(ni & ~1) == sub) {
- if ((ni & 1) != 0) {
- break; // Visited 2 paths. Give up.
- } else {
- // The Region node was visited before only once.
- nlist.remove(j);
- region_was_visited_before = true;
- for (; i < sub->req(); i++) {
- Node* in = sub->in(i);
- if (in != NULL && !in->is_top() && in != sub) {
- break;
- }
- }
- i++; // Take other path.
- break;
- }
+ // Was this Region node visited before?
+ // If so, we have reached it because we accidentally took a
+ // loop-back edge from 'sub' back into the body of the loop,
+ // and worked our way up again to the loop header 'sub'.
+ // So, take the first unexplored path on the way up to 'dom'.
+ for (int j = nlist.size() - 1; j >= 0; j--) {
+ intptr_t ni = (intptr_t)nlist.at(j);
+ Node* visited = (Node*)(ni & ~1);
+ bool visited_twice_already = ((ni & 1) != 0);
+ if (visited == sub) {
+ if (visited_twice_already) {
+ // Visited 2 paths, but still stuck in loop body. Give up.
+ return false;
}
- }
- if (j >= 0 && (ni & 1) != 0) {
- result = false; // Visited 2 paths. Give up.
- break;
- }
- // The Region node was not visited before.
- }
- for (; i < sub->req(); i++) {
- Node* in = sub->in(i);
- if (in != NULL && !in->is_top() && in != sub) {
+ // The Region node was visited before only once.
+ // (We will repush with the low bit set, below.)
+ nlist.remove(j);
+ // We will find a new edge and re-insert.
+ region_was_visited_before = true;
break;
}
}
- if (i < sub->req()) {
- up = sub->in(i);
- if (region_was_visited_before && sub != up) {
- // Set 0 bit to indicate that both paths were taken.
- nlist.push((Node*)((intptr_t)sub + 1));
- } else {
- nlist.push(sub);
+
+ // Find an incoming edge which has not been seen yet; walk through it.
+ assert(up == sub, "");
+ uint skip = region_was_visited_before ? 1 : 0;
+ for (uint i = 1; i < sub->req(); i++) {
+ Node* in = sub->in(i);
+ if (in != NULL && !in->is_top() && in != sub) {
+ if (skip == 0) {
+ up = in;
+ break;
+ }
+ --skip; // skip this nontrivial input
}
}
+
+ // Set 0 bit to indicate that both paths were taken.
+ nlist.push((Node*)((intptr_t)sub + (region_was_visited_before ? 1 : 0)));
}
- if (sub == up) {
- result = false; // some kind of tight cycle
- break;
+
+ if (up == sub) {
+ break; // some kind of tight cycle
+ }
+ if (up == orig_sub && met_dom) {
+ // returned back after visiting 'dom'
+ break; // some kind of cycle
}
if (--iterations_without_region_limit < 0) {
- result = false; // dead cycle
- break;
+ break; // dead cycle
}
sub = up;
}
- return result;
+
+ // Did not meet Root or Start node in pred. chain.
+ // Conservative answer for dead code.
+ return false;
}
//------------------------------remove_dead_region-----------------------------
--- a/hotspot/src/share/vm/runtime/globals.hpp Mon Jun 16 13:38:17 2008 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Tue Jun 17 09:33:34 2008 -0700
@@ -2246,6 +2246,9 @@
product(bool, AggressiveOpts, false, \
"Enable aggressive optimizations - see arguments.cpp") \
\
+ product(bool, UseStringCache, false, \
+ "Enable String cache capabilities on String.java") \
+ \
/* statistics */ \
develop(bool, UseVTune, false, \
"enable support for Intel's VTune profiler") \
--- a/hotspot/src/share/vm/runtime/thread.cpp Mon Jun 16 13:38:17 2008 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp Tue Jun 17 09:33:34 2008 -0700
@@ -2926,21 +2926,42 @@
}
if (AggressiveOpts) {
- // Forcibly initialize java/util/HashMap and mutate the private
- // static final "frontCacheEnabled" field before we start creating instances
+ {
+ // Forcibly initialize java/util/HashMap and mutate the private
+ // static final "frontCacheEnabled" field before we start creating instances
#ifdef ASSERT
- klassOop tmp_k = SystemDictionary::find(vmSymbolHandles::java_util_HashMap(), Handle(), Handle(), CHECK_0);
- assert(tmp_k == NULL, "java/util/HashMap should not be loaded yet");
+ klassOop tmp_k = SystemDictionary::find(vmSymbolHandles::java_util_HashMap(), Handle(), Handle(), CHECK_0);
+ assert(tmp_k == NULL, "java/util/HashMap should not be loaded yet");
#endif
- klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_util_HashMap(), Handle(), Handle(), CHECK_0);
- KlassHandle k = KlassHandle(THREAD, k_o);
- guarantee(k.not_null(), "Must find java/util/HashMap");
- instanceKlassHandle ik = instanceKlassHandle(THREAD, k());
- ik->initialize(CHECK_0);
- fieldDescriptor fd;
- // Possible we might not find this field; if so, don't break
- if (ik->find_local_field(vmSymbols::frontCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) {
- k()->bool_field_put(fd.offset(), true);
+ klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_util_HashMap(), Handle(), Handle(), CHECK_0);
+ KlassHandle k = KlassHandle(THREAD, k_o);
+ guarantee(k.not_null(), "Must find java/util/HashMap");
+ instanceKlassHandle ik = instanceKlassHandle(THREAD, k());
+ ik->initialize(CHECK_0);
+ fieldDescriptor fd;
+ // Possible we might not find this field; if so, don't break
+ if (ik->find_local_field(vmSymbols::frontCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) {
+ k()->bool_field_put(fd.offset(), true);
+ }
+ }
+
+ if (UseStringCache) {
+ // Forcibly initialize java/lang/String and mutate the private
+ // static final "stringCacheEnabled" field before we start creating instances
+#ifdef ASSERT
+ klassOop tmp_k = SystemDictionary::find(vmSymbolHandles::java_lang_String(), Handle(), Handle(), CHECK_0);
+ assert(tmp_k == NULL, "java/lang/String should not be loaded yet");
+#endif
+ klassOop k_o = SystemDictionary::resolve_or_null(vmSymbolHandles::java_lang_String(), Handle(), Handle(), CHECK_0);
+ KlassHandle k = KlassHandle(THREAD, k_o);
+ guarantee(k.not_null(), "Must find java/lang/String");
+ instanceKlassHandle ik = instanceKlassHandle(THREAD, k());
+ ik->initialize(CHECK_0);
+ fieldDescriptor fd;
+ // Possible we might not find this field; if so, don't break
+ if (ik->find_local_field(vmSymbols::stringCacheEnabled_name(), vmSymbols::bool_signature(), &fd)) {
+ k()->bool_field_put(fd.offset(), true);
+ }
}
}