Mercurial > hg > graal-compiler
changeset 712:6e33bfd4139b
Merge
author | never |
---|---|
date | Tue, 14 Apr 2009 12:25:54 -0700 |
parents | 68cd0d7ee9bb (diff) 9610b2a8ab4e (current diff) |
children | 4961a8a726a4 67a2f5ba5582 |
files | src/share/vm/runtime/arguments.cpp src/share/vm/runtime/globals.hpp |
diffstat | 24 files changed, 442 insertions(+), 155 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Fri Apr 10 15:01:14 2009 -0700 +++ b/.hgtags Tue Apr 14 12:25:54 2009 -0700 @@ -26,3 +26,5 @@ 8b22ccb5aba2c6c11bddf6488a7bb7ef5b4bf2be jdk7-b49 dae503d9f04c1a11e182dbf7f770509c28dc0609 jdk7-b50 2581d90c6c9b2012da930eb4742add94a03069a0 jdk7-b51 +1b1e8f1a4fe8cebc01c022484f78148e17b62a0d jdk7-b52 +032c6af894dae8d939b3dd31d82042549e7793e0 jdk7-b53
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java Fri Apr 10 15:01:14 2009 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java Tue Apr 14 12:25:54 2009 -0700 @@ -48,6 +48,8 @@ private static AddressField lastJavaPCField; private static CIntegerField threadStateField; private static AddressField osThreadField; + private static AddressField stackBaseField; + private static CIntegerField stackSizeField; private static JavaThreadPDAccess access; @@ -83,6 +85,8 @@ lastJavaPCField = anchorType.getAddressField("_last_Java_pc"); threadStateField = type.getCIntegerField("_thread_state"); osThreadField = type.getAddressField("_osthread"); + stackBaseField = type.getAddressField("_stack_base"); + stackSizeField = type.getCIntegerField("_stack_size"); UNINITIALIZED = db.lookupIntConstant("_thread_uninitialized").intValue(); NEW = db.lookupIntConstant("_thread_new").intValue(); @@ -312,6 +316,14 @@ return (OSThread) VMObjectFactory.newObject(OSThread.class, osThreadField.getValue(addr)); } + public Address getStackBase() { + return stackBaseField.getValue(); + } + + public long getStackSize() { + return stackSizeField.getValue(); + } + /** Gets the Java-side thread object for this JavaThread */ public Oop getThreadObj() { return VM.getVM().getObjectHeap().newOop(threadObjField.getValue(addr)); @@ -345,11 +357,18 @@ if (Assert.ASSERTS_ENABLED) { Assert.that(VM.getVM().isDebugging(), "Not yet implemented for non-debugging system"); } - Address highest = highestLock(); Address sp = lastSPDbg(); + Address stackBase = getStackBase(); // Be robust - if ((highest == null) || (sp == null)) return false; - return (highest.greaterThanOrEqual(a) && sp.lessThanOrEqual(a)); + if (sp == null) return false; + return stackBase.greaterThanOrEqual(a) && sp.lessThanOrEqual(a); + } + + public boolean isLockOwned(Address a) { + Address stackBase = getStackBase(); + Address stackLimit = stackBase.addOffsetTo(-getStackSize()); + + return stackBase.greaterThanOrEqual(a) && stackLimit.lessThanOrEqual(a); // FIXME: should traverse MonitorArray/MonitorChunks as in VM }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Thread.java Fri Apr 10 15:01:14 2009 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Thread.java Tue Apr 14 12:25:54 2009 -0700 @@ -38,7 +38,6 @@ private static int HAS_ASYNC_EXCEPTION; private static AddressField activeHandlesField; - private static AddressField highestLockField; private static AddressField currentPendingMonitorField; private static AddressField currentWaitingMonitorField; @@ -60,7 +59,6 @@ tlabFieldOffset = type.getField("_tlab").getOffset(); activeHandlesField = type.getAddressField("_active_handles"); - highestLockField = type.getAddressField("_highest_lock"); currentPendingMonitorField = type.getAddressField("_current_pending_monitor"); currentWaitingMonitorField = type.getAddressField("_current_waiting_monitor"); } @@ -121,10 +119,6 @@ // pending exception } - public Address highestLock() { - return highestLockField.getValue(addr); - } - public ObjectMonitor getCurrentPendingMonitor() { Address monitorAddr = currentPendingMonitorField.getValue(addr); if (monitorAddr == null) {
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java Fri Apr 10 15:01:14 2009 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/Threads.java Tue Apr 14 12:25:54 2009 -0700 @@ -164,20 +164,11 @@ } } - long leastDiff = 0; - boolean leastDiffInitialized = false; - JavaThread theOwner = null; for (JavaThread thread = first(); thread != null; thread = thread.next()) { - Address addr = thread.highestLock(); - if (addr == null || addr.lessThan(o)) continue; - long diff = addr.minus(o); - if (!leastDiffInitialized || diff < leastDiff) { - leastDiffInitialized = true; - leastDiff = diff; - theOwner = thread; - } + if (thread.isLockOwned(o)) + return thread; } - return theOwner; + return null; } public JavaThread owningThreadFromMonitor(ObjectMonitor monitor) {
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Fri Apr 10 15:01:14 2009 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Tue Apr 14 12:25:54 2009 -0700 @@ -342,8 +342,10 @@ throw new RuntimeException("Attempt to initialize VM twice"); } soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian()); + debugger.putHeapConst(soleInstance.getHeapOopSize(), Universe.getNarrowOopBase(), Universe.getNarrowOopShift()); + for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { ((Observer) iter.next()).update(null, null); }
--- a/make/hotspot_version Fri Apr 10 15:01:14 2009 -0700 +++ b/make/hotspot_version Tue Apr 14 12:25:54 2009 -0700 @@ -31,11 +31,11 @@ # # Don't put quotes (fail windows build). -HOTSPOT_VM_COPYRIGHT=Copyright 2008 +HOTSPOT_VM_COPYRIGHT=Copyright 2009 -HS_MAJOR_VER=15 +HS_MAJOR_VER=16 HS_MINOR_VER=0 -HS_BUILD_NUMBER=04 +HS_BUILD_NUMBER=01 JDK_MAJOR_VER=1 JDK_MINOR_VER=7
--- a/src/os/linux/vm/os_linux.cpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/os/linux/vm/os_linux.cpp Tue Apr 14 12:25:54 2009 -0700 @@ -1518,21 +1518,51 @@ const char* os::get_temp_directory() { return "/tmp/"; } -void os::dll_build_name( - char* buffer, size_t buflen, const char* pname, const char* fname) { - // copied from libhpi +static bool file_exists(const char* filename) { + struct stat statbuf; + if (filename == NULL || strlen(filename) == 0) { + return false; + } + return os::stat(filename, &statbuf) == 0; +} + +void os::dll_build_name(char* buffer, size_t buflen, + const char* pname, const char* fname) { + // Copied from libhpi const size_t pnamelen = pname ? strlen(pname) : 0; - /* Quietly truncate on buffer overflow. Should be an error. */ + // Quietly truncate on buffer overflow. Should be an error. if (pnamelen + strlen(fname) + 10 > (size_t) buflen) { *buffer = '\0'; return; } if (pnamelen == 0) { - sprintf(buffer, "lib%s.so", fname); + snprintf(buffer, buflen, "lib%s.so", fname); + } else if (strchr(pname, *os::path_separator()) != NULL) { + int n; + char** pelements = split_path(pname, &n); + for (int i = 0 ; i < n ; i++) { + // Really shouldn't be NULL, but check can't hurt + if (pelements[i] == NULL || strlen(pelements[i]) == 0) { + continue; // skip the empty path values + } + snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname); + if (file_exists(buffer)) { + break; + } + } + // release the storage + for (int i = 0 ; i < n ; i++) { + if (pelements[i] != NULL) { + FREE_C_HEAP_ARRAY(char, pelements[i]); + } + } + if (pelements != NULL) { + FREE_C_HEAP_ARRAY(char*, pelements); + } } else { - sprintf(buffer, "%s/lib%s.so", pname, fname); + snprintf(buffer, buflen, "%s/lib%s.so", pname, fname); } }
--- a/src/os/solaris/vm/os_solaris.cpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/os/solaris/vm/os_solaris.cpp Tue Apr 14 12:25:54 2009 -0700 @@ -1827,21 +1827,51 @@ const char* os::get_temp_directory() { return "/tmp/"; } -void os::dll_build_name( - char* buffer, size_t buflen, const char* pname, const char* fname) { - // copied from libhpi +static bool file_exists(const char* filename) { + struct stat statbuf; + if (filename == NULL || strlen(filename) == 0) { + return false; + } + return os::stat(filename, &statbuf) == 0; +} + +void os::dll_build_name(char* buffer, size_t buflen, + const char* pname, const char* fname) { + // Copied from libhpi const size_t pnamelen = pname ? strlen(pname) : 0; - /* Quietly truncate on buffer overflow. Should be an error. */ + // Quietly truncate on buffer overflow. Should be an error. if (pnamelen + strlen(fname) + 10 > (size_t) buflen) { *buffer = '\0'; return; } if (pnamelen == 0) { - sprintf(buffer, "lib%s.so", fname); + snprintf(buffer, buflen, "lib%s.so", fname); + } else if (strchr(pname, *os::path_separator()) != NULL) { + int n; + char** pelements = split_path(pname, &n); + for (int i = 0 ; i < n ; i++) { + // really shouldn't be NULL but what the heck, check can't hurt + if (pelements[i] == NULL || strlen(pelements[i]) == 0) { + continue; // skip the empty path values + } + snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname); + if (file_exists(buffer)) { + break; + } + } + // release the storage + for (int i = 0 ; i < n ; i++) { + if (pelements[i] != NULL) { + FREE_C_HEAP_ARRAY(char, pelements[i]); + } + } + if (pelements != NULL) { + FREE_C_HEAP_ARRAY(char*, pelements); + } } else { - sprintf(buffer, "%s/lib%s.so", pname, fname); + snprintf(buffer, buflen, "%s/lib%s.so", pname, fname); } }
--- a/src/os/windows/vm/os_windows.cpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/os/windows/vm/os_windows.cpp Tue Apr 14 12:25:54 2009 -0700 @@ -1004,26 +1004,61 @@ } } -void os::dll_build_name(char *holder, size_t holderlen, - const char* pname, const char* fname) -{ - // copied from libhpi - const size_t pnamelen = pname ? strlen(pname) : 0; - const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0; - - /* Quietly truncates on buffer overflow. Should be an error. */ - if (pnamelen + strlen(fname) + 10 > holderlen) { - *holder = '\0'; - return; +static bool file_exists(const char* filename) { + if (filename == NULL || strlen(filename) == 0) { + return false; + } + return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES; +} + +void os::dll_build_name(char *buffer, size_t buflen, + const char* pname, const char* fname) { + // Copied from libhpi + const size_t pnamelen = pname ? strlen(pname) : 0; + const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0; + + // Quietly truncates on buffer overflow. Should be an error. + if (pnamelen + strlen(fname) + 10 > buflen) { + *buffer = '\0'; + return; + } + + if (pnamelen == 0) { + jio_snprintf(buffer, buflen, "%s.dll", fname); + } else if (c == ':' || c == '\\') { + jio_snprintf(buffer, buflen, "%s%s.dll", pname, fname); + } else if (strchr(pname, *os::path_separator()) != NULL) { + int n; + char** pelements = split_path(pname, &n); + for (int i = 0 ; i < n ; i++) { + char* path = pelements[i]; + // Really shouldn't be NULL, but check can't hurt + size_t plen = (path == NULL) ? 0 : strlen(path); + if (plen == 0) { + continue; // skip the empty path values + } + const char lastchar = path[plen - 1]; + if (lastchar == ':' || lastchar == '\\') { + jio_snprintf(buffer, buflen, "%s%s.dll", path, fname); + } else { + jio_snprintf(buffer, buflen, "%s\\%s.dll", path, fname); + } + if (file_exists(buffer)) { + break; + } } - - if (pnamelen == 0) { - sprintf(holder, "%s.dll", fname); - } else if (c == ':' || c == '\\') { - sprintf(holder, "%s%s.dll", pname, fname); - } else { - sprintf(holder, "%s\\%s.dll", pname, fname); + // release the storage + for (int i = 0 ; i < n ; i++) { + if (pelements[i] != NULL) { + FREE_C_HEAP_ARRAY(char, pelements[i]); + } } + if (pelements != NULL) { + FREE_C_HEAP_ARRAY(char*, pelements); + } + } else { + jio_snprintf(buffer, buflen, "%s\\%s.dll", pname, fname); + } } // Needs to be in os specific directory because windows requires another
--- a/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Tue Apr 14 12:25:54 2009 -0700 @@ -34,10 +34,12 @@ Generation* old_gen_, int thread_num_, ObjToScanQueueSet* work_queue_set_, + GrowableArray<oop>** overflow_stack_set_, size_t desired_plab_sz_, ParallelTaskTerminator& term_) : _to_space(to_space_), _old_gen(old_gen_), _young_gen(gen_), _thread_num(thread_num_), _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false), + _overflow_stack(overflow_stack_set_[thread_num_]), _ageTable(false), // false ==> not the global age table, no perf data. _to_space_alloc_buffer(desired_plab_sz_), _to_space_closure(gen_, this), _old_gen_closure(gen_, this), @@ -57,11 +59,6 @@ _start = os::elapsedTime(); _old_gen_closure.set_generation(old_gen_); _old_gen_root_closure.set_generation(old_gen_); - if (UseCompressedOops) { - _overflow_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(512, true); - } else { - _overflow_stack = NULL; - } } #ifdef _MSC_VER #pragma warning( pop ) @@ -155,7 +152,7 @@ } bool ParScanThreadState::take_from_overflow_stack() { - assert(UseCompressedOops, "Else should not call"); + assert(ParGCUseLocalOverflow, "Else should not call"); assert(young_gen()->overflow_list() == NULL, "Error"); ObjToScanQueue* queue = work_queue(); GrowableArray<oop>* of_stack = overflow_stack(); @@ -183,7 +180,7 @@ } void ParScanThreadState::push_on_overflow_stack(oop p) { - assert(UseCompressedOops, "Else should not call"); + assert(ParGCUseLocalOverflow, "Else should not call"); overflow_stack()->push(p); assert(young_gen()->overflow_list() == NULL, "Error"); } @@ -260,6 +257,7 @@ ParNewGeneration& gen, Generation& old_gen, ObjToScanQueueSet& queue_set, + GrowableArray<oop>** overflow_stacks_, size_t desired_plab_sz, ParallelTaskTerminator& term); inline ParScanThreadState& thread_sate(int i); @@ -282,6 +280,7 @@ ParScanThreadStateSet::ParScanThreadStateSet( int num_threads, Space& to_space, ParNewGeneration& gen, Generation& old_gen, ObjToScanQueueSet& queue_set, + GrowableArray<oop>** overflow_stack_set_, size_t desired_plab_sz, ParallelTaskTerminator& term) : ResourceArray(sizeof(ParScanThreadState), num_threads), _gen(gen), _next_gen(old_gen), _term(term), @@ -292,7 +291,7 @@ for (int i = 0; i < num_threads; ++i) { new ((ParScanThreadState*)_data + i) ParScanThreadState(&to_space, &gen, &old_gen, i, &queue_set, - desired_plab_sz, term); + overflow_stack_set_, desired_plab_sz, term); } } @@ -519,6 +518,17 @@ for (uint i2 = 0; i2 < ParallelGCThreads; i2++) _task_queues->queue(i2)->initialize(); + _overflow_stacks = NEW_C_HEAP_ARRAY(GrowableArray<oop>*, ParallelGCThreads); + guarantee(_overflow_stacks != NULL, "Overflow stack set allocation failure"); + for (uint i = 0; i < ParallelGCThreads; i++) { + if (ParGCUseLocalOverflow) { + _overflow_stacks[i] = new (ResourceObj::C_HEAP) GrowableArray<oop>(512, true); + guarantee(_overflow_stacks[i] != NULL, "Overflow Stack allocation failure."); + } else { + _overflow_stacks[i] = NULL; + } + } + if (UsePerfData) { EXCEPTION_MARK; ResourceMark rm; @@ -784,7 +794,7 @@ ParallelTaskTerminator _term(workers->total_workers(), task_queues()); ParScanThreadStateSet thread_state_set(workers->total_workers(), *to(), *this, *_next_gen, *task_queues(), - desired_plab_sz(), _term); + _overflow_stacks, desired_plab_sz(), _term); ParNewGenTask tsk(this, _next_gen, reserved().end(), &thread_state_set); int n_workers = workers->total_workers(); @@ -1238,11 +1248,12 @@ #define BUSY (oop(0x1aff1aff)) void ParNewGeneration::push_on_overflow_list(oop from_space_obj, ParScanThreadState* par_scan_state) { assert(is_in_reserved(from_space_obj), "Should be from this generation"); - if (UseCompressedOops) { + if (ParGCUseLocalOverflow) { // In the case of compressed oops, we use a private, not-shared // overflow stack. par_scan_state->push_on_overflow_stack(from_space_obj); } else { + assert(!UseCompressedOops, "Error"); // if the object has been forwarded to itself, then we cannot // use the klass pointer for the linked list. Instead we have // to allocate an oopDesc in the C-Heap and use that for the linked list. @@ -1275,9 +1286,10 @@ bool ParNewGeneration::take_from_overflow_list(ParScanThreadState* par_scan_state) { bool res; - if (UseCompressedOops) { + if (ParGCUseLocalOverflow) { res = par_scan_state->take_from_overflow_stack(); } else { + assert(!UseCompressedOops, "Error"); res = take_from_overflow_list_work(par_scan_state); } return res; @@ -1305,6 +1317,7 @@ (size_t)ParGCDesiredObjsFromOverflowList); assert(par_scan_state->overflow_stack() == NULL, "Error"); + assert(!UseCompressedOops, "Error"); if (_overflow_list == NULL) return false; // Otherwise, there was something there; try claiming the list.
--- a/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Tue Apr 14 12:25:54 2009 -0700 @@ -33,8 +33,8 @@ // but they must be here to allow ParScanClosure::do_oop_work to be defined // in genOopClosures.inline.hpp. -typedef OopTaskQueue ObjToScanQueue; -typedef OopTaskQueueSet ObjToScanQueueSet; +typedef OopTaskQueue ObjToScanQueue; +typedef OopTaskQueueSet ObjToScanQueueSet; // Enable this to get push/pop/steal stats. const int PAR_STATS_ENABLED = 0; @@ -116,7 +116,9 @@ ParScanThreadState(Space* to_space_, ParNewGeneration* gen_, Generation* old_gen_, int thread_num_, - ObjToScanQueueSet* work_queue_set_, size_t desired_plab_sz_, + ObjToScanQueueSet* work_queue_set_, + GrowableArray<oop>** overflow_stack_set_, + size_t desired_plab_sz_, ParallelTaskTerminator& term_); public: @@ -296,9 +298,12 @@ char pad[64 - sizeof(ObjToScanQueue)]; // prevent false sharing }; - // The per-thread work queues, available here for stealing. + // The per-worker-thread work queues ObjToScanQueueSet* _task_queues; + // Per-worker-thread local overflow stacks + GrowableArray<oop>** _overflow_stacks; + // Desired size of survivor space plab's PLABStats _plab_stats;
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Tue Apr 14 12:25:54 2009 -0700 @@ -508,6 +508,7 @@ assert(destination <= target_end, "sanity"); assert(destination + _region_data[src_region].data_size() > target_end, "region should not fit into target space"); + assert(is_region_aligned(target_end), "sanity"); size_t split_region = src_region; HeapWord* split_destination = destination; @@ -538,14 +539,12 @@ // max(top, max(new_top, clear_top)) // // where clear_top is a new field in SpaceInfo. Would have to set clear_top - // to destination + partial_obj_size, where both have the values passed to - // this routine. + // to target_end. const RegionData* const sr = region(split_region); const size_t beg_idx = addr_to_region_idx(region_align_up(sr->destination() + sr->partial_obj_size())); - const size_t end_idx = - addr_to_region_idx(region_align_up(destination + partial_obj_size)); + const size_t end_idx = addr_to_region_idx(target_end); if (TraceParallelOldGCSummaryPhase) { gclog_or_tty->print_cr("split: clearing source_region field in ["
--- a/src/share/vm/runtime/arguments.cpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/runtime/arguments.cpp Tue Apr 14 12:25:54 2009 -0700 @@ -852,16 +852,13 @@ FreeHeap(value); } return true; - } - else if (strcmp(key, "sun.java.command") == 0) { - + } else if (strcmp(key, "sun.java.command") == 0) { _java_command = value; // don't add this property to the properties exposed to the java application FreeHeap(key); return true; - } - else if (strcmp(key, "sun.java.launcher.pid") == 0) { + } else if (strcmp(key, "sun.java.launcher.pid") == 0) { // launcher.pid property is private and is processed // in process_sun_java_launcher_properties(); // the sun.java.launcher property is passed on to the java application @@ -870,13 +867,14 @@ FreeHeap(value); } return true; - } - else if (strcmp(key, "java.vendor.url.bug") == 0) { + } else if (strcmp(key, "java.vendor.url.bug") == 0) { // save it in _java_vendor_url_bug, so JVM fatal error handler can access // its value without going through the property list or making a Java call. _java_vendor_url_bug = value; + } else if (strcmp(key, "sun.boot.library.path") == 0) { + PropertyList_unique_add(&_system_properties, key, value, true); + return true; } - // Create new property and add at the end of the list PropertyList_unique_add(&_system_properties, key, value); return true; @@ -895,7 +893,7 @@ // Ensure Agent_OnLoad has the correct initial values. // This may not be the final mode; mode may change later in onload phase. PropertyList_unique_add(&_system_properties, "java.vm.info", - (char*)Abstract_VM_Version::vm_info_string()); + (char*)Abstract_VM_Version::vm_info_string(), false); UseInterpreter = true; UseCompiler = true; @@ -971,7 +969,7 @@ } else { no_shared_spaces(); - // By default YoungPLABSize and OldPLABSize are set to 4096 and 1024 correspondinly, + // By default YoungPLABSize and OldPLABSize are set to 4096 and 1024 respectively, // these settings are default for Parallel Scavenger. For ParNew+Tenured configuration // we set them to 1024 and 1024. // See CR 6362902. @@ -987,6 +985,16 @@ if (AlwaysTenure) { FLAG_SET_CMDLINE(intx, MaxTenuringThreshold, 0); } + // When using compressed oops, we use local overflow stacks, + // rather than using a global overflow list chained through + // the klass word of the object's pre-image. + if (UseCompressedOops && !ParGCUseLocalOverflow) { + if (!FLAG_IS_DEFAULT(ParGCUseLocalOverflow)) { + warning("Forcing +ParGCUseLocalOverflow: needed if using compressed references"); + } + FLAG_SET_DEFAULT(ParGCUseLocalOverflow, true); + } + assert(ParGCUseLocalOverflow || !UseCompressedOops, "Error"); } } @@ -2771,7 +2779,7 @@ } // This add maintains unique property key in the list. -void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, char* v) { +void Arguments::PropertyList_unique_add(SystemProperty** plist, const char* k, char* v, jboolean append) { if (plist == NULL) return; @@ -2779,7 +2787,11 @@ SystemProperty* prop; for (prop = *plist; prop != NULL; prop = prop->next()) { if (strcmp(k, prop->key()) == 0) { - prop->set_value(v); + if (append) { + prop->append_value(v); + } else { + prop->set_value(v); + } return; } }
--- a/src/share/vm/runtime/arguments.hpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/runtime/arguments.hpp Tue Apr 14 12:25:54 2009 -0700 @@ -475,10 +475,13 @@ // System properties static void init_system_properties(); - // Proptery List manipulation + // Property List manipulation static void PropertyList_add(SystemProperty** plist, SystemProperty *element); static void PropertyList_add(SystemProperty** plist, const char* k, char* v); - static void PropertyList_unique_add(SystemProperty** plist, const char* k, char* v); + static void PropertyList_unique_add(SystemProperty** plist, const char* k, char* v) { + PropertyList_unique_add(plist, k, v, false); + } + static void PropertyList_unique_add(SystemProperty** plist, const char* k, char* v, jboolean append); static const char* PropertyList_get_value(SystemProperty* plist, const char* key); static int PropertyList_count(SystemProperty* pl); static const char* PropertyList_get_key_at(SystemProperty* pl,int index);
--- a/src/share/vm/runtime/globals.hpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/runtime/globals.hpp Tue Apr 14 12:25:54 2009 -0700 @@ -1323,8 +1323,11 @@ product(intx, ParGCArrayScanChunk, 50, \ "Scan a subset and push remainder, if array is bigger than this") \ \ + product(bool, ParGCUseLocalOverflow, false, \ + "Instead of a global overflow list, use local overflow stacks") \ + \ product(bool, ParGCTrimOverflow, true, \ - "Eagerly trim the overflow lists (useful for UseCompressedOops") \ + "Eagerly trim the local overflow lists (when ParGCUseLocalOverflow") \ \ notproduct(bool, ParGCWorkQueueOverflowALot, false, \ "Whether we should simulate work queue overflow in ParNew") \
--- a/src/share/vm/runtime/hpi.hpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/runtime/hpi.hpp Tue Apr 14 12:25:54 2009 -0700 @@ -90,7 +90,7 @@ static inline struct protoent* get_proto_by_name(char* name); // HPI_LibraryInterface - static inline void dll_build_name(char *buf, int buf_len, char* path, + static inline void dll_build_name(char *buf, int buf_len, const char* path, const char *name); static inline void* dll_load(const char *name, char *ebuf, int ebuflen); static inline void dll_unload(void *lib); @@ -137,7 +137,15 @@ return result; \ } - +#define VM_HPIDECL_VOID(name, names, func, arg_type, arg_print, arg) \ + inline void hpi::name arg_type { \ + if (TraceHPI) { \ + tty->print("hpi::" names "("); \ + tty->print arg_print; \ + tty->print(") = "); \ + } \ + func arg; \ + } #define HPIDECL_VOID(name, names, intf, func, arg_type, arg_print, arg) \ inline void hpi::name arg_type { \ @@ -197,11 +205,11 @@ (fd, size)); // HPI_LibraryInterface -HPIDECL_VOID(dll_build_name, "dll_build_name", _library, BuildLibName, - (char *buf, int buf_len, char *path, const char *name), - ("buf = %p, buflen = %d, path = %s, name = %s", - buf, buf_len, path, name), - (buf, buf_len, path, name)); +VM_HPIDECL_VOID(dll_build_name, "dll_build_name", os::dll_build_name, + (char *buf, int buf_len, const char *path, const char *name), + ("buf = %p, buflen = %d, path = %s, name = %s", + buf, buf_len, path, name), + (buf, buf_len, path, name)); VM_HPIDECL(dll_load, "dll_load", os::dll_load, void *, "(void *)%p",
--- a/src/share/vm/runtime/javaCalls.cpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/runtime/javaCalls.cpp Tue Apr 14 12:25:54 2009 -0700 @@ -37,11 +37,6 @@ guarantee(!thread->is_Compiler_thread(), "cannot make java calls from the compiler"); _result = result; - // Make sure that that the value of the higest_lock is at least the same as the current stackpointer, - // since, the Java code is highly likely to use locks. - // Use '(address)this' to guarantee that highest_lock address is conservative and inside our thread - thread->update_highest_lock((address)this); - // Allocate handle block for Java code. This must be done before we change thread_state to _thread_in_Java_or_stub, // since it can potentially block. JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread);
--- a/src/share/vm/runtime/os.cpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/runtime/os.cpp Tue Apr 14 12:25:54 2009 -0700 @@ -863,7 +863,6 @@ bool os::set_boot_path(char fileSep, char pathSep) { - const char* home = Arguments::get_java_home(); int home_len = (int)strlen(home); @@ -893,6 +892,60 @@ return true; } +/* + * Splits a path, based on its separator, the number of + * elements is returned back in n. + * It is the callers responsibility to: + * a> check the value of n, and n may be 0. + * b> ignore any empty path elements + * c> free up the data. + */ +char** os::split_path(const char* path, int* n) { + *n = 0; + if (path == NULL || strlen(path) == 0) { + return NULL; + } + const char psepchar = *os::path_separator(); + char* inpath = (char*)NEW_C_HEAP_ARRAY(char, strlen(path) + 1); + if (inpath == NULL) { + return NULL; + } + strncpy(inpath, path, strlen(path)); + int count = 1; + char* p = strchr(inpath, psepchar); + // Get a count of elements to allocate memory + while (p != NULL) { + count++; + p++; + p = strchr(p, psepchar); + } + char** opath = (char**) NEW_C_HEAP_ARRAY(char*, count); + if (opath == NULL) { + return NULL; + } + + // do the actual splitting + p = inpath; + for (int i = 0 ; i < count ; i++) { + size_t len = strcspn(p, os::path_separator()); + if (len > JVM_MAXPATHLEN) { + return NULL; + } + // allocate the string and add terminator storage + char* s = (char*)NEW_C_HEAP_ARRAY(char, len + 1); + if (s == NULL) { + return NULL; + } + strncpy(s, p, len); + s[len] = '\0'; + opath[i] = s; + p += len + 1; + } + FREE_C_HEAP_ARRAY(char, inpath); + *n = count; + return opath; +} + void os::set_memory_serialize_page(address page) { int count = log2_intptr(sizeof(class JavaThread)) - log2_intptr(64); _mem_serialize_page = (volatile int32_t *)page;
--- a/src/share/vm/runtime/os.hpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/runtime/os.hpp Tue Apr 14 12:25:54 2009 -0700 @@ -607,6 +607,7 @@ char fileSep, char pathSep); static bool set_boot_path(char fileSep, char pathSep); + static char** split_path(const char* path, int* n); }; // Note that "PAUSE" is almost always used with synchronization
--- a/src/share/vm/runtime/synchronizer.cpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/runtime/synchronizer.cpp Tue Apr 14 12:25:54 2009 -0700 @@ -1117,10 +1117,10 @@ // Optimization: if the mark->locker stack address is associated // with this thread we could simply set m->_owner = Self and - // m->OwnerIsThread = 1. Note that a thread can inflate an object + // m->OwnerIsThread = 1. Note that a thread can inflate an object // that it has stack-locked -- as might happen in wait() -- directly // with CAS. That is, we can avoid the xchg-NULL .... ST idiom. - m->set_owner (mark->locker()); + m->set_owner(mark->locker()); m->set_object(object); // TODO-FIXME: assert BasicLock->dhw != 0. @@ -1214,10 +1214,9 @@ BiasedLocking::revoke_at_safepoint(obj); } assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); - } - - THREAD->update_highest_lock((address)lock); - slow_enter (obj, lock, THREAD) ; + } + + slow_enter (obj, lock, THREAD) ; } void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
--- a/src/share/vm/runtime/thread.cpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/runtime/thread.cpp Tue Apr 14 12:25:54 2009 -0700 @@ -128,7 +128,6 @@ debug_only(_allow_allocation_count = 0;) NOT_PRODUCT(_allow_safepoint_count = 0;) CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;) - _highest_lock = NULL; _jvmti_env_iteration_count = 0; _vm_operation_started_count = 0; _vm_operation_completed_count = 0; @@ -790,19 +789,6 @@ } #endif -bool Thread::lock_is_in_stack(address adr) const { - assert(Thread::current() == this, "lock_is_in_stack can only be called from current thread"); - // High limit: highest_lock is set during thread execution - // Low limit: address of the local variable dummy, rounded to 4K boundary. - // (The rounding helps finding threads in unsafe mode, even if the particular stack - // frame has been popped already. Correct as long as stacks are at least 4K long and aligned.) - address end = os::current_stack_pointer(); - if (_highest_lock >= adr && adr >= end) return true; - - return false; -} - - bool Thread::is_in_stack(address adr) const { assert(Thread::current() == this, "is_in_stack can only be called from current thread"); address end = os::current_stack_pointer(); @@ -818,8 +804,7 @@ // should be revisited, and they should be removed if possible. bool Thread::is_lock_owned(address adr) const { - if (lock_is_in_stack(adr) ) return true; - return false; + return (_stack_base >= adr && adr >= (_stack_base - _stack_size)); } bool Thread::set_as_starting_thread() { @@ -1664,7 +1649,7 @@ } bool JavaThread::is_lock_owned(address adr) const { - if (lock_is_in_stack(adr)) return true; + if (Thread::is_lock_owned(adr)) return true; for (MonitorChunk* chunk = monitor_chunks(); chunk != NULL; chunk = chunk->next()) { if (chunk->contains(adr)) return true; @@ -2443,7 +2428,7 @@ if (thread_oop != NULL && java_lang_Thread::is_daemon(thread_oop)) st->print("daemon "); Thread::print_on(st); // print guess for valid stack memory region (assume 4K pages); helps lock debugging - st->print_cr("[" INTPTR_FORMAT ".." INTPTR_FORMAT "]", (intptr_t)last_Java_sp() & ~right_n_bits(12), highest_lock()); + st->print_cr("[" INTPTR_FORMAT "]", (intptr_t)last_Java_sp() & ~right_n_bits(12)); if (thread_oop != NULL && JDK_Version::is_gte_jdk15x_version()) { st->print_cr(" java.lang.Thread.State: %s", java_lang_Thread::thread_status_name(thread_oop)); } @@ -3733,25 +3718,13 @@ // heavyweight monitors, then the owner is the stack address of the // Lock Word in the owning Java thread's stack. // - // We can't use Thread::is_lock_owned() or Thread::lock_is_in_stack() because - // those routines rely on the "current" stack pointer. That would be our - // stack pointer which is not relevant to the question. Instead we use the - // highest lock ever entered by the thread and find the thread that is - // higher than and closest to our target stack address. - // - address least_diff = 0; - bool least_diff_initialized = false; JavaThread* the_owner = NULL; { MutexLockerEx ml(doLock ? Threads_lock : NULL); ALL_JAVA_THREADS(q) { - address addr = q->highest_lock(); - if (addr == NULL || addr < owner) continue; // thread has entered no monitors or is too low - address diff = (address)(addr - owner); - if (!least_diff_initialized || diff < least_diff) { - least_diff_initialized = true; - least_diff = diff; + if (q->is_lock_owned(owner)) { the_owner = q; + break; } } }
--- a/src/share/vm/runtime/thread.hpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/runtime/thread.hpp Tue Apr 14 12:25:54 2009 -0700 @@ -200,14 +200,6 @@ friend class ThreadLocalStorage; friend class GC_locker; - // In order for all threads to be able to use fast locking, we need to know the highest stack - // address of where a lock is on the stack (stacks normally grow towards lower addresses). This - // variable is initially set to NULL, indicating no locks are used by the thread. During the thread's - // execution, it will be set whenever locking can happen, i.e., when we call out to Java code or use - // an ObjectLocker. The value is never decreased, hence, it will over the lifetime of a thread - // approximate the real stackbase. - address _highest_lock; // Highest stack address where a JavaLock exist - ThreadLocalAllocBuffer _tlab; // Thread-local eden int _vm_operation_started_count; // VM_Operation support @@ -400,18 +392,14 @@ // Sweeper support void nmethods_do(); - // Fast-locking support - address highest_lock() const { return _highest_lock; } - void update_highest_lock(address base) { if (base > _highest_lock) _highest_lock = base; } - // Tells if adr belong to this thread. This is used // for checking if a lock is owned by the running thread. - // Warning: the method can only be used on the running thread - // Fast lock support uses these methods - virtual bool lock_is_in_stack(address adr) const; + + // Used by fast lock support virtual bool is_lock_owned(address adr) const; // Check if address is in the stack of the thread (not just for locks). + // Warning: the method can only be used on the running thread bool is_in_stack(address adr) const; // Sets this thread as starting thread. Returns failure if thread
--- a/src/share/vm/runtime/vmStructs.cpp Fri Apr 10 15:01:14 2009 -0700 +++ b/src/share/vm/runtime/vmStructs.cpp Tue Apr 14 12:25:54 2009 -0700 @@ -656,7 +656,6 @@ \ volatile_nonstatic_field(Thread, _suspend_flags, uint32_t) \ nonstatic_field(Thread, _active_handles, JNIHandleBlock*) \ - nonstatic_field(Thread, _highest_lock, address) \ nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \ nonstatic_field(Thread, _current_pending_monitor, ObjectMonitor*) \ nonstatic_field(Thread, _current_pending_monitor_is_from_java, bool) \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/6819213/TestBootNativeLibraryPath.java Tue Apr 14 12:25:54 2009 -0700 @@ -0,0 +1,133 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test TestBootNativeLibraryPath.java + * @bug 6819213 + * @compile -XDignore.symbol.file TestBootNativeLibraryPath.java + * @summary verify sun.boot.native.library.path is expandable on 32 bit systems + * @run main TestBootNativeLibraryPath + * @author ksrini +*/ + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.tools.JavaCompiler; +import javax.tools.ToolProvider; + +public class TestBootNativeLibraryPath { + + private static final String TESTFILE = "Test6"; + + static void createTestClass() throws IOException { + FileOutputStream fos = new FileOutputStream(TESTFILE + ".java"); + PrintStream ps = new PrintStream(fos); + ps.println("public class " + TESTFILE + "{"); + ps.println("public static void main(String[] args) {\n"); + ps.println("System.out.println(System.getProperty(\"sun.boot.library.path\"));\n"); + ps.println("}}\n"); + ps.close(); + fos.close(); + + JavaCompiler javac = ToolProvider.getSystemJavaCompiler(); + String javacOpts[] = {TESTFILE + ".java"}; + if (javac.run(null, null, null, javacOpts) != 0) { + throw new RuntimeException("compilation of " + TESTFILE + ".java Failed"); + } + } + + static List<String> doExec(String... args) { + String javaCmd = System.getProperty("java.home") + "/bin/java"; + if (!new File(javaCmd).exists()) { + javaCmd = System.getProperty("java.home") + "/bin/java.exe"; + } + + ArrayList<String> cmds = new ArrayList<String>(); + cmds.add(javaCmd); + for (String x : args) { + cmds.add(x); + } + System.out.println("cmds=" + cmds); + ProcessBuilder pb = new ProcessBuilder(cmds); + + Map<String, String> env = pb.environment(); + pb.directory(new File(".")); + + List<String> out = new ArrayList<String>(); + try { + pb.redirectErrorStream(true); + Process p = pb.start(); + BufferedReader rd = new BufferedReader(new InputStreamReader(p.getInputStream()),8192); + String in = rd.readLine(); + while (in != null) { + out.add(in); + System.out.println(in); + in = rd.readLine(); + } + int retval = p.waitFor(); + p.destroy(); + if (retval != 0) { + throw new RuntimeException("Error: test returned non-zero value"); + } + return out; + } catch (Exception ex) { + ex.printStackTrace(); + throw new RuntimeException(ex.getMessage()); + } + } + + public static void main(String[] args) { + try { + if (!System.getProperty("sun.arch.data.model").equals("32")) { + System.out.println("Warning: test skipped for 64-bit systems\n"); + return; + } + String osname = System.getProperty("os.name"); + if (osname.startsWith("Windows")) { + osname = "Windows"; + } + + createTestClass(); + + // Test a simple path + String libpath = File.pathSeparator + "tmp" + File.pathSeparator + "foobar"; + List<String> processOut = null; + String sunbootlibrarypath = "-Dsun.boot.library.path=" + libpath; + processOut = doExec(sunbootlibrarypath, "-cp", ".", TESTFILE); + if (processOut == null || !processOut.get(0).endsWith(libpath)) { + throw new RuntimeException("Error: did not get expected error string"); + } + } catch (IOException ex) { + throw new RuntimeException("Unexpected error " + ex); + } + } +}