# HG changeset patch # User ysr # Date 1214338834 25200 # Node ID 69fefd031e6c7f6f4cb62d56d5373e580629e609 # Parent 60fb9c4db4e6033bf7cb28679c91d9424bc39774# Parent 337e0e51cd6b6eaa9bb3033e13dabe65572cdc6a Merge diff -r 60fb9c4db4e6 -r 69fefd031e6c .hgtags --- a/.hgtags Mon Jun 23 16:49:37 2008 -0700 +++ b/.hgtags Tue Jun 24 13:20:34 2008 -0700 @@ -2,3 +2,4 @@ 7836be3e92d0a4f9ee7566f602c91f5609534e66 jdk7-b25 ad0b851458ff9d1d490ed2d79bb84f75a9fdb753 jdk7-b26 e3d2692f8442e2d951166dc9bd9a330684754438 jdk7-b27 +c14dab40ed9bf45ad21150bd70c9c80cdf655415 jdk7-b28 diff -r 60fb9c4db4e6 -r 69fefd031e6c make/defs.make --- a/make/defs.make Mon Jun 23 16:49:37 2008 -0700 +++ b/make/defs.make Tue Jun 24 13:20:34 2008 -0700 @@ -261,3 +261,21 @@ EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jni.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jmm.h + +# A list of object files built without the platform specific PIC flags, e.g. +# -fPIC on linux. Performance measurements show that by compiling GC related +# code, we could significantly reduce the GC pause time on 32 bit Linux/Unix +# platforms. See 6454213 for more details. +include $(GAMMADIR)/make/scm.make + +ifneq ($(OSNAME), windows) + ifndef LP64 + NONPIC_DIRS = memory oops gc_implementation gc_interface + NONPIC_DIRS := $(foreach dir,$(NONPIC_DIRS), $(GAMMADIR)/src/share/vm/$(dir)) + # Look for source files under NONPIC_DIRS + NONPIC_FILES := $(foreach dir,$(NONPIC_DIRS),\ + $(shell find $(dir) \( $(SCM_DIRS) \) -prune -o \ + -name '*.cpp' -print)) + NONPIC_OBJ_FILES := $(notdir $(subst .cpp,.o,$(NONPIC_FILES))) + endif +endif diff -r 60fb9c4db4e6 -r 69fefd031e6c make/hotspot_version --- a/make/hotspot_version Mon Jun 23 16:49:37 2008 -0700 +++ b/make/hotspot_version Tue Jun 24 13:20:34 2008 -0700 @@ -33,9 +33,9 @@ # Don't put quotes (fail windows build). HOTSPOT_VM_COPYRIGHT=Copyright 2008 -HS_MAJOR_VER=13 +HS_MAJOR_VER=14 HS_MINOR_VER=0 -HS_BUILD_NUMBER=02 +HS_BUILD_NUMBER=01 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 diff -r 60fb9c4db4e6 -r 69fefd031e6c make/linux/makefiles/gcc.make --- a/make/linux/makefiles/gcc.make Mon Jun 23 16:49:37 2008 -0700 +++ b/make/linux/makefiles/gcc.make Tue Jun 24 13:20:34 2008 -0700 @@ -50,14 +50,7 @@ VM_PICFLAG/LIBJVM = $(PICFLAG) VM_PICFLAG/AOUT = - -ifneq ($(BUILDARCH), i486) VM_PICFLAG = $(VM_PICFLAG/$(LINK_INTO)) -else -# PIC has significant overhead on x86, build nonpic VM for now. -# Link JVM at a "good" base location to avoid unnecessary .text patching. -JVM_BASE_ADDR = 0x06000000 -endif CFLAGS += $(VM_PICFLAG) CFLAGS += -fno-rtti diff -r 60fb9c4db4e6 -r 69fefd031e6c make/linux/makefiles/rules.make --- a/make/linux/makefiles/rules.make Mon Jun 23 16:49:37 2008 -0700 +++ b/make/linux/makefiles/rules.make Tue Jun 24 13:20:34 2008 -0700 @@ -133,10 +133,22 @@ COMPILE_DONE = && { echo Done with $<; } endif +include $(GAMMADIR)/make/defs.make + +# The non-PIC object files are only generated for 32 bit platforms. +ifdef LP64 %.o: %.cpp @echo Compiling $< $(QUIETLY) $(REMOVE_TARGET) $(QUIETLY) $(COMPILE.CC) -o $@ $< $(COMPILE_DONE) +else +%.o: %.cpp + @echo Compiling $< + $(QUIETLY) $(REMOVE_TARGET) + $(QUIETLY) $(if $(findstring $@, $(NONPIC_OBJ_FILES)), \ + $(subst $(VM_PICFLAG), ,$(COMPILE.CC)) -o $@ $< $(COMPILE_DONE), \ + $(COMPILE.CC) -o $@ $< $(COMPILE_DONE)) +endif %.o: %.s @echo Assembling $< diff -r 60fb9c4db4e6 -r 69fefd031e6c make/solaris/makefiles/jvmg.make --- a/make/solaris/makefiles/jvmg.make Mon Jun 23 16:49:37 2008 -0700 +++ b/make/solaris/makefiles/jvmg.make Tue Jun 24 13:20:34 2008 -0700 @@ -30,7 +30,7 @@ ifeq ("${Platform_compiler}", "sparcWorks") -ifeq ($(COMPILER_REV),5.8)) +ifeq ($(COMPILER_REV),5.8) # SS11 SEGV when compiling with -g and -xarch=v8, using different backend DEBUG_CFLAGS/compileBroker.o = $(DEBUG_CFLAGS) -xO0 DEBUG_CFLAGS/jvmtiTagMap.o = $(DEBUG_CFLAGS) -xO0 diff -r 60fb9c4db4e6 -r 69fefd031e6c make/solaris/makefiles/rules.make --- a/make/solaris/makefiles/rules.make Mon Jun 23 16:49:37 2008 -0700 +++ b/make/solaris/makefiles/rules.make Tue Jun 24 13:20:34 2008 -0700 @@ -133,19 +133,7 @@ COMPILE_DONE = && { echo Done with $<; } endif -# A list of directories under which all source code are built without -KPIC/-Kpic -# flag. Performance measurements show that compiling GC related code will -# dramatically reduce the gc pause time. See bug 6454213 for more details. - -include $(GAMMADIR)/make/scm.make - -NONPIC_DIRS = memory oops gc_implementation gc_interface -NONPIC_DIRS := $(foreach dir,$(NONPIC_DIRS), $(GAMMADIR)/src/share/vm/$(dir)) -# Look for source code under NONPIC_DIRS -NONPIC_FILES := $(foreach dir,$(NONPIC_DIRS),\ - $(shell find $(dir) \( $(SCM_DIRS) \) -prune -o \ - -name '*.cpp' -print)) -NONPIC_OBJ_FILES := $(notdir $(subst .cpp,.o,$(NONPIC_FILES))) +include $(GAMMADIR)/make/defs.make # Sun compiler for 64 bit Solaris does not support building non-PIC object files. ifdef LP64 diff -r 60fb9c4db4e6 -r 69fefd031e6c src/os/linux/vm/jvm_linux.cpp --- a/src/os/linux/vm/jvm_linux.cpp Mon Jun 23 16:49:37 2008 -0700 +++ b/src/os/linux/vm/jvm_linux.cpp Tue Jun 24 13:20:34 2008 -0700 @@ -132,7 +132,7 @@ */ struct siglabel { - char *name; + const char *name; int number; }; diff -r 60fb9c4db4e6 -r 69fefd031e6c src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Mon Jun 23 16:49:37 2008 -0700 +++ b/src/os/linux/vm/os_linux.cpp Tue Jun 24 13:20:34 2008 -0700 @@ -75,8 +75,8 @@ bool os::Linux::_is_floating_stack = false; bool os::Linux::_is_NPTL = false; bool os::Linux::_supports_fast_thread_cpu_time = false; -char * os::Linux::_glibc_version = NULL; -char * os::Linux::_libpthread_version = NULL; +const char * os::Linux::_glibc_version = NULL; +const char * os::Linux::_libpthread_version = NULL; static jlong initial_time_count=0; @@ -213,9 +213,9 @@ // the system call returns 1. This causes the VM to act as if it is // a single processor and elide locking (see is_MP() call). static bool unsafe_chroot_detected = false; -static char *unstable_chroot_error = "/proc file system not found.\n" - "Java may be unstable running multithreaded in a chroot " - "environment on Linux when /proc filesystem is not mounted."; +static const char *unstable_chroot_error = "/proc file system not found.\n" + "Java may be unstable running multithreaded in a chroot " + "environment on Linux when /proc filesystem is not mounted."; void os::Linux::initialize_system_info() { _processor_count = sysconf(_SC_NPROCESSORS_CONF); @@ -544,26 +544,23 @@ if (n > 0) { char *str = (char *)malloc(n); confstr(_CS_GNU_LIBPTHREAD_VERSION, str, n); - // Vanilla RH-9 (glibc 2.3.2) has a bug that confstr() always tells // us "NPTL-0.29" even we are running with LinuxThreads. Check if this - // is the case: + // is the case. LinuxThreads has a hard limit on max number of threads. + // So sysconf(_SC_THREAD_THREADS_MAX) will return a positive value. + // On the other hand, NPTL does not have such a limit, sysconf() + // will return -1 and errno is not changed. Check if it is really NPTL. if (strcmp(os::Linux::glibc_version(), "glibc 2.3.2") == 0 && - strstr(str, "NPTL")) { - // LinuxThreads has a hard limit on max number of threads. So - // sysconf(_SC_THREAD_THREADS_MAX) will return a positive value. - // On the other hand, NPTL does not have such a limit, sysconf() - // will return -1 and errno is not changed. Check if it is really - // NPTL: - if (sysconf(_SC_THREAD_THREADS_MAX) > 0) { - free(str); - str = "linuxthreads"; - } + strstr(str, "NPTL") && + sysconf(_SC_THREAD_THREADS_MAX) > 0) { + free(str); + os::Linux::set_libpthread_version("linuxthreads"); + } else { + os::Linux::set_libpthread_version(str); } - os::Linux::set_libpthread_version(str); } else { - // glibc before 2.3.2 only has LinuxThreads. - os::Linux::set_libpthread_version("linuxthreads"); + // glibc before 2.3.2 only has LinuxThreads. + os::Linux::set_libpthread_version("linuxthreads"); } if (strstr(libpthread_version(), "NPTL")) { @@ -4643,11 +4640,7 @@ // Unlike system(), this function can be called from signal handler. It // doesn't block SIGINT et al. int os::fork_and_exec(char* cmd) { - char * argv[4]; - argv[0] = "sh"; - argv[1] = "-c"; - argv[2] = cmd; - argv[3] = NULL; + const char * argv[4] = {"sh", "-c", cmd, NULL}; // fork() in LinuxThreads/NPTL is not async-safe. It needs to run // pthread_atfork handlers and reset pthread library. All we need is a @@ -4672,7 +4665,7 @@ // IA64 should use normal execve() from glibc to match the glibc fork() // above. NOT_IA64(syscall(__NR_execve, "/bin/sh", argv, environ);) - IA64_ONLY(execve("/bin/sh", argv, environ);) + IA64_ONLY(execve("/bin/sh", (char* const*)argv, environ);) // execve failed _exit(-1); diff -r 60fb9c4db4e6 -r 69fefd031e6c src/os/linux/vm/os_linux.hpp --- a/src/os/linux/vm/os_linux.hpp Mon Jun 23 16:49:37 2008 -0700 +++ b/src/os/linux/vm/os_linux.hpp Tue Jun 24 13:20:34 2008 -0700 @@ -52,8 +52,8 @@ static address _initial_thread_stack_bottom; static uintptr_t _initial_thread_stack_size; - static char *_glibc_version; - static char *_libpthread_version; + static const char *_glibc_version; + static const char *_libpthread_version; static bool _is_floating_stack; static bool _is_NPTL; @@ -72,8 +72,8 @@ static julong physical_memory() { return _physical_memory; } static void initialize_system_info(); - static void set_glibc_version(char *s) { _glibc_version = s; } - static void set_libpthread_version(char *s) { _libpthread_version = s; } + static void set_glibc_version(const char *s) { _glibc_version = s; } + static void set_libpthread_version(const char *s) { _libpthread_version = s; } static bool supports_variable_stack_size(); @@ -134,8 +134,8 @@ static bool chained_handler(int sig, siginfo_t* siginfo, void* context); // GNU libc and libpthread version strings - static char *glibc_version() { return _glibc_version; } - static char *libpthread_version() { return _libpthread_version; } + static const char *glibc_version() { return _glibc_version; } + static const char *libpthread_version() { return _libpthread_version; } // NPTL or LinuxThreads? static bool is_LinuxThreads() { return !_is_NPTL; } diff -r 60fb9c4db4e6 -r 69fefd031e6c src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Mon Jun 23 16:49:37 2008 -0700 +++ b/src/share/vm/classfile/vmSymbols.hpp Tue Jun 24 13:20: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") \ diff -r 60fb9c4db4e6 -r 69fefd031e6c src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Mon Jun 23 16:49:37 2008 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Tue Jun 24 13:20:34 2008 -0700 @@ -1004,6 +1004,9 @@ DEBUG_ONLY(mark_bitmap()->verify_clear();) DEBUG_ONLY(summary_data().verify_clear();) + + // Have worker threads release resources the next time they run a task. + gc_task_manager()->release_all_resources(); } void PSParallelCompact::post_compact() @@ -1949,12 +1952,6 @@ TimeStamp compaction_start; TimeStamp collection_exit; - // "serial_CM" is needed until the parallel implementation - // of the move and update is done. - ParCompactionManager* serial_CM = new ParCompactionManager(); - // Don't initialize more than once. - // serial_CM->initialize(&summary_data(), mark_bitmap()); - ParallelScavengeHeap* heap = gc_heap(); GCCause::Cause gc_cause = heap->gc_cause(); PSYoungGen* young_gen = heap->young_gen(); @@ -1969,6 +1966,10 @@ PreGCValues pre_gc_values; pre_compact(&pre_gc_values); + // Get the compaction manager reserved for the VM thread. + ParCompactionManager* const vmthread_cm = + ParCompactionManager::manager_array(gc_task_manager()->workers()); + // Place after pre_compact() where the number of invocations is incremented. AdaptiveSizePolicyOutput(size_policy, heap->total_collections()); @@ -2008,7 +2009,7 @@ bool marked_for_unloading = false; marking_start.update(); - marking_phase(serial_CM, maximum_heap_compaction); + marking_phase(vmthread_cm, maximum_heap_compaction); #ifndef PRODUCT if (TraceParallelOldGCMarkingPhase) { @@ -2039,7 +2040,7 @@ #endif bool max_on_system_gc = UseMaximumCompactionOnSystemGC && is_system_gc; - summary_phase(serial_CM, maximum_heap_compaction || max_on_system_gc); + summary_phase(vmthread_cm, maximum_heap_compaction || max_on_system_gc); #ifdef ASSERT if (VerifyParallelOldWithMarkSweep && @@ -2067,13 +2068,13 @@ // code can use the the forwarding pointers to // check the new pointer calculation. The restore_marks() // has to be done before the real compact. - serial_CM->set_action(ParCompactionManager::VerifyUpdate); - compact_perm(serial_CM); - compact_serial(serial_CM); - serial_CM->set_action(ParCompactionManager::ResetObjects); - compact_perm(serial_CM); - compact_serial(serial_CM); - serial_CM->set_action(ParCompactionManager::UpdateAndCopy); + vmthread_cm->set_action(ParCompactionManager::VerifyUpdate); + compact_perm(vmthread_cm); + compact_serial(vmthread_cm); + vmthread_cm->set_action(ParCompactionManager::ResetObjects); + compact_perm(vmthread_cm); + compact_serial(vmthread_cm); + vmthread_cm->set_action(ParCompactionManager::UpdateAndCopy); // For debugging only PSMarkSweep::restore_marks(); @@ -2084,16 +2085,14 @@ compaction_start.update(); // Does the perm gen always have to be done serially because // klasses are used in the update of an object? - compact_perm(serial_CM); + compact_perm(vmthread_cm); if (UseParallelOldGCCompacting) { compact(); } else { - compact_serial(serial_CM); + compact_serial(vmthread_cm); } - delete serial_CM; - // Reset the mark bitmap, summary data, and do other bookkeeping. Must be // done before resizing. post_compact(); diff -r 60fb9c4db4e6 -r 69fefd031e6c src/share/vm/opto/memnode.cpp --- a/src/share/vm/opto/memnode.cpp Mon Jun 23 16:49:37 2008 -0700 +++ b/src/share/vm/opto/memnode.cpp Tue Jun 24 13:20: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)) diff -r 60fb9c4db4e6 -r 69fefd031e6c src/share/vm/opto/node.cpp --- a/src/share/vm/opto/node.cpp Mon Jun 23 16:49:37 2008 -0700 +++ b/src/share/vm/opto/node.cpp Tue Jun 24 13:20: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----------------------------- diff -r 60fb9c4db4e6 -r 69fefd031e6c src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Mon Jun 23 16:49:37 2008 -0700 +++ b/src/share/vm/runtime/globals.hpp Tue Jun 24 13:20:34 2008 -0700 @@ -2261,6 +2261,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") \ diff -r 60fb9c4db4e6 -r 69fefd031e6c src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Mon Jun 23 16:49:37 2008 -0700 +++ b/src/share/vm/runtime/thread.cpp Tue Jun 24 13:20:34 2008 -0700 @@ -2947,21 +2947,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); + } } }