From b34027a600a7461dde91563b9d48b3bc444217f2 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Fri, 29 Jan 2010 14:51:38 -0800 Subject: [PATCH 01/31] 6885297: java -XX:RefDiscoveryPolicy=2 or -XX:TLABWasteTargetPercent=0 cause VM crash Interval checking is now being performed on the values passed in for these two flags. The current acceptable range for RefDiscoveryPolicy is [0..1], and for TLABWasteTargetPercent it is [1..100]. Reviewed-by: apetrusenko, ysr --- hotspot/src/share/vm/includeDB_core | 1 + .../share/vm/memory/referenceProcessor.hpp | 7 ++++-- hotspot/src/share/vm/runtime/arguments.cpp | 24 +++++++++++++++++++ hotspot/src/share/vm/runtime/arguments.hpp | 2 ++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index a4e809b52ab..bf077f2cbf8 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -175,6 +175,7 @@ arguments.cpp jvmtiExport.hpp arguments.cpp management.hpp arguments.cpp oop.inline.hpp arguments.cpp os_.inline.hpp +arguments.cpp referenceProcessor.hpp arguments.cpp universe.inline.hpp arguments.cpp vm_version_.hpp diff --git a/hotspot/src/share/vm/memory/referenceProcessor.hpp b/hotspot/src/share/vm/memory/referenceProcessor.hpp index 6642d9d0d43..5d0023e0af5 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.hpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp @@ -263,10 +263,13 @@ class ReferenceProcessor : public CHeapObj { int parallel_gc_threads = 1, bool mt_processing = false, bool discovered_list_needs_barrier = false); + // RefDiscoveryPolicy values - enum { + enum DiscoveryPolicy { ReferenceBasedDiscovery = 0, - ReferentBasedDiscovery = 1 + ReferentBasedDiscovery = 1, + DiscoveryPolicyMin = ReferenceBasedDiscovery, + DiscoveryPolicyMax = ReferentBasedDiscovery }; static void init_statics(); diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 499fba2f1be..66d84c5c4d2 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1487,6 +1487,20 @@ bool Arguments::created_by_java_launcher() { //=========================================================================================================== // Parsing of main arguments +bool Arguments::verify_interval(uintx val, uintx min, + uintx max, const char* name) { + // Returns true iff value is in the inclusive interval [min..max] + // false, otherwise. + if (val >= min && val <= max) { + return true; + } + jio_fprintf(defaultStream::error_stream(), + "%s of " UINTX_FORMAT " is invalid; must be between " UINTX_FORMAT + " and " UINTX_FORMAT "\n", + name, val, min, max); + return false; +} + bool Arguments::verify_percentage(uintx value, const char* name) { if (value <= 100) { return true; @@ -1723,6 +1737,16 @@ bool Arguments::check_vm_args_consistency() { status = false; } + status = status && verify_interval(RefDiscoveryPolicy, + ReferenceProcessor::DiscoveryPolicyMin, + ReferenceProcessor::DiscoveryPolicyMax, + "RefDiscoveryPolicy"); + + // Limit the lower bound of this flag to 1 as it is used in a division + // expression. + status = status && verify_interval(TLABWasteTargetPercent, + 1, 100, "TLABWasteTargetPercent"); + return status; } diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index a68c6cad904..2747c2d5035 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -336,6 +336,8 @@ class Arguments : AllStatic { static bool is_bad_option(const JavaVMOption* option, jboolean ignore) { return is_bad_option(option, ignore, NULL); } + static bool verify_interval(uintx val, uintx min, + uintx max, const char* name); static bool verify_percentage(uintx value, const char* name); static void describe_range_error(ArgsRange errcode); static ArgsRange check_memory_size(julong size, julong min_size); From c61ab190cf88bbb133c0ec88b2ce10bb54899c03 Mon Sep 17 00:00:00 2001 From: "Y. Srinivas Ramakrishna" Date: Mon, 1 Feb 2010 17:29:01 -0800 Subject: [PATCH 02/31] 6904516: More object array barrier fixes, following up on 6906727 Fixed missing pre-barrier calls for G1, modified C1 to call pre- and correct post-barrier interfaces, deleted obsolete interface, (temporarily) disabled redundant deferred barrier in BacktraceBuilder. Reviewed-by: coleenp, jmasa, kvn, never --- hotspot/src/share/vm/c1/c1_Runtime1.cpp | 24 ++++++++++++------- .../src/share/vm/classfile/javaClasses.cpp | 17 ++++++++++--- .../gc_implementation/g1/g1CollectedHeap.cpp | 2 ++ hotspot/src/share/vm/memory/barrierSet.hpp | 2 -- .../src/share/vm/memory/barrierSet.inline.hpp | 18 ++++---------- hotspot/src/share/vm/runtime/stubRoutines.cpp | 12 +++++++++- 6 files changed, 47 insertions(+), 28 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index 9093885ce45..98738ed4bf4 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -1075,6 +1075,7 @@ enum { }; +// Below length is the # elements copied. template int obj_arraycopy_work(oopDesc* src, T* src_addr, oopDesc* dst, T* dst_addr, int length) { @@ -1083,22 +1084,22 @@ template int obj_arraycopy_work(oopDesc* src, T* src_addr, // barrier. The assert will fail if this is not the case. // Note that we use the non-virtual inlineable variant of write_ref_array. BarrierSet* bs = Universe::heap()->barrier_set(); - assert(bs->has_write_ref_array_opt(), - "Barrier set must have ref array opt"); + assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt"); + assert(bs->has_write_ref_array_pre_opt(), "For pre-barrier as well."); if (src == dst) { // same object, no check + bs->write_ref_array_pre(dst_addr, length); Copy::conjoint_oops_atomic(src_addr, dst_addr, length); - bs->write_ref_array(MemRegion((HeapWord*)dst_addr, - (HeapWord*)(dst_addr + length))); + bs->write_ref_array((HeapWord*)dst_addr, length); return ac_ok; } else { klassOop bound = objArrayKlass::cast(dst->klass())->element_klass(); klassOop stype = objArrayKlass::cast(src->klass())->element_klass(); if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) { // Elements are guaranteed to be subtypes, so no check necessary + bs->write_ref_array_pre(dst_addr, length); Copy::conjoint_oops_atomic(src_addr, dst_addr, length); - bs->write_ref_array(MemRegion((HeapWord*)dst_addr, - (HeapWord*)(dst_addr + length))); + bs->write_ref_array((HeapWord*)dst_addr, length); return ac_ok; } } @@ -1162,9 +1163,16 @@ JRT_LEAF(void, Runtime1::oop_arraycopy(HeapWord* src, HeapWord* dst, int num)) #endif if (num == 0) return; - Copy::conjoint_oops_atomic((oop*) src, (oop*) dst, num); BarrierSet* bs = Universe::heap()->barrier_set(); - bs->write_ref_array(MemRegion(dst, dst + num)); + assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt"); + assert(bs->has_write_ref_array_pre_opt(), "For pre-barrier as well."); + if (UseCompressedOops) { + bs->write_ref_array_pre((narrowOop*)dst, num); + } else { + bs->write_ref_array_pre((oop*)dst, num); + } + Copy::conjoint_oops_atomic((oop*) src, (oop*) dst, num); + bs->write_ref_array(dst, num); JRT_END diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index 173f2e26e5d..730f1c7abc8 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -1121,10 +1121,23 @@ class BacktraceBuilder: public StackObj { } void flush() { + // The following appears to have been an optimization to save from + // doing a barrier for each individual store into the _methods array, + // but rather to do it for the entire array after the series of writes. + // That optimization seems to have been lost when compressed oops was + // implemented. However, the extra card-marks below was left in place, + // but is now redundant because the individual stores into the + // _methods array already execute the barrier code. CR 6918185 has + // been filed so the original code may be restored by deferring the + // barriers until after the entire sequence of stores, thus re-enabling + // the intent of the original optimization. In the meantime the redundant + // card mark below is now disabled. if (_dirty && _methods != NULL) { +#if 0 BarrierSet* bs = Universe::heap()->barrier_set(); assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt"); bs->write_ref_array((HeapWord*)_methods->base(), _methods->length()); +#endif _dirty = false; } } @@ -1168,9 +1181,7 @@ class BacktraceBuilder: public StackObj { method = mhandle(); } - _methods->obj_at_put(_index, method); - // bad for UseCompressedOops - // *_methods->obj_at_addr(_index) = method; + _methods->obj_at_put(_index, method); _bcis->ushort_at_put(_index, bci); _index++; _dirty = true; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index c3319d13e79..0c73f4d6c67 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -2505,6 +2505,7 @@ G1CollectedHeap* G1CollectedHeap::heap() { } void G1CollectedHeap::gc_prologue(bool full /* Ignored */) { + // always_do_update_barrier = false; assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); // Call allocation profiler AllocationProfiler::iterate_since_last_gc(); @@ -2518,6 +2519,7 @@ void G1CollectedHeap::gc_epilogue(bool full /* Ignored */) { // is set. COMPILER2_PRESENT(assert(DerivedPointerTable::is_empty(), "derived pointer present")); + // always_do_update_barrier = true; } void G1CollectedHeap::do_collection_pause() { diff --git a/hotspot/src/share/vm/memory/barrierSet.hpp b/hotspot/src/share/vm/memory/barrierSet.hpp index c624f2506e2..4188e11fa96 100644 --- a/hotspot/src/share/vm/memory/barrierSet.hpp +++ b/hotspot/src/share/vm/memory/barrierSet.hpp @@ -124,8 +124,6 @@ public: // Below length is the # array elements being written virtual void write_ref_array_pre( oop* dst, int length) {} virtual void write_ref_array_pre(narrowOop* dst, int length) {} - // Below MemRegion mr is expected to be HeapWord-aligned - inline void write_ref_array(MemRegion mr); // Below count is the # array elements being written, starting // at the address "start", which may not necessarily be HeapWord-aligned inline void write_ref_array(HeapWord* start, size_t count); diff --git a/hotspot/src/share/vm/memory/barrierSet.inline.hpp b/hotspot/src/share/vm/memory/barrierSet.inline.hpp index ddc398348ca..f8858253e17 100644 --- a/hotspot/src/share/vm/memory/barrierSet.inline.hpp +++ b/hotspot/src/share/vm/memory/barrierSet.inline.hpp @@ -42,16 +42,6 @@ void BarrierSet::write_ref_field(void* field, oop new_val) { } } -void BarrierSet::write_ref_array(MemRegion mr) { - assert((HeapWord*)align_size_down((uintptr_t)mr.start(), HeapWordSize) == mr.start() , "Unaligned start"); - assert((HeapWord*)align_size_up ((uintptr_t)mr.end(), HeapWordSize) == mr.end(), "Unaligned end" ); - if (kind() == CardTableModRef) { - ((CardTableModRefBS*)this)->inline_write_ref_array(mr); - } else { - write_ref_array_work(mr); - } -} - // count is number of array elements being written void BarrierSet::write_ref_array(HeapWord* start, size_t count) { assert(count <= (size_t)max_intx, "count too large"); @@ -61,12 +51,12 @@ void BarrierSet::write_ref_array(HeapWord* start, size_t count) { // strictly necessary for current uses, but a case of good hygiene and, // if you will, aesthetics) and the second upward (this is essential for // current uses) to a HeapWord boundary, so we mark all cards overlapping - // this write. In the event that this evolves in the future to calling a + // this write. If this evolves in the future to calling a // logging barrier of narrow oop granularity, like the pre-barrier for G1 // (mentioned here merely by way of example), we will need to change this - // interface, much like the pre-barrier one above, so it is "exactly precise" - // (if i may be allowed the adverbial redundancy for emphasis) and does not - // include narrow oop slots not included in the original write interval. + // interface, so it is "exactly precise" (if i may be allowed the adverbial + // redundancy for emphasis) and does not include narrow oop slots not + // included in the original write interval. HeapWord* aligned_start = (HeapWord*)align_size_down((uintptr_t)start, HeapWordSize); HeapWord* aligned_end = (HeapWord*)align_size_up ((uintptr_t)end, HeapWordSize); // If compressed oops were not being used, these should already be aligned diff --git a/hotspot/src/share/vm/runtime/stubRoutines.cpp b/hotspot/src/share/vm/runtime/stubRoutines.cpp index 25c02cd5ff8..22b1df86804 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp @@ -196,11 +196,19 @@ void stubRoutines_init2() { StubRoutines::initialize2(); } // Default versions of arraycopy functions // +static void gen_arraycopy_barrier_pre(oop* dest, size_t count) { + assert(count != 0, "count should be non-zero"); + assert(count <= (size_t)max_intx, "count too large"); + BarrierSet* bs = Universe::heap()->barrier_set(); + assert(bs->has_write_ref_array_pre_opt(), "Must have pre-barrier opt"); + bs->write_ref_array_pre(dest, (int)count); +} + static void gen_arraycopy_barrier(oop* dest, size_t count) { assert(count != 0, "count should be non-zero"); BarrierSet* bs = Universe::heap()->barrier_set(); assert(bs->has_write_ref_array_opt(), "Barrier set must have ref array opt"); - bs->write_ref_array(MemRegion((HeapWord*)dest, (HeapWord*)(dest + count))); + bs->write_ref_array((HeapWord*)dest, count); } JRT_LEAF(void, StubRoutines::jbyte_copy(jbyte* src, jbyte* dest, size_t count)) @@ -240,6 +248,7 @@ JRT_LEAF(void, StubRoutines::oop_copy(oop* src, oop* dest, size_t count)) SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy #endif // !PRODUCT assert(count != 0, "count should be non-zero"); + gen_arraycopy_barrier_pre(dest, count); Copy::conjoint_oops_atomic(src, dest, count); gen_arraycopy_barrier(dest, count); JRT_END @@ -281,6 +290,7 @@ JRT_LEAF(void, StubRoutines::arrayof_oop_copy(HeapWord* src, HeapWord* dest, siz SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy #endif // !PRODUCT assert(count != 0, "count should be non-zero"); + gen_arraycopy_barrier_pre((oop *) dest, count); Copy::arrayof_conjoint_oops(src, dest, count); gen_arraycopy_barrier((oop *) dest, count); JRT_END From 7f9ba03c32e41b6ff298b8c3358edbd6616a95c6 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Tue, 2 Feb 2010 18:39:50 -0800 Subject: [PATCH 03/31] 6914402: G1: assert(!is_young_card(cached_ptr),"shouldn't get a card in young region") Invalid assert. Filter cards evicted from the card count cache instead. Reviewed-by: apetrusenko, tonyp --- .../g1/concurrentG1Refine.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp index 11c288073d3..79874f0df69 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp @@ -300,7 +300,23 @@ jbyte* ConcurrentG1Refine::cache_insert(jbyte* card_ptr, bool* defer) { int count; jbyte* cached_ptr = add_card_count(card_ptr, &count, defer); assert(cached_ptr != NULL, "bad cached card ptr"); - assert(!is_young_card(cached_ptr), "shouldn't get a card in young region"); + + if (is_young_card(cached_ptr)) { + // The region containing cached_ptr has been freed during a clean up + // pause, reallocated, and tagged as young. + assert(cached_ptr != card_ptr, "shouldn't be"); + + // We've just inserted a new old-gen card pointer into the card count + // cache and evicted the previous contents of that count slot. + // The evicted card pointer has been determined to be in a young region + // and so cannot be the newly inserted card pointer (that will be + // in an old region). + // The count for newly inserted card will be set to zero during the + // insertion, so we don't want to defer the cleaning of the newly + // inserted card pointer. + assert(*defer == false, "deferring non-hot card"); + return NULL; + } // The card pointer we obtained from card count cache is not hot // so do not store it in the cache; return it for immediate From c157b744edc089486b7427af0ad41d6da751b4ba Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Fri, 5 Feb 2010 11:05:50 -0500 Subject: [PATCH 04/31] 6920977: G1: guarantee(k == probe->klass(),"klass should be in dictionary") fails The guarantee is too strict and the test will fail (incorrectly) if the class is not in the system dictionary but in the placeholders. Reviewed-by: acorn, phh --- .../share/vm/classfile/loaderConstraints.cpp | 21 +++++++++++++++++-- .../share/vm/classfile/loaderConstraints.hpp | 2 +- .../share/vm/classfile/systemDictionary.cpp | 2 +- hotspot/src/share/vm/includeDB_core | 1 + 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/classfile/loaderConstraints.cpp b/hotspot/src/share/vm/classfile/loaderConstraints.cpp index daaaa327556..0a8693403d1 100644 --- a/hotspot/src/share/vm/classfile/loaderConstraints.cpp +++ b/hotspot/src/share/vm/classfile/loaderConstraints.cpp @@ -457,7 +457,8 @@ void LoaderConstraintTable::merge_loader_constraints( } -void LoaderConstraintTable::verify(Dictionary* dictionary) { +void LoaderConstraintTable::verify(Dictionary* dictionary, + PlaceholderTable* placeholders) { Thread *thread = Thread::current(); for (int cindex = 0; cindex < _loader_constraint_size; cindex++) { for (LoaderConstraintEntry* probe = bucket(cindex); @@ -472,7 +473,23 @@ void LoaderConstraintTable::verify(Dictionary* dictionary) { unsigned int d_hash = dictionary->compute_hash(name, loader); int d_index = dictionary->hash_to_index(d_hash); klassOop k = dictionary->find_class(d_index, d_hash, name, loader); - guarantee(k == probe->klass(), "klass should be in dictionary"); + if (k != NULL) { + // We found the class in the system dictionary, so we should + // make sure that the klassOop matches what we already have. + guarantee(k == probe->klass(), "klass should be in dictionary"); + } else { + // If we don't find the class in the system dictionary, it + // has to be in the placeholders table. + unsigned int p_hash = placeholders->compute_hash(name, loader); + int p_index = placeholders->hash_to_index(p_hash); + PlaceholderEntry* entry = placeholders->get_entry(p_index, p_hash, + name, loader); + + // The instanceKlass might not be on the entry, so the only + // thing we can check here is whether we were successful in + // finding the class in the placeholders table. + guarantee(entry != NULL, "klass should be in the placeholders"); + } } for (int n = 0; n< probe->num_loaders(); n++) { guarantee(probe->loader(n)->is_oop_or_null(), "should be oop"); diff --git a/hotspot/src/share/vm/classfile/loaderConstraints.hpp b/hotspot/src/share/vm/classfile/loaderConstraints.hpp index 6928180d22a..53ce146b168 100644 --- a/hotspot/src/share/vm/classfile/loaderConstraints.hpp +++ b/hotspot/src/share/vm/classfile/loaderConstraints.hpp @@ -84,7 +84,7 @@ public: void purge_loader_constraints(BoolObjectClosure* is_alive); - void verify(Dictionary* dictionary); + void verify(Dictionary* dictionary, PlaceholderTable* placeholders); #ifndef PRODUCT void print(); #endif diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index fb22282e97c..1db0a5cfb15 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -2573,7 +2573,7 @@ void SystemDictionary::verify() { // Verify constraint table guarantee(constraints() != NULL, "Verify of loader constraints failed"); - constraints()->verify(dictionary()); + constraints()->verify(dictionary(), placeholders()); } diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 675a6657e0b..bf994522030 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -2654,6 +2654,7 @@ loaderConstraints.cpp resourceArea.hpp loaderConstraints.cpp safepoint.hpp loaderConstraints.hpp dictionary.hpp +loaderConstraints.hpp placeholders.hpp loaderConstraints.hpp hashtable.hpp location.cpp debugInfo.hpp From c1be36be1bd47aeebee56d0c75e581368c4e818e Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Fri, 5 Feb 2010 11:07:40 -0800 Subject: [PATCH 05/31] 6920293: OptimizeStringConcat causing core dumps Reviewed-by: kvn, twisti --- hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp | 7 ++++--- hotspot/src/share/vm/code/nmethod.cpp | 5 ++++- hotspot/src/share/vm/opto/stringopts.cpp | 9 +++++---- hotspot/src/share/vm/runtime/sharedRuntime.cpp | 9 ++++++--- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp index 59ed458b23f..a11901ed6d4 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -730,11 +730,12 @@ void os::print_context(outputStream *st, void *context) { st->print(", RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]); st->print(", RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]); st->cr(); - st->print(", R8=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]); + st->print( "R8=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]); st->print(", R9=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]); st->print(", R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]); st->print(", R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]); - st->print(", R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]); + st->cr(); + st->print( "R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]); st->print(", R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]); st->print(", R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]); st->print(", R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]); diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 814a4069f37..54db5a983dc 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -2010,7 +2010,10 @@ address nmethod::continuation_for_implicit_exception(address pc) { print_pcs(); } #endif - guarantee(cont_offset != 0, "unhandled implicit exception in compiled code"); + if (cont_offset == 0) { + // Let the normal error handling report the exception + return NULL; + } return instructions_begin() + cont_offset; } diff --git a/hotspot/src/share/vm/opto/stringopts.cpp b/hotspot/src/share/vm/opto/stringopts.cpp index 192d31f8257..01476453b3d 100644 --- a/hotspot/src/share/vm/opto/stringopts.cpp +++ b/hotspot/src/share/vm/opto/stringopts.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2009-2010 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 @@ -1073,7 +1073,7 @@ void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, N kit.set_control(head); kit.set_memory(mem, char_adr_idx); - Node* q = __ DivI(kit.null(), i_phi, __ intcon(10)); + Node* q = __ DivI(NULL, i_phi, __ intcon(10)); Node* r = __ SubI(i_phi, __ AddI(__ LShiftI(q, __ intcon(3)), __ LShiftI(q, __ intcon(1)))); Node* m1 = __ SubI(charPos, __ intcon(1)); @@ -1270,14 +1270,15 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { // length = length + (s.count - s.offset); RegionNode *r = new (C, 3) RegionNode(3); kit.gvn().set_type(r, Type::CONTROL); - Node *phi = new (C, 3) PhiNode(r, type->join(TypeInstPtr::NOTNULL)); + Node *phi = new (C, 3) PhiNode(r, type); kit.gvn().set_type(phi, phi->bottom_type()); Node* p = __ Bool(__ CmpP(arg, kit.null()), BoolTest::ne); IfNode* iff = kit.create_and_map_if(kit.control(), p, PROB_MIN, COUNT_UNKNOWN); Node* notnull = __ IfTrue(iff); Node* isnull = __ IfFalse(iff); + kit.set_control(notnull); // set control for the cast_not_null r->init_req(1, notnull); - phi->init_req(1, arg); + phi->init_req(1, kit.cast_not_null(arg, false)); r->init_req(2, isnull); phi->init_req(2, null_string); kit.set_control(r); diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 1b49095ddc1..31f8dab8676 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -607,7 +607,9 @@ address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread, _implicit_null_throws++; #endif target_pc = nm->continuation_for_implicit_exception(pc); - guarantee(target_pc != 0, "must have a continuation point"); + // If there's an unexpected fault, target_pc might be NULL, + // in which case we want to fall through into the normal + // error handling code. } break; // fall through @@ -621,14 +623,15 @@ address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread, _implicit_div0_throws++; #endif target_pc = nm->continuation_for_implicit_exception(pc); - guarantee(target_pc != 0, "must have a continuation point"); + // If there's an unexpected fault, target_pc might be NULL, + // in which case we want to fall through into the normal + // error handling code. break; // fall through } default: ShouldNotReachHere(); } - guarantee(target_pc != NULL, "must have computed destination PC for implicit exception"); assert(exception_kind == IMPLICIT_NULL || exception_kind == IMPLICIT_DIVIDE_BY_ZERO, "wrong implicit exception kind"); // for AbortVMOnException flag From 2fd8d35905395d628a052f89c0160bf2c3d3d4f0 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Sun, 7 Feb 2010 12:15:06 -0800 Subject: [PATCH 06/31] 6923002: assert(false,"this call site should not be polymorphic") Clear the total count when a receiver information is cleared. Reviewed-by: never, jrose --- .../cpu/sparc/vm/c1_LIRAssembler_sparc.cpp | 19 +++++++++------ .../src/cpu/sparc/vm/interp_masm_sparc.cpp | 4 ++-- .../src/cpu/sparc/vm/sharedRuntime_sparc.cpp | 4 +++- .../src/cpu/x86/vm/c1_LIRAssembler_x86.cpp | 2 +- hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp | 4 ++-- hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp | 4 ++-- hotspot/src/share/vm/ci/ciMethod.cpp | 3 ++- hotspot/src/share/vm/oops/methodDataOop.hpp | 23 ++++++++++++++++++- hotspot/src/share/vm/opto/doCall.cpp | 4 ++-- hotspot/src/share/vm/opto/runtime.cpp | 4 ++-- hotspot/src/share/vm/runtime/arguments.cpp | 5 +++- 11 files changed, 54 insertions(+), 22 deletions(-) diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index a4c9ce59d39..177cf631281 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -2730,9 +2730,6 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { } Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()) - mdo_offset_bias); - __ lduw(counter_addr, tmp1); - __ add(tmp1, DataLayout::counter_increment, tmp1); - __ stw(tmp1, counter_addr); Bytecodes::Code bc = method->java_code_at_bci(bci); // Perform additional virtual call profiling for invokevirtual and // invokeinterface bytecodes @@ -2822,15 +2819,23 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { __ set(DataLayout::counter_increment, tmp1); __ st_ptr(tmp1, mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) - mdo_offset_bias); - if (i < (VirtualCallData::row_limit() - 1)) { - __ br(Assembler::always, false, Assembler::pt, update_done); - __ delayed()->nop(); - } + __ br(Assembler::always, false, Assembler::pt, update_done); + __ delayed()->nop(); __ bind(next_test); } + // Receiver did not match any saved receiver and there is no empty row for it. + // Increment total counter to indicate polymorphic case. + __ lduw(counter_addr, tmp1); + __ add(tmp1, DataLayout::counter_increment, tmp1); + __ stw(tmp1, counter_addr); __ bind(update_done); } + } else { + // Static call + __ lduw(counter_addr, tmp1); + __ add(tmp1, DataLayout::counter_increment, tmp1); + __ stw(tmp1, counter_addr); } } diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index 01702ee2b2f..604c2b9e4e4 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -1733,7 +1733,7 @@ void InterpreterMacroAssembler::record_klass_in_profile_helper( brx(Assembler::zero, false, Assembler::pn, found_null); delayed()->nop(); // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polimorphic case. + // Increment total counter to indicate polymorphic case. increment_mdp_data_at(in_bytes(CounterData::count_offset()), scratch); ba(false, done); delayed()->nop(); diff --git a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp index 79c765415f6..50a5b6de13b 100644 --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -851,10 +851,10 @@ void AdapterGenerator::gen_c2i_adapter( __ set(reg2offset(r_1) + extraspace + bias, ld_off); #else int ld_off = reg2offset(r_1) + extraspace + bias; +#endif // _LP64 #ifdef ASSERT G1_forced = true; #endif // ASSERT -#endif // _LP64 r_1 = G1_scratch->as_VMReg();// as part of the load/store shuffle if (!r_2->is_valid()) __ ld (base, ld_off, G1_scratch); else __ ldx(base, ld_off, G1_scratch); @@ -865,9 +865,11 @@ void AdapterGenerator::gen_c2i_adapter( if (sig_bt[i] == T_OBJECT || sig_bt[i] == T_ARRAY) { store_c2i_object(r, base, st_off); } else if (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) { +#ifndef _LP64 if (TieredCompilation) { assert(G1_forced || sig_bt[i] != T_LONG, "should not use register args for longs"); } +#endif // _LP64 store_c2i_long(r, base, st_off, r_2->is_stack()); } else { store_c2i_int(r, base, st_off); diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 056b8a82d03..efd242d9928 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -3279,7 +3279,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { __ bind(next_test); } // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polimorphic case. + // Increment total counter to indicate polymorphic case. __ addl(counter_addr, DataLayout::counter_increment); __ bind(update_done); diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp index bf1e36648d7..205e5d80de5 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -1308,7 +1308,7 @@ void InterpreterMacroAssembler::record_klass_in_profile_helper( if (is_virtual_call) { jccb(Assembler::zero, found_null); // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polimorphic case. + // Increment total counter to indicate polymorphic case. increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); jmp(done); bind(found_null); diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp index 7e6b71fa147..62acfa226fb 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 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 @@ -1341,7 +1341,7 @@ void InterpreterMacroAssembler::record_klass_in_profile_helper( if (is_virtual_call) { jccb(Assembler::zero, found_null); // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polimorphic case. + // Increment total counter to indicate polymorphic case. increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); jmp(done); bind(found_null); diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index 3d9b04a8e3d..54a04f8af1f 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -445,7 +445,8 @@ ciCallProfile ciMethod::call_profile_at_bci(int bci) { (morphism == ciCallProfile::MorphismLimit && count == 0)) { #ifdef ASSERT if (count > 0) { - tty->print_cr("bci: %d", bci); + this->print_short_name(tty); + tty->print_cr(" @ bci:%d", bci); this->print_codes(); assert(false, "this call site should not be polymorphic"); } diff --git a/hotspot/src/share/vm/oops/methodDataOop.hpp b/hotspot/src/share/vm/oops/methodDataOop.hpp index e1c8eaf10af..ca585f8b692 100644 --- a/hotspot/src/share/vm/oops/methodDataOop.hpp +++ b/hotspot/src/share/vm/oops/methodDataOop.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 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 @@ -545,6 +545,10 @@ public: return cell_offset(counter_cell_count); } + void set_count(uint count) { + set_uint_at(count_off, count); + } + #ifndef PRODUCT void print_data_on(outputStream* st); #endif @@ -692,6 +696,23 @@ public: void clear_row(uint row) { assert(row < row_limit(), "oob"); + // Clear total count - indicator of polymorphic call site. + // The site may look like as monomorphic after that but + // it allow to have more accurate profiling information because + // there was execution phase change since klasses were unloaded. + // If the site is still polymorphic then MDO will be updated + // to reflect it. But it could be the case that the site becomes + // only bimorphic. Then keeping total count not 0 will be wrong. + // Even if we use monomorphic (when it is not) for compilation + // we will only have trap, deoptimization and recompile again + // with updated MDO after executing method in Interpreter. + // An additional receiver will be recorded in the cleaned row + // during next call execution. + // + // Note: our profiling logic works with empty rows in any slot. + // We do sorting a profiling info (ciCallProfile) for compilation. + // + set_count(0); set_receiver(row, NULL); set_receiver_count(row, 0); } diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index d9c1a23bd39..2f3f734fd45 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 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 @@ -70,7 +70,7 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index, CompileLog* log = this->log(); if (log != NULL) { int rid = (receiver_count >= 0)? log->identify(profile.receiver(0)): -1; - int r2id = (profile.morphism() == 2)? log->identify(profile.receiver(1)):-1; + int r2id = (rid != -1 && profile.has_receiver(1))? log->identify(profile.receiver(1)):-1; log->begin_elem("call method='%d' count='%d' prof_factor='%g'", log->identify(call_method), site_count, prof_factor); if (call_is_virtual) log->print(" virtual='1'"); diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index 3bf145b0d17..d44a9ce9160 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 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 @@ -708,7 +708,7 @@ JRT_LEAF(void, OptoRuntime::profile_receiver_type_C(DataLayout* data, oopDesc* r *(mdp + count_off) = DataLayout::counter_increment; } else { // Receiver did not match any saved receiver and there is no empty row for it. - // Increment total counter to indicate polimorphic case. + // Increment total counter to indicate polymorphic case. intptr_t* count_p = (intptr_t*)(((byte*)(data)) + in_bytes(CounterData::count_offset())); *count_p += DataLayout::counter_increment; } diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 499fba2f1be..6e2c9dd3721 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -2500,6 +2500,9 @@ jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_req SOLARIS_ONLY(FLAG_SET_DEFAULT(UseISM, false)); } + // Tiered compilation is undefined with C1. + TieredCompilation = false; + #else if (!FLAG_IS_DEFAULT(OptoLoopAlignment) && FLAG_IS_DEFAULT(MaxLoopPad)) { FLAG_SET_DEFAULT(MaxLoopPad, OptoLoopAlignment-1); From 7d7887d46c5354daca3e12aad48310ba4461a669 Mon Sep 17 00:00:00 2001 From: Neo Jia Date: Mon, 8 Feb 2010 13:49:03 -0500 Subject: [PATCH 07/31] 6587322: dtrace probe object__alloc doesn't fire in some situations on amd64 Fix misplaced probe point Reviewed-by: rasbold, phh --- .../src/cpu/x86/vm/templateTable_x86_64.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp index f461b10e451..fdd492a7495 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp @@ -3238,17 +3238,19 @@ void TemplateTable::_new() { __ xorl(rcx, rcx); // use zero reg to clear memory (shorter code) __ store_klass_gap(rax, rcx); // zero klass gap for compressed oops __ store_klass(rax, rsi); // store klass last + + { + SkipIfEqual skip(_masm, &DTraceAllocProbes, false); + // Trigger dtrace event for fastpath + __ push(atos); // save the return value + __ call_VM_leaf( + CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), rax); + __ pop(atos); // restore the return value + + } __ jmp(done); } - { - SkipIfEqual skip(_masm, &DTraceAllocProbes, false); - // Trigger dtrace event for fastpath - __ push(atos); // save the return value - __ call_VM_leaf( - CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), rax); - __ pop(atos); // restore the return value - } // slow case __ bind(slow_case); From a88853347fa2a62d3670800026225e5b032aa0bd Mon Sep 17 00:00:00 2001 From: Antonios Printezis Date: Mon, 8 Feb 2010 14:23:01 -0500 Subject: [PATCH 08/31] 6802453: G1: hr()->is_in_reserved(from),"Precondition." The operations of re-using a RSet component and expanding the same RSet component were not mutually exlusive, and this could lead to RSets getting corrupted and entries being dropped. Reviewed-by: iveresov, johnc --- .../gc_implementation/g1/heapRegionRemSet.cpp | 96 +++++++++++-------- 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp index dd04bc8dcb8..aac289e67d6 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp @@ -258,42 +258,6 @@ class PosParPRT: public PerRegionTable { ReserveParTableExpansion = 1 }; - void par_expand() { - int n = HeapRegionRemSet::num_par_rem_sets()-1; - if (n <= 0) return; - if (_par_tables == NULL) { - PerRegionTable* res = - (PerRegionTable*) - Atomic::cmpxchg_ptr((PerRegionTable*)ReserveParTableExpansion, - &_par_tables, NULL); - if (res != NULL) return; - // Otherwise, we reserved the right to do the expansion. - - PerRegionTable** ptables = NEW_C_HEAP_ARRAY(PerRegionTable*, n); - for (int i = 0; i < n; i++) { - PerRegionTable* ptable = PerRegionTable::alloc(hr()); - ptables[i] = ptable; - } - // Here we do not need an atomic. - _par_tables = ptables; -#if COUNT_PAR_EXPANDS - print_par_expand(); -#endif - // We must put this table on the expanded list. - PosParPRT* exp_head = _par_expanded_list; - while (true) { - set_next_par_expanded(exp_head); - PosParPRT* res = - (PosParPRT*) - Atomic::cmpxchg_ptr(this, &_par_expanded_list, exp_head); - if (res == exp_head) return; - // Otherwise. - exp_head = res; - } - ShouldNotReachHere(); - } - } - void par_contract() { assert(_par_tables != NULL, "Precondition."); int n = HeapRegionRemSet::num_par_rem_sets()-1; @@ -391,13 +355,49 @@ public: void set_next(PosParPRT* nxt) { _next = nxt; } PosParPRT** next_addr() { return &_next; } + bool should_expand(int tid) { + return par_tables() == NULL && tid > 0 && hr()->is_gc_alloc_region(); + } + + void par_expand() { + int n = HeapRegionRemSet::num_par_rem_sets()-1; + if (n <= 0) return; + if (_par_tables == NULL) { + PerRegionTable* res = + (PerRegionTable*) + Atomic::cmpxchg_ptr((PerRegionTable*)ReserveParTableExpansion, + &_par_tables, NULL); + if (res != NULL) return; + // Otherwise, we reserved the right to do the expansion. + + PerRegionTable** ptables = NEW_C_HEAP_ARRAY(PerRegionTable*, n); + for (int i = 0; i < n; i++) { + PerRegionTable* ptable = PerRegionTable::alloc(hr()); + ptables[i] = ptable; + } + // Here we do not need an atomic. + _par_tables = ptables; +#if COUNT_PAR_EXPANDS + print_par_expand(); +#endif + // We must put this table on the expanded list. + PosParPRT* exp_head = _par_expanded_list; + while (true) { + set_next_par_expanded(exp_head); + PosParPRT* res = + (PosParPRT*) + Atomic::cmpxchg_ptr(this, &_par_expanded_list, exp_head); + if (res == exp_head) return; + // Otherwise. + exp_head = res; + } + ShouldNotReachHere(); + } + } + void add_reference(OopOrNarrowOopStar from, int tid) { // Expand if necessary. PerRegionTable** pt = par_tables(); - if (par_tables() == NULL && tid > 0 && hr()->is_gc_alloc_region()) { - par_expand(); - pt = par_tables(); - } if (pt != NULL) { // We always have to assume that mods to table 0 are in parallel, // because of the claiming scheme in parallel expansion. A thread @@ -696,7 +696,21 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, int tid) { // OtherRegionsTable for why this is OK. assert(prt != NULL, "Inv"); - prt->add_reference(from, tid); + if (prt->should_expand(tid)) { + MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag); + HeapRegion* prt_hr = prt->hr(); + if (prt_hr == from_hr) { + // Make sure the table still corresponds to the same region + prt->par_expand(); + prt->add_reference(from, tid); + } + // else: The table has been concurrently coarsened, evicted, and + // the table data structure re-used for another table. So, we + // don't need to add the reference any more given that the table + // has been coarsened and the whole region will be scanned anyway. + } else { + prt->add_reference(from, tid); + } if (G1RecordHRRSOops) { HeapRegionRemSet::record(hr(), from); #if HRRS_VERBOSE From 3f7a94c3f2d0599322b8dcbbf81216fb49eb6563 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Mon, 8 Feb 2010 12:20:09 -0800 Subject: [PATCH 09/31] 6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used Set the reexecute bit for runtime calls _new_array_Java when they used for _multianewarray bytecode. Reviewed-by: never --- hotspot/src/share/vm/code/pcDesc.cpp | 5 +- hotspot/src/share/vm/opto/graphKit.cpp | 16 +++-- hotspot/src/share/vm/opto/parse3.cpp | 16 ++++- hotspot/test/compiler/6910605/Test.java | 78 +++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 hotspot/test/compiler/6910605/Test.java diff --git a/hotspot/src/share/vm/code/pcDesc.cpp b/hotspot/src/share/vm/code/pcDesc.cpp index 5b981645a1b..5d6456bf513 100644 --- a/hotspot/src/share/vm/code/pcDesc.cpp +++ b/hotspot/src/share/vm/code/pcDesc.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -52,7 +52,8 @@ void PcDesc::print(nmethod* code) { tty->print(" "); sd->method()->print_short_name(tty); tty->print(" @%d", sd->bci()); - tty->print(" reexecute=%s", sd->should_reexecute()?"true":"false"); + if (sd->should_reexecute()) + tty->print(" reexecute=true"); tty->cr(); } #endif diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index 57fea648024..6c177904c20 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2001-2010 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 @@ -752,12 +752,20 @@ bool GraphKit::dead_locals_are_killed() { // Helper function for enforcing certain bytecodes to reexecute if // deoptimization happens -static bool should_reexecute_implied_by_bytecode(JVMState *jvms) { +static bool should_reexecute_implied_by_bytecode(JVMState *jvms, bool is_anewarray) { ciMethod* cur_method = jvms->method(); int cur_bci = jvms->bci(); if (cur_method != NULL && cur_bci != InvocationEntryBci) { Bytecodes::Code code = cur_method->java_code_at_bci(cur_bci); - return Interpreter::bytecode_should_reexecute(code); + return Interpreter::bytecode_should_reexecute(code) || + is_anewarray && code == Bytecodes::_multianewarray; + // Reexecute _multianewarray bytecode which was replaced with + // sequence of [a]newarray. See Parse::do_multianewarray(). + // + // Note: interpreter should not have it set since this optimization + // is limited by dimensions and guarded by flag so in some cases + // multianewarray() runtime calls will be generated and + // the bytecode should not be reexecutes (stack will not be reset). } else return false; } @@ -808,7 +816,7 @@ void GraphKit::add_safepoint_edges(SafePointNode* call, bool must_throw) { // For a known set of bytecodes, the interpreter should reexecute them if // deoptimization happens. We set the reexecute state for them here if (out_jvms->is_reexecute_undefined() && //don't change if already specified - should_reexecute_implied_by_bytecode(out_jvms)) { + should_reexecute_implied_by_bytecode(out_jvms, call->is_AllocateArray())) { out_jvms->set_should_reexecute(true); //NOTE: youngest_jvms not changed } diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index 40f9940bd71..9f0a034bb63 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 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 @@ -439,8 +439,18 @@ void Parse::do_multianewarray() { // Can use multianewarray instead of [a]newarray if only one dimension, // or if all non-final dimensions are small constants. - if (expand_count == 1 || (1 <= expand_count && expand_count <= expand_limit)) { - Node* obj = expand_multianewarray(array_klass, &length[0], ndimensions, ndimensions); + if (ndimensions == 1 || (1 <= expand_count && expand_count <= expand_limit)) { + Node* obj = NULL; + // Set the original stack and the reexecute bit for the interpreter + // to reexecute the multianewarray bytecode if deoptimization happens. + // Do it unconditionally even for one dimension multianewarray. + // Note: the reexecute bit will be set in GraphKit::add_safepoint_edges() + // when AllocateArray node for newarray is created. + { PreserveReexecuteState preexecs(this); + _sp += ndimensions; + // Pass 0 as nargs since uncommon trap code does not need to restore stack. + obj = expand_multianewarray(array_klass, &length[0], ndimensions, 0); + } //original reexecute and sp are set back here push(obj); return; } diff --git a/hotspot/test/compiler/6910605/Test.java b/hotspot/test/compiler/6910605/Test.java new file mode 100644 index 00000000000..42a26e17717 --- /dev/null +++ b/hotspot/test/compiler/6910605/Test.java @@ -0,0 +1,78 @@ +/* + * Copyright 2010 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 + * @bug 6910605 + * @summary C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used + * + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot -Xbatch Test + * + * original test: nsk/coverage/runtime/runtime007 + */ + +import java.io.*; + +public class Test { + public static int buf=0; + + public static void main( String argv[] ) { + System.exit(run(argv, System.out)+95); + } + + public static int run(String argv[],PrintStream out) { + int ret=0, retx=0, bad=0; + + for( int i=0; (i < 100000) && (bad < 10) ; i++ ) { + retx = OptoRuntime_f2i_Type(out); + ret += retx; + if( retx !=0 ) { + out.println("i="+i); + bad++; + } + } + return ret==0 ? 0 : 2 ; + } + + public static int OptoRuntime_f2i_Type(PrintStream out) { + int c1=2, c2=3, c3=4, c4=5, c5=6; + int j=0, k=0; + try { + int[][] iii=(int[][])(new int[c1][c2]); + + for( j=0; jGetVMGlobals(env, names, globals, count); if (num_flags == 0) { free(globals); From 22409a57040728fdaa0cdd49f0ea1c7dc98e7d69 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 9 Feb 2010 01:31:13 -0800 Subject: [PATCH 11/31] 6910618: C2: Error: assert(d->is_oop(),"JVM_ArrayCopy: dst not an oop") Mark in PcDesc call sites which return oop and save the result oop across objects reallocation during deoptimization. Reviewed-by: never --- hotspot/src/share/vm/c1/c1_IR.hpp | 3 +- hotspot/src/share/vm/code/debugInfoRec.cpp | 2 + hotspot/src/share/vm/code/debugInfoRec.hpp | 1 + hotspot/src/share/vm/code/nmethod.cpp | 9 ++- hotspot/src/share/vm/code/pcDesc.hpp | 4 + hotspot/src/share/vm/code/scopeDesc.cpp | 7 +- hotspot/src/share/vm/code/scopeDesc.hpp | 6 +- hotspot/src/share/vm/includeDB_core | 1 + hotspot/src/share/vm/opto/output.cpp | 8 +- .../share/vm/prims/jvmtiCodeBlobEvents.cpp | 2 +- .../src/share/vm/runtime/deoptimization.cpp | 27 ++++++- hotspot/test/compiler/6910618/Test.java | 74 +++++++++++++++++++ 12 files changed, 133 insertions(+), 11 deletions(-) create mode 100644 hotspot/test/compiler/6910618/Test.java diff --git a/hotspot/src/share/vm/c1/c1_IR.hpp b/hotspot/src/share/vm/c1/c1_IR.hpp index e1af926aef1..32ed4a40d00 100644 --- a/hotspot/src/share/vm/c1/c1_IR.hpp +++ b/hotspot/src/share/vm/c1/c1_IR.hpp @@ -253,7 +253,8 @@ class IRScopeDebugInfo: public CompilationResourceObj { // reexecute allowed only for the topmost frame bool reexecute = topmost ? should_reexecute() : false; bool is_method_handle_invoke = false; - recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, locvals, expvals, monvals); + bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis. + recorder->describe_scope(pc_offset, scope()->method(), bci(), reexecute, is_method_handle_invoke, return_oop, locvals, expvals, monvals); } }; diff --git a/hotspot/src/share/vm/code/debugInfoRec.cpp b/hotspot/src/share/vm/code/debugInfoRec.cpp index a1cac29439f..14765e4fc53 100644 --- a/hotspot/src/share/vm/code/debugInfoRec.cpp +++ b/hotspot/src/share/vm/code/debugInfoRec.cpp @@ -282,6 +282,7 @@ void DebugInformationRecorder::describe_scope(int pc_offset, int bci, bool reexecute, bool is_method_handle_invoke, + bool return_oop, DebugToken* locals, DebugToken* expressions, DebugToken* monitors) { @@ -296,6 +297,7 @@ void DebugInformationRecorder::describe_scope(int pc_offset, // Record flags into pcDesc. last_pd->set_should_reexecute(reexecute); last_pd->set_is_method_handle_invoke(is_method_handle_invoke); + last_pd->set_return_oop(return_oop); // serialize sender stream offest stream()->write_int(sender_stream_offset); diff --git a/hotspot/src/share/vm/code/debugInfoRec.hpp b/hotspot/src/share/vm/code/debugInfoRec.hpp index c67efa09b25..8282a051f08 100644 --- a/hotspot/src/share/vm/code/debugInfoRec.hpp +++ b/hotspot/src/share/vm/code/debugInfoRec.hpp @@ -89,6 +89,7 @@ class DebugInformationRecorder: public ResourceObj { int bci, bool reexecute, bool is_method_handle_invoke = false, + bool return_oop = false, DebugToken* locals = NULL, DebugToken* expressions = NULL, DebugToken* monitors = NULL); diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 54db5a983dc..7ffb0f57026 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.cpp @@ -988,7 +988,8 @@ ScopeDesc* nmethod::scope_desc_at(address pc) { PcDesc* pd = pc_desc_at(pc); guarantee(pd != NULL, "scope must be present"); return new ScopeDesc(this, pd->scope_decode_offset(), - pd->obj_decode_offset(), pd->should_reexecute()); + pd->obj_decode_offset(), pd->should_reexecute(), + pd->return_oop()); } @@ -2159,7 +2160,8 @@ void nmethod::verify_interrupt_point(address call_site) { PcDesc* pd = pc_desc_at(ic->end_of_call()); assert(pd != NULL, "PcDesc must exist"); for (ScopeDesc* sd = new ScopeDesc(this, pd->scope_decode_offset(), - pd->obj_decode_offset(), pd->should_reexecute()); + pd->obj_decode_offset(), pd->should_reexecute(), + pd->return_oop()); !sd->is_top(); sd = sd->sender()) { sd->verify(); } @@ -2424,7 +2426,8 @@ ScopeDesc* nmethod::scope_desc_in(address begin, address end) { PcDesc* p = pc_desc_near(begin+1); if (p != NULL && p->real_pc(this) <= end) { return new ScopeDesc(this, p->scope_decode_offset(), - p->obj_decode_offset(), p->should_reexecute()); + p->obj_decode_offset(), p->should_reexecute(), + p->return_oop()); } return NULL; } diff --git a/hotspot/src/share/vm/code/pcDesc.hpp b/hotspot/src/share/vm/code/pcDesc.hpp index 74d3baaf2f7..c666810613a 100644 --- a/hotspot/src/share/vm/code/pcDesc.hpp +++ b/hotspot/src/share/vm/code/pcDesc.hpp @@ -39,6 +39,7 @@ class PcDesc VALUE_OBJ_CLASS_SPEC { struct { unsigned int reexecute: 1; unsigned int is_method_handle_invoke: 1; + unsigned int return_oop: 1; } bits; bool operator ==(const PcDescFlags& other) { return word == other.word; } } _flags; @@ -76,6 +77,9 @@ class PcDesc VALUE_OBJ_CLASS_SPEC { bool is_method_handle_invoke() const { return _flags.bits.is_method_handle_invoke; } void set_is_method_handle_invoke(bool z) { _flags.bits.is_method_handle_invoke = z; } + bool return_oop() const { return _flags.bits.return_oop; } + void set_return_oop(bool z) { _flags.bits.return_oop = z; } + // Returns the real pc address real_pc(const nmethod* code) const; diff --git a/hotspot/src/share/vm/code/scopeDesc.cpp b/hotspot/src/share/vm/code/scopeDesc.cpp index a034530e6bf..5b411c5bef1 100644 --- a/hotspot/src/share/vm/code/scopeDesc.cpp +++ b/hotspot/src/share/vm/code/scopeDesc.cpp @@ -26,19 +26,21 @@ # include "incls/_scopeDesc.cpp.incl" -ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute) { +ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop) { _code = code; _decode_offset = decode_offset; _objects = decode_object_values(obj_decode_offset); _reexecute = reexecute; + _return_oop = return_oop; decode_body(); } -ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute) { +ScopeDesc::ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop) { _code = code; _decode_offset = decode_offset; _objects = decode_object_values(DebugInformationRecorder::serialized_null); _reexecute = reexecute; + _return_oop = return_oop; decode_body(); } @@ -48,6 +50,7 @@ ScopeDesc::ScopeDesc(const ScopeDesc* parent) { _decode_offset = parent->_sender_decode_offset; _objects = parent->_objects; _reexecute = false; //reexecute only applies to the first scope + _return_oop = false; decode_body(); } diff --git a/hotspot/src/share/vm/code/scopeDesc.hpp b/hotspot/src/share/vm/code/scopeDesc.hpp index d030eaea849..345769ae550 100644 --- a/hotspot/src/share/vm/code/scopeDesc.hpp +++ b/hotspot/src/share/vm/code/scopeDesc.hpp @@ -52,17 +52,18 @@ class SimpleScopeDesc : public StackObj { class ScopeDesc : public ResourceObj { public: // Constructor - ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute); + ScopeDesc(const nmethod* code, int decode_offset, int obj_decode_offset, bool reexecute, bool return_oop); // Calls above, giving default value of "serialized_null" to the // "obj_decode_offset" argument. (We don't use a default argument to // avoid a .hpp-.hpp dependency.) - ScopeDesc(const nmethod* code, int decode_offset, bool reexecute); + ScopeDesc(const nmethod* code, int decode_offset, bool reexecute, bool return_oop); // JVM state methodHandle method() const { return _method; } int bci() const { return _bci; } bool should_reexecute() const { return _reexecute; } + bool return_oop() const { return _return_oop; } GrowableArray* locals(); GrowableArray* expressions(); @@ -88,6 +89,7 @@ class ScopeDesc : public ResourceObj { methodHandle _method; int _bci; bool _reexecute; + bool _return_oop; // Decoding offsets int _decode_offset; diff --git a/hotspot/src/share/vm/includeDB_core b/hotspot/src/share/vm/includeDB_core index 1d60e4de8c5..b7e931fd2ac 100644 --- a/hotspot/src/share/vm/includeDB_core +++ b/hotspot/src/share/vm/includeDB_core @@ -1483,6 +1483,7 @@ deoptimization.cpp thread.hpp deoptimization.cpp vframe.hpp deoptimization.cpp vframeArray.hpp deoptimization.cpp vframe_hp.hpp +deoptimization.cpp vmreg_.inline.hpp deoptimization.cpp xmlstream.hpp deoptimization.hpp allocation.hpp diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index 65cc41b18a2..deb2ac2c3c3 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -795,6 +795,7 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { int safepoint_pc_offset = current_offset; bool is_method_handle_invoke = false; + bool return_oop = false; // Add the safepoint in the DebugInfoRecorder if( !mach->is_MachCall() ) { @@ -807,6 +808,11 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { if (mcall->is_MachCallJava()) is_method_handle_invoke = mcall->as_MachCallJava()->_method_handle_invoke; + // Check if a call returns an object. + if (mcall->return_value_is_used() && + mcall->tf()->range()->field_at(TypeFunc::Parms)->isa_ptr()) { + return_oop = true; + } safepoint_pc_offset += mcall->ret_addr_offset(); debug_info()->add_safepoint(safepoint_pc_offset, mcall->_oop_map); } @@ -919,7 +925,7 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { assert(jvms->bci() >= InvocationEntryBci && jvms->bci() <= 0x10000, "must be a valid or entry BCI"); assert(!jvms->should_reexecute() || depth == max_depth, "reexecute allowed only for the youngest"); // Now we can describe the scope. - debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, locvals, expvals, monvals); + debug_info()->describe_scope(safepoint_pc_offset, scope_method, jvms->bci(), jvms->should_reexecute(), is_method_handle_invoke, return_oop, locvals, expvals, monvals); } // End jvms loop // Mark the end of the scope set. diff --git a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp index 93217303fcf..d09bf8152ff 100644 --- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp +++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp @@ -402,7 +402,7 @@ void JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nmethod *nm, address scopes_data = nm->scopes_data_begin(); for( pcd = nm->scopes_pcs_begin(); pcd < nm->scopes_pcs_end(); ++pcd ) { - ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute()); + ScopeDesc sc0(nm, pcd->scope_decode_offset(), pcd->should_reexecute(), pcd->return_oop()); ScopeDesc *sd = &sc0; while( !sd->is_top() ) { sd = sd->sender(); } int bci = sd->bci(); diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index 6a8f8e1224e..db34edbeefa 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -145,6 +145,27 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread if (EliminateAllocations) { assert (chunk->at(0)->scope() != NULL,"expect only compiled java frames"); GrowableArray* objects = chunk->at(0)->scope()->objects(); + + // The flag return_oop() indicates call sites which return oop + // in compiled code. Such sites include java method calls, + // runtime calls (for example, used to allocate new objects/arrays + // on slow code path) and any other calls generated in compiled code. + // It is not guaranteed that we can get such information here only + // by analyzing bytecode in deoptimized frames. This is why this flag + // is set during method compilation (see Compile::Process_OopMap_Node()). + bool save_oop_result = chunk->at(0)->scope()->return_oop(); + Handle return_value; + if (save_oop_result) { + // Reallocation may trigger GC. If deoptimization happened on return from + // call which returns oop we need to save it since it is not in oopmap. + oop result = deoptee.saved_oop_result(&map); + assert(result == NULL || result->is_oop(), "must be oop"); + return_value = Handle(thread, result); + assert(Universe::heap()->is_in_or_null(result), "must be heap pointer"); + if (TraceDeoptimization) { + tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, result, thread); + } + } bool reallocated = false; if (objects != NULL) { JRT_BLOCK @@ -158,9 +179,13 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread ttyLocker ttyl; tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, thread); print_objects(objects); - } + } #endif } + if (save_oop_result) { + // Restore result. + deoptee.set_saved_oop_result(&map, return_value()); + } } if (EliminateLocks) { #ifndef PRODUCT diff --git a/hotspot/test/compiler/6910618/Test.java b/hotspot/test/compiler/6910618/Test.java new file mode 100644 index 00000000000..76480ae0bb1 --- /dev/null +++ b/hotspot/test/compiler/6910618/Test.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 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 + * @bug 6910605 + * @summary C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used + * + * @run main/othervm -Xmx64m -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot -XX:+DoEscapeAnalysis -Xbatch -XX:InlineSmallCode=2000 Test + * + */ + +/* + * Added InlineSmallCode=2000 to guaranty inlining of StringBuilder::append() to allow scalar replace StringBuilder object. + * + * original test: gc/gctests/StringGC + */ + +public class Test { + private final String toAdd = "0123456789abcdef"; + private int maxLength; + private static final int numberOfThreads = 8; + + private class StringAdder extends Thread { + private String s; + + public void test() { + s = s + toAdd; + } + public void run() { + do { + test(); + } while (s.length() < maxLength); + } + } + + public void test() throws InterruptedException { + maxLength = toAdd.length() * 15000/ numberOfThreads; + StringAdder[] sa = new StringAdder[numberOfThreads]; + for (int i = 0; i < numberOfThreads; i++) { + sa[i] = new StringAdder(); + sa[i].start(); + } + for (int i = 0; i < numberOfThreads; i++) { + sa[i].join(); + } + } + + public static void main(String[] args) throws InterruptedException { + Test t = new Test(); + t.test(); + } +} From 1a1e14549843281bf9bd9d94c81a638ca42428a4 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 9 Feb 2010 10:21:06 -0800 Subject: [PATCH 12/31] 6924097: assert((_type == Type::MEMORY) == (_adr_type != 0),"adr_type for memory phis only") Use PhiNode::make_blank(r, n) method to construct the phi. Reviewed-by: never --- hotspot/src/share/vm/opto/loopopts.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/opto/loopopts.cpp b/hotspot/src/share/vm/opto/loopopts.cpp index 68e5f468c10..05295751f1f 100644 --- a/hotspot/src/share/vm/opto/loopopts.cpp +++ b/hotspot/src/share/vm/opto/loopopts.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2010 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 @@ -47,7 +47,7 @@ Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) { int offset = t_oop->offset(); phi = new (C,region->req()) PhiNode(region, type, NULL, iid, index, offset); } else { - phi = new (C,region->req()) PhiNode(region, type); + phi = PhiNode::make_blank(region, n); } uint old_unique = C->unique(); for( uint i = 1; i < region->req(); i++ ) { From 0356567ed8ca3f41b7acca83a9fd98b045424699 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Tue, 9 Feb 2010 13:56:09 -0800 Subject: [PATCH 13/31] 6782663: Data produced by PrintGCApplicationConcurrentTime and PrintGCApplicationStoppedTime is not accurate Update and display the timers associated with these flags for all safepoints. Reviewed-by: ysr, jcoomes --- hotspot/src/share/vm/runtime/vmThread.cpp | 13 +------------ .../src/share/vm/services/runtimeService.cpp | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/hotspot/src/share/vm/runtime/vmThread.cpp b/hotspot/src/share/vm/runtime/vmThread.cpp index 26dad9a689c..ae7377b3ca1 100644 --- a/hotspot/src/share/vm/runtime/vmThread.cpp +++ b/hotspot/src/share/vm/runtime/vmThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2010 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 @@ -426,11 +426,6 @@ void VMThread::loop() { // follow that also require a safepoint if (_cur_vm_operation->evaluate_at_safepoint()) { - if (PrintGCApplicationConcurrentTime) { - gclog_or_tty->print_cr("Application time: %3.7f seconds", - RuntimeService::last_application_time_sec()); - } - _vm_queue->set_drain_list(safepoint_ops); // ensure ops can be scanned SafepointSynchronize::begin(); @@ -477,12 +472,6 @@ void VMThread::loop() { // Complete safepoint synchronization SafepointSynchronize::end(); - if (PrintGCApplicationStoppedTime) { - gclog_or_tty->print_cr("Total time for which application threads " - "were stopped: %3.7f seconds", - RuntimeService::last_safepoint_time_sec()); - } - } else { // not a safepoint operation if (TraceLongCompiles) { elapsedTimer t; diff --git a/hotspot/src/share/vm/services/runtimeService.cpp b/hotspot/src/share/vm/services/runtimeService.cpp index 16811a2aa5b..3e966009bef 100644 --- a/hotspot/src/share/vm/services/runtimeService.cpp +++ b/hotspot/src/share/vm/services/runtimeService.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2010 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 @@ -104,6 +104,13 @@ void RuntimeService::init() { void RuntimeService::record_safepoint_begin() { HS_DTRACE_PROBE(hs_private, safepoint__begin); + + // Print the time interval in which the app was executing + if (PrintGCApplicationConcurrentTime) { + gclog_or_tty->print_cr("Application time: %3.7f seconds", + last_application_time_sec()); + } + // update the time stamp to begin recording safepoint time _safepoint_timer.update(); if (UsePerfData) { @@ -122,6 +129,15 @@ void RuntimeService::record_safepoint_synchronized() { void RuntimeService::record_safepoint_end() { HS_DTRACE_PROBE(hs_private, safepoint__end); + + // Print the time interval for which the app was stopped + // during the current safepoint operation. + if (PrintGCApplicationStoppedTime) { + gclog_or_tty->print_cr("Total time for which application threads " + "were stopped: %3.7f seconds", + last_safepoint_time_sec()); + } + // update the time stamp to begin recording app time _app_timer.update(); if (UsePerfData) { From ee38364a9207afc197a99ace522d68f2c409fd22 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Wed, 10 Feb 2010 13:23:50 +0000 Subject: [PATCH 14/31] 6693244: Java Web Start app fails on 6u10 beta w/ AssertionError in AuthenticationInfo.requestCompleted Reviewed-by: michaelm --- .../sun/net/www/protocol/http/AuthenticationInfo.java | 11 +++++++---- jdk/test/ProblemList.txt | 1 - jdk/test/java/net/Authenticator/B4769350.java | 7 +++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java b/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java index 1fbf5def0a6..6115401ff02 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java @@ -111,7 +111,7 @@ public abstract class AuthenticationInfo extends AuthCacheValue implements Clone * at the same time, then all but the first will block until * the first completes its authentication. */ - static private HashMap requests = new HashMap (); + static private HashMap requests = new HashMap<>(); /* check if a request for this destination is in progress * return false immediately if not. Otherwise block until @@ -125,7 +125,7 @@ public abstract class AuthenticationInfo extends AuthCacheValue implements Clone synchronized (requests) { Thread t, c; c = Thread.currentThread(); - if ((t=(Thread)requests.get(key))==null) { + if ((t = requests.get(key)) == null) { requests.put (key, c); return false; } @@ -147,8 +147,11 @@ public abstract class AuthenticationInfo extends AuthCacheValue implements Clone */ static private void requestCompleted (String key) { synchronized (requests) { - boolean waspresent = requests.remove (key) != null; - assert waspresent; + Thread thread = requests.get(key); + if (thread != null && thread == Thread.currentThread()) { + boolean waspresent = requests.remove(key) != null; + assert waspresent; + } requests.notifyAll(); } } diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 43d53e18b12..ddcd68d3624 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -692,7 +692,6 @@ java/net/URLConnection/TimeoutTest.java generic-all java/net/URLConnection/ZeroContentLength.java generic-all # Solaris 11 i586 fails with samevm, not sure why -java/net/Authenticator/B4769350.java generic-all java/net/HttpURLConnection/HttpResponseCode.java generic-all java/net/ResponseCache/B6181108.java generic-all java/net/ResponseCache/ResponseCacheTest.java generic-all diff --git a/jdk/test/java/net/Authenticator/B4769350.java b/jdk/test/java/net/Authenticator/B4769350.java index e21cd869daf..1f673763508 100644 --- a/jdk/test/java/net/Authenticator/B4769350.java +++ b/jdk/test/java/net/Authenticator/B4769350.java @@ -26,9 +26,12 @@ * @bug 4769350 * @library ../../../sun/net/www/httptest/ * @build HttpCallback HttpServer ClosedChannelList HttpTransaction AbstractCallback - * @run main B4769350 server - * @run main B4769350 proxy + * @run main/othervm B4769350 server + * @run main/othervm B4769350 proxy * @summary proxy authentication username and password caching only works in serial case + * Run in othervm since the test sets system properties that are read by the + * networking stack and cached when the HTTP handler is invoked, and previous + * tests may already have invoked the HTTP handler. */ import java.io.*; From d9eac222f1d8360643dd49408282d87b56d2b859 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Wed, 10 Feb 2010 17:51:07 -0800 Subject: [PATCH 15/31] 6915413: Module build: building of specified jdk components instead of all Define new SUBDIRS_* variables for specifying components for one group Reviewed-by: ohair --- jdk/make/Makefile | 7 +- jdk/make/com/Makefile | 2 + jdk/make/com/sun/Makefile | 15 +- jdk/make/com/sun/demo/Makefile | 2 + jdk/make/com/sun/demo/jvmti/Makefile | 2 + jdk/make/com/sun/inputmethods/Makefile | 2 + jdk/make/com/sun/java/Makefile | 5 +- jdk/make/com/sun/java/browser/Makefile | 2 + jdk/make/com/sun/jmx/Makefile | 2 + jdk/make/com/sun/jndi/Makefile | 2 + jdk/make/com/sun/jndi/rmi/Makefile | 2 + jdk/make/com/sun/nio/Makefile | 2 + jdk/make/com/sun/org/Makefile | 2 + jdk/make/com/sun/org/apache/Makefile | 1 + jdk/make/com/sun/security/Makefile | 5 +- jdk/make/com/sun/tools/Makefile | 2 + jdk/make/com/sun/tracing/Makefile | 2 + jdk/make/common/Defs.gmk | 130 +----------- jdk/make/common/Sanity.gmk | 3 +- jdk/make/common/Subdirs.gmk | 204 +++++++++++++++++++ jdk/make/common/shared/Sanity.gmk | 18 +- jdk/make/java/Makefile | 12 +- jdk/make/java/hpi/Makefile | 2 + jdk/make/java/java/Makefile | 2 + jdk/make/java/java/genlocales.gmk | 2 +- jdk/make/java/main/Makefile | 2 + jdk/make/java/nio/FILES_java.gmk | 1 - jdk/make/java/nio/Makefile | 4 + jdk/make/java/nio/mxbean/Makefile | 34 ++++ jdk/make/java/redist/Makefile | 5 +- jdk/make/java/text/Makefile | 89 +------- jdk/make/java/text/{ => base}/FILES_java.gmk | 5 - jdk/make/java/text/base/Makefile | 108 ++++++++++ jdk/make/java/text/bidi/Makefile | 44 ++++ jdk/make/javax/Makefile | 29 +-- jdk/make/javax/rmi/Makefile | 2 + jdk/make/javax/sound/Makefile | 1 + jdk/make/javax/swing/Makefile | 1 + jdk/make/jpda/Makefile | 1 + jdk/make/jpda/transport/Makefile | 2 + jdk/make/mkdemo/Makefile | 8 +- jdk/make/mkdemo/applets/Makefile | 1 + jdk/make/mkdemo/jfc/Makefile | 1 + jdk/make/mkdemo/jni/Makefile | 2 + jdk/make/mkdemo/jvmti/Makefile | 2 + jdk/make/mkdemo/management/Makefile | 2 + jdk/make/mkdemo/scripting/Makefile | 1 + jdk/make/mksample/Makefile | 7 +- jdk/make/mksample/jmx/Makefile | 2 + jdk/make/mksample/nio/Makefile | 2 + jdk/make/mksample/scripting/Makefile | 2 + jdk/make/mksample/webservices/Makefile | 1 + jdk/make/org/Makefile | 1 + jdk/make/org/ietf/Makefile | 2 + jdk/make/sun/Makefile | 17 +- jdk/make/sun/cmm/Makefile | 2 + jdk/make/sun/image/Makefile | 2 + jdk/make/sun/management/Makefile | 2 + jdk/make/sun/net/Makefile | 2 + jdk/make/sun/net/spi/Makefile | 4 +- jdk/make/sun/net/spi/nameservice/Makefile | 2 + jdk/make/sun/nio/Makefile | 2 + jdk/make/sun/org/Makefile | 2 + jdk/make/sun/org/mozilla/Makefile | 2 + jdk/make/sun/rmi/Makefile | 2 + jdk/make/sun/security/Makefile | 6 +- jdk/make/sun/tracing/Makefile | 2 + jdk/make/tools/Makefile | 2 + 68 files changed, 595 insertions(+), 246 deletions(-) create mode 100644 jdk/make/common/Subdirs.gmk create mode 100644 jdk/make/java/nio/mxbean/Makefile rename jdk/make/java/text/{ => base}/FILES_java.gmk (98%) create mode 100644 jdk/make/java/text/base/Makefile create mode 100644 jdk/make/java/text/bidi/Makefile diff --git a/jdk/make/Makefile b/jdk/make/Makefile index 04c5a563ee7..8b0b176b7d7 100644 --- a/jdk/make/Makefile +++ b/jdk/make/Makefile @@ -240,7 +240,12 @@ import_product: all build:: sanity-all post-sanity-all -SUBDIRS = tools java javax org sun sunw com jpda mkdemo mksample launchers +SUBDIRS = tools java javax sun com +SUBDIRS_tools = launchers +SUBDIRS_misc = org sunw jpda mkdemo mksample + +include $(BUILDDIR)/common/Subdirs.gmk + all build:: $(SUBDIRS-loop) diff --git a/jdk/make/com/Makefile b/jdk/make/com/Makefile index 1edfc3a7bec..9c42c32fc06 100644 --- a/jdk/make/com/Makefile +++ b/jdk/make/com/Makefile @@ -32,6 +32,8 @@ PRODUCT = com include $(BUILDDIR)/common/Defs.gmk SUBDIRS = sun +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/Makefile b/jdk/make/com/sun/Makefile index a6549e2a4d1..c8cbd18a9e7 100644 --- a/jdk/make/com/sun/Makefile +++ b/jdk/make/com/sun/Makefile @@ -38,10 +38,19 @@ ifndef OPENJDK endif endif +# jarsigner is part of JRE +SUBDIRS = java security net/ssl jarsigner + +SUBDIRS_management = jmx +SUBDIRS_desktop = image inputmethods +SUBDIRS_enterprise = crypto/provider jndi \ + org xml rowset net/httpserver +SUBDIRS_misc = $(SCRIPT_SUBDIR) tracing servicetag nio demo + # Omit mirror since it's built with the apt tool. -SUBDIRS = $(SCRIPT_SUBDIR) image security crypto/provider jndi jmx \ - java inputmethods org xml rowset net/httpserver net/ssl demo \ - tools jarsigner tracing servicetag nio +SUBDIRS_tools = tools + +include $(BUILDDIR)/common/Subdirs.gmk all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/demo/Makefile b/jdk/make/com/sun/demo/Makefile index 09650fe33e7..ac33c2385b2 100644 --- a/jdk/make/com/sun/demo/Makefile +++ b/jdk/make/com/sun/demo/Makefile @@ -38,6 +38,8 @@ PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk SUBDIRS = jvmti +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/demo/jvmti/Makefile b/jdk/make/com/sun/demo/jvmti/Makefile index 6fedad20f87..5c0b4447496 100644 --- a/jdk/make/com/sun/demo/jvmti/Makefile +++ b/jdk/make/com/sun/demo/jvmti/Makefile @@ -38,6 +38,8 @@ PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk SUBDIRS = hprof +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/inputmethods/Makefile b/jdk/make/com/sun/inputmethods/Makefile index a4b7c9f97a9..ce84f392448 100644 --- a/jdk/make/com/sun/inputmethods/Makefile +++ b/jdk/make/com/sun/inputmethods/Makefile @@ -32,6 +32,8 @@ PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk SUBDIRS = indicim thaiim +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/java/Makefile b/jdk/make/com/sun/java/Makefile index dd16695dea7..3f6faff597e 100644 --- a/jdk/make/com/sun/java/Makefile +++ b/jdk/make/com/sun/java/Makefile @@ -31,7 +31,10 @@ BUILDDIR = ../../.. PRODUCT = plugin include $(BUILDDIR)/common/Defs.gmk -SUBDIRS = browser pack +SUBDIRS = pack +SUBDIRS_misc = browser +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/java/browser/Makefile b/jdk/make/com/sun/java/browser/Makefile index d43bbe14214..148ba370827 100644 --- a/jdk/make/com/sun/java/browser/Makefile +++ b/jdk/make/com/sun/java/browser/Makefile @@ -32,6 +32,8 @@ PRODUCT = plugin include $(BUILDDIR)/common/Defs.gmk SUBDIRS = dom net +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/jmx/Makefile b/jdk/make/com/sun/jmx/Makefile index 81470f0befe..ceff8a333d5 100644 --- a/jdk/make/com/sun/jmx/Makefile +++ b/jdk/make/com/sun/jmx/Makefile @@ -51,6 +51,8 @@ else SUBDIRS = snmp endif +include $(BUILDDIR)/common/Subdirs.gmk + all build: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/jndi/Makefile b/jdk/make/com/sun/jndi/Makefile index 04a11126bd9..204582ad5e0 100644 --- a/jdk/make/com/sun/jndi/Makefile +++ b/jdk/make/com/sun/jndi/Makefile @@ -31,6 +31,8 @@ BUILDDIR = ../../.. include $(BUILDDIR)/common/Defs.gmk SUBDIRS = toolkit cosnaming ldap rmi dns +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/jndi/rmi/Makefile b/jdk/make/com/sun/jndi/rmi/Makefile index eeefabf853b..0298182beda 100644 --- a/jdk/make/com/sun/jndi/rmi/Makefile +++ b/jdk/make/com/sun/jndi/rmi/Makefile @@ -31,6 +31,8 @@ BUILDDIR = ../../../.. include $(BUILDDIR)/common/Defs.gmk SUBDIRS = registry +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/nio/Makefile b/jdk/make/com/sun/nio/Makefile index 74151db7d61..1d6d18affc4 100644 --- a/jdk/make/com/sun/nio/Makefile +++ b/jdk/make/com/sun/nio/Makefile @@ -31,6 +31,8 @@ BUILDDIR = ../../.. include $(BUILDDIR)/common/Defs.gmk SUBDIRS = sctp +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/org/Makefile b/jdk/make/com/sun/org/Makefile index c0f1b841eb8..033b47d24b2 100644 --- a/jdk/make/com/sun/org/Makefile +++ b/jdk/make/com/sun/org/Makefile @@ -32,6 +32,8 @@ PRODUCT = org include $(BUILDDIR)/common/Defs.gmk SUBDIRS = apache +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/org/apache/Makefile b/jdk/make/com/sun/org/apache/Makefile index 3427d05ed02..5bd353371ae 100644 --- a/jdk/make/com/sun/org/apache/Makefile +++ b/jdk/make/com/sun/org/apache/Makefile @@ -31,6 +31,7 @@ BUILDDIR = ../../../.. include $(BUILDDIR)/common/Defs.gmk SUBDIRS = xml +include $(BUILDDIR)/common/Subdirs.gmk all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/security/Makefile b/jdk/make/com/sun/security/Makefile index 41df70fb42c..4fc43e4a8d8 100644 --- a/jdk/make/com/sun/security/Makefile +++ b/jdk/make/com/sun/security/Makefile @@ -30,7 +30,10 @@ BUILDDIR = ../../.. include $(BUILDDIR)/common/Defs.gmk -SUBDIRS = jgss sasl auth auth/module +SUBDIRS = auth +SUBDIRS_misc = jgss sasl auth/module +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/com/sun/tools/Makefile b/jdk/make/com/sun/tools/Makefile index be2b39c8461..1187cdf8091 100644 --- a/jdk/make/com/sun/tools/Makefile +++ b/jdk/make/com/sun/tools/Makefile @@ -35,6 +35,8 @@ include $(BUILDDIR)/common/Defs.gmk AUTO_FILES_JAVA_DIRS = com/sun/tools/extcheck SUBDIRS = attach +include $(BUILDDIR)/common/Subdirs.gmk + all build: $(SUBDIRS-loop) clean clobber:: diff --git a/jdk/make/com/sun/tracing/Makefile b/jdk/make/com/sun/tracing/Makefile index 166aee38db4..e2599024755 100644 --- a/jdk/make/com/sun/tracing/Makefile +++ b/jdk/make/com/sun/tracing/Makefile @@ -33,6 +33,8 @@ PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk SUBDIRS = dtrace +include $(BUILDDIR)/common/Subdirs.gmk + all build: $(SUBDIRS-loop) clean clobber:: diff --git a/jdk/make/common/Defs.gmk b/jdk/make/common/Defs.gmk index 88a49d4443e..75077b666a8 100644 --- a/jdk/make/common/Defs.gmk +++ b/jdk/make/common/Defs.gmk @@ -576,17 +576,17 @@ endef define install-file $(prep-target) $(CP) $< $@ -$(install-module-file) +@$(install-module-file) endef define chmod-file $(CHMOD) $1 $@ -$(call chmod-module-file, $1) +@$(call chmod-module-file, $1) endef define install-sym-link $(LN) -s $1 $@ -$(call install-module-sym-link, $1) +@$(call install-module-sym-link, $1) endef # @@ -607,131 +607,9 @@ define java-vm-cleanup if [ -w $(HOTSPOT_LOG_NAME) ] ; then $(RM) $(HOTSPOT_LOG_NAME); fi endef -# Default make settings for processing SUBDIRS with clobber or clean names -SUBDIRS_MAKEFLAGS-clobber = INCREMENTAL_BUILD=false -SUBDIRS_MAKEFLAGS-clean = INCREMENTAL_BUILD=false - # Current directory CURRENT_DIRECTORY := $(shell $(PWD)) -# If no timing wanted, we need to define these as empty -ifdef NO_TIMING - -TIMING_ID:=NA - -define TIMING_start -t=0:0:0:0 -endef - -define TIMING_end -time_used=0 -endef - -else # NO_TIMING - -# Default timing id -TIMING_ID:=$(shell $(BASENAME) $(CURRENT_DIRECTORY)) - -# Timing start (must be used in same shell, e.g. same command line) -# Defines the shell variable $1 to have the start time. -define TIMING_start -$1=`$(DATE) +%j:%H:%M:%S` -endef - -# Timing end (must be used in same shell, e.g. same command line) -# Expects shell variable $1 to have been defined as the start time. -# Expects shell variable $2 to have timing id string -# Sets total_seconds shell variable as the total seconds used. -# Sets time_used shell variable to contain format "%dh%dm%ds" -define TIMING_end -begTime="$${$1}"; \ -timing_id="$${$2}"; \ -endTime=`$(DATE) +%j:%H:%M:%S`; \ -d1=`$(ECHO) $${begTime} | $(CUT) -d':' -f1 | $(SED) -e 's@^0*@@'`; \ -if [ "$${d1}" = "" ] ; then d1=0; fi; \ -h1=`$(ECHO) $${begTime} | $(CUT) -d':' -f2 | $(SED) -e 's@^0*@@'`; \ -if [ "$${h1}" = "" ] ; then h1=0; fi; \ -m1=`$(ECHO) $${begTime} | $(CUT) -d':' -f3 | $(SED) -e 's@^0*@@'`; \ -if [ "$${m1}" = "" ] ; then m1=0; fi; \ -s1=`$(ECHO) $${begTime} | $(CUT) -d':' -f4 | $(SED) -e 's@^0*@@'`; \ -if [ "$${s1}" = "" ] ; then s1=0; fi; \ -d2=`$(ECHO) $${endTime} | $(CUT) -d':' -f1 | $(SED) -e 's@^0*@@'`; \ -if [ "$${d2}" = "" ] ; then d2=0; fi; \ -h2=`$(ECHO) $${endTime} | $(CUT) -d':' -f2 | $(SED) -e 's@^0*@@'`; \ -if [ "$${h2}" = "" ] ; then h2=0; fi; \ -m2=`$(ECHO) $${endTime} | $(CUT) -d':' -f3 | $(SED) -e 's@^0*@@'`; \ -if [ "$${m2}" = "" ] ; then m2=0; fi; \ -s2=`$(ECHO) $${endTime} | $(CUT) -d':' -f4 | $(SED) -e 's@^0*@@'`; \ -if [ "$${s2}" = "" ] ; then s2=0; fi; \ -t1_secs=`$(EXPR) $${d1} '*' 60 '*' 60 '*' 24 '+' $${h1} '*' 60 '*' 60 \ - '+' $${m1} '*' 60 '+' $${s1}`; \ -t2_secs=`$(EXPR) $${d2} '*' 60 '*' 60 '*' 24 '+' $${h2} '*' 60 '*' 60 \ - '+' $${m2} '*' 60 '+' $${s2}`; \ -total_seconds=`$(EXPR) $${t2_secs} '-' $${t1_secs}`; \ -if [ "$${total_seconds}" -lt 0 ] ; then total_seconds=0; fi; \ -t_hour=`$(EXPR) $${total_seconds} '/' '(' 60 '*' 60 ')'`h; \ -t_min=`$(EXPR) '(' $${total_seconds} '%' '(' 60 '*' 60 ')' ')' '/' 60`m; \ -t_sec=`$(EXPR) $${total_seconds} '%' 60`s; \ -time_used=$${t_sec}; \ -if [ "$${t_hour}" != "0h" ] ; then \ -time_used=$${t_hour}$${t_min}$${t_sec}; \ -elif [ "$${t_min}" != "0m" ] ; then \ -time_used=$${t_min}$${t_sec}; \ -else \ -time_used=$${t_sec}; \ -fi; \ -$(PRINTF) " Timing: %05d seconds or %s for %s\n" \ - $${total_seconds} $${time_used} $${timing_id} -endef - -endif # NO_TIMING - -# Given a SUBDIRS list, cd into them and make them -# SUBDIRS_MAKEFLAGS Make settings for a subdir make -# SUBDIRS_MAKEFLAGS-$@ Make settings specific to this target -define SUBDIRS-loop -@$(ECHO) "Begin Processing SUBDIRS: $(SUBDIRS)" -@for i in DUMMY $(SUBDIRS) ; do \ - if [ "$$i" != "DUMMY" ] ; then \ - $(ECHO) ">>>Recursively making "$$i" "$@" @ `$(DATE)` ..."; \ - timing_id="$(TIMING_ID)-`$(BASENAME) $${i}`"; \ - $(call TIMING_start,startTime); \ - curDir=$(CURRENT_DIRECTORY); \ - $(CD) $$i; $(MAKE) $@ TIMING_ID=$${timing_id} \ - $(SUBDIRS_MAKEFLAGS) \ - $(SUBDIRS_MAKEFLAGS-$@) \ - FULL_VERSION=$(FULL_VERSION) \ - RELEASE=$(RELEASE) || exit 1; \ - $(CD) $${curDir}; \ - $(call TIMING_end,startTime,timing_id); \ - $(ECHO) "<<>>Recursively making "$$i" "$@" @ `$(DATE)` ..."; \ - timing_id="$(TIMING_ID)-`$(BASENAME) $${i}`"; \ - $(call TIMING_start,startTime); \ - curDir=$(CURRENT_DIRECTORY); \ - $(CD) $$i; $(MAKE) $@ TIMING_ID=$${timing_id} \ - $(OTHERSUBDIRS_MAKEFLAGS) \ - FULL_VERSION=$(FULL_VERSION) \ - RELEASE=$(RELEASE) || exit 1; \ - $(CD) $${curDir}; \ - $(call TIMING_end,startTime,timing_id); \ - $(ECHO) "<< subdirs for the named group +# +# By default, subdirs specified in the SUBDIRS and all SUBDIRS_* +# variables will be built. +# +# BUILD_MODULES variable can be used to specify one or more groups +# to be built (BUILD_MODULES=all will build all groups). +# +# Variables of the currently supported groups are: +# SUBDIRS_desktop +# SUBDIRS_management +# SUBDIRS_enterprise +# SUBDIRS_misc +# SUBDIRS_tools +# +# Change to the above list also need to update +# make/common/shared/Sanity.gmk. NOTE: this list is subject +# to change till the JDK 7 SE profiles/modules are finalized. +# +# Eventually we want to restructure the make directory +# according to these grouping (e.g. make/desktop/...) and +# the SUBDIRS_ variables would not be needed. +# +# To build the desktop and tools groups only, you can do: +# gnumake BUILD_MODULES="desktop tools" ... +# + +# Iterate the subdirectories specified in $1. +# - cd into each subdir and make them + +# Given a SUBDIRS* list (first argument), cd into them and make them +# SUBDIRS_MAKEFLAGS Make settings for a subdir make +# SUBDIRS_MAKEFLAGS-$@ Make settings specific to this target +# +define subdirs-group-loop +@$(ECHO) "Begin Processing SUBDIRS: $($1)" +@for i in DUMMY $($1) ; do \ + if [ "$$i" != "DUMMY" ] ; then \ + $(MAKE) -C $$i $@ $(SUBDIRS_MAKEFLAGS) $(SUBDIRS_MAKEFLAGS-$@) \ + FULL_VERSION=$(FULL_VERSION) RELEASE=$(RELEASE) || exit 1; \ + fi ; \ +done +@$(ECHO) "Done Processing SUBDIRS: $($1)" +endef + +# Given a OTHERSUBDIRS list, cd into them and make them (extra loop define) +# OTHERSUBDIRS_MAKEFLAGS Make settings for a subdir make +define OTHERSUBDIRS-loop +@$(ECHO) "Begin Processing OTHERSUBDIRS: $(OTHERSUBDIRS)" +@for i in DUMMY $(OTHERSUBDIRS) ; do \ + if [ "$$i" != "DUMMY" ] ; then \ + $(MAKE) -C $$i $@ $(OTHERSUBDIRS_MAKEFLAGS) \ + FULL_VERSION=$(FULL_VERSION) RELEASE=$(RELEASE) || exit 1; \ + fi ; \ +done +@$(ECHO) "Done Processing OTHERSUBDIRS: $(OTHERSUBDIRS)" +endef + +# +# Iterate the list specified in SUBDIRS_ only if +# SUBDIRS_ is set and or "all" is specified +# in the BUILD_MODULES variable +# +ifdef SUBDIRS_desktop + ifneq (,$(findstring desktop, $(BUILD_MODULES))) + define subdirs-desktop-loop + @$(call subdirs-group-loop,SUBDIRS_desktop) + endef + else + define subdirs-desktop-loop + endef + endif +else + define subdirs-desktop-loop + endef +endif # SUBDIRS_desktop + +ifdef SUBDIRS_enterprise + ifneq (,$(findstring enterprise, $(BUILD_MODULES))) + define subdirs-enterprise-loop + @$(call subdirs-group-loop,SUBDIRS_enterprise) + endef + else + define subdirs-enterprise-loop + endef + endif +else +define subdirs-enterprise-loop +endef +endif # SUBDIRS_enterprise + +ifdef SUBDIRS_management + ifneq (,$(findstring management, $(BUILD_MODULES))) + define subdirs-management-loop + @$(call subdirs-group-loop,SUBDIRS_management) + endef + else + define subdirs-management-loop + endef + endif +else +define subdirs-management-loop +endef +endif # SUBDIRS_management + +ifdef SUBDIRS_misc + ifneq (,$(findstring misc, $(BUILD_MODULES))) + define subdirs-misc-loop + @$(call subdirs-group-loop,SUBDIRS_misc) + endef + else + define subdirs-misc-loop + endef + endif +else +define subdirs-misc-loop +endef +endif # SUBDIRS_misc + +ifdef SUBDIRS_tools + ifneq (,$(findstring tools, $(BUILD_MODULES))) + define subdirs-tools-loop + @$(call subdirs-group-loop,SUBDIRS_tools) + endef + else + define subdirs-tools-loop + endef + endif +else +define subdirs-tools-loop +endef +endif # SUBDIRS_tools + +# +# If BUILD_MODULES is not set or it's set to "all", +# iterate all groups. +SUBDIRS_all = $(SUBDIRS) $(SUBDIRS_desktop) $(SUBDIRS_enterprise) \ + $(SUBDIRS_management) $(SUBDIRS_misc) $(SUBDIRS_tools) + +ifndef BUILD_MODULES +define SUBDIRS-loop + @$(call subdirs-group-loop,SUBDIRS_all) +endef + +else + +ifneq (,$(findstring all, $(BUILD_MODULES))) +define SUBDIRS-loop + @$(call subdirs-group-loop,SUBDIRS_all) +endef + +else # BUILD_MODULES set +# +# Iterate SUBDIRS and the groups specified in BUILD_MODULES +# +define SUBDIRS-loop + @$(call subdirs-group-loop,SUBDIRS) + @$(subdirs-desktop-loop) + @$(subdirs-enterprise-loop) + @$(subdirs-management-loop) + @$(subdirs-misc-loop) + @$(subdirs-tools-loop) +endef + +endif +endif # BUILD_MODULES diff --git a/jdk/make/common/shared/Sanity.gmk b/jdk/make/common/shared/Sanity.gmk index 7499f6bb189..e7e3978bc8d 100644 --- a/jdk/make/common/shared/Sanity.gmk +++ b/jdk/make/common/shared/Sanity.gmk @@ -218,7 +218,8 @@ include $(JDK_MAKE_SHARED_DIR)/Sanity-Settings.gmk sane-zip_version \ sane-unzip_version \ sane-msvcrt_path \ - sane-freetype + sane-freetype \ + sane-build_modules ###################################################### # check for COPYRIGHT_YEAR variable @@ -844,6 +845,21 @@ else sane-freetype: endif +###################################################### +# if specified, BUILD_MODULES must contain valid values. +###################################################### +MODULES_REGEX="all|base|desktop|management|enterprise|misc|tools" +sane-build_modules: +ifdef BUILD_MODULES + @for m in $(BUILD_MODULES) ; do \ + valid=`$(ECHO) $$m | $(EGREP) $(MODULES_REGEX)`; \ + if [ "x$$valid" = "x" ] ; then \ + $(ECHO) "ERROR: $$m set in the BUILD_MODULES variable is invalid.\n" \ + "" >> $(ERROR_FILE); \ + fi \ + done +endif + ###################################################### # CUPS_HEADERS_PATH must be valid ###################################################### diff --git a/jdk/make/java/Makefile b/jdk/make/java/Makefile index ca48cc9bef5..e3d046f7ae4 100644 --- a/jdk/make/java/Makefile +++ b/jdk/make/java/Makefile @@ -38,9 +38,13 @@ SUBDIRS += hpi version jvm redist verify fdlibm java sun_nio jli main zip # Others # Note: java_crw_demo java_hprof_demo are demos but must be delivered built in sdk -SUBDIRS += security npt java_crw_demo java_hprof_demo \ - math awt util text applet net nio dyn \ - sql rmi jar beans logging management instrument + +SUBDIRS += security math util text net nio jar + +SUBDIRS_desktop = awt applet beans +SUBDIRS_management = management +SUBDIRS_misc = npt java_crw_demo java_hprof_demo \ + logging instrument dyn sql rmi ifeq ($(PLATFORM), solaris) @@ -53,6 +57,8 @@ ifeq ($(PLATFORM), linux) SUBDIRS += jexec endif # PLATFORM +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/java/hpi/Makefile b/jdk/make/java/hpi/Makefile index ee6453832ec..69f3861c0b1 100644 --- a/jdk/make/java/hpi/Makefile +++ b/jdk/make/java/hpi/Makefile @@ -34,6 +34,8 @@ include $(BUILDDIR)/common/Defs.gmk # Build specified the HPI implementations # SUBDIRS = $(HPIS) +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/java/java/Makefile b/jdk/make/java/java/Makefile index e3d5ee4231c..26853ac3aa8 100644 --- a/jdk/make/java/java/Makefile +++ b/jdk/make/java/java/Makefile @@ -218,6 +218,8 @@ ifeq ($(PLATFORM), solaris) endif SUBDIRS = reflect +include $(BUILDDIR)/common/Subdirs.gmk + all build: $(SUBDIRS-loop) clean clobber:: diff --git a/jdk/make/java/java/genlocales.gmk b/jdk/make/java/java/genlocales.gmk index 3adb769490d..df9aec72678 100644 --- a/jdk/make/java/java/genlocales.gmk +++ b/jdk/make/java/java/genlocales.gmk @@ -49,7 +49,7 @@ Euro_Resources_properties := $(FILES_compiled_properties) # $(BUILDDIR)/java/text/FILES_java.gmk contains the "sun.text.resources" for # European language support -include $(BUILDDIR)/java/text/FILES_java.gmk +include $(BUILDDIR)/java/text/base/FILES_java.gmk Euro_Resources_java += $(FILES_java) diff --git a/jdk/make/java/main/Makefile b/jdk/make/java/main/Makefile index 4e90729d4ea..9758d6dd8a1 100644 --- a/jdk/make/java/main/Makefile +++ b/jdk/make/java/main/Makefile @@ -36,6 +36,8 @@ SUBDIRS = java javaw else SUBDIRS = java endif +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/java/nio/FILES_java.gmk b/jdk/make/java/nio/FILES_java.gmk index e38e4c67d0b..f1f58dc9720 100644 --- a/jdk/make/java/nio/FILES_java.gmk +++ b/jdk/make/java/nio/FILES_java.gmk @@ -26,7 +26,6 @@ FILES_src = \ java/nio/Bits.java \ java/nio/Buffer.java \ - java/nio/BufferPoolMXBean.java \ java/nio/ByteOrder.java \ java/nio/MappedByteBuffer.java \ java/nio/StringCharBuffer.java \ diff --git a/jdk/make/java/nio/Makefile b/jdk/make/java/nio/Makefile index 6dd15eac239..b2a17e26991 100644 --- a/jdk/make/java/nio/Makefile +++ b/jdk/make/java/nio/Makefile @@ -304,7 +304,11 @@ endif # PLATFORM # Rules # +SUBDIRS_management = mxbean +include $(BUILDDIR)/common/Subdirs.gmk + build: sources + $(SUBDIRS-loop) clean clobber:: $(RM) -r $(NIO_GEN) $(SNIO_GEN) diff --git a/jdk/make/java/nio/mxbean/Makefile b/jdk/make/java/nio/mxbean/Makefile new file mode 100644 index 00000000000..383d4dc18c5 --- /dev/null +++ b/jdk/make/java/nio/mxbean/Makefile @@ -0,0 +1,34 @@ +# +# Copyright 2010 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. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# 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. +# + +BUILDDIR = ../../.. +MODULE = management +PACKAGE = java.nio +PRODUCT = java +include $(BUILDDIR)/common/Defs.gmk + +FILES_java = java/nio/BufferPoolMXBean.java + +include $(BUILDDIR)/common/Classes.gmk diff --git a/jdk/make/java/redist/Makefile b/jdk/make/java/redist/Makefile index d66244920f3..28821008ab6 100644 --- a/jdk/make/java/redist/Makefile +++ b/jdk/make/java/redist/Makefile @@ -62,7 +62,10 @@ CLASSSHARINGDATA_DIR = $(BUILDDIR)/tools/sharing # Needed to do file copy ABS_BUILDDIR :=$(call FullPath,$(BUILDDIR)) -SUBDIRS = fonts sajdi +SUBDIRS_desktop = fonts +SUBDIRS_tools = sajdi +include $(BUILDDIR)/common/Subdirs.gmk + all clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/java/text/Makefile b/jdk/make/java/text/Makefile index 001f4717a9e..4bda138f676 100644 --- a/jdk/make/java/text/Makefile +++ b/jdk/make/java/text/Makefile @@ -1,5 +1,5 @@ # -# Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. +# Copyright 2010 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 @@ -23,86 +23,19 @@ # have any questions. # -BUILDDIR = ../.. -MODULE = base -PACKAGE = java.text -PRODUCT = sun +# +# Makefile for building all of java.text +# +BUILDDIR = ../.. +PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk -# -# Files -# -include FILES_java.gmk +SUBDIRS = base +SUBDIRS_desktop = bidi -# -# Include -# -include $(BUILDDIR)/common/Classes.gmk +include $(BUILDDIR)/common/Subdirs.gmk -# -# Rules to add data files BreakIterator -# -TEXT_CLASSES = $(BUILDTOOLCLASSDIR)/java.text/classes - -# input -# -# Notes: sun.text.resources.BreakIteratorRules no longer goes to runtime. -# They are used at JDK build phase in order to create $(BIFILES) which -# are used on runtime instead. -# -TEXT_SRCDIR = $(SHARE_SRC)/classes/sun/text/resources -TEXT_SOURCES = $(TEXT_SRCDIR)/BreakIteratorRules.java \ - $(TEXT_SRCDIR)/BreakIteratorInfo.java -UNICODEDATA = $(BUILDDIR)/tools/UnicodeData - -# output -TEXT_CLASSDIR = $(CLASSBINDIR)/sun/text/resources -BIFILES = $(TEXT_CLASSDIR)/CharacterBreakIteratorData \ - $(TEXT_CLASSDIR)/WordBreakIteratorData \ - $(TEXT_CLASSDIR)/LineBreakIteratorData \ - $(TEXT_CLASSDIR)/SentenceBreakIteratorData - -ICU_FILES = $(TEXT_CLASSDIR)/unorm.icu \ - $(TEXT_CLASSDIR)/uprops.icu \ - $(TEXT_CLASSDIR)/ubidi.icu - -# builder -GENERATEBREAKITERATORDATA_JARFILE = \ - $(BUILDTOOLJARDIR)/generatebreakiteratordata.jar - -$(BIFILES): $(GENERATEBREAKITERATORDATA_JARFILE) \ - $(UNICODEDATA)/UnicodeData.txt \ - $(TEXT_SOURCES) - $(prep-target) - $(RM) -r $(TEXT_CLASSES) - $(MKDIR) -p $(TEXT_CLASSES) - $(BOOT_JAVAC_CMD) -d $(TEXT_CLASSES) \ - -sourcepath $(TEXT_SRCDIR) \ - $(TEXT_SOURCES) - $(MKDIR) -p $(TEXT_CLASSDIR) - $(BOOT_JAVA_CMD) -Xbootclasspath/p:$(TEXT_CLASSES) \ - -jar $(GENERATEBREAKITERATORDATA_JARFILE) \ - -o $(TEXT_CLASSDIR) \ - -spec $(UNICODEDATA)/UnicodeData.txt - @$(java-vm-cleanup) - -build: $(BIFILES) $(ICU_FILES) - -# -# Extra rules to copy unorm.icu, uprops.icu, and ubidi.icu -# -$(TEXT_CLASSDIR)/unorm.icu: $(TEXT_SRCDIR)/unorm.icu - $(install-file) - -$(TEXT_CLASSDIR)/uprops.icu: $(TEXT_SRCDIR)/uprops.icu - $(install-file) - -$(TEXT_CLASSDIR)/ubidi.icu: $(TEXT_SRCDIR)/ubidi.icu - $(install-file) - -clean clobber:: - $(RM) -r $(TEXT_CLASSES) - $(RM) -r $(BIFILES) - $(RM) $(ICU_FILES) +all build clean clobber:: + $(SUBDIRS-loop) diff --git a/jdk/make/java/text/FILES_java.gmk b/jdk/make/java/text/base/FILES_java.gmk similarity index 98% rename from jdk/make/java/text/FILES_java.gmk rename to jdk/make/java/text/base/FILES_java.gmk index ada9bde7fee..6ca1f72c5b8 100644 --- a/jdk/make/java/text/FILES_java.gmk +++ b/jdk/make/java/text/base/FILES_java.gmk @@ -29,7 +29,6 @@ FILES_java = \ java/text/AttributedString.java \ java/text/BreakDictionary.java \ java/text/BreakIterator.java \ - java/text/Bidi.java \ java/text/CharacterIterator.java \ java/text/CharacterIteratorFieldDelegate.java \ java/text/ChoiceFormat.java \ @@ -76,10 +75,6 @@ FILES_java = \ sun/text/Normalizer.java \ sun/text/SupplementaryCharacterData.java \ sun/text/UCompactIntArray.java \ - sun/text/bidi/BidiBase.java \ - sun/text/bidi/BidiLine.java \ - sun/text/bidi/BidiRun.java \ - \ sun/text/normalizer/CharTrie.java \ sun/text/normalizer/CharacterIteratorWrapper.java \ sun/text/normalizer/ICUBinary.java \ diff --git a/jdk/make/java/text/base/Makefile b/jdk/make/java/text/base/Makefile new file mode 100644 index 00000000000..d4cc5164a1f --- /dev/null +++ b/jdk/make/java/text/base/Makefile @@ -0,0 +1,108 @@ +# +# Copyright 1996-2006 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. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# 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. +# + +BUILDDIR = ../../.. +MODULE = base +PACKAGE = java.text +PRODUCT = sun + +include $(BUILDDIR)/common/Defs.gmk + +# +# Files +# +include FILES_java.gmk + +# +# Include +# +include $(BUILDDIR)/common/Classes.gmk + +# +# Rules to add data files BreakIterator +# +TEXT_CLASSES = $(BUILDTOOLCLASSDIR)/java.text/classes + +# input +# +# Notes: sun.text.resources.BreakIteratorRules no longer goes to runtime. +# They are used at JDK build phase in order to create $(BIFILES) which +# are used on runtime instead. +# +TEXT_SRCDIR = $(SHARE_SRC)/classes/sun/text/resources +TEXT_SOURCES = $(TEXT_SRCDIR)/BreakIteratorRules.java \ + $(TEXT_SRCDIR)/BreakIteratorInfo.java +UNICODEDATA = $(BUILDDIR)/tools/UnicodeData + +# output +TEXT_CLASSDIR = $(CLASSBINDIR)/sun/text/resources +BIFILES = $(TEXT_CLASSDIR)/CharacterBreakIteratorData \ + $(TEXT_CLASSDIR)/WordBreakIteratorData \ + $(TEXT_CLASSDIR)/LineBreakIteratorData \ + $(TEXT_CLASSDIR)/SentenceBreakIteratorData + +ICU_FILES = $(TEXT_CLASSDIR)/unorm.icu \ + $(TEXT_CLASSDIR)/uprops.icu \ + $(TEXT_CLASSDIR)/ubidi.icu + +# builder +GENERATEBREAKITERATORDATA_JARFILE = \ + $(BUILDTOOLJARDIR)/generatebreakiteratordata.jar + +$(BIFILES): $(GENERATEBREAKITERATORDATA_JARFILE) \ + $(UNICODEDATA)/UnicodeData.txt \ + $(TEXT_SOURCES) + $(prep-target) + $(RM) -r $(TEXT_CLASSES) + $(MKDIR) -p $(TEXT_CLASSES) + $(BOOT_JAVAC_CMD) -d $(TEXT_CLASSES) \ + -sourcepath $(TEXT_SRCDIR) \ + $(TEXT_SOURCES) + $(MKDIR) -p $(TEXT_CLASSDIR) + $(BOOT_JAVA_CMD) -Xbootclasspath/p:$(TEXT_CLASSES) \ + -jar $(GENERATEBREAKITERATORDATA_JARFILE) \ + -o $(TEXT_CLASSDIR) \ + -spec $(UNICODEDATA)/UnicodeData.txt + @$(java-vm-cleanup) + +build: $(BIFILES) $(ICU_FILES) + +# +# Extra rules to copy unorm.icu, uprops.icu, and ubidi.icu +# +$(TEXT_CLASSDIR)/unorm.icu: $(TEXT_SRCDIR)/unorm.icu + $(install-file) + +$(TEXT_CLASSDIR)/uprops.icu: $(TEXT_SRCDIR)/uprops.icu + $(install-file) + +$(TEXT_CLASSDIR)/ubidi.icu: $(TEXT_SRCDIR)/ubidi.icu + $(install-file) + +clean clobber:: + $(RM) -r $(TEXT_CLASSES) + $(RM) -r $(BIFILES) + $(RM) $(ICU_FILES) + diff --git a/jdk/make/java/text/bidi/Makefile b/jdk/make/java/text/bidi/Makefile new file mode 100644 index 00000000000..e61c5335340 --- /dev/null +++ b/jdk/make/java/text/bidi/Makefile @@ -0,0 +1,44 @@ +# +# Copyright 2010 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. Sun designates this +# particular file as subject to the "Classpath" exception as provided +# by Sun in the LICENSE file that accompanied this code. +# +# 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. +# + +BUILDDIR = ../../.. +PACKAGE = java.text +PRODUCT = sun +include $(BUILDDIR)/common/Defs.gmk + +# +# Files for Bidi that is not in the base module +# +FILES_java = \ + java/text/Bidi.java \ + sun/text/bidi/BidiBase.java \ + sun/text/bidi/BidiLine.java \ + sun/text/bidi/BidiRun.java \ + sun/text/CodePointIterator.java + +# +# Include +# +include $(BUILDDIR)/common/Classes.gmk diff --git a/jdk/make/javax/Makefile b/jdk/make/javax/Makefile index 8ec72ade7e1..15f5cd7ecb2 100644 --- a/jdk/make/javax/Makefile +++ b/jdk/make/javax/Makefile @@ -30,19 +30,24 @@ BUILDDIR = .. include $(BUILDDIR)/common/Defs.gmk -# imageio uses xml, so build it last +SUBDIRS = others -SUBDIRS = \ - others \ - accessibility \ - print \ - swing \ - crypto \ - sound \ - sql \ - rmi \ - management \ - imageio +SUBDIRS_management = management + +SUBDIRS_misc = \ + crypto \ + sql \ + rmi + +# imageio uses xml, so build it last +SUBDIRS_desktop = \ + accessibility \ + print \ + swing \ + sound \ + imageio + +include $(BUILDDIR)/common/Subdirs.gmk all build: $(SUBDIRS-loop) diff --git a/jdk/make/javax/rmi/Makefile b/jdk/make/javax/rmi/Makefile index 10910f5d213..49f6c817900 100644 --- a/jdk/make/javax/rmi/Makefile +++ b/jdk/make/javax/rmi/Makefile @@ -31,6 +31,8 @@ BUILDDIR = ../.. include $(BUILDDIR)/common/Defs.gmk SUBDIRS = ssl +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/javax/sound/Makefile b/jdk/make/javax/sound/Makefile index 8b4948a15e1..cc6c274e785 100644 --- a/jdk/make/javax/sound/Makefile +++ b/jdk/make/javax/sound/Makefile @@ -159,6 +159,7 @@ vpath %.cpp $(PLATFORM_SRC)/native/com/sun/media/sound # Include rules # include $(BUILDDIR)/common/Library.gmk +include $(BUILDDIR)/common/Subdirs.gmk # # Rules that copy files. diff --git a/jdk/make/javax/swing/Makefile b/jdk/make/javax/swing/Makefile index 16bfcac03ab..7331426a075 100644 --- a/jdk/make/javax/swing/Makefile +++ b/jdk/make/javax/swing/Makefile @@ -40,6 +40,7 @@ AUTO_JAVA_PRUNE = plaf SUBDIRS = html32dtd plaf include $(BUILDDIR)/common/Classes.gmk +include $(BUILDDIR)/common/Subdirs.gmk build: other_files $(SUBDIRS-loop) diff --git a/jdk/make/jpda/Makefile b/jdk/make/jpda/Makefile index b2567882efa..857952b24bc 100644 --- a/jdk/make/jpda/Makefile +++ b/jdk/make/jpda/Makefile @@ -35,6 +35,7 @@ include $(BUILDDIR)/common/Defs.gmk # Core. # SUBDIRS = jdwp back front transport expr tty bdi gui +include $(BUILDDIR)/common/Subdirs.gmk all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/jpda/transport/Makefile b/jdk/make/jpda/transport/Makefile index 9069032fa6e..dddc0dbc84f 100644 --- a/jdk/make/jpda/transport/Makefile +++ b/jdk/make/jpda/transport/Makefile @@ -36,6 +36,8 @@ SUBDIRS = socket ifeq ($(PLATFORM), windows) SUBDIRS += shmem endif # PLATFORM + +include $(BUILDDIR)/common/Subdirs.gmk all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/mkdemo/Makefile b/jdk/make/mkdemo/Makefile index b0bd7f5902d..86e9de6a030 100644 --- a/jdk/make/mkdemo/Makefile +++ b/jdk/make/mkdemo/Makefile @@ -31,7 +31,13 @@ BUILDDIR = .. PRODUCT = demos include $(BUILDDIR)/common/Defs.gmk -SUBDIRS = applets jfc jvmti management jni scripting jpda +SUBDIRS = jni +SUBDIRS_desktop = applets jfc +SUBDIRS_management = management +SUBDIRS_misc = scripting +SUBDIRS_tools = jpda jvmti + +include $(BUILDDIR)/common/Subdirs.gmk all build:: nbproject $(SUBDIRS-loop) diff --git a/jdk/make/mkdemo/applets/Makefile b/jdk/make/mkdemo/applets/Makefile index f8000bfdc7c..79e0a9d2bb9 100644 --- a/jdk/make/mkdemo/applets/Makefile +++ b/jdk/make/mkdemo/applets/Makefile @@ -40,6 +40,7 @@ endif SUBDIRS_MAKEFLAGS += DEMO_IS_APPLET=true +include $(BUILDDIR)/common/Subdirs.gmk all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/mkdemo/jfc/Makefile b/jdk/make/mkdemo/jfc/Makefile index 06817a1cb23..e57ca5b9c1f 100644 --- a/jdk/make/mkdemo/jfc/Makefile +++ b/jdk/make/mkdemo/jfc/Makefile @@ -46,6 +46,7 @@ ifndef OPENJDK SUBDIRS += Java2D SwingSet2 Stylepad endif +include $(BUILDDIR)/common/Subdirs.gmk all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/mkdemo/jni/Makefile b/jdk/make/mkdemo/jni/Makefile index 4cc363902e5..dd9e617c3c2 100644 --- a/jdk/make/mkdemo/jni/Makefile +++ b/jdk/make/mkdemo/jni/Makefile @@ -37,6 +37,8 @@ ifeq ($(PLATFORM),solaris) SUBDIRS += Poller endif +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/mkdemo/jvmti/Makefile b/jdk/make/mkdemo/jvmti/Makefile index c966170fceb..f59a9d287c8 100644 --- a/jdk/make/mkdemo/jvmti/Makefile +++ b/jdk/make/mkdemo/jvmti/Makefile @@ -48,6 +48,8 @@ SUBDIRS = \ waiters \ hprof +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/mkdemo/management/Makefile b/jdk/make/mkdemo/management/Makefile index e80b30afe0c..42d3c7c6775 100644 --- a/jdk/make/mkdemo/management/Makefile +++ b/jdk/make/mkdemo/management/Makefile @@ -38,6 +38,8 @@ SUBDIRS = FullThreadDump \ MemoryMonitor \ JTop +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/mkdemo/scripting/Makefile b/jdk/make/mkdemo/scripting/Makefile index b32cfb77d5a..42e46ed3b04 100644 --- a/jdk/make/mkdemo/scripting/Makefile +++ b/jdk/make/mkdemo/scripting/Makefile @@ -32,6 +32,7 @@ PRODUCT = demos include $(BUILDDIR)/common/Defs.gmk SUBDIRS = jconsole-plugin +include $(BUILDDIR)/common/Subdirs.gmk all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/mksample/Makefile b/jdk/make/mksample/Makefile index 2d87ebd734c..0822f031de8 100644 --- a/jdk/make/mksample/Makefile +++ b/jdk/make/mksample/Makefile @@ -37,13 +37,18 @@ else WEBSERVICES_SUBDIR = webservices endif -SUBDIRS = nio jmx scripting $(WEBSERVICES_SUBDIR) nbproject +SUBDIRS = +SUBDIRS_misc = nio scripting nbproject +SUBDIRS_enterprise = $(WEBSERVICES_SUBDIR) +SUBDIRS_management = jmx # include dtrace samples in Solaris builds ifeq ($(PLATFORM), solaris) SUBDIRS += dtrace endif +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/mksample/jmx/Makefile b/jdk/make/mksample/jmx/Makefile index 94d0a1843df..0528442dce0 100644 --- a/jdk/make/mksample/jmx/Makefile +++ b/jdk/make/mksample/jmx/Makefile @@ -32,6 +32,8 @@ PRODUCT = java include $(BUILDDIR)/common/Defs.gmk SUBDIRS = jmx-scandir +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/mksample/nio/Makefile b/jdk/make/mksample/nio/Makefile index 5fcfd03a783..03fc36d3ac2 100644 --- a/jdk/make/mksample/nio/Makefile +++ b/jdk/make/mksample/nio/Makefile @@ -32,6 +32,8 @@ PRODUCT = java include $(BUILDDIR)/common/Defs.gmk SUBDIRS = file multicast server +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/mksample/scripting/Makefile b/jdk/make/mksample/scripting/Makefile index 0fd9e8737e5..2cae9f6c40e 100644 --- a/jdk/make/mksample/scripting/Makefile +++ b/jdk/make/mksample/scripting/Makefile @@ -32,6 +32,8 @@ PRODUCT = java include $(BUILDDIR)/common/Defs.gmk SUBDIRS = scriptpad +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/mksample/webservices/Makefile b/jdk/make/mksample/webservices/Makefile index 208db3c6448..4dee839c34b 100644 --- a/jdk/make/mksample/webservices/Makefile +++ b/jdk/make/mksample/webservices/Makefile @@ -32,6 +32,7 @@ PRODUCT = java include $(BUILDDIR)/common/Defs.gmk SUBDIRS = EbayClient EbayServer +include $(BUILDDIR)/common/Subdirs.gmk all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/org/Makefile b/jdk/make/org/Makefile index 0b66445eccd..1d249295be7 100644 --- a/jdk/make/org/Makefile +++ b/jdk/make/org/Makefile @@ -32,6 +32,7 @@ PRODUCT = org include $(BUILDDIR)/common/Defs.gmk SUBDIRS = ietf jcp +include $(BUILDDIR)/common/Subdirs.gmk all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/org/ietf/Makefile b/jdk/make/org/ietf/Makefile index 9c4618701ca..0d3835b2459 100644 --- a/jdk/make/org/ietf/Makefile +++ b/jdk/make/org/ietf/Makefile @@ -31,6 +31,8 @@ BUILDDIR = ../.. include $(BUILDDIR)/common/Defs.gmk SUBDIRS = jgss +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/sun/Makefile b/jdk/make/sun/Makefile index 7cf480fa83d..8e224e52aeb 100644 --- a/jdk/make/sun/Makefile +++ b/jdk/make/sun/Makefile @@ -58,13 +58,18 @@ ifdef OPENJDK else RENDER_SUBDIR = dcpr endif + # nio need to be compiled before awt to have all charsets ready -SUBDIRS = jar security javazic misc jkernel net audio $(RENDER_SUBDIR) image \ - nio awt splashscreen $(XAWT_SUBDIR) \ - $(HEADLESS_SUBDIR) $(DGA_SUBDIR) \ - font jpeg cmm applet rmi beans $(JDBC_SUBDIR) \ - jawt text launcher management $(ORG_SUBDIR) \ - native2ascii serialver tools jconsole tracing +SUBDIRS = jar security javazic misc net nio text launcher +SUBDIRS_desktop = audio $(RENDER_SUBDIR) image \ + awt splashscreen $(XAWT_SUBDIR) \ + $(HEADLESS_SUBDIR) $(DGA_SUBDIR) \ + jawt font jpeg cmm applet beans +SUBDIRS_management = management +SUBDIRS_misc = jkernel $(ORG_SUBDIR) \ + rmi $(JDBC_SUBDIR) tracing +SUBDIRS_tools = native2ascii serialver tools jconsole +include $(BUILDDIR)/common/Subdirs.gmk all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/sun/cmm/Makefile b/jdk/make/sun/cmm/Makefile index dc8a87b6e69..e6738821c59 100644 --- a/jdk/make/sun/cmm/Makefile +++ b/jdk/make/sun/cmm/Makefile @@ -36,6 +36,8 @@ else # !OPENJDK ICCPROFILE_SRC_DIR = $(CLOSED_SRC)/share/lib/cmm/kcms endif # OPENJDK +include $(BUILDDIR)/common/Subdirs.gmk + # # ICC Profiles used by the CMM. # diff --git a/jdk/make/sun/image/Makefile b/jdk/make/sun/image/Makefile index 0a264b669d1..cd69637b9ef 100644 --- a/jdk/make/sun/image/Makefile +++ b/jdk/make/sun/image/Makefile @@ -43,6 +43,8 @@ ifeq ($(PLATFORM),solaris) endif endif +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/sun/management/Makefile b/jdk/make/sun/management/Makefile index a54b1dd0be9..516cd0dc599 100644 --- a/jdk/make/sun/management/Makefile +++ b/jdk/make/sun/management/Makefile @@ -47,6 +47,8 @@ else endif SUBDIRS += jmxremote +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/sun/net/Makefile b/jdk/make/sun/net/Makefile index d5d3dd16a2b..7ddc94f04b2 100644 --- a/jdk/make/sun/net/Makefile +++ b/jdk/make/sun/net/Makefile @@ -29,6 +29,8 @@ PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk SUBDIRS = others spi +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/sun/net/spi/Makefile b/jdk/make/sun/net/spi/Makefile index 7fa860032e6..7ecefa88ff2 100644 --- a/jdk/make/sun/net/spi/Makefile +++ b/jdk/make/sun/net/spi/Makefile @@ -26,7 +26,9 @@ BUILDDIR = ../../.. include $(BUILDDIR)/common/Defs.gmk -SUBDIRS = nameservice +SUBDIRS_misc = nameservice +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/sun/net/spi/nameservice/Makefile b/jdk/make/sun/net/spi/nameservice/Makefile index 4c9aba37a8f..f7df0b79ae7 100644 --- a/jdk/make/sun/net/spi/nameservice/Makefile +++ b/jdk/make/sun/net/spi/nameservice/Makefile @@ -27,6 +27,8 @@ BUILDDIR = ../../../.. include $(BUILDDIR)/common/Defs.gmk SUBDIRS = dns +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/sun/nio/Makefile b/jdk/make/sun/nio/Makefile index 76051c1b17a..538c0bc37bb 100644 --- a/jdk/make/sun/nio/Makefile +++ b/jdk/make/sun/nio/Makefile @@ -29,6 +29,8 @@ PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk SUBDIRS = cs +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/sun/org/Makefile b/jdk/make/sun/org/Makefile index 7d3496aa95b..ddfb2c5fcf5 100644 --- a/jdk/make/sun/org/Makefile +++ b/jdk/make/sun/org/Makefile @@ -32,6 +32,8 @@ PRODUCT = org include $(BUILDDIR)/common/Defs.gmk SUBDIRS = mozilla +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/sun/org/mozilla/Makefile b/jdk/make/sun/org/mozilla/Makefile index 47f467f16ac..2eadf61de0c 100644 --- a/jdk/make/sun/org/mozilla/Makefile +++ b/jdk/make/sun/org/mozilla/Makefile @@ -32,6 +32,8 @@ PRODUCT = org include $(BUILDDIR)/common/Defs.gmk SUBDIRS = javascript +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/sun/rmi/Makefile b/jdk/make/sun/rmi/Makefile index 59179b0c0f0..3acbd21de39 100644 --- a/jdk/make/sun/rmi/Makefile +++ b/jdk/make/sun/rmi/Makefile @@ -43,6 +43,8 @@ ifeq ($(PLATFORM), windows) SUBDIRS += cgi endif # PLATFORM +include $(BUILDDIR)/common/Subdirs.gmk + # Then do the rest all build clean clobber :: $(SUBDIRS-loop) diff --git a/jdk/make/sun/security/Makefile b/jdk/make/sun/security/Makefile index 92371cc60cb..1950c892623 100644 --- a/jdk/make/sun/security/Makefile +++ b/jdk/make/sun/security/Makefile @@ -67,8 +67,10 @@ ifdef DISABLE_INTREE_EC INTREE_EC = endif -SUBDIRS = $(INTREE_EC) other action util tools jgss krb5 smartcardio \ - $(PKCS11) $(JGSS_WRAPPER) $(MSCAPI) +SUBDIRS = $(INTREE_EC) other action util krb5 +SUBDIRS_misc = jgss $(PKCS11) $(JGSS_WRAPPER) $(MSCAPI) smartcardio +SUBDIRS_tools = tools +include $(BUILDDIR)/common/Subdirs.gmk all build clean clobber:: $(SUBDIRS-loop) diff --git a/jdk/make/sun/tracing/Makefile b/jdk/make/sun/tracing/Makefile index 5c3711f0054..f9f4439cdeb 100644 --- a/jdk/make/sun/tracing/Makefile +++ b/jdk/make/sun/tracing/Makefile @@ -33,6 +33,8 @@ PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk SUBDIRS = dtrace +include $(BUILDDIR)/common/Subdirs.gmk + all build: $(SUBDIRS-loop) clean clobber:: diff --git a/jdk/make/tools/Makefile b/jdk/make/tools/Makefile index d92550cdd95..24c0fb19cb6 100644 --- a/jdk/make/tools/Makefile +++ b/jdk/make/tools/Makefile @@ -56,6 +56,8 @@ ifndef DISABLE_NIMBUS SUBDIRS += generate_nimbus endif +include $(BUILDDIR)/common/Subdirs.gmk + all build clean clobber:: $(SUBDIRS-loop) From 52b92d5593c491a394d94b1a437a3ee0254ac55d Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Thu, 11 Feb 2010 15:52:19 -0800 Subject: [PATCH 16/31] 6923991: G1: improve scalability of RSet scanning Implemented block-based work stealing. Moved copying during the rset scanning phase to the main copying phase. Made the size of rset table depend on the region size. Reviewed-by: apetrusenko, tonyp --- .../gc_implementation/g1/g1CollectedHeap.cpp | 33 ++-- .../gc_implementation/g1/g1CollectedHeap.hpp | 24 +-- .../g1/g1CollectorPolicy.cpp | 1 + .../vm/gc_implementation/g1/g1OopClosures.hpp | 26 +++- .../g1/g1OopClosures.inline.hpp | 13 ++ .../vm/gc_implementation/g1/g1RemSet.cpp | 61 +++----- .../vm/gc_implementation/g1/g1_globals.hpp | 20 ++- .../g1/g1_specialized_oop_closures.hpp | 6 +- .../gc_implementation/g1/heapRegionRemSet.cpp | 35 +++-- .../gc_implementation/g1/heapRegionRemSet.hpp | 17 ++- .../vm/gc_implementation/g1/sparsePRT.cpp | 143 ++++++++++-------- .../vm/gc_implementation/g1/sparsePRT.hpp | 38 +++-- .../src/share/vm/memory/cardTableModRefBS.hpp | 10 ++ .../share/vm/utilities/globalDefinitions.hpp | 4 + 14 files changed, 263 insertions(+), 168 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 0c73f4d6c67..9b2b71292d8 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -2646,6 +2646,13 @@ G1CollectedHeap::cleanup_surviving_young_words() { // +struct PrepareForRSScanningClosure : public HeapRegionClosure { + bool doHeapRegion(HeapRegion *r) { + r->rem_set()->set_iter_claimed(0); + return false; + } +}; + void G1CollectedHeap::do_collection_pause_at_safepoint() { if (PrintHeapAtGC) { @@ -2784,6 +2791,8 @@ G1CollectedHeap::do_collection_pause_at_safepoint() { gclog_or_tty->print_cr("\nAfter pause, heap:"); print(); #endif + PrepareForRSScanningClosure prepare_for_rs_scan; + collection_set_iterate(&prepare_for_rs_scan); setup_surviving_young_words(); @@ -3781,22 +3790,16 @@ oop G1ParCopyHelper::copy_to_survivor_space(oop old) { return obj; } -template +template template -void G1ParCopyClosure +void G1ParCopyClosure ::do_oop_work(T* p) { oop obj = oopDesc::load_decode_heap_oop(p); assert(barrier != G1BarrierRS || obj != NULL, "Precondition: G1BarrierRS implies obj is nonNull"); - // The only time we skip the cset test is when we're scanning - // references popped from the queue. And we only push on the queue - // references that we know point into the cset, so no point in - // checking again. But we'll leave an assert here for peace of mind. - assert(!skip_cset_test || _g1->obj_in_cs(obj), "invariant"); - // here the null check is implicit in the cset_fast_test() test - if (skip_cset_test || _g1->in_cset_fast_test(obj)) { + if (_g1->in_cset_fast_test(obj)) { #if G1_REM_SET_LOGGING gclog_or_tty->print_cr("Loc "PTR_FORMAT" contains pointer "PTR_FORMAT" " "into CS.", p, (void*) obj); @@ -3813,7 +3816,6 @@ void G1ParCopyClosure update_rs(_from, p, _par_scan_state->queue_num()); } @@ -3823,8 +3825,8 @@ void G1ParCopyClosure ::do_oop_work(oop* p); -template void G1ParCopyClosure::do_oop_work(narrowOop* p); +template void G1ParCopyClosure::do_oop_work(oop* p); +template void G1ParCopyClosure::do_oop_work(narrowOop* p); template void G1ParScanPartialArrayClosure::do_oop_nv(T* p) { assert(has_partial_array_mask(p), "invariant"); @@ -3896,11 +3898,11 @@ public: assert(UseCompressedOops, "Error"); narrowOop* p = (narrowOop*) stolen_task; assert(has_partial_array_mask(p) || - _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "Error"); + _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "Error"); pss->push_on_queue(p); } else { oop* p = (oop*) stolen_task; - assert(has_partial_array_mask(p) || _g1h->obj_in_cs(*p), "Error"); + assert(has_partial_array_mask(p) || _g1h->is_in_g1_reserved(*p), "Error"); pss->push_on_queue(p); } continue; @@ -3962,6 +3964,7 @@ public: G1ParScanExtRootClosure only_scan_root_cl(_g1h, &pss); G1ParScanPermClosure only_scan_perm_cl(_g1h, &pss); G1ParScanHeapRSClosure only_scan_heap_rs_cl(_g1h, &pss); + G1ParPushHeapRSClosure push_heap_rs_cl(_g1h, &pss); G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss); G1ParScanAndMarkPermClosure scan_mark_perm_cl(_g1h, &pss); @@ -3985,7 +3988,7 @@ public: _g1h->g1_process_strong_roots(/* not collecting perm */ false, SharedHeap::SO_AllClasses, scan_root_cl, - &only_scan_heap_rs_cl, + &push_heap_rs_cl, scan_so_cl, scan_perm_cl, i); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 51325935385..692b3e7f32a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -1623,7 +1623,7 @@ public: template void push_on_queue(T* ref) { assert(ref != NULL, "invariant"); assert(has_partial_array_mask(ref) || - _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(ref)), "invariant"); + _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(ref)), "invariant"); #ifdef ASSERT if (has_partial_array_mask(ref)) { oop p = clear_partial_array_mask(ref); @@ -1644,9 +1644,9 @@ public: assert((oop*)ref != NULL, "pop_local() returned true"); assert(UseCompressedOops || !ref.is_narrow(), "Error"); assert(has_partial_array_mask((oop*)ref) || - _g1h->obj_in_cs(ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)ref) - : oopDesc::load_decode_heap_oop((oop*)ref)), - "invariant"); + _g1h->is_in_g1_reserved(ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)ref) + : oopDesc::load_decode_heap_oop((oop*)ref)), + "invariant"); IF_G1_DETAILED_STATS(note_pop()); } else { StarTask null_task; @@ -1659,9 +1659,9 @@ public: assert((oop*)new_ref != NULL, "pop() from a local non-empty stack"); assert(UseCompressedOops || !new_ref.is_narrow(), "Error"); assert(has_partial_array_mask((oop*)new_ref) || - _g1h->obj_in_cs(new_ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)new_ref) - : oopDesc::load_decode_heap_oop((oop*)new_ref)), - "invariant"); + _g1h->is_in_g1_reserved(new_ref.is_narrow() ? oopDesc::load_decode_heap_oop((narrowOop*)new_ref) + : oopDesc::load_decode_heap_oop((oop*)new_ref)), + "invariant"); ref = new_ref; } @@ -1825,12 +1825,12 @@ public: assert(UseCompressedOops, "Error"); narrowOop* p = (narrowOop*)ref_to_scan; assert(!has_partial_array_mask(p) && - _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity"); + _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity"); deal_with_reference(p); } else { oop* p = (oop*)ref_to_scan; - assert((has_partial_array_mask(p) && _g1h->obj_in_cs(clear_partial_array_mask(p))) || - _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity"); + assert((has_partial_array_mask(p) && _g1h->is_in_g1_reserved(clear_partial_array_mask(p))) || + _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity"); deal_with_reference(p); } } @@ -1844,12 +1844,12 @@ public: assert(UseCompressedOops, "Error"); narrowOop* p = (narrowOop*)ref_to_scan; assert(!has_partial_array_mask(p) && - _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity"); + _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity"); deal_with_reference(p); } else { oop* p = (oop*)ref_to_scan; assert((has_partial_array_mask(p) && _g1h->obj_in_cs(clear_partial_array_mask(p))) || - _g1h->obj_in_cs(oopDesc::load_decode_heap_oop(p)), "sanity"); + _g1h->is_in_g1_reserved(oopDesc::load_decode_heap_oop(p)), "sanity"); deal_with_reference(p); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 487fb6d954a..7702c788f21 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -205,6 +205,7 @@ G1CollectorPolicy::G1CollectorPolicy() : // policy is created before the heap, we have to set this up here, // so it's done as soon as possible. HeapRegion::setup_heap_region_size(Arguments::min_heap_size()); + HeapRegionRemSet::setup_remset_size(); _recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime()); _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp index f710203a1e9..fa143ba9bb3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp @@ -53,6 +53,15 @@ public: bool apply_to_weak_ref_discovered_field() { return true; } }; +class G1ParPushHeapRSClosure : public G1ParClosureSuper { +public: + G1ParPushHeapRSClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : + G1ParClosureSuper(g1, par_scan_state) { } + template void do_oop_nv(T* p); + virtual void do_oop(oop* p) { do_oop_nv(p); } + virtual void do_oop(narrowOop* p) { do_oop_nv(p); } +}; + class G1ParScanClosure : public G1ParClosureSuper { public: G1ParScanClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) : @@ -100,7 +109,7 @@ public: }; template + bool do_mark_forwardee> class G1ParCopyClosure : public G1ParCopyHelper { G1ParScanClosure _scanner; template void do_oop_work(T* p); @@ -116,12 +125,13 @@ public: virtual void do_oop(narrowOop* p) { do_oop_nv(p); } }; -typedef G1ParCopyClosure G1ParScanExtRootClosure; -typedef G1ParCopyClosure G1ParScanPermClosure; -typedef G1ParCopyClosure G1ParScanHeapRSClosure; -typedef G1ParCopyClosure G1ParScanAndMarkExtRootClosure; -typedef G1ParCopyClosure G1ParScanAndMarkPermClosure; -typedef G1ParCopyClosure G1ParScanAndMarkHeapRSClosure; +typedef G1ParCopyClosure G1ParScanExtRootClosure; +typedef G1ParCopyClosure G1ParScanPermClosure; +typedef G1ParCopyClosure G1ParScanHeapRSClosure; +typedef G1ParCopyClosure G1ParScanAndMarkExtRootClosure; +typedef G1ParCopyClosure G1ParScanAndMarkPermClosure; +typedef G1ParCopyClosure G1ParScanAndMarkHeapRSClosure; + // This is the only case when we set skip_cset_test. Basically, this // closure is (should?) only be called directly while we're draining // the overflow and task queues. In that case we know that the @@ -132,7 +142,7 @@ typedef G1ParCopyClosure G1ParScanAndMarkHea // We need a separate closure to handle references during evacuation // failure processing, as we cannot asume that the reference already // points into the collection set (like G1ParScanHeapEvacClosure does). -typedef G1ParCopyClosure G1ParScanHeapEvacFailureClosure; +typedef G1ParCopyClosure G1ParScanHeapEvacFailureClosure; class FilterIntoCSClosure: public OopClosure { G1CollectedHeap* _g1; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp index 2ba92a7f8d3..32697da3648 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp @@ -104,3 +104,16 @@ template inline void G1ParScanClosure::do_oop_nv(T* p) { } } } + +template inline void G1ParPushHeapRSClosure::do_oop_nv(T* p) { + T heap_oop = oopDesc::load_heap_oop(p); + + if (!oopDesc::is_null(heap_oop)) { + oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); + if (_g1->in_cset_fast_test(obj)) { + Prefetch::write(obj->mark_addr(), 0); + Prefetch::read(obj->mark_addr(), (HeapWordSize*2)); + _par_scan_state->push_on_queue(p); + } + } +} diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index 224263e54ea..fa8916e52c5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -155,8 +155,8 @@ class ScanRSClosure : public HeapRegionClosure { G1BlockOffsetSharedArray* _bot_shared; CardTableModRefBS *_ct_bs; int _worker_i; + int _block_size; bool _try_claimed; - size_t _min_skip_distance, _max_skip_distance; public: ScanRSClosure(OopsInHeapRegionClosure* oc, int worker_i) : _oc(oc), @@ -168,8 +168,7 @@ public: _g1h = G1CollectedHeap::heap(); _bot_shared = _g1h->bot_shared(); _ct_bs = (CardTableModRefBS*) (_g1h->barrier_set()); - _min_skip_distance = 16; - _max_skip_distance = 2 * _g1h->n_par_threads() * _min_skip_distance; + _block_size = MAX2(G1RSetScanBlockSize, 1); } void set_try_claimed() { _try_claimed = true; } @@ -225,12 +224,15 @@ public: HeapRegionRemSetIterator* iter = _g1h->rem_set_iterator(_worker_i); hrrs->init_iterator(iter); size_t card_index; - size_t skip_distance = 0, current_card = 0, jump_to_card = 0; - while (iter->has_next(card_index)) { - if (current_card < jump_to_card) { - ++current_card; - continue; + + // We claim cards in block so as to recude the contention. The block size is determined by + // the G1RSetScanBlockSize parameter. + size_t jump_to_card = hrrs->iter_claimed_next(_block_size); + for (size_t current_card = 0; iter->has_next(card_index); current_card++) { + if (current_card >= jump_to_card + _block_size) { + jump_to_card = hrrs->iter_claimed_next(_block_size); } + if (current_card < jump_to_card) continue; HeapWord* card_start = _g1h->bot_shared()->address_for_index(card_index); #if 0 gclog_or_tty->print("Rem set iteration yielded card [" PTR_FORMAT ", " PTR_FORMAT ").\n", @@ -247,22 +249,14 @@ public: // If the card is dirty, then we will scan it during updateRS. if (!card_region->in_collection_set() && !_ct_bs->is_card_dirty(card_index)) { - if (!_ct_bs->is_card_claimed(card_index) && _ct_bs->claim_card(card_index)) { - scanCard(card_index, card_region); - } else if (_try_claimed) { - if (jump_to_card == 0 || jump_to_card != current_card) { - // We did some useful work in the previous iteration. - // Decrease the distance. - skip_distance = MAX2(skip_distance >> 1, _min_skip_distance); - } else { - // Previous iteration resulted in a claim failure. - // Increase the distance. - skip_distance = MIN2(skip_distance << 1, _max_skip_distance); - } - jump_to_card = current_card + skip_distance; - } + // We make the card as "claimed" lazily (so races are possible but they're benign), + // which reduces the number of duplicate scans (the rsets of the regions in the cset + // can intersect). + if (!_ct_bs->is_card_claimed(card_index)) { + _ct_bs->set_card_claimed(card_index); + scanCard(card_index, card_region); + } } - ++current_card; } if (!_try_claimed) { hrrs->set_iter_complete(); @@ -299,30 +293,18 @@ void HRInto_G1RemSet::scanRS(OopsInHeapRegionClosure* oc, int worker_i) { double rs_time_start = os::elapsedTime(); HeapRegion *startRegion = calculateStartRegion(worker_i); - BufferingOopsInHeapRegionClosure boc(oc); - ScanRSClosure scanRScl(&boc, worker_i); + ScanRSClosure scanRScl(oc, worker_i); _g1->collection_set_iterate_from(startRegion, &scanRScl); scanRScl.set_try_claimed(); _g1->collection_set_iterate_from(startRegion, &scanRScl); - boc.done(); - double closure_app_time_sec = boc.closure_app_seconds(); - double scan_rs_time_sec = (os::elapsedTime() - rs_time_start) - - closure_app_time_sec; - double closure_app_time_ms = closure_app_time_sec * 1000.0; + double scan_rs_time_sec = os::elapsedTime() - rs_time_start; assert( _cards_scanned != NULL, "invariant" ); _cards_scanned[worker_i] = scanRScl.cards_done(); _g1p->record_scan_rs_start_time(worker_i, rs_time_start * 1000.0); _g1p->record_scan_rs_time(worker_i, scan_rs_time_sec * 1000.0); - - double scan_new_refs_time_ms = _g1p->get_scan_new_refs_time(worker_i); - if (scan_new_refs_time_ms > 0.0) { - closure_app_time_ms += scan_new_refs_time_ms; - } - - _g1p->record_obj_copy_time(worker_i, closure_app_time_ms); } void HRInto_G1RemSet::updateRS(int worker_i) { @@ -449,9 +431,8 @@ HRInto_G1RemSet::scanNewRefsRS_work(OopsInHeapRegionClosure* oc, oc->do_oop(p); } } - _g1p->record_scan_new_refs_time(worker_i, - (os::elapsedTime() - scan_new_refs_start_sec) - * 1000.0); + double scan_new_refs_time_ms = (os::elapsedTime() - scan_new_refs_start_sec) * 1000.0; + _g1p->record_scan_new_refs_time(worker_i, scan_new_refs_time_ms); } void HRInto_G1RemSet::cleanupHRRS() { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp index 4e6ce1361bd..7e084731a2d 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp @@ -207,8 +207,20 @@ develop(bool, G1PrintOopAppls, false, \ "When true, print applications of closures to external locs.") \ \ - develop(intx, G1LogRSRegionEntries, 7, \ - "Log_2 of max number of regions for which we keep bitmaps.") \ + develop(intx, G1RSetRegionEntriesBase, 256, \ + "Max number of regions in a fine-grain table per MB.") \ + \ + product(intx, G1RSetRegionEntries, 0, \ + "Max number of regions for which we keep bitmaps." \ + "Will be set ergonomically by default") \ + \ + develop(intx, G1RSetSparseRegionEntriesBase, 4, \ + "Max number of entries per region in a sparse table " \ + "per MB.") \ + \ + product(intx, G1RSetSparseRegionEntries, 0, \ + "Max number of entries per region in a sparse table." \ + "Will be set ergonomically by default.") \ \ develop(bool, G1RecordHRRSOops, false, \ "When true, record recent calls to rem set operations.") \ @@ -293,6 +305,10 @@ develop(bool, G1VerifyCTCleanup, false, \ "Verify card table cleanup.") \ \ + product(uintx, G1RSetScanBlockSize, 64, \ + "Size of a work unit of cards claimed by a worker thread" \ + "during RSet scanning.") \ + \ develop(bool, ReduceInitialCardMarksForG1, false, \ "When ReduceInitialCardMarks is true, this flag setting " \ " controls whether G1 allows the RICM optimization") diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp index 101d330077e..266bbb5abdc 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp @@ -33,11 +33,12 @@ enum G1Barrier { }; template + bool do_mark_forwardee> class G1ParCopyClosure; class G1ParScanClosure; +class G1ParPushHeapRSClosure; -typedef G1ParCopyClosure G1ParScanHeapEvacClosure; +typedef G1ParCopyClosure G1ParScanHeapEvacClosure; class FilterIntoCSClosure; class FilterOutOfRegionClosure; @@ -51,6 +52,7 @@ class FilterAndMarkInHeapRegionAndIntoCSClosure; #define FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES(f) \ f(G1ParScanHeapEvacClosure,_nv) \ f(G1ParScanClosure,_nv) \ + f(G1ParPushHeapRSClosure,_nv) \ f(FilterIntoCSClosure,_nv) \ f(FilterOutOfRegionClosure,_nv) \ f(FilterInHeapRegionAndIntoCSClosure,_nv) \ diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp index aac289e67d6..883b2b1ef26 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp @@ -505,12 +505,13 @@ OtherRegionsTable::OtherRegionsTable(HeapRegion* hr) : typedef PosParPRT* PosParPRTPtr; if (_max_fine_entries == 0) { assert(_mod_max_fine_entries_mask == 0, "Both or none."); - _max_fine_entries = (size_t)(1 << G1LogRSRegionEntries); + size_t max_entries_log = (size_t)log2_long((jlong)G1RSetRegionEntries); + _max_fine_entries = (size_t)(1 << max_entries_log); _mod_max_fine_entries_mask = _max_fine_entries - 1; #if SAMPLE_FOR_EVICTION assert(_fine_eviction_sample_size == 0 && _fine_eviction_stride == 0, "All init at same time."); - _fine_eviction_sample_size = MAX2((size_t)4, (size_t)G1LogRSRegionEntries); + _fine_eviction_sample_size = MAX2((size_t)4, max_entries_log); _fine_eviction_stride = _max_fine_entries / _fine_eviction_sample_size; #endif } @@ -655,13 +656,6 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, int tid) { #endif } - // Otherwise, transfer from sparse to fine-grain. - CardIdx_t cards[SparsePRTEntry::CardsPerEntry]; - if (G1HRRSUseSparseTable) { - bool res = _sparse_table.get_cards(from_hrs_ind, &cards[0]); - assert(res, "There should have been an entry"); - } - if (_n_fine_entries == _max_fine_entries) { prt = delete_region_table(); } else { @@ -676,10 +670,12 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, int tid) { _fine_grain_regions[ind] = prt; _n_fine_entries++; - // Add in the cards from the sparse table. if (G1HRRSUseSparseTable) { - for (int i = 0; i < SparsePRTEntry::CardsPerEntry; i++) { - CardIdx_t c = cards[i]; + // Transfer from sparse to fine-grain. + SparsePRTEntry *sprt_entry = _sparse_table.get_entry(from_hrs_ind); + assert(sprt_entry != NULL, "There should have been an entry"); + for (int i = 0; i < SparsePRTEntry::cards_num(); i++) { + CardIdx_t c = sprt_entry->card(i); if (c != SparsePRTEntry::NullEntry) { prt->add_card(c); } @@ -1084,6 +1080,19 @@ HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa, {} +void HeapRegionRemSet::setup_remset_size() { + // Setup sparse and fine-grain tables sizes. + // table_size = base * (log(region_size / 1M) + 1) + int region_size_log_mb = MAX2((int)HeapRegion::LogOfHRGrainBytes - (int)LOG_M, 0); + if (FLAG_IS_DEFAULT(G1RSetSparseRegionEntries)) { + G1RSetSparseRegionEntries = G1RSetSparseRegionEntriesBase * (region_size_log_mb + 1); + } + if (FLAG_IS_DEFAULT(G1RSetRegionEntries)) { + G1RSetRegionEntries = G1RSetRegionEntriesBase * (region_size_log_mb + 1); + } + guarantee(G1RSetSparseRegionEntries > 0 && G1RSetRegionEntries > 0 , "Sanity"); +} + void HeapRegionRemSet::init_for_par_iteration() { _iter_state = Unclaimed; } @@ -1399,7 +1408,7 @@ void HeapRegionRemSet::test() { os::sleep(Thread::current(), (jlong)5000, false); G1CollectedHeap* g1h = G1CollectedHeap::heap(); - // Run with "-XX:G1LogRSRegionEntries=2", so that 1 and 5 end up in same + // Run with "-XX:G1LogRSetRegionEntries=2", so that 1 and 5 end up in same // hash bucket. HeapRegion* hr0 = g1h->region_at(0); HeapRegion* hr1 = g1h->region_at(1); diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp index d525b5ad306..c51286290af 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp @@ -187,7 +187,8 @@ private: void clear_outgoing_entries(); enum ParIterState { Unclaimed, Claimed, Complete }; - ParIterState _iter_state; + volatile ParIterState _iter_state; + volatile jlong _iter_claimed; // Unused unless G1RecordHRRSOops is true. @@ -209,6 +210,7 @@ public: HeapRegion* hr); static int num_par_rem_sets(); + static void setup_remset_size(); HeapRegion* hr() const { return _other_regions.hr(); @@ -272,6 +274,19 @@ public: // Returns "true" iff the region's iteration is complete. bool iter_is_complete(); + // Support for claiming blocks of cards during iteration + void set_iter_claimed(size_t x) { _iter_claimed = (jlong)x; } + size_t iter_claimed() const { return (size_t)_iter_claimed; } + // Claim the next block of cards + size_t iter_claimed_next(size_t step) { + size_t current, next; + do { + current = iter_claimed(); + next = current + step; + } while (Atomic::cmpxchg((jlong)next, &_iter_claimed, (jlong)current) != (jlong)current); + return current; + } + // Initialize the given iterator to iterate over this rem set. void init_iterator(HeapRegionRemSetIterator* iter) const; diff --git a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp index cef8297a367..c6b835b3513 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp @@ -27,7 +27,7 @@ #define SPARSE_PRT_VERBOSE 0 -#define UNROLL_CARD_LOOPS 1 +#define UNROLL_CARD_LOOPS 1 void SparsePRT::init_iterator(SparsePRTIter* sprt_iter) { sprt_iter->init(this); @@ -36,27 +36,32 @@ void SparsePRT::init_iterator(SparsePRTIter* sprt_iter) { void SparsePRTEntry::init(RegionIdx_t region_ind) { _region_ind = region_ind; _next_index = NullEntry; + #if UNROLL_CARD_LOOPS - assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll."); - _cards[0] = NullEntry; - _cards[1] = NullEntry; - _cards[2] = NullEntry; - _cards[3] = NullEntry; + assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); + for (int i = 0; i < cards_num(); i += UnrollFactor) { + _cards[i] = NullEntry; + _cards[i + 1] = NullEntry; + _cards[i + 2] = NullEntry; + _cards[i + 3] = NullEntry; + } #else - for (int i = 0; i < CardsPerEntry; i++) + for (int i = 0; i < cards_num(); i++) _cards[i] = NullEntry; #endif } bool SparsePRTEntry::contains_card(CardIdx_t card_index) const { #if UNROLL_CARD_LOOPS - assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll."); - if (_cards[0] == card_index) return true; - if (_cards[1] == card_index) return true; - if (_cards[2] == card_index) return true; - if (_cards[3] == card_index) return true; + assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); + for (int i = 0; i < cards_num(); i += UnrollFactor) { + if (_cards[i] == card_index || + _cards[i + 1] == card_index || + _cards[i + 2] == card_index || + _cards[i + 3] == card_index) return true; + } #else - for (int i = 0; i < CardsPerEntry; i++) { + for (int i = 0; i < cards_num(); i++) { if (_cards[i] == card_index) return true; } #endif @@ -67,14 +72,16 @@ bool SparsePRTEntry::contains_card(CardIdx_t card_index) const { int SparsePRTEntry::num_valid_cards() const { int sum = 0; #if UNROLL_CARD_LOOPS - assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll."); - if (_cards[0] != NullEntry) sum++; - if (_cards[1] != NullEntry) sum++; - if (_cards[2] != NullEntry) sum++; - if (_cards[3] != NullEntry) sum++; + assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); + for (int i = 0; i < cards_num(); i += UnrollFactor) { + sum += (_cards[i] != NullEntry); + sum += (_cards[i + 1] != NullEntry); + sum += (_cards[i + 2] != NullEntry); + sum += (_cards[i + 3] != NullEntry); + } #else - for (int i = 0; i < CardsPerEntry; i++) { - if (_cards[i] != NulLEntry) sum++; + for (int i = 0; i < cards_num(); i++) { + sum += (_cards[i] != NullEntry); } #endif // Otherwise, we're full. @@ -83,27 +90,27 @@ int SparsePRTEntry::num_valid_cards() const { SparsePRTEntry::AddCardResult SparsePRTEntry::add_card(CardIdx_t card_index) { #if UNROLL_CARD_LOOPS - assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll."); - CardIdx_t c = _cards[0]; - if (c == card_index) return found; - if (c == NullEntry) { _cards[0] = card_index; return added; } - c = _cards[1]; - if (c == card_index) return found; - if (c == NullEntry) { _cards[1] = card_index; return added; } - c = _cards[2]; - if (c == card_index) return found; - if (c == NullEntry) { _cards[2] = card_index; return added; } - c = _cards[3]; - if (c == card_index) return found; - if (c == NullEntry) { _cards[3] = card_index; return added; } + assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); + CardIdx_t c; + for (int i = 0; i < cards_num(); i += UnrollFactor) { + c = _cards[i]; + if (c == card_index) return found; + if (c == NullEntry) { _cards[i] = card_index; return added; } + c = _cards[i + 1]; + if (c == card_index) return found; + if (c == NullEntry) { _cards[i + 1] = card_index; return added; } + c = _cards[i + 2]; + if (c == card_index) return found; + if (c == NullEntry) { _cards[i + 2] = card_index; return added; } + c = _cards[i + 3]; + if (c == card_index) return found; + if (c == NullEntry) { _cards[i + 3] = card_index; return added; } + } #else - for (int i = 0; i < CardsPerEntry; i++) { + for (int i = 0; i < cards_num(); i++) { CardIdx_t c = _cards[i]; if (c == card_index) return found; - if (c == NullEntry) { - _cards[i] = card_index; - return added; - } + if (c == NullEntry) { _cards[i] = card_index; return added; } } #endif // Otherwise, we're full. @@ -112,13 +119,15 @@ SparsePRTEntry::AddCardResult SparsePRTEntry::add_card(CardIdx_t card_index) { void SparsePRTEntry::copy_cards(CardIdx_t* cards) const { #if UNROLL_CARD_LOOPS - assert(CardsPerEntry == 4, "Assumption. If changes, un-unroll."); - cards[0] = _cards[0]; - cards[1] = _cards[1]; - cards[2] = _cards[2]; - cards[3] = _cards[3]; + assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); + for (int i = 0; i < cards_num(); i += UnrollFactor) { + cards[i] = _cards[i]; + cards[i + 1] = _cards[i + 1]; + cards[i + 2] = _cards[i + 2]; + cards[i + 3] = _cards[i + 3]; + } #else - for (int i = 0; i < CardsPerEntry; i++) { + for (int i = 0; i < cards_num(); i++) { cards[i] = _cards[i]; } #endif @@ -133,7 +142,7 @@ void SparsePRTEntry::copy_cards(SparsePRTEntry* e) const { RSHashTable::RSHashTable(size_t capacity) : _capacity(capacity), _capacity_mask(capacity-1), _occupied_entries(0), _occupied_cards(0), - _entries(NEW_C_HEAP_ARRAY(SparsePRTEntry, capacity)), + _entries((SparsePRTEntry*)NEW_C_HEAP_ARRAY(char, SparsePRTEntry::size() * capacity)), _buckets(NEW_C_HEAP_ARRAY(int, capacity)), _free_list(NullEntry), _free_region(0) { @@ -161,8 +170,8 @@ void RSHashTable::clear() { "_capacity too large"); // This will put -1 == NullEntry in the key field of all entries. - memset(_entries, -1, _capacity * sizeof(SparsePRTEntry)); - memset(_buckets, -1, _capacity * sizeof(int)); + memset(_entries, NullEntry, _capacity * SparsePRTEntry::size()); + memset(_buckets, NullEntry, _capacity * sizeof(int)); _free_list = NullEntry; _free_region = 0; } @@ -175,8 +184,8 @@ bool RSHashTable::add_card(RegionIdx_t region_ind, CardIdx_t card_index) { if (res == SparsePRTEntry::added) _occupied_cards++; #if SPARSE_PRT_VERBOSE gclog_or_tty->print_cr(" after add_card[%d]: valid-cards = %d.", - pointer_delta(e, _entries, sizeof(SparsePRTEntry)), - e->num_valid_cards()); + pointer_delta(e, _entries, SparsePRTEntry::size()), + e->num_valid_cards()); #endif assert(e->num_valid_cards() > 0, "Postcondition"); return res != SparsePRTEntry::overflow; @@ -199,6 +208,22 @@ bool RSHashTable::get_cards(RegionIdx_t region_ind, CardIdx_t* cards) { return true; } +SparsePRTEntry* RSHashTable::get_entry(RegionIdx_t region_ind) { + int ind = (int) (region_ind & capacity_mask()); + int cur_ind = _buckets[ind]; + SparsePRTEntry* cur; + while (cur_ind != NullEntry && + (cur = entry(cur_ind))->r_ind() != region_ind) { + cur_ind = cur->next_index(); + } + + if (cur_ind == NullEntry) return NULL; + // Otherwise... + assert(cur->r_ind() == region_ind, "Postcondition of loop + test above."); + assert(cur->num_valid_cards() > 0, "Inv"); + return cur; +} + bool RSHashTable::delete_entry(RegionIdx_t region_ind) { int ind = (int) (region_ind & capacity_mask()); int* prev_loc = &_buckets[ind]; @@ -225,20 +250,8 @@ RSHashTable::entry_for_region_ind(RegionIdx_t region_ind) const { int ind = (int) (region_ind & capacity_mask()); int cur_ind = _buckets[ind]; SparsePRTEntry* cur; - // XXX - // int k = 0; while (cur_ind != NullEntry && (cur = entry(cur_ind))->r_ind() != region_ind) { - /* - k++; - if (k > 10) { - gclog_or_tty->print_cr("RSHashTable::entry_for_region_ind(%d): " - "k = %d, cur_ind = %d.", region_ind, k, cur_ind); - if (k >= 1000) { - while (1) ; - } - } - */ cur_ind = cur->next_index(); } @@ -319,7 +332,7 @@ size_t /* RSHashTable:: */ RSHashTableIter::compute_card_ind(CardIdx_t ci) { bool /* RSHashTable:: */ RSHashTableIter::has_next(size_t& card_index) { _card_ind++; CardIdx_t ci; - if (_card_ind < SparsePRTEntry::CardsPerEntry && + if (_card_ind < SparsePRTEntry::cards_num() && ((ci = _rsht->entry(_bl_ind)->card(_card_ind)) != SparsePRTEntry::NullEntry)) { card_index = compute_card_ind(ci); @@ -359,7 +372,7 @@ bool RSHashTable::contains_card(RegionIdx_t region_index, CardIdx_t card_index) size_t RSHashTable::mem_size() const { return sizeof(this) + - capacity() * (sizeof(SparsePRTEntry) + sizeof(int)); + capacity() * (SparsePRTEntry::size() + sizeof(int)); } // ---------------------------------------------------------------------- @@ -446,6 +459,10 @@ bool SparsePRT::get_cards(RegionIdx_t region_id, CardIdx_t* cards) { return _next->get_cards(region_id, cards); } +SparsePRTEntry* SparsePRT::get_entry(RegionIdx_t region_id) { + return _next->get_entry(region_id); +} + bool SparsePRT::delete_entry(RegionIdx_t region_id) { return _next->delete_entry(region_id); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp index c5a39737c52..5c35c69b813 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp @@ -32,21 +32,28 @@ // insertions only enqueue old versions for deletions, but do not delete // old versions synchronously. - class SparsePRTEntry: public CHeapObj { public: - enum SomePublicConstants { - CardsPerEntry = 4, - NullEntry = -1 + NullEntry = -1, + UnrollFactor = 4 }; - private: RegionIdx_t _region_ind; int _next_index; - CardIdx_t _cards[CardsPerEntry]; - + CardIdx_t _cards[1]; + // WARNING: Don't put any data members beyond this line. Card array has, in fact, variable length. + // It should always be the last data member. public: + // Returns the size of the entry, used for entry allocation. + static size_t size() { return sizeof(SparsePRTEntry) + sizeof(CardIdx_t) * (cards_num() - 1); } + // Returns the size of the card array. + static int cards_num() { + // The number of cards should be a multiple of 4, because that's our current + // unrolling factor. + static const int s = MAX2(G1RSetSparseRegionEntries & ~(UnrollFactor - 1), UnrollFactor); + return s; + } // Set the region_ind to the given value, and delete all cards. inline void init(RegionIdx_t region_ind); @@ -134,12 +141,15 @@ public: bool add_card(RegionIdx_t region_id, CardIdx_t card_index); bool get_cards(RegionIdx_t region_id, CardIdx_t* cards); + bool delete_entry(RegionIdx_t region_id); bool contains_card(RegionIdx_t region_id, CardIdx_t card_index) const; void add_entry(SparsePRTEntry* e); + SparsePRTEntry* get_entry(RegionIdx_t region_id); + void clear(); size_t capacity() const { return _capacity; } @@ -148,7 +158,7 @@ public: size_t occupied_cards() const { return _occupied_cards; } size_t mem_size() const; - SparsePRTEntry* entry(int i) const { return &_entries[i]; } + SparsePRTEntry* entry(int i) const { return (SparsePRTEntry*)((char*)_entries + SparsePRTEntry::size() * i); } void print(); }; @@ -157,7 +167,7 @@ public: class RSHashTableIter VALUE_OBJ_CLASS_SPEC { int _tbl_ind; // [-1, 0.._rsht->_capacity) int _bl_ind; // [-1, 0.._rsht->_capacity) - short _card_ind; // [0..CardsPerEntry) + short _card_ind; // [0..SparsePRTEntry::cards_num()) RSHashTable* _rsht; size_t _heap_bot_card_ind; @@ -176,7 +186,7 @@ public: RSHashTableIter(size_t heap_bot_card_ind) : _tbl_ind(RSHashTable::NullEntry), _bl_ind(RSHashTable::NullEntry), - _card_ind((SparsePRTEntry::CardsPerEntry-1)), + _card_ind((SparsePRTEntry::cards_num() - 1)), _rsht(NULL), _heap_bot_card_ind(heap_bot_card_ind) {} @@ -185,7 +195,7 @@ public: _rsht = rsht; _tbl_ind = -1; // So that first increment gets to 0. _bl_ind = RSHashTable::NullEntry; - _card_ind = (SparsePRTEntry::CardsPerEntry-1); + _card_ind = (SparsePRTEntry::cards_num() - 1); } bool has_next(size_t& card_index); @@ -241,9 +251,13 @@ public: // If the table hold an entry for "region_ind", Copies its // cards into "cards", which must be an array of length at least - // "CardsPerEntry", and returns "true"; otherwise, returns "false". + // "SparePRTEntry::cards_num()", and returns "true"; otherwise, + // returns "false". bool get_cards(RegionIdx_t region_ind, CardIdx_t* cards); + // Return the pointer to the entry associated with the given region. + SparsePRTEntry* get_entry(RegionIdx_t region_ind); + // If there is an entry for "region_ind", removes it and return "true"; // otherwise returns "false." bool delete_entry(RegionIdx_t region_ind); diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.hpp b/hotspot/src/share/vm/memory/cardTableModRefBS.hpp index bffdd50926b..02fd91db16a 100644 --- a/hotspot/src/share/vm/memory/cardTableModRefBS.hpp +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.hpp @@ -339,6 +339,16 @@ public: return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val(); } + void set_card_claimed(size_t card_index) { + jbyte val = _byte_map[card_index]; + if (val == clean_card_val()) { + val = (jbyte)claimed_card_val(); + } else { + val |= (jbyte)claimed_card_val(); + } + _byte_map[card_index] = val; + } + bool claim_card(size_t card_index); bool is_card_clean(size_t card_index) { diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp index 32ecd64c880..a83f4ba23e9 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp @@ -139,6 +139,10 @@ const size_t M = K*K; const size_t G = M*K; const size_t HWperKB = K / sizeof(HeapWord); +const size_t LOG_K = 10; +const size_t LOG_M = 2 * LOG_K; +const size_t LOG_G = 2 * LOG_M; + const jint min_jint = (jint)1 << (sizeof(jint)*BitsPerByte-1); // 0x80000000 == smallest jint const jint max_jint = (juint)min_jint - 1; // 0x7FFFFFFF == largest jint From ab8d48e8511370a7533719c60abfa5cc28a72b6b Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Fri, 12 Feb 2010 10:24:02 +0800 Subject: [PATCH 17/31] 6925639: keytool -genkeypair -help missing dname option Reviewed-by: mullan --- jdk/src/share/classes/sun/security/tools/KeyTool.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/sun/security/tools/KeyTool.java b/jdk/src/share/classes/sun/security/tools/KeyTool.java index 9cd0775cb1f..d3031ad77f0 100644 --- a/jdk/src/share/classes/sun/security/tools/KeyTool.java +++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java @@ -151,7 +151,7 @@ public final class KeyTool { enum Command { CERTREQ("Generates a certificate request", - ALIAS, SIGALG, FILEOUT, KEYPASS, KEYSTORE, + ALIAS, SIGALG, FILEOUT, KEYPASS, KEYSTORE, DNAME, STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V, PROTECTED), CHANGEALIAS("Changes an entry's alias", @@ -167,7 +167,7 @@ public final class KeyTool { STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V, PROTECTED), GENKEYPAIR("Generates a key pair", - ALIAS, KEYALG, KEYSIZE, SIGALG, DESTALIAS, + ALIAS, KEYALG, KEYSIZE, SIGALG, DESTALIAS, DNAME, STARTDATE, EXT, VALIDITY, KEYPASS, KEYSTORE, STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V, PROTECTED), @@ -176,7 +176,7 @@ public final class KeyTool { STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V, PROTECTED), GENCERT("Generates certificate from a certificate request", - RFC, INFILE, OUTFILE, ALIAS, SIGALG, + RFC, INFILE, OUTFILE, ALIAS, SIGALG, DNAME, STARTDATE, EXT, VALIDITY, KEYPASS, KEYSTORE, STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG, PROVIDERPATH, V, PROTECTED), From d4437819bd8dabee05bd64c5379fdcc4af1135bf Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 12 Feb 2010 08:54:13 -0800 Subject: [PATCH 18/31] 6925249: assert(last_sp < (intptr_t*) interpreter_frame_monitor_begin(),"bad tos") Fix assert since top deoptimized frame has last_sp == interpreter_frame_monitor_begin if there are no expressions. Reviewed-by: twisti --- hotspot/src/cpu/x86/vm/frame_x86.inline.hpp | 3 ++- hotspot/src/share/vm/runtime/deoptimization.cpp | 15 --------------- hotspot/src/share/vm/runtime/frame.cpp | 8 ++++---- hotspot/src/share/vm/runtime/vframeArray.cpp | 7 +++---- 4 files changed, 9 insertions(+), 24 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp index 809e26cfaa1..bf68ce9270f 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.inline.hpp @@ -233,7 +233,8 @@ inline intptr_t* frame::interpreter_frame_tos_address() const { } else { // sp() may have been extended or shrunk by an adapter. At least // check that we don't fall behind the legal region. - assert(last_sp < (intptr_t*) interpreter_frame_monitor_begin(), "bad tos"); + // For top deoptimized frame last_sp == interpreter_frame_monitor_end. + assert(last_sp <= (intptr_t*) interpreter_frame_monitor_end(), "bad tos"); return last_sp; } } diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index db34edbeefa..d3d60d9152a 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -938,21 +938,6 @@ vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, Re if (TraceDeoptimization) { ttyLocker ttyl; tty->print_cr(" Created vframeArray " INTPTR_FORMAT, array); - if (Verbose) { - int count = 0; - // this used to leak deoptimizedVFrame like it was going out of style!!! - for (int index = 0; index < array->frames(); index++ ) { - vframeArrayElement* e = array->element(index); - e->print(tty); - - /* - No printing yet. - array->vframe_at(index)->print_activation(count++); - // better as... - array->print_activation_for(index, count++); - */ - } - } } #endif // PRODUCT diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index 5844107c5c0..30782f355c6 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -606,12 +606,12 @@ void frame::interpreter_frame_print_on(outputStream* st) const { for (BasicObjectLock* current = interpreter_frame_monitor_end(); current < interpreter_frame_monitor_begin(); current = next_monitor_in_interpreter_frame(current)) { - st->print_cr(" [ - obj "); + st->print(" - obj ["); current->obj()->print_value_on(st); - st->cr(); - st->print_cr(" - lock "); + st->print_cr("]"); + st->print(" - lock ["); current->lock()->print_on(st); - st->cr(); + st->print_cr("]"); } // monitor st->print_cr(" - monitor[" INTPTR_FORMAT "]", interpreter_frame_monitor_begin()); diff --git a/hotspot/src/share/vm/runtime/vframeArray.cpp b/hotspot/src/share/vm/runtime/vframeArray.cpp index 3f507d2174f..6a9aac2efc9 100644 --- a/hotspot/src/share/vm/runtime/vframeArray.cpp +++ b/hotspot/src/share/vm/runtime/vframeArray.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -186,7 +186,7 @@ void vframeArrayElement::unpack_on_stack(int callee_parameters, int popframe_preserved_args_size_in_bytes = 0; int popframe_preserved_args_size_in_words = 0; if (is_top_frame) { - JvmtiThreadState *state = thread->jvmti_thread_state(); + JvmtiThreadState *state = thread->jvmti_thread_state(); if (JvmtiExport::can_pop_frame() && (thread->has_pending_popframe() || thread->popframe_forcing_deopt_reexecution())) { if (thread->has_pending_popframe()) { @@ -381,7 +381,6 @@ void vframeArrayElement::unpack_on_stack(int callee_parameters, RegisterMap map(thread); vframe* f = vframe::new_vframe(iframe(), &map, thread); f->print(); - iframe()->interpreter_frame_print_on(tty); tty->print_cr("locals size %d", locals()->size()); tty->print_cr("expression size %d", expressions()->size()); @@ -582,7 +581,7 @@ void vframeArray::print_on_2(outputStream* st) { } void vframeArrayElement::print(outputStream* st) { - st->print_cr(" - interpreter_frame -> sp: ", INTPTR_FORMAT, iframe()->sp()); + st->print_cr(" - interpreter_frame -> sp: " INTPTR_FORMAT, iframe()->sp()); } void vframeArray::print_value_on(outputStream* st) const { From 2930227188519f965ae5729defa192b9fdface1a Mon Sep 17 00:00:00 2001 From: Dmitry Cherepanov Date: Fri, 12 Feb 2010 19:58:10 +0300 Subject: [PATCH 19/31] 6705345: Enable multiple file selection in AWT FileDialog Reviewed-by: art, anthony, alexp --- .../share/classes/java/awt/FileDialog.java | 117 ++++++- .../share/classes/sun/awt/AWTAccessor.java | 47 +++ .../classes/sun/awt/X11/XFileDialogPeer.java | 25 +- .../sun/awt/windows/WFileDialogPeer.java | 83 +++-- .../native/sun/windows/awt_FileDialog.cpp | 98 +++++- .../native/sun/windows/awt_FileDialog.h | 4 + .../FileDialog/MultipleMode/MultipleMode.html | 20 ++ .../FileDialog/MultipleMode/MultipleMode.java | 289 ++++++++++++++++++ 8 files changed, 639 insertions(+), 44 deletions(-) create mode 100644 jdk/test/java/awt/FileDialog/MultipleMode/MultipleMode.html create mode 100644 jdk/test/java/awt/FileDialog/MultipleMode/MultipleMode.java diff --git a/jdk/src/share/classes/java/awt/FileDialog.java b/jdk/src/share/classes/java/awt/FileDialog.java index 973ba4e16ee..34cd2f8179a 100644 --- a/jdk/src/share/classes/java/awt/FileDialog.java +++ b/jdk/src/share/classes/java/awt/FileDialog.java @@ -28,6 +28,8 @@ import java.awt.peer.FileDialogPeer; import java.io.FilenameFilter; import java.io.IOException; import java.io.ObjectInputStream; +import java.io.File; +import sun.awt.AWTAccessor; /** * The FileDialog class displays a dialog window @@ -93,6 +95,25 @@ public class FileDialog extends Dialog { */ String file; + /** + * Contains the File instances for all the files that the user selects. + * + * @serial + * @see getFiles + * @since 1.7 + */ + private File[] files; + + /** + * Represents whether the file dialog allows the multiple file selection. + * + * @serial + * @see #setMultipleMode + * @see #isMultipleMode + * @since 1.7 + */ + private boolean multipleMode = false; + /* * The filter used as the file dialog's filename filter. * The file dialog will only be displaying files whose @@ -123,6 +144,26 @@ public class FileDialog extends Dialog { } } + static { + AWTAccessor.setFileDialogAccessor( + new AWTAccessor.FileDialogAccessor() { + public void setFiles(FileDialog fileDialog, String directory, String files[]) { + fileDialog.setFiles(directory, files); + } + public void setFile(FileDialog fileDialog, String file) { + fileDialog.file = ("".equals(file)) ? null : file; + } + public void setDirectory(FileDialog fileDialog, String directory) { + fileDialog.dir = ("".equals(directory)) ? null : directory; + } + public boolean isMultipleMode(FileDialog fileDialog) { + synchronized (fileDialog.getObjectLock()) { + return fileDialog.multipleMode; + } + } + }); + } + /** * Initialize JNI field and method IDs for fields that may be accessed from C. @@ -370,6 +411,51 @@ public class FileDialog extends Dialog { return file; } + /** + * Returns files that the user selects. + *

+ * If the user cancels the file dialog, + * then the method returns an empty array. + * + * @return files that the user selects or an empty array + * if the user cancels the file dialog. + * @see #setFile(String) + * @see #getFile + * @since 1.7 + */ + public File[] getFiles() { + synchronized (getObjectLock()) { + if (files != null) { + return files.clone(); + } else { + return new File[0]; + } + } + } + + /** + * Stores the names of all the files that the user selects. + * + * Note that the method is private and it's intended to be used + * by the peers through the AWTAccessor API. + * + * @param directory the current directory + * @param files the array that contains the short names of + * all the files that the user selects. + * + * @see #getFiles + * @since 1.7 + */ + private void setFiles(String directory, String files[]) { + synchronized (getObjectLock()) { + int filesNumber = (files != null) ? files.length : 0; + this.files = new File[filesNumber]; + for (int i = 0; i < filesNumber; i++) { + this.files[i] = new File(directory, files[i]); + } + } + } + /** * Sets the selected file for this file dialog window to be the * specified file. This file becomes the default file if it is set @@ -380,7 +466,8 @@ public class FileDialog extends Dialog { * as the file. * * @param file the file being set - * @see java.awt.FileDialog#getFile + * @see #getFile + * @see #getFiles */ public void setFile(String file) { this.file = (file != null && file.equals("")) ? null : file; @@ -390,6 +477,34 @@ public class FileDialog extends Dialog { } } + /** + * Enables or disables multiple file selection for the file dialog. + * + * @param enable if {@code true}, multiple file selection is enabled; + * {@code false} - disabled. + * @see #isMultipleMode + * @since 1.7 + */ + public void setMultipleMode(boolean enable) { + synchronized (getObjectLock()) { + this.multipleMode = enable; + } + } + + /** + * Returns whether the file dialog allows the multiple file selection. + * + * @return {@code true} if the file dialog allows the multiple + * file selection; {@code false} otherwise. + * @see #setMultipleMode + * @since 1.7 + */ + public boolean isMultipleMode() { + synchronized (getObjectLock()) { + return multipleMode; + } + } + /** * Determines this file dialog's filename filter. A filename filter * allows the user to specify which files appear in the file dialog diff --git a/jdk/src/share/classes/sun/awt/AWTAccessor.java b/jdk/src/share/classes/sun/awt/AWTAccessor.java index 964e3e0e7ec..79a75937c25 100644 --- a/jdk/src/share/classes/sun/awt/AWTAccessor.java +++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java @@ -390,6 +390,30 @@ public final class AWTAccessor { boolean isTrayIconPopup(PopupMenu popupMenu); } + /* + * An accessor for the FileDialog class + */ + public interface FileDialogAccessor { + /* + * Sets the files the user selects + */ + void setFiles(FileDialog fileDialog, String directory, String files[]); + + /* + * Sets the file the user selects + */ + void setFile(FileDialog fileDialog, String file); + + /* + * Sets the directory the user selects + */ + void setDirectory(FileDialog fileDialog, String directory); + + /* + * Returns whether the file dialog allows the multiple file selection. + */ + boolean isMultipleMode(FileDialog fileDialog); + } /* * The java.awt.Component class accessor object. @@ -431,6 +455,11 @@ public final class AWTAccessor { */ private static PopupMenuAccessor popupMenuAccessor; + /* + * The java.awt.FileDialog class accessor object. + */ + private static FileDialogAccessor fileDialogAccessor; + /* * Set an accessor object for the java.awt.Component class. */ @@ -567,4 +596,22 @@ public final class AWTAccessor { } return popupMenuAccessor; } + + /* + * Set an accessor object for the java.awt.FileDialog class. + */ + public static void setFileDialogAccessor(FileDialogAccessor fda) { + fileDialogAccessor = fda; + } + + /* + * Retrieve the accessor object for the java.awt.FileDialog class. + */ + public static FileDialogAccessor getFileDialogAccessor() { + if (fileDialogAccessor == null) { + unsafe.ensureClassInitialized(FileDialog.class); + } + return fileDialogAccessor; + } + } diff --git a/jdk/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java b/jdk/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java index a50437a1ee8..24acdee5721 100644 --- a/jdk/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java +++ b/jdk/src/solaris/classes/sun/awt/X11/XFileDialogPeer.java @@ -37,6 +37,7 @@ import javax.swing.plaf.ComponentUI; import java.security.AccessController; import java.security.PrivilegedAction; import sun.util.logging.PlatformLogger; +import sun.awt.AWTAccessor; class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListener, ItemListener, KeyEventDispatcher, XChoicePeerListener { private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XFileDialogPeer"); @@ -171,6 +172,10 @@ class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListe filterField = new TextField(); selectionField = new TextField(); + boolean isMultipleMode = + AWTAccessor.getFileDialogAccessor().isMultipleMode(target); + fileList.setMultipleMode(isMultipleMode); + // the insets used by the components in the fileDialog Insets noInset = new Insets(0, 0, 0, 0); Insets textFieldInset = new Insets(0, 8, 0, 8); @@ -380,7 +385,8 @@ class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListe * handle the selection event */ void handleSelection(String file) { - int index = file.lastIndexOf('/'); + + int index = file.lastIndexOf(java.io.File.separatorChar); if (index == -1) { savedDir = this.dir; @@ -389,8 +395,12 @@ class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListe savedDir = file.substring(0, index+1); savedFile = file.substring(index+1); } - target.setDirectory(savedDir); - target.setFile(savedFile); + + AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor(); + + fileDialogAccessor.setDirectory(target, savedDir); + fileDialogAccessor.setFile(target, savedFile); + fileDialogAccessor.setFiles(target, savedDir, fileList.getSelectedItems()); } /** @@ -404,8 +414,13 @@ class XFileDialogPeer extends XDialogPeer implements FileDialogPeer, ActionListe setFilterField(null); directoryList.clear(); fileList.clear(); - target.setFile(null); - target.setDirectory(null); + + AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor(); + + fileDialogAccessor.setDirectory(target, null); + fileDialogAccessor.setFile(target, null); + fileDialogAccessor.setFiles(target, null, null); + handleQuitButton(); } diff --git a/jdk/src/windows/classes/sun/awt/windows/WFileDialogPeer.java b/jdk/src/windows/classes/sun/awt/windows/WFileDialogPeer.java index bc4e8470f4c..e5843dda7d5 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WFileDialogPeer.java +++ b/jdk/src/windows/classes/sun/awt/windows/WFileDialogPeer.java @@ -117,26 +117,57 @@ public class WFileDialogPeer extends WWindowPeer implements FileDialogPeer { } } - // NOTE: This method is called by privileged threads. - // DO NOT INVOKE CLIENT CODE ON THIS THREAD! - void handleSelected(final String file) { - final FileDialog fileDialog = (FileDialog)target; - WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() { - public void run() { - int index = file.lastIndexOf(java.io.File.separatorChar);/*2509*//*ibm*/ - String dir; + /* + * The function converts the file names (the buffer parameter) + * in the Windows format into the Java format and saves the results + * into the FileDialog instance. + * + * If it's the multi-select mode, the buffer contains the current + * directory followed by the short names of the files. + * The directory and file name strings are NULL separated. + * If it's the single-select mode, the buffer doesn't have the NULL + * separator between the path and the file name. + * + * NOTE: This method is called by privileged threads. + * DO NOT INVOKE CLIENT CODE ON THIS THREAD! + */ + void handleSelected(final char[] buffer) + { + String[] wFiles = (new String(buffer)).split("\0"); // NULL is the delimiter + boolean multiple = (wFiles.length > 1); - if (index == -1) { - dir = "."+java.io.File.separator; - fileDialog.setFile(file); - } - else { - dir = file.substring(0, index + 1); - fileDialog.setFile(file.substring(index + 1)); - } - fileDialog.setDirectory(dir); - fileDialog.hide(); + String jDirectory = null; + String jFile = null; + String jFiles[] = null; + + if (multiple) { + jDirectory = wFiles[0]; + jFiles = new String[wFiles.length - 1]; + System.arraycopy(wFiles, 1, jFiles, 0, jFiles.length); + jFile = jFiles[1]; // choose any file + } else { + int index = wFiles[0].lastIndexOf(java.io.File.separatorChar); + if (index == -1) { + jDirectory = "."+java.io.File.separator; + jFile = wFiles[0]; + } else { + jDirectory = wFiles[0].substring(0, index + 1); + jFile = wFiles[0].substring(index + 1); } + jFiles = new String[] { jFile }; + } + + final FileDialog fileDialog = (FileDialog)target; + AWTAccessor.FileDialogAccessor fileDialogAccessor = AWTAccessor.getFileDialogAccessor(); + + fileDialogAccessor.setDirectory(fileDialog, jDirectory); + fileDialogAccessor.setFile(fileDialog, jFile); + fileDialogAccessor.setFiles(fileDialog, jDirectory, jFiles); + + WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() { + public void run() { + fileDialog.hide(); + } }); } // handleSelected() @@ -144,11 +175,14 @@ public class WFileDialogPeer extends WWindowPeer implements FileDialogPeer { // DO NOT INVOKE CLIENT CODE ON THIS THREAD! void handleCancel() { final FileDialog fileDialog = (FileDialog)target; + + AWTAccessor.getFileDialogAccessor().setFile(fileDialog, null); + AWTAccessor.getFileDialogAccessor().setFiles(fileDialog, null, null); + WToolkit.executeOnEventHandlerThread(fileDialog, new Runnable() { - public void run() { - fileDialog.setFile(null); - fileDialog.hide(); - } + public void run() { + fileDialog.hide(); + } }); } // handleCancel() @@ -244,4 +278,9 @@ public class WFileDialogPeer extends WWindowPeer implements FileDialogPeer { public void createScreenSurface(boolean isResize) {} @Override public void replaceSurfaceData() {} + + public boolean isMultipleMode() { + FileDialog fileDialog = (FileDialog)target; + return AWTAccessor.getFileDialogAccessor().isMultipleMode(fileDialog); + } } diff --git a/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp b/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp index 080e8d42741..8d81cf8aa26 100644 --- a/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp +++ b/jdk/src/windows/native/sun/windows/awt_FileDialog.cpp @@ -44,6 +44,7 @@ jmethodID AwtFileDialog::setHWndMID; jmethodID AwtFileDialog::handleSelectedMID; jmethodID AwtFileDialog::handleCancelMID; jmethodID AwtFileDialog::checkFilenameFilterMID; +jmethodID AwtFileDialog::isMultipleModeMID; /* FileDialog ids */ jfieldID AwtFileDialog::modeID; @@ -57,6 +58,13 @@ static TCHAR s_fileFilterString[MAX_FILTER_STRING]; /* Non-localized suffix of the filter string */ static const TCHAR s_additionalString[] = TEXT(" (*.*)\0*.*\0"); +// Default limit of the output buffer. +#define SINGLE_MODE_BUFFER_LIMIT MAX_PATH+1 +#define MULTIPLE_MODE_BUFFER_LIMIT 32768 + +// The name of the property holding the pointer to the OPENFILENAME structure. +static LPCTSTR OpenFileNameProp = TEXT("AWT_OFN"); + /***********************************************************************/ void @@ -140,6 +148,8 @@ FileDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) FileDialogWndProc); ::SetProp(parent, NativeDialogWndProcProp, reinterpret_cast(lpfnWndProc)); + ::SetProp(parent, OpenFileNameProp, (void *)lParam); + break; } case WM_DESTROY: { @@ -149,6 +159,7 @@ FileDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) lpfnWndProc); ::RemoveProp(parent, ModalDialogPeerProp); ::RemoveProp(parent, NativeDialogWndProcProp); + ::RemoveProp(parent, OpenFileNameProp); break; } case WM_NOTIFY: { @@ -174,6 +185,30 @@ FileDialogHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) // to unblock all the windows blocked by this dialog as it will // be closed soon env->CallVoidMethod(peer, AwtFileDialog::setHWndMID, (jlong)0); + } else if (notifyEx->hdr.code == CDN_SELCHANGE) { + // reallocate the buffer if the buffer is too small + LPOPENFILENAME lpofn = (LPOPENFILENAME)GetProp(parent, OpenFileNameProp); + + UINT nLength = CommDlg_OpenSave_GetSpec(parent, NULL, 0) + + CommDlg_OpenSave_GetFolderPath(parent, NULL, 0); + + if (lpofn->nMaxFile < nLength) + { + // allocate new buffer + LPTSTR newBuffer = new TCHAR[nLength]; + + if (newBuffer) { + memset(newBuffer, 0, nLength * sizeof(TCHAR)); + LPTSTR oldBuffer = lpofn->lpstrFile; + lpofn->lpstrFile = newBuffer; + lpofn->nMaxFile = nLength; + // free the previously allocated buffer + if (oldBuffer) { + delete[] oldBuffer; + } + + } + } } } break; @@ -193,7 +228,6 @@ AwtFileDialog::Show(void *p) WCHAR unicodeChar = L' '; LPTSTR fileBuffer = NULL; LPTSTR currentDirectory = NULL; - OPENFILENAME ofn; jint mode = 0; BOOL result = FALSE; DWORD dlgerr; @@ -204,6 +238,10 @@ AwtFileDialog::Show(void *p) jobject target = NULL; jobject parent = NULL; AwtComponent* awtParent = NULL; + jboolean multipleMode = JNI_FALSE; + + OPENFILENAME ofn; + memset(&ofn, 0, sizeof(ofn)); /* * There's a situation (see bug 4906972) when InvokeFunction (by which this method is called) @@ -233,7 +271,16 @@ AwtFileDialog::Show(void *p) (jstring)env->GetObjectField(target, AwtFileDialog::dirID); JavaStringBuffer directoryBuffer(env, directory); - fileBuffer = new TCHAR[MAX_PATH+1]; + multipleMode = env->CallBooleanMethod(peer, AwtFileDialog::isMultipleModeMID); + + UINT bufferLimit; + if (multipleMode == JNI_TRUE) { + bufferLimit = MULTIPLE_MODE_BUFFER_LIMIT; + } else { + bufferLimit = SINGLE_MODE_BUFFER_LIMIT; + } + LPTSTR fileBuffer = new TCHAR[bufferLimit]; + memset(fileBuffer, 0, bufferLimit * sizeof(TCHAR)); file = (jstring)env->GetObjectField(target, AwtFileDialog::fileID); if (file != NULL) { @@ -244,8 +291,6 @@ AwtFileDialog::Show(void *p) fileBuffer[0] = _T('\0'); } - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); ofn.lpstrFilter = s_fileFilterString; ofn.nFilterIndex = 1; @@ -265,19 +310,23 @@ AwtFileDialog::Show(void *p) ofn.hwndOwner = NULL; } ofn.lpstrFile = fileBuffer; - ofn.nMaxFile = MAX_PATH; + ofn.nMaxFile = bufferLimit; ofn.lpstrTitle = titleBuffer; ofn.lpstrInitialDir = directoryBuffer; ofn.Flags = OFN_LONGNAMES | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_ENABLEHOOK | OFN_EXPLORER | OFN_ENABLESIZING; fileFilter = env->GetObjectField(peer, AwtFileDialog::fileFilterID); - if (!JNU_IsNull(env,fileFilter)) { - ofn.Flags |= OFN_ENABLEINCLUDENOTIFY; - } + if (!JNU_IsNull(env,fileFilter)) { + ofn.Flags |= OFN_ENABLEINCLUDENOTIFY; + } ofn.lCustData = (LPARAM)peer; ofn.lpfnHook = (LPOFNHOOKPROC)FileDialogHookProc; + if (multipleMode == JNI_TRUE) { + ofn.Flags |= OFN_ALLOWMULTISELECT; + } + // Save current directory, so we can reset if it changes. currentDirectory = new TCHAR[MAX_PATH+1]; @@ -318,11 +367,12 @@ AwtFileDialog::Show(void *p) // Report result to peer. if (result) { - jstring tmpJString = (_tcslen(ofn.lpstrFile) == 0 ? - JNU_NewStringPlatform(env, L"") : - JNU_NewStringPlatform(env, ofn.lpstrFile)); - env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, tmpJString); - env->DeleteLocalRef(tmpJString); + jint length = (jint)GetBufferLength(ofn.lpstrFile, ofn.nMaxFile); + jcharArray jnames = env->NewCharArray(length); + env->SetCharArrayRegion(jnames, 0, length, (jchar*)ofn.lpstrFile); + + env->CallVoidMethod(peer, AwtFileDialog::handleSelectedMID, jnames); + env->DeleteLocalRef(jnames); } else { env->CallVoidMethod(peer, AwtFileDialog::handleCancelMID); } @@ -338,7 +388,8 @@ AwtFileDialog::Show(void *p) env->DeleteGlobalRef(peer); delete[] currentDirectory; - delete[] fileBuffer; + if (ofn.lpstrFile) + delete[] ofn.lpstrFile; throw; } @@ -351,7 +402,8 @@ AwtFileDialog::Show(void *p) env->DeleteGlobalRef(peer); delete[] currentDirectory; - delete[] fileBuffer; + if (ofn.lpstrFile) + delete[] ofn.lpstrFile; } BOOL @@ -416,6 +468,18 @@ void AwtFileDialog::_ToBack(void *param) env->DeleteGlobalRef(self); } +// Returns the length of the double null terminated output buffer +UINT AwtFileDialog::GetBufferLength(LPTSTR buffer, UINT limit) +{ + UINT index = 0; + while ((index < limit) && + (buffer[index] != NULL || buffer[index+1] != NULL)) + { + index++; + } + return index; +} + /************************************************************************ * WFileDialogPeer native methods */ @@ -434,11 +498,12 @@ Java_sun_awt_windows_WFileDialogPeer_initIDs(JNIEnv *env, jclass cls) AwtFileDialog::setHWndMID = env->GetMethodID(cls, "setHWnd", "(J)V"); AwtFileDialog::handleSelectedMID = - env->GetMethodID(cls, "handleSelected", "(Ljava/lang/String;)V"); + env->GetMethodID(cls, "handleSelected", "([C)V"); AwtFileDialog::handleCancelMID = env->GetMethodID(cls, "handleCancel", "()V"); AwtFileDialog::checkFilenameFilterMID = env->GetMethodID(cls, "checkFilenameFilter", "(Ljava/lang/String;)Z"); + AwtFileDialog::isMultipleModeMID = env->GetMethodID(cls, "isMultipleMode", "()Z"); /* java.awt.FileDialog fields */ cls = env->FindClass("java/awt/FileDialog"); @@ -455,6 +520,7 @@ Java_sun_awt_windows_WFileDialogPeer_initIDs(JNIEnv *env, jclass cls) DASSERT(AwtFileDialog::setHWndMID != NULL); DASSERT(AwtFileDialog::handleSelectedMID != NULL); DASSERT(AwtFileDialog::handleCancelMID != NULL); + DASSERT(AwtFileDialog::isMultipleModeMID != NULL); DASSERT(AwtFileDialog::modeID != NULL); DASSERT(AwtFileDialog::dirID != NULL); diff --git a/jdk/src/windows/native/sun/windows/awt_FileDialog.h b/jdk/src/windows/native/sun/windows/awt_FileDialog.h index 82638d30752..d20a355d2c0 100644 --- a/jdk/src/windows/native/sun/windows/awt_FileDialog.h +++ b/jdk/src/windows/native/sun/windows/awt_FileDialog.h @@ -49,6 +49,7 @@ public: static jmethodID handleSelectedMID; static jmethodID handleCancelMID; static jmethodID checkFilenameFilterMID; + static jmethodID isMultipleModeMID; /* java.awt.FileDialog field and method ids */ static jfieldID modeID; @@ -68,6 +69,9 @@ public: static void _DisposeOrHide(void *param); static void _ToFront(void *param); static void _ToBack(void *param); + +private: + static UINT GetBufferLength(LPTSTR buffer, UINT limit); }; #endif /* FILE_DIALOG_H */ diff --git a/jdk/test/java/awt/FileDialog/MultipleMode/MultipleMode.html b/jdk/test/java/awt/FileDialog/MultipleMode/MultipleMode.html new file mode 100644 index 00000000000..a52ee581eba --- /dev/null +++ b/jdk/test/java/awt/FileDialog/MultipleMode/MultipleMode.html @@ -0,0 +1,20 @@ + + + + MultipleMode + + + +

MultipleMode
Bug ID: 6467204

+ +

See the dialog box (usually in upper left corner) for instructions

+ + + + diff --git a/jdk/test/java/awt/FileDialog/MultipleMode/MultipleMode.java b/jdk/test/java/awt/FileDialog/MultipleMode/MultipleMode.java new file mode 100644 index 00000000000..b231b9e9c84 --- /dev/null +++ b/jdk/test/java/awt/FileDialog/MultipleMode/MultipleMode.java @@ -0,0 +1,289 @@ +/* + * Copyright 2010 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 + @bug 6467204 + @summary Need to implement "extended" native FileDialog for JFileChooser + @author dmitry.cherepanov@sun.com area=awt.filedialog + @run applet/manual=yesno MultipleMode.html +*/ + +// Note there is no @ in front of test above. This is so that the +// harness will not mistake this file as a test file. It should +// only see the html file as a test file. (the harness runs all +// valid test files, so it would run this test twice if this file +// were valid as well as the html file.) +// Also, note the area= after Your Name in the author tag. Here, you +// should put which functional area the test falls in. See the +// AWT-core home page -> test areas and/or -> AWT team for a list of +// areas. +// There are several places where ManualYesNoTest appear. It is +// recommended that these be changed by a global search and replace, +// such as ESC-% in xemacs. + + + +/** + * MultipleMode.java + * + * summary: + */ + +import java.applet.Applet; +import java.awt.*; +import java.awt.event.*; +import java.io.File; + + +//Manual tests should run as applet tests if possible because they +// get their environments cleaned up, including AWT threads, any +// test created threads, and any system resources used by the test +// such as file descriptors. (This is normally not a problem as +// main tests usually run in a separate VM, however on some platforms +// such as the Mac, separate VMs are not possible and non-applet +// tests will cause problems). Also, you don't have to worry about +// synchronisation stuff in Applet tests the way you do in main +// tests... + + +public class MultipleMode extends Applet +{ + //Declare things used in the test, like buttons and labels here + + public void init() + { + //Create instructions for the user here, as well as set up + // the environment -- set the layout manager, add buttons, + // etc. + this.setLayout (new BorderLayout ()); + + String[] instructions = + { + " 1. Turn the 'multiple' checkbox off and press the 'open' button ", + " 2. Verify that the file dialog doesn't allow the multiple file selection ", + " 3. Select any file and close the file dialog ", + " 4. The results will be displayed, verify the results ", + " 5. Turn the 'multiple' checkbox on and press the 'open' button ", + " 6. Verify that the file dialog allows the multiple file selection ", + " 7. Select several files and close the file dialog ", + " 8. The results will be displayed, verify the results " + }; + Sysout.createDialogWithInstructions( instructions ); + + }//End init() + + public void start () + { + final Checkbox mode = new Checkbox("multiple", true); + Button open = new Button("open"); + open.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + FileDialog d = new FileDialog((Frame)null); + d.setMultipleMode(mode.getState()); + d.setVisible(true); + + // print the results + Sysout.println("DIR:"); + Sysout.println(d.getDirectory()); + Sysout.println("FILE:"); + Sysout.println(d.getFile()); + Sysout.println("FILES:"); + File files[] = d.getFiles(); + for (File f : files) { + Sysout.println(String.valueOf(f)); + } + } + }); + + setLayout(new FlowLayout()); + add(mode); + add(open); + + //Get things going. Request focus, set size, et cetera + setSize (200,200); + setVisible(true); + validate(); + + }// start() + + //The rest of this class is the actions which perform the test... + + //Use Sysout.println to communicate with the user NOT System.out!! + //Sysout.println ("Something Happened!"); + +}// class ManualYesNoTest + +/* Place other classes related to the test after this line */ + + + + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + private static boolean numbering = false; + private static int messageNumber = 0; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + /* Enables message counting for the tester. */ + public static void enableNumbering(boolean enable){ + numbering = enable; + } + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + if (numbering) { + messageIn = "" + messageNumber + " " + messageIn; + messageNumber++; + } + dialog.displayMessage( messageIn ); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class From 17a0e10b07879019e0894847a237e6c21475f092 Mon Sep 17 00:00:00 2001 From: Gary Benson Date: Fri, 12 Feb 2010 10:34:11 -0800 Subject: [PATCH 20/31] 6926048: Improve Zero performance Make Zero figure out result types in a similar way to C++ interpreter implementation. Reviewed-by: kvn --- .../src/cpu/zero/vm/cppInterpreter_zero.cpp | 29 ++++++++++++++++--- .../src/cpu/zero/vm/cppInterpreter_zero.hpp | 6 +++- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 8fcb75c8b36..4f94d8851c4 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -1,6 +1,6 @@ /* * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008, 2009 Red Hat, Inc. + * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -145,7 +145,7 @@ void CppInterpreter::main_loop(int recurse, TRAPS) { } else if (istate->msg() == BytecodeInterpreter::return_from_method) { // Copy the result into the caller's frame - result_slots = type2size[method->result_type()]; + result_slots = type2size[result_type_of(method)]; assert(result_slots >= 0 && result_slots <= 2, "what?"); result = istate->stack() + result_slots; break; @@ -394,9 +394,10 @@ void CppInterpreter::native_entry(methodOop method, intptr_t UNUSED, TRAPS) { // Push our result if (!HAS_PENDING_EXCEPTION) { - stack->set_sp(stack->sp() - type2size[method->result_type()]); + BasicType type = result_type_of(method); + stack->set_sp(stack->sp() - type2size[type]); - switch (method->result_type()) { + switch (type) { case T_VOID: break; @@ -707,6 +708,26 @@ int AbstractInterpreter::BasicType_as_index(BasicType type) { return i; } +BasicType CppInterpreter::result_type_of(methodOop method) { + BasicType t; + switch (method->result_index()) { + case 0 : t = T_BOOLEAN; break; + case 1 : t = T_CHAR; break; + case 2 : t = T_BYTE; break; + case 3 : t = T_SHORT; break; + case 4 : t = T_INT; break; + case 5 : t = T_LONG; break; + case 6 : t = T_VOID; break; + case 7 : t = T_FLOAT; break; + case 8 : t = T_DOUBLE; break; + case 9 : t = T_OBJECT; break; + default: ShouldNotReachHere(); + } + assert(AbstractInterpreter::BasicType_as_index(t) == method->result_index(), + "out of step with AbstractInterpreter::BasicType_as_index"); + return t; +} + address InterpreterGenerator::generate_empty_entry() { if (!UseFastEmptyMethods) return NULL; diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp index 18b9891e937..24c698c7ce5 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.hpp @@ -1,6 +1,6 @@ /* * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008 Red Hat, Inc. + * Copyright 2007, 2008, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,3 +41,7 @@ private: // Stack overflow checks static bool stack_overflow_imminent(JavaThread *thread); + + private: + // Fast result type determination + static BasicType result_type_of(methodOop method); From 652882e3b4ec81af7e2d8b83fc3c936e080e00ab Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Fri, 12 Feb 2010 11:33:33 -0800 Subject: [PATCH 21/31] 6925868: Eliminate pack200's dependency on logging Replace j.u.l.Logger with sun.util.logging.PlatformLogger Reviewed-by: alanb, forax --- .../sun/java/util/jar/pack/PackageReader.java | 3 +- .../sun/java/util/jar/pack/PackageWriter.java | 3 +- .../com/sun/java/util/jar/pack/Utils.java | 65 +++++++++++++------ 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java index dedf1da5ab5..d472bbbe51d 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageReader.java @@ -27,7 +27,6 @@ package com.sun.java.util.jar.pack; import java.io.*; import java.util.*; -import java.util.logging.Level; import com.sun.java.util.jar.pack.Package.Class; import com.sun.java.util.jar.pack.Package.File; import com.sun.java.util.jar.pack.Package.InnerClass; @@ -162,7 +161,7 @@ class PackageReader extends BandStructure { ok = true; } catch (Exception ee) { - Utils.log.log(Level.WARNING, "Error on input: "+ee, ee); + Utils.log.warning("Error on input: "+ee, ee); if (verbose > 0) Utils.log.info("Stream offsets:"+ " served="+in.getBytesServed()+ diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java index a93cc293d23..2128c93cf3c 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/PackageWriter.java @@ -27,7 +27,6 @@ package com.sun.java.util.jar.pack; import java.io.*; import java.util.*; -import java.util.logging.Level; import com.sun.java.util.jar.pack.Package.Class; import com.sun.java.util.jar.pack.Package.File; import com.sun.java.util.jar.pack.Package.InnerClass; @@ -84,7 +83,7 @@ class PackageWriter extends BandStructure { ok = true; } catch (Exception ee) { - Utils.log.log(Level.WARNING, "Error on output: "+ee, ee); + Utils.log.warning("Error on output: "+ee, ee); //if (verbose > 0) ee.printStackTrace(); // Write partial output only if we are verbose. if (verbose > 0) finalOut.close(); diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java index c595e799a40..f33828fe261 100644 --- a/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/Utils.java @@ -28,9 +28,10 @@ package com.sun.java.util.jar.pack; import java.util.*; import java.util.jar.*; import java.util.zip.*; -import java.util.logging.*; import java.io.*; +import sun.util.logging.PlatformLogger; + class Utils { static final String COM_PREFIX = "com.sun.java.util.jar.pack."; static final String METAINF = "META-INF"; @@ -130,31 +131,53 @@ class Utils { = Boolean.getBoolean(Utils.COM_PREFIX+"nolog"); - static final Logger log - = new Logger("java.util.jar.Pack200", null) { - public void log(LogRecord record) { - int verbose = currentPropMap().getInteger(DEBUG_VERBOSE); - if (verbose > 0) { - if (nolog && - record.getLevel().intValue() < Level.WARNING.intValue()) { - System.out.println(record.getMessage()); - } else { - super.log(record); - } - } - } + static class Pack200Logger { + private final String name; + private PlatformLogger log; + Pack200Logger(String name) { + this.name = name; + } - public void fine(String msg) { - int verbose = currentPropMap().getInteger(DEBUG_VERBOSE); - if (verbose > 0) { - System.out.println(msg); + private synchronized PlatformLogger getLogger() { + if (log == null) { + log = PlatformLogger.getLogger(name); + } + return log; + } + + public void warning(String msg, Object param) { + int verbose = currentPropMap().getInteger(DEBUG_VERBOSE); + if (verbose > 0) { + getLogger().warning(msg, param); + } + } + + public void warning(String msg) { + warning(msg, null); + } + + public void info(String msg) { + int verbose = currentPropMap().getInteger(DEBUG_VERBOSE); + if (verbose > 0) { + if (nolog) { + System.out.println(msg); + } else { + getLogger().info(msg); } } - }; - static { - LogManager.getLogManager().addLogger(log); + } + + public void fine(String msg) { + int verbose = currentPropMap().getInteger(DEBUG_VERBOSE); + if (verbose > 0) { + System.out.println(msg); + } + } } + static final Pack200Logger log + = new Pack200Logger("java.util.jar.Pack200"); + // Returns the Max Version String of this implementation static String getVersionString() { return "Pack200, Vendor: Sun Microsystems, Version: " + From 892336beb1099adf46b2ad315fb3edb7c4fe8855 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 16 Feb 2010 16:17:46 -0800 Subject: [PATCH 22/31] 6926697: "optimized" VM build failed: The type "AdapterHandlerTableIterator" is incomplete Define AdapterHandlerTableIterator class as non product instead of debug. Reviewed-by: never --- hotspot/src/share/vm/runtime/sharedRuntime.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 3098625858e..bc79954b978 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -1947,7 +1947,7 @@ class AdapterHandlerTable : public BasicHashtable { private: -#ifdef ASSERT +#ifndef PRODUCT static int _lookups; // number of calls to lookup static int _buckets; // number of buckets checked static int _equals; // number of buckets checked with matching hash @@ -1983,16 +1983,16 @@ class AdapterHandlerTable : public BasicHashtable { // Find a entry with the same fingerprint if it exists AdapterHandlerEntry* lookup(int total_args_passed, BasicType* sig_bt) { - debug_only(_lookups++); + NOT_PRODUCT(_lookups++); AdapterFingerPrint fp(total_args_passed, sig_bt); unsigned int hash = fp.compute_hash(); int index = hash_to_index(hash); for (AdapterHandlerEntry* e = bucket(index); e != NULL; e = e->next()) { - debug_only(_buckets++); + NOT_PRODUCT(_buckets++); if (e->hash() == hash) { - debug_only(_equals++); + NOT_PRODUCT(_equals++); if (fp.equals(e->fingerprint())) { -#ifdef ASSERT +#ifndef PRODUCT if (fp.is_compact()) _compact++; _hits++; #endif @@ -2003,6 +2003,7 @@ class AdapterHandlerTable : public BasicHashtable { return NULL; } +#ifndef PRODUCT void print_statistics() { ResourceMark rm; int longest = 0; @@ -2021,15 +2022,14 @@ class AdapterHandlerTable : public BasicHashtable { } tty->print_cr("AdapterHandlerTable: empty %d longest %d total %d average %f", empty, longest, total, total / (double)nonempty); -#ifdef ASSERT tty->print_cr("AdapterHandlerTable: lookups %d buckets %d equals %d hits %d compact %d", _lookups, _buckets, _equals, _hits, _compact); -#endif } +#endif }; -#ifdef ASSERT +#ifndef PRODUCT int AdapterHandlerTable::_lookups; int AdapterHandlerTable::_buckets; From 51fc36cc9af2f73ceafefc0dedb0db44e1de773c Mon Sep 17 00:00:00 2001 From: Tom Rodriguez Date: Tue, 16 Feb 2010 20:07:48 -0800 Subject: [PATCH 23/31] 6877221: Endless deoptimizations in OSR nmethod Reviewed-by: kvn --- hotspot/src/share/vm/opto/parse1.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index 169cdc9754b..4cae42dd2cc 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -824,7 +824,6 @@ bool Parse::can_rerun_bytecode() { case Bytecodes::_ddiv: case Bytecodes::_checkcast: case Bytecodes::_instanceof: - case Bytecodes::_athrow: case Bytecodes::_anewarray: case Bytecodes::_newarray: case Bytecodes::_multianewarray: @@ -834,6 +833,8 @@ bool Parse::can_rerun_bytecode() { return true; break; + // Don't rerun athrow since it's part of the exception path. + case Bytecodes::_athrow: case Bytecodes::_invokestatic: case Bytecodes::_invokedynamic: case Bytecodes::_invokespecial: From 0c605ed991d733113daac7af5612f604bab7e842 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Thu, 18 Feb 2010 11:35:41 +0100 Subject: [PATCH 24/31] 6926782: CodeBuffer size too small after 6921352 After 6921352 the CodeBuffer size was too small. Reviewed-by: kvn, never --- hotspot/src/share/vm/opto/callGenerator.cpp | 7 +++-- hotspot/src/share/vm/opto/compile.cpp | 4 ++- hotspot/src/share/vm/opto/compile.hpp | 9 +++++- hotspot/src/share/vm/opto/output.cpp | 33 ++++++++++++++++----- 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp index 37272feb19e..a358e535076 100644 --- a/hotspot/src/share/vm/opto/callGenerator.cpp +++ b/hotspot/src/share/vm/opto/callGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2010 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 @@ -136,8 +136,10 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) { } // Mark the call node as virtual, sort of: call->set_optimized_virtual(true); - if (method()->is_method_handle_invoke()) + if (method()->is_method_handle_invoke()) { call->set_method_handle_invoke(true); + kit.C->set_has_method_handle_invokes(true); + } } kit.set_arguments_for_java_call(call); kit.set_edges_for_java_call(call, false, _separate_io_proj); @@ -194,6 +196,7 @@ JVMState* DynamicCallGenerator::generate(JVMState* jvms) { call->set_optimized_virtual(true); // Take extra care (in the presence of argument motion) not to trash the SP: call->set_method_handle_invoke(true); + kit.C->set_has_method_handle_invokes(true); // Pass the target MethodHandle as first argument and shift the // other arguments. diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 84102e1553c..5ca0286b545 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -465,6 +465,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr _code_buffer("Compile::Fill_buffer"), _orig_pc_slot(0), _orig_pc_slot_offset_in_bytes(0), + _has_method_handle_invokes(false), _node_bundling_limit(0), _node_bundling_base(NULL), _java_calls(0), @@ -759,6 +760,7 @@ Compile::Compile( ciEnv* ci_env, _do_escape_analysis(false), _failure_reason(NULL), _code_buffer("Compile::Fill_buffer"), + _has_method_handle_invokes(false), _node_bundling_limit(0), _node_bundling_base(NULL), _java_calls(0), diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index c683110355d..7027d29d533 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -1,5 +1,5 @@ /* - * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2010 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 @@ -166,6 +166,9 @@ class Compile : public Phase { bool _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing #endif + // JSR 292 + bool _has_method_handle_invokes; // True if this method has MethodHandle invokes. + // Compilation environment. Arena _comp_arena; // Arena with lifetime equivalent to Compile ciEnv* _env; // CI interface @@ -336,6 +339,10 @@ class Compile : public Phase { void set_parsed_irreducible_loop(bool z) { _parsed_irreducible_loop = z; } #endif + // JSR 292 + bool has_method_handle_invokes() const { return _has_method_handle_invokes; } + void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; } + void begin_method() { #ifndef PRODUCT if (_printer) _printer->begin_method(this); diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index deb2ac2c3c3..fb5db8e7791 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -805,8 +805,12 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { mcall = mach->as_MachCall(); // Is the call a MethodHandle call? - if (mcall->is_MachCallJava()) - is_method_handle_invoke = mcall->as_MachCallJava()->_method_handle_invoke; + if (mcall->is_MachCallJava()) { + if (mcall->as_MachCallJava()->_method_handle_invoke) { + assert(has_method_handle_invokes(), "must have been set during call generation"); + is_method_handle_invoke = true; + } + } // Check if a call returns an object. if (mcall->return_value_is_used() && @@ -1092,9 +1096,21 @@ void Compile::Fill_buffer() { deopt_handler_req += MAX_stubs_size; // add marginal slop for handler stub_req += MAX_stubs_size; // ensure per-stub margin code_req += MAX_inst_size; // ensure per-instruction margin + if (StressCodeBuffers) code_req = const_req = stub_req = exception_handler_req = deopt_handler_req = 0x10; // force expansion - int total_req = code_req + pad_req + stub_req + exception_handler_req + deopt_handler_req + const_req; + + int total_req = + code_req + + pad_req + + stub_req + + exception_handler_req + + deopt_handler_req + // deopt handler + const_req; + + if (has_method_handle_invokes()) + total_req += deopt_handler_req; // deopt MH handler + CodeBuffer* cb = code_buffer(); cb->initialize(total_req, locs_req); @@ -1436,10 +1452,13 @@ void Compile::Fill_buffer() { _code_offsets.set_value(CodeOffsets::Exceptions, emit_exception_handler(*cb)); // Emit the deopt handler code. _code_offsets.set_value(CodeOffsets::Deopt, emit_deopt_handler(*cb)); - // Emit the MethodHandle deopt handler code. We can use the same - // code as for the normal deopt handler, we just need a different - // entry point address. - _code_offsets.set_value(CodeOffsets::DeoptMH, emit_deopt_handler(*cb)); + + // Emit the MethodHandle deopt handler code (if required). + if (has_method_handle_invokes()) { + // We can use the same code as for the normal deopt handler, we + // just need a different entry point address. + _code_offsets.set_value(CodeOffsets::DeoptMH, emit_deopt_handler(*cb)); + } } // One last check for failed CodeBuffer::expand: From 51b9396b40431c74a8b35106783e579da8b24df3 Mon Sep 17 00:00:00 2001 From: Gary Benson Date: Thu, 18 Feb 2010 06:54:48 -0800 Subject: [PATCH 25/31] 6927165: Zero S/390 fixes Fixes two failures on 31-bit S/390. Reviewed-by: twisti --- hotspot/src/cpu/zero/vm/globals_zero.hpp | 4 ++-- hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/hotspot/src/cpu/zero/vm/globals_zero.hpp b/hotspot/src/cpu/zero/vm/globals_zero.hpp index e8a32f1d47a..e50df6f3dd1 100644 --- a/hotspot/src/cpu/zero/vm/globals_zero.hpp +++ b/hotspot/src/cpu/zero/vm/globals_zero.hpp @@ -1,6 +1,6 @@ /* * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008, 2009 Red Hat, Inc. + * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ define_pd_global(intx, PreInflateSpin, 10); define_pd_global(intx, StackYellowPages, 2); define_pd_global(intx, StackRedPages, 1); -define_pd_global(intx, StackShadowPages, 3 LP64_ONLY(+3) DEBUG_ONLY(+3)); +define_pd_global(intx, StackShadowPages, 5 LP64_ONLY(+1) DEBUG_ONLY(+3)); define_pd_global(bool, RewriteBytecodes, true); define_pd_global(bool, RewriteFrequentPairs, true); diff --git a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp index d226d5ca726..86d356269ae 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp +++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.hpp @@ -1,6 +1,6 @@ /* * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. - * Copyright 2007, 2008 Red Hat, Inc. + * Copyright 2007, 2008, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,13 @@ "stfd %0, 0(%2)\n" : "=f"(tmp) : "b"(src), "b"(dst)); +#elif defined(S390) && !defined(_LP64) + double tmp; + asm volatile ("ld %0, 0(%1)\n" + "std %0, 0(%2)\n" + : "=r"(tmp) + : "a"(src), "a"(dst)); #else *(jlong *) dst = *(jlong *) src; -#endif // PPC && !_LP64 +#endif } From d0d4cbff17f267e65b4a629268a8529160ef4bbf Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 18 Feb 2010 13:31:26 -0800 Subject: [PATCH 26/31] Added tag jdk7-b84 for changeset a1aa32963dec --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index b7fa87f7cf1..c5db610c7bb 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -58,3 +58,4 @@ a3242906c7747b5d9bcc3d118c7c3c69aa40f4b7 jdk7-b80 8403096d1fe7ff5318df9708cfec84a3fd3e1cf9 jdk7-b81 e1176f86805fe07fd9fb9da065dc51b47712ce76 jdk7-b82 6880a3af9addb41541e80ebe8cde6f79ec402a58 jdk7-b83 +2f3ea057d1ad56cf3b269cdc4de2741411151982 jdk7-b84 From 85b4073f996db362f7dd8a792fbaaf583387d9c1 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 18 Feb 2010 13:31:31 -0800 Subject: [PATCH 27/31] Added tag jdk7-b84 for changeset 31557f5428d0 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 166e8acf79d..3170f3ef824 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -80,3 +80,4 @@ ac59d4e6dae51ac5fc31a9a4940d1857f91161b1 hs16-b08 9ab385cb0c42997e16a7761ebcd25c90560a2714 hs15-b04 fafab5d5349c7c066d677538db67a1ee0fb33bd2 hs15-b05 3f370a32906eb5ba993fabd7b4279be7f31052b9 jdk7-b83 +ffc8d176b84bcfb5ac21302b4feb3b0c0d69b97c jdk7-b84 From 0d12029d1b7337d3581255d03a613ddf0863b3d7 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 18 Feb 2010 13:31:46 -0800 Subject: [PATCH 28/31] Added tag jdk7-b84 for changeset b8df1478b109 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index cf518808601..5daf5ca76cf 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -58,3 +58,4 @@ e6a5d095c356a547cf5b3c8885885aca5e91e09b jdk7-b77 10b993d417fcdb40480dad7032ac241f4b87f1af jdk7-b81 69ef657320ad5c35cfa12e4d8322d877e778f8b3 jdk7-b82 9027c6b9d7e2c9ca04a1add691b5b50d0f22b1aa jdk7-b83 +7cb9388bb1a16365fa5118c5efa38b1cd58be40d jdk7-b84 From fbd3f3a787a4e1fe2aa24daa24d648a788d42a3e Mon Sep 17 00:00:00 2001 From: Erik Trimble Date: Thu, 18 Feb 2010 22:16:12 -0800 Subject: [PATCH 29/31] 6927886: Bump the HS17 build number to 10 Update the HS17 build number to 10 Reviewed-by: jcoomes --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 88a4e7e30ff..b6f0792ede5 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2009 HS_MAJOR_VER=17 HS_MINOR_VER=0 -HS_BUILD_NUMBER=09 +HS_BUILD_NUMBER=10 JDK_MAJOR_VER=1 JDK_MINOR_VER=7 From 6e3ed53d0a7a226276ecaddccb083fefcd5d5627 Mon Sep 17 00:00:00 2001 From: Damjan Jovanovic Date: Mon, 22 Feb 2010 15:27:11 +0000 Subject: [PATCH 30/31] 6912868: "java.net.useSystemProxies" behavior fails to check "use_same_proxy" in GNOME Reviewed-by: alanb, chegar --- .../native/sun/net/spi/DefaultProxySelector.c | 41 ++++++++++--- .../java/net/ProxySelector/SystemProxies.java | 61 +++++++++++++++++++ 2 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 jdk/test/java/net/ProxySelector/SystemProxies.java diff --git a/jdk/src/solaris/native/sun/net/spi/DefaultProxySelector.c b/jdk/src/solaris/native/sun/net/spi/DefaultProxySelector.c index eefc522e918..4610b4b2b8c 100644 --- a/jdk/src/solaris/native/sun/net/spi/DefaultProxySelector.c +++ b/jdk/src/solaris/native/sun/net/spi/DefaultProxySelector.c @@ -44,6 +44,7 @@ * The GConf-2 settings used are: * - /system/http_proxy/use_http_proxy boolean * - /system/http_proxy/use_authentcation boolean + * - /system/http_proxy/use_same_proxy boolean * - /system/http_proxy/host string * - /system/http_proxy/authentication_user string * - /system/http_proxy/authentication_password string @@ -158,6 +159,7 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env, char *mode = NULL; int pport = 0; int use_proxy; + int use_same_proxy = 0; const char* urlhost; jobject isa = NULL; jobject proxy = NULL; @@ -179,6 +181,15 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env, * entries. */ + use_same_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_same_proxy", NULL); + if (use_same_proxy) { + use_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_http_proxy", NULL); + if (use_proxy) { + phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL); + pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL); + } + } + /** * HTTP: * /system/http_proxy/use_http_proxy (boolean) @@ -188,8 +199,10 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env, if (strcasecmp(cproto, "http") == 0) { use_proxy = (*my_get_bool_func)(gconf_client, "/system/http_proxy/use_http_proxy", NULL); if (use_proxy) { - phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL); - pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL); + if (!use_same_proxy) { + phost = (*my_get_string_func)(gconf_client, "/system/http_proxy/host", NULL); + pport = (*my_get_int_func)(gconf_client, "/system/http_proxy/port", NULL); + } CHECK_NULL(type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID)); } } @@ -203,8 +216,10 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env, if (strcasecmp(cproto, "https") == 0) { mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL); if (mode != NULL && (strcasecmp(mode,"manual") == 0)) { - phost = (*my_get_string_func)(gconf_client, "/system/proxy/secure_host", NULL); - pport = (*my_get_int_func)(gconf_client, "/system/proxy/secure_port", NULL); + if (!use_same_proxy) { + phost = (*my_get_string_func)(gconf_client, "/system/proxy/secure_host", NULL); + pport = (*my_get_int_func)(gconf_client, "/system/proxy/secure_port", NULL); + } use_proxy = (phost != NULL); if (use_proxy) type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID); @@ -220,8 +235,10 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env, if (strcasecmp(cproto, "ftp") == 0) { mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL); if (mode != NULL && (strcasecmp(mode,"manual") == 0)) { - phost = (*my_get_string_func)(gconf_client, "/system/proxy/ftp_host", NULL); - pport = (*my_get_int_func)(gconf_client, "/system/proxy/ftp_port", NULL); + if (!use_same_proxy) { + phost = (*my_get_string_func)(gconf_client, "/system/proxy/ftp_host", NULL); + pport = (*my_get_int_func)(gconf_client, "/system/proxy/ftp_port", NULL); + } use_proxy = (phost != NULL); if (use_proxy) type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID); @@ -237,8 +254,10 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env, if (strcasecmp(cproto, "gopher") == 0) { mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL); if (mode != NULL && (strcasecmp(mode,"manual") == 0)) { - phost = (*my_get_string_func)(gconf_client, "/system/proxy/gopher_host", NULL); - pport = (*my_get_int_func)(gconf_client, "/system/proxy/gopher_port", NULL); + if (!use_same_proxy) { + phost = (*my_get_string_func)(gconf_client, "/system/proxy/gopher_host", NULL); + pport = (*my_get_int_func)(gconf_client, "/system/proxy/gopher_port", NULL); + } use_proxy = (phost != NULL); if (use_proxy) type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_httpID); @@ -254,8 +273,10 @@ Java_sun_net_spi_DefaultProxySelector_getSystemProxy(JNIEnv *env, if (strcasecmp(cproto, "socks") == 0) { mode = (*my_get_string_func)(gconf_client, "/system/proxy/mode", NULL); if (mode != NULL && (strcasecmp(mode,"manual") == 0)) { - phost = (*my_get_string_func)(gconf_client, "/system/proxy/socks_host", NULL); - pport = (*my_get_int_func)(gconf_client, "/system/proxy/socks_port", NULL); + if (!use_same_proxy) { + phost = (*my_get_string_func)(gconf_client, "/system/proxy/socks_host", NULL); + pport = (*my_get_int_func)(gconf_client, "/system/proxy/socks_port", NULL); + } use_proxy = (phost != NULL); if (use_proxy) type_proxy = (*env)->GetStaticObjectField(env, ptype_class, ptype_socksID); diff --git a/jdk/test/java/net/ProxySelector/SystemProxies.java b/jdk/test/java/net/ProxySelector/SystemProxies.java new file mode 100644 index 00000000000..5d7a7bc6ecd --- /dev/null +++ b/jdk/test/java/net/ProxySelector/SystemProxies.java @@ -0,0 +1,61 @@ +/* + * Copyright 2010 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. + */ + +/* + * This is a manual test to determine the proxies set on the system for various + * protocols. See bug 6912868. + */ +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; + +public class SystemProxies { + + static final String uriAuthority = "myMachine/"; + static final ProxySelector proxySel = ProxySelector.getDefault(); + + public static void main(String[] args) { + if (! "true".equals(System.getProperty("java.net.useSystemProxies"))) { + System.out.println("Usage: java -Djava.net.useSystemProxies SystemProxies"); + return; + } + + printProxies("http://"); + printProxies("https://"); + printProxies("ftp://"); + } + + static void printProxies(String proto) { + String uriStr = proto + uriAuthority; + try { + List proxies = proxySel.select(new URI(uriStr)); + System.out.println("Proxies returned for " + uriStr); + for (Proxy proxy : proxies) + System.out.println("\t" + proxy); + } catch (URISyntaxException e) { + System.err.println(e); + } + } +} From 6c012bed487d92000415ff100811e888c764e634 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Tue, 23 Feb 2010 17:08:23 +0000 Subject: [PATCH 31/31] 6365587: Proxy-Connection header sent through tunnel Reviewed-by: michaelm --- .../classes/sun/net/www/protocol/http/HttpURLConnection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 732e9b3dce3..ac5eb2d281c 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -423,7 +423,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { // Try keep-alive only on first attempt if (!failedOnce && http.getHttpKeepAliveSet()) { - if (http.usingProxy) { + if (http.usingProxy && tunnelState() != TunnelState.TUNNELING) { requests.setIfNotSet("Proxy-Connection", "keep-alive"); } else { requests.setIfNotSet("Connection", "keep-alive");