Merge
This commit is contained in:
commit
e4961abb71
1
.hgtags
1
.hgtags
@ -284,3 +284,4 @@ b409bc51bc23cfd51f2bd04ea919ec83535af9d0 jdk9-b37
|
||||
4e7c4d692e934cb9023af8201e7c2b510e9c4ee1 jdk9-b39
|
||||
82f4cb44b2d7af2352f48568a64b7b6a5ae960cd jdk9-b40
|
||||
9fffb959eb4197ff806e4ac12244761815b4deee jdk9-b41
|
||||
3107be2ba9c6e208a0b86bc7100a141abbc5b5fb jdk9-b42
|
||||
|
@ -284,3 +284,4 @@ d42c0a90afc3c66ca87543076ec9aafd4b4680de jdk9-b38
|
||||
512dbbeb1730edcebfec873fc3f1455660b32000 jdk9-b39
|
||||
cf136458ee747e151a27aa9ea0c1492ea55ef3e7 jdk9-b40
|
||||
67395f7ca2db3b52e3a62a84888487de5cb9210a jdk9-b41
|
||||
f7c11da0b0481d49cc7a65a453336c108191e821 jdk9-b42
|
||||
|
@ -73,31 +73,25 @@ AC_DEFUN([BOOTJDK_DO_CHECK],
|
||||
AC_MSG_NOTICE([(This might be an JRE instead of an JDK)])
|
||||
BOOT_JDK_FOUND=no
|
||||
else
|
||||
# Do we have an rt.jar? (On MacOSX it is called classes.jar)
|
||||
if test ! -f "$BOOT_JDK/jre/lib/rt.jar" && test ! -f "$BOOT_JDK/../Classes/classes.jar"; then
|
||||
AC_MSG_NOTICE([Potential Boot JDK found at $BOOT_JDK did not contain an rt.jar; ignoring])
|
||||
# Oh, this is looking good! We probably have found a proper JDK. Is it the correct version?
|
||||
BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | head -n 1`
|
||||
|
||||
# Extra M4 quote needed to protect [] in grep expression.
|
||||
[FOUND_CORRECT_VERSION=`echo $BOOT_JDK_VERSION | grep '\"1\.[89]\.'`]
|
||||
if test "x$FOUND_CORRECT_VERSION" = x; then
|
||||
AC_MSG_NOTICE([Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring])
|
||||
AC_MSG_NOTICE([(Your Boot JDK must be version 8 or 9)])
|
||||
BOOT_JDK_FOUND=no
|
||||
else
|
||||
# Oh, this is looking good! We probably have found a proper JDK. Is it the correct version?
|
||||
BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | head -n 1`
|
||||
|
||||
# Extra M4 quote needed to protect [] in grep expression.
|
||||
[FOUND_CORRECT_VERSION=`echo $BOOT_JDK_VERSION | grep '\"1\.[89]\.'`]
|
||||
if test "x$FOUND_CORRECT_VERSION" = x; then
|
||||
AC_MSG_NOTICE([Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring])
|
||||
AC_MSG_NOTICE([(Your Boot JDK must be version 8 or 9)])
|
||||
BOOT_JDK_FOUND=no
|
||||
else
|
||||
# We're done! :-)
|
||||
BOOT_JDK_FOUND=yes
|
||||
BASIC_FIXUP_PATH(BOOT_JDK)
|
||||
AC_MSG_CHECKING([for Boot JDK])
|
||||
AC_MSG_RESULT([$BOOT_JDK])
|
||||
AC_MSG_CHECKING([Boot JDK version])
|
||||
BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $TR '\n\r' ' '`
|
||||
AC_MSG_RESULT([$BOOT_JDK_VERSION])
|
||||
fi # end check jdk version
|
||||
fi # end check rt.jar
|
||||
# We're done! :-)
|
||||
BOOT_JDK_FOUND=yes
|
||||
BASIC_FIXUP_PATH(BOOT_JDK)
|
||||
AC_MSG_CHECKING([for Boot JDK])
|
||||
AC_MSG_RESULT([$BOOT_JDK])
|
||||
AC_MSG_CHECKING([Boot JDK version])
|
||||
BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $TR '\n\r' ' '`
|
||||
AC_MSG_RESULT([$BOOT_JDK_VERSION])
|
||||
fi # end check jdk version
|
||||
fi # end check javac
|
||||
fi # end check java
|
||||
fi # end check boot jdk found
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -284,3 +284,4 @@ ffd90c81d4ef9d94d880fc852e2fc482ecd9b374 jdk9-b36
|
||||
53bf36cb722db50815712258a77cb6bbe25a2f5f jdk9-b39
|
||||
e27c725d6c9d155667b35255f442d4ceb8c3c084 jdk9-b40
|
||||
1908b886ba1eda46fa725cf1160fe5d30fd1a7e5 jdk9-b41
|
||||
078bb11af876fe528d4b516f33ad4dd9bb60549e jdk9-b42
|
||||
|
@ -444,3 +444,4 @@ c363a8b87e477ee45d6d3cb2a36cb365141bc596 jdk9-b38
|
||||
9cb75e5e394827ccbaf2e15524108a412dc4ddc5 jdk9-b39
|
||||
6b09b3193d731e3288e2a240c504a20d0a06c766 jdk9-b40
|
||||
1d29b13e8a515a7ea3b882f140576d5d675bc11f jdk9-b41
|
||||
38cb4fbd47e3472bd1b5ebac83bda96fe4869c4f jdk9-b42
|
||||
|
@ -675,7 +675,7 @@ OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) {
|
||||
case handle_exception_nofpu_id:
|
||||
case handle_exception_id:
|
||||
// At this point all registers MAY be live.
|
||||
oop_map = save_live_registers(sasm, 1 /*thread*/, id == handle_exception_nofpu_id);
|
||||
oop_map = save_live_registers(sasm, 1 /*thread*/, id != handle_exception_nofpu_id);
|
||||
break;
|
||||
case handle_exception_from_callee_id: {
|
||||
// At this point all registers except exception oop (RAX) and
|
||||
@ -748,7 +748,7 @@ OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) {
|
||||
case handle_exception_nofpu_id:
|
||||
case handle_exception_id:
|
||||
// Restore the registers that were saved at the beginning.
|
||||
restore_live_registers(sasm, id == handle_exception_nofpu_id);
|
||||
restore_live_registers(sasm, id != handle_exception_nofpu_id);
|
||||
break;
|
||||
case handle_exception_from_callee_id:
|
||||
// WIN64_ONLY: No need to add frame::arg_reg_save_area_bytes to SP
|
||||
|
@ -4144,8 +4144,29 @@ int os::available(int fd, jlong *bytes) {
|
||||
char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
|
||||
char *addr, size_t bytes, bool read_only,
|
||||
bool allow_exec) {
|
||||
Unimplemented();
|
||||
return NULL;
|
||||
int prot;
|
||||
int flags = MAP_PRIVATE;
|
||||
|
||||
if (read_only) {
|
||||
prot = PROT_READ;
|
||||
} else {
|
||||
prot = PROT_READ | PROT_WRITE;
|
||||
}
|
||||
|
||||
if (allow_exec) {
|
||||
prot |= PROT_EXEC;
|
||||
}
|
||||
|
||||
if (addr != NULL) {
|
||||
flags |= MAP_FIXED;
|
||||
}
|
||||
|
||||
char* mapped_address = (char*)mmap(addr, (size_t)bytes, prot, flags,
|
||||
fd, file_offset);
|
||||
if (mapped_address == MAP_FAILED) {
|
||||
return NULL;
|
||||
}
|
||||
return mapped_address;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3108,21 +3108,39 @@ void ClassFileParser::apply_parsed_class_attributes(instanceKlassHandle k) {
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer ownership of metadata allocated to the InstanceKlass.
|
||||
void ClassFileParser::apply_parsed_class_metadata(
|
||||
instanceKlassHandle this_klass,
|
||||
int java_fields_count, TRAPS) {
|
||||
// Assign annotations if needed
|
||||
if (_annotations != NULL || _type_annotations != NULL ||
|
||||
_fields_annotations != NULL || _fields_type_annotations != NULL) {
|
||||
// Create the Annotations object that will
|
||||
// hold the annotations array for the Klass.
|
||||
void ClassFileParser::create_combined_annotations(TRAPS) {
|
||||
if (_annotations == NULL &&
|
||||
_type_annotations == NULL &&
|
||||
_fields_annotations == NULL &&
|
||||
_fields_type_annotations == NULL) {
|
||||
// Don't create the Annotations object unnecessarily.
|
||||
return;
|
||||
}
|
||||
|
||||
Annotations* annotations = Annotations::allocate(_loader_data, CHECK);
|
||||
annotations->set_class_annotations(_annotations);
|
||||
annotations->set_class_type_annotations(_type_annotations);
|
||||
annotations->set_fields_annotations(_fields_annotations);
|
||||
annotations->set_fields_type_annotations(_fields_type_annotations);
|
||||
this_klass->set_annotations(annotations);
|
||||
}
|
||||
|
||||
// This is the Annotations object that will be
|
||||
// assigned to InstanceKlass being constructed.
|
||||
_combined_annotations = annotations;
|
||||
|
||||
// The annotations arrays below has been transfered the
|
||||
// _combined_annotations so these fields can now be cleared.
|
||||
_annotations = NULL;
|
||||
_type_annotations = NULL;
|
||||
_fields_annotations = NULL;
|
||||
_fields_type_annotations = NULL;
|
||||
}
|
||||
|
||||
// Transfer ownership of metadata allocated to the InstanceKlass.
|
||||
void ClassFileParser::apply_parsed_class_metadata(
|
||||
instanceKlassHandle this_klass,
|
||||
int java_fields_count, TRAPS) {
|
||||
_cp->set_pool_holder(this_klass());
|
||||
this_klass->set_constants(_cp);
|
||||
this_klass->set_fields(_fields, java_fields_count);
|
||||
@ -3130,6 +3148,7 @@ void ClassFileParser::apply_parsed_class_metadata(
|
||||
this_klass->set_inner_classes(_inner_classes);
|
||||
this_klass->set_local_interfaces(_local_interfaces);
|
||||
this_klass->set_transitive_interfaces(_transitive_interfaces);
|
||||
this_klass->set_annotations(_combined_annotations);
|
||||
|
||||
// Clear out these fields so they don't get deallocated by the destructor
|
||||
clear_class_metadata();
|
||||
@ -4002,6 +4021,10 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
ClassAnnotationCollector parsed_annotations;
|
||||
parse_classfile_attributes(&parsed_annotations, CHECK_(nullHandle));
|
||||
|
||||
// Finalize the Annotations metadata object,
|
||||
// now that all annotation arrays have been created.
|
||||
create_combined_annotations(CHECK_(nullHandle));
|
||||
|
||||
// Make sure this is the end of class file stream
|
||||
guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle));
|
||||
|
||||
@ -4302,10 +4325,27 @@ ClassFileParser::~ClassFileParser() {
|
||||
InstanceKlass::deallocate_interfaces(_loader_data, _super_klass(),
|
||||
_local_interfaces, _transitive_interfaces);
|
||||
|
||||
MetadataFactory::free_array<u1>(_loader_data, _annotations);
|
||||
MetadataFactory::free_array<u1>(_loader_data, _type_annotations);
|
||||
Annotations::free_contents(_loader_data, _fields_annotations);
|
||||
Annotations::free_contents(_loader_data, _fields_type_annotations);
|
||||
if (_combined_annotations != NULL) {
|
||||
// After all annotations arrays have been created, they are installed into the
|
||||
// Annotations object that will be assigned to the InstanceKlass being created.
|
||||
|
||||
// Deallocate the Annotations object and the installed annotations arrays.
|
||||
_combined_annotations->deallocate_contents(_loader_data);
|
||||
|
||||
// If the _combined_annotations pointer is non-NULL,
|
||||
// then the other annotations fields should have been cleared.
|
||||
assert(_annotations == NULL, "Should have been cleared");
|
||||
assert(_type_annotations == NULL, "Should have been cleared");
|
||||
assert(_fields_annotations == NULL, "Should have been cleared");
|
||||
assert(_fields_type_annotations == NULL, "Should have been cleared");
|
||||
} else {
|
||||
// If the annotations arrays were not installed into the Annotations object,
|
||||
// then they have to be deallocated explicitly.
|
||||
MetadataFactory::free_array<u1>(_loader_data, _annotations);
|
||||
MetadataFactory::free_array<u1>(_loader_data, _type_annotations);
|
||||
Annotations::free_contents(_loader_data, _fields_annotations);
|
||||
Annotations::free_contents(_loader_data, _fields_type_annotations);
|
||||
}
|
||||
|
||||
clear_class_metadata();
|
||||
|
||||
|
@ -75,6 +75,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
Array<u2>* _inner_classes;
|
||||
Array<Klass*>* _local_interfaces;
|
||||
Array<Klass*>* _transitive_interfaces;
|
||||
Annotations* _combined_annotations;
|
||||
AnnotationArray* _annotations;
|
||||
AnnotationArray* _type_annotations;
|
||||
Array<AnnotationArray*>* _fields_annotations;
|
||||
@ -86,6 +87,8 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
void set_class_generic_signature_index(u2 x) { _generic_signature_index = x; }
|
||||
void set_class_sde_buffer(char* x, int len) { _sde_buffer = x; _sde_length = len; }
|
||||
|
||||
void create_combined_annotations(TRAPS);
|
||||
|
||||
void init_parsed_class_attributes(ClassLoaderData* loader_data) {
|
||||
_loader_data = loader_data;
|
||||
_synthetic_flag = false;
|
||||
@ -110,6 +113,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
_inner_classes = NULL;
|
||||
_local_interfaces = NULL;
|
||||
_transitive_interfaces = NULL;
|
||||
_combined_annotations = NULL;
|
||||
_annotations = _type_annotations = NULL;
|
||||
_fields_annotations = _fields_type_annotations = NULL;
|
||||
}
|
||||
|
@ -795,11 +795,6 @@ void ConcurrentMarkSweepGeneration::promotion_failure_occurred() {
|
||||
}
|
||||
}
|
||||
|
||||
CompactibleSpace*
|
||||
ConcurrentMarkSweepGeneration::first_compaction_space() const {
|
||||
return _cmsSpace;
|
||||
}
|
||||
|
||||
void ConcurrentMarkSweepGeneration::reset_after_compaction() {
|
||||
// Clear the promotion information. These pointers can be adjusted
|
||||
// along with all the other pointers into the heap but
|
||||
@ -810,10 +805,6 @@ void ConcurrentMarkSweepGeneration::reset_after_compaction() {
|
||||
}
|
||||
}
|
||||
|
||||
void ConcurrentMarkSweepGeneration::space_iterate(SpaceClosure* blk, bool usedOnly) {
|
||||
blk->do_space(_cmsSpace);
|
||||
}
|
||||
|
||||
void ConcurrentMarkSweepGeneration::compute_new_size() {
|
||||
assert_locked_or_safepoint(Heap_lock);
|
||||
|
||||
@ -884,7 +875,7 @@ void ConcurrentMarkSweepGeneration::compute_new_size_free_list() {
|
||||
expand_bytes);
|
||||
}
|
||||
// safe if expansion fails
|
||||
expand(expand_bytes, 0, CMSExpansionCause::_satisfy_free_ratio);
|
||||
expand_for_gc_cause(expand_bytes, 0, CMSExpansionCause::_satisfy_free_ratio);
|
||||
if (PrintGCDetails && Verbose) {
|
||||
gclog_or_tty->print_cr(" Expanded free fraction %f",
|
||||
((double) free()) / capacity());
|
||||
@ -1050,8 +1041,7 @@ oop ConcurrentMarkSweepGeneration::promote(oop obj, size_t obj_size) {
|
||||
if (res == NULL) {
|
||||
// expand and retry
|
||||
size_t s = _cmsSpace->expansionSpaceRequired(obj_size); // HeapWords
|
||||
expand(s*HeapWordSize, MinHeapDeltaBytes,
|
||||
CMSExpansionCause::_satisfy_promotion);
|
||||
expand_for_gc_cause(s*HeapWordSize, MinHeapDeltaBytes, CMSExpansionCause::_satisfy_promotion);
|
||||
// Since there's currently no next generation, we don't try to promote
|
||||
// into a more senior generation.
|
||||
assert(next_gen() == NULL, "assumption, based upon which no attempt "
|
||||
@ -2626,13 +2616,6 @@ oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl) { \
|
||||
|
||||
ALL_SINCE_SAVE_MARKS_CLOSURES(CMS_SINCE_SAVE_MARKS_DEFN)
|
||||
|
||||
void
|
||||
ConcurrentMarkSweepGeneration::younger_refs_iterate(OopsInGenClosure* cl) {
|
||||
cl->set_generation(this);
|
||||
younger_refs_in_space_iterate(_cmsSpace, cl);
|
||||
cl->reset_generation();
|
||||
}
|
||||
|
||||
void
|
||||
ConcurrentMarkSweepGeneration::oop_iterate(ExtendedOopClosure* cl) {
|
||||
if (freelistLock()->owned_by_self()) {
|
||||
@ -2805,23 +2788,17 @@ ConcurrentMarkSweepGeneration::expand_and_allocate(size_t word_size,
|
||||
CMSSynchronousYieldRequest yr;
|
||||
assert(!tlab, "Can't deal with TLAB allocation");
|
||||
MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
|
||||
expand(word_size*HeapWordSize, MinHeapDeltaBytes,
|
||||
CMSExpansionCause::_satisfy_allocation);
|
||||
expand_for_gc_cause(word_size*HeapWordSize, MinHeapDeltaBytes, CMSExpansionCause::_satisfy_allocation);
|
||||
if (GCExpandToAllocateDelayMillis > 0) {
|
||||
os::sleep(Thread::current(), GCExpandToAllocateDelayMillis, false);
|
||||
}
|
||||
return have_lock_and_allocate(word_size, tlab);
|
||||
}
|
||||
|
||||
// YSR: All of this generation expansion/shrinking stuff is an exact copy of
|
||||
// TenuredGeneration, which makes me wonder if we should move this
|
||||
// to CardGeneration and share it...
|
||||
bool ConcurrentMarkSweepGeneration::expand(size_t bytes, size_t expand_bytes) {
|
||||
return CardGeneration::expand(bytes, expand_bytes);
|
||||
}
|
||||
|
||||
void ConcurrentMarkSweepGeneration::expand(size_t bytes, size_t expand_bytes,
|
||||
CMSExpansionCause::Cause cause)
|
||||
void ConcurrentMarkSweepGeneration::expand_for_gc_cause(
|
||||
size_t bytes,
|
||||
size_t expand_bytes,
|
||||
CMSExpansionCause::Cause cause)
|
||||
{
|
||||
|
||||
bool success = expand(bytes, expand_bytes);
|
||||
@ -2850,8 +2827,7 @@ HeapWord* ConcurrentMarkSweepGeneration::expand_and_par_lab_allocate(CMSParGCThr
|
||||
return NULL;
|
||||
}
|
||||
// Otherwise, we try expansion.
|
||||
expand(word_sz*HeapWordSize, MinHeapDeltaBytes,
|
||||
CMSExpansionCause::_allocate_par_lab);
|
||||
expand_for_gc_cause(word_sz*HeapWordSize, MinHeapDeltaBytes, CMSExpansionCause::_allocate_par_lab);
|
||||
// Now go around the loop and try alloc again;
|
||||
// A competing par_promote might beat us to the expansion space,
|
||||
// so we may go around the loop again if promotion fails again.
|
||||
@ -2878,8 +2854,7 @@ bool ConcurrentMarkSweepGeneration::expand_and_ensure_spooling_space(
|
||||
return false;
|
||||
}
|
||||
// Otherwise, we try expansion.
|
||||
expand(refill_size_bytes, MinHeapDeltaBytes,
|
||||
CMSExpansionCause::_allocate_par_spooling_space);
|
||||
expand_for_gc_cause(refill_size_bytes, MinHeapDeltaBytes, CMSExpansionCause::_allocate_par_spooling_space);
|
||||
// Now go around the loop and try alloc again;
|
||||
// A competing allocation might beat us to the expansion space,
|
||||
// so we may go around the loop again if allocation fails again.
|
||||
@ -2889,77 +2864,16 @@ bool ConcurrentMarkSweepGeneration::expand_and_ensure_spooling_space(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConcurrentMarkSweepGeneration::shrink_by(size_t bytes) {
|
||||
assert_locked_or_safepoint(ExpandHeap_lock);
|
||||
// Shrink committed space
|
||||
_virtual_space.shrink_by(bytes);
|
||||
// Shrink space; this also shrinks the space's BOT
|
||||
_cmsSpace->set_end((HeapWord*) _virtual_space.high());
|
||||
size_t new_word_size = heap_word_size(_cmsSpace->capacity());
|
||||
// Shrink the shared block offset array
|
||||
_bts->resize(new_word_size);
|
||||
MemRegion mr(_cmsSpace->bottom(), new_word_size);
|
||||
// Shrink the card table
|
||||
Universe::heap()->barrier_set()->resize_covered_region(mr);
|
||||
|
||||
if (Verbose && PrintGC) {
|
||||
size_t new_mem_size = _virtual_space.committed_size();
|
||||
size_t old_mem_size = new_mem_size + bytes;
|
||||
gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K",
|
||||
name(), old_mem_size/K, new_mem_size/K);
|
||||
}
|
||||
}
|
||||
|
||||
void ConcurrentMarkSweepGeneration::shrink(size_t bytes) {
|
||||
assert_locked_or_safepoint(Heap_lock);
|
||||
size_t size = ReservedSpace::page_align_size_down(bytes);
|
||||
// Only shrink if a compaction was done so that all the free space
|
||||
// in the generation is in a contiguous block at the end.
|
||||
if (size > 0 && did_compact()) {
|
||||
shrink_by(size);
|
||||
if (did_compact()) {
|
||||
CardGeneration::shrink(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
bool ConcurrentMarkSweepGeneration::grow_by(size_t bytes) {
|
||||
void ConcurrentMarkSweepGeneration::assert_correct_size_change_locking() {
|
||||
assert_locked_or_safepoint(Heap_lock);
|
||||
bool result = _virtual_space.expand_by(bytes);
|
||||
if (result) {
|
||||
size_t new_word_size =
|
||||
heap_word_size(_virtual_space.committed_size());
|
||||
MemRegion mr(_cmsSpace->bottom(), new_word_size);
|
||||
_bts->resize(new_word_size); // resize the block offset shared array
|
||||
Universe::heap()->barrier_set()->resize_covered_region(mr);
|
||||
// Hmmmm... why doesn't CFLS::set_end verify locking?
|
||||
// This is quite ugly; FIX ME XXX
|
||||
_cmsSpace->assert_locked(freelistLock());
|
||||
_cmsSpace->set_end((HeapWord*)_virtual_space.high());
|
||||
|
||||
// update the space and generation capacity counters
|
||||
if (UsePerfData) {
|
||||
_space_counters->update_capacity();
|
||||
_gen_counters->update_all();
|
||||
}
|
||||
|
||||
if (Verbose && PrintGC) {
|
||||
size_t new_mem_size = _virtual_space.committed_size();
|
||||
size_t old_mem_size = new_mem_size - bytes;
|
||||
gclog_or_tty->print_cr("Expanding %s from " SIZE_FORMAT "K by " SIZE_FORMAT "K to " SIZE_FORMAT "K",
|
||||
name(), old_mem_size/K, bytes/K, new_mem_size/K);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ConcurrentMarkSweepGeneration::grow_to_reserved() {
|
||||
assert_locked_or_safepoint(Heap_lock);
|
||||
bool success = true;
|
||||
const size_t remaining_bytes = _virtual_space.uncommitted_size();
|
||||
if (remaining_bytes > 0) {
|
||||
success = grow_by(remaining_bytes);
|
||||
DEBUG_ONLY(if (!success) warning("grow to reserved failed");)
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void ConcurrentMarkSweepGeneration::shrink_free_list_by(size_t bytes) {
|
||||
|
@ -30,9 +30,10 @@
|
||||
#include "gc_implementation/shared/gcStats.hpp"
|
||||
#include "gc_implementation/shared/gcWhen.hpp"
|
||||
#include "gc_implementation/shared/generationCounters.hpp"
|
||||
#include "memory/cardGeneration.hpp"
|
||||
#include "memory/freeBlockDictionary.hpp"
|
||||
#include "memory/generation.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
#include "memory/space.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "runtime/virtualspace.hpp"
|
||||
#include "services/memoryService.hpp"
|
||||
@ -171,9 +172,7 @@ class CMSBitMap VALUE_OBJ_CLASS_SPEC {
|
||||
// Represents a marking stack used by the CMS collector.
|
||||
// Ideally this should be GrowableArray<> just like MSC's marking stack(s).
|
||||
class CMSMarkStack: public CHeapObj<mtGC> {
|
||||
//
|
||||
friend class CMSCollector; // To get at expansion stats further below.
|
||||
//
|
||||
|
||||
VirtualSpace _virtual_space; // Space for the stack
|
||||
oop* _base; // Bottom of stack
|
||||
@ -1032,6 +1031,9 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
|
||||
void set_expansion_cause(CMSExpansionCause::Cause v) { _expansion_cause = v;}
|
||||
CMSExpansionCause::Cause expansion_cause() const { return _expansion_cause; }
|
||||
|
||||
// Accessing spaces
|
||||
CompactibleSpace* space() const { return (CompactibleSpace*)_cmsSpace; }
|
||||
|
||||
private:
|
||||
// For parallel young-gen GC support.
|
||||
CMSParGCThreadState** _par_gc_thread_states;
|
||||
@ -1065,6 +1067,10 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
|
||||
double initiating_occupancy() const { return _initiating_occupancy; }
|
||||
void init_initiating_occupancy(intx io, uintx tr);
|
||||
|
||||
void expand_for_gc_cause(size_t bytes, size_t expand_bytes, CMSExpansionCause::Cause cause);
|
||||
|
||||
void assert_correct_size_change_locking();
|
||||
|
||||
public:
|
||||
ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size,
|
||||
int level, CardTableRS* ct,
|
||||
@ -1101,23 +1107,14 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
|
||||
// Override
|
||||
virtual void ref_processor_init();
|
||||
|
||||
// Grow generation by specified size (returns false if unable to grow)
|
||||
bool grow_by(size_t bytes);
|
||||
// Grow generation to reserved size.
|
||||
bool grow_to_reserved();
|
||||
|
||||
void clear_expansion_cause() { _expansion_cause = CMSExpansionCause::_no_expansion; }
|
||||
|
||||
// Space enquiries
|
||||
size_t capacity() const;
|
||||
size_t used() const;
|
||||
size_t free() const;
|
||||
double occupancy() const { return ((double)used())/((double)capacity()); }
|
||||
size_t contiguous_available() const;
|
||||
size_t unsafe_max_alloc_nogc() const;
|
||||
|
||||
// over-rides
|
||||
MemRegion used_region() const;
|
||||
MemRegion used_region_at_save_marks() const;
|
||||
|
||||
// Does a "full" (forced) collection invoked on this generation collect
|
||||
@ -1128,10 +1125,6 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
|
||||
return !ScavengeBeforeFullGC;
|
||||
}
|
||||
|
||||
void space_iterate(SpaceClosure* blk, bool usedOnly = false);
|
||||
|
||||
// Support for compaction
|
||||
CompactibleSpace* first_compaction_space() const;
|
||||
// Adjust quantities in the generation affected by
|
||||
// the compaction.
|
||||
void reset_after_compaction();
|
||||
@ -1191,18 +1184,13 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
|
||||
}
|
||||
|
||||
// Allocation failure
|
||||
void expand(size_t bytes, size_t expand_bytes,
|
||||
CMSExpansionCause::Cause cause);
|
||||
virtual bool expand(size_t bytes, size_t expand_bytes);
|
||||
void shrink(size_t bytes);
|
||||
void shrink_by(size_t bytes);
|
||||
HeapWord* expand_and_par_lab_allocate(CMSParGCThreadState* ps, size_t word_sz);
|
||||
bool expand_and_ensure_spooling_space(PromotionInfo* promo);
|
||||
|
||||
// Iteration support and related enquiries
|
||||
void save_marks();
|
||||
bool no_allocs_since_save_marks();
|
||||
void younger_refs_iterate(OopsInGenClosure* cl);
|
||||
|
||||
// Iteration support specific to CMS generations
|
||||
void save_sweep_limit();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -369,22 +369,6 @@ inline void ConcurrentMarkSweepGeneration::save_sweep_limit() {
|
||||
cmsSpace()->save_sweep_limit();
|
||||
}
|
||||
|
||||
inline size_t ConcurrentMarkSweepGeneration::capacity() const {
|
||||
return _cmsSpace->capacity();
|
||||
}
|
||||
|
||||
inline size_t ConcurrentMarkSweepGeneration::used() const {
|
||||
return _cmsSpace->used();
|
||||
}
|
||||
|
||||
inline size_t ConcurrentMarkSweepGeneration::free() const {
|
||||
return _cmsSpace->free();
|
||||
}
|
||||
|
||||
inline MemRegion ConcurrentMarkSweepGeneration::used_region() const {
|
||||
return _cmsSpace->used_region();
|
||||
}
|
||||
|
||||
inline MemRegion ConcurrentMarkSweepGeneration::used_region_at_save_marks() const {
|
||||
return _cmsSpace->used_region_at_save_marks();
|
||||
}
|
||||
|
@ -352,7 +352,7 @@ void YoungList::print() {
|
||||
}
|
||||
|
||||
void G1RegionMappingChangedListener::reset_from_card_cache(uint start_idx, size_t num_regions) {
|
||||
OtherRegionsTable::invalidate(start_idx, num_regions);
|
||||
HeapRegionRemSet::invalidate_from_card_cache(start_idx, num_regions);
|
||||
}
|
||||
|
||||
void G1RegionMappingChangedListener::on_commit(uint start_idx, size_t num_regions, bool zero_filled) {
|
||||
|
@ -407,20 +407,8 @@ void FromCardCache::clear(uint region_idx) {
|
||||
}
|
||||
}
|
||||
|
||||
void OtherRegionsTable::initialize(uint max_regions) {
|
||||
FromCardCache::initialize(HeapRegionRemSet::num_par_rem_sets(), max_regions);
|
||||
}
|
||||
|
||||
void OtherRegionsTable::invalidate(uint start_idx, size_t num_regions) {
|
||||
FromCardCache::invalidate(start_idx, num_regions);
|
||||
}
|
||||
|
||||
void OtherRegionsTable::print_from_card_cache() {
|
||||
FromCardCache::print();
|
||||
}
|
||||
|
||||
void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) {
|
||||
uint cur_hrm_ind = hr()->hrm_index();
|
||||
uint cur_hrm_ind = _hr->hrm_index();
|
||||
|
||||
if (G1TraceHeapRegionRememberedSet) {
|
||||
gclog_or_tty->print_cr("ORT::add_reference_work(" PTR_FORMAT "->" PTR_FORMAT ").",
|
||||
@ -434,7 +422,7 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) {
|
||||
|
||||
if (G1TraceHeapRegionRememberedSet) {
|
||||
gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = %d)",
|
||||
hr()->bottom(), from_card,
|
||||
_hr->bottom(), from_card,
|
||||
FromCardCache::at(tid, cur_hrm_ind));
|
||||
}
|
||||
|
||||
@ -477,13 +465,13 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) {
|
||||
if (G1HRRSUseSparseTable &&
|
||||
_sparse_table.add_card(from_hrm_ind, card_index)) {
|
||||
if (G1RecordHRRSOops) {
|
||||
HeapRegionRemSet::record(hr(), from);
|
||||
HeapRegionRemSet::record(_hr, from);
|
||||
if (G1TraceHeapRegionRememberedSet) {
|
||||
gclog_or_tty->print(" Added card " PTR_FORMAT " to region "
|
||||
"[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n",
|
||||
align_size_down(uintptr_t(from),
|
||||
CardTableModRefBS::card_size),
|
||||
hr()->bottom(), from);
|
||||
_hr->bottom(), from);
|
||||
}
|
||||
}
|
||||
if (G1TraceHeapRegionRememberedSet) {
|
||||
@ -539,13 +527,13 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) {
|
||||
prt->add_reference(from);
|
||||
|
||||
if (G1RecordHRRSOops) {
|
||||
HeapRegionRemSet::record(hr(), from);
|
||||
HeapRegionRemSet::record(_hr, from);
|
||||
if (G1TraceHeapRegionRememberedSet) {
|
||||
gclog_or_tty->print("Added card " PTR_FORMAT " to region "
|
||||
"[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n",
|
||||
align_size_down(uintptr_t(from),
|
||||
CardTableModRefBS::card_size),
|
||||
hr()->bottom(), from);
|
||||
_hr->bottom(), from);
|
||||
}
|
||||
}
|
||||
assert(contains_reference(from), "We just added it!");
|
||||
@ -614,7 +602,7 @@ PerRegionTable* OtherRegionsTable::delete_region_table() {
|
||||
if (G1TraceHeapRegionRememberedSet) {
|
||||
gclog_or_tty->print("Coarsened entry in region [" PTR_FORMAT "...] "
|
||||
"for region [" PTR_FORMAT "...] (" SIZE_FORMAT " coarse entries).\n",
|
||||
hr()->bottom(),
|
||||
_hr->bottom(),
|
||||
max->hr()->bottom(),
|
||||
_n_coarse_entries);
|
||||
}
|
||||
@ -627,13 +615,11 @@ PerRegionTable* OtherRegionsTable::delete_region_table() {
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
// At present, this must be called stop-world single-threaded.
|
||||
void OtherRegionsTable::scrub(CardTableModRefBS* ctbs,
|
||||
BitMap* region_bm, BitMap* card_bm) {
|
||||
// First eliminated garbage regions from the coarse map.
|
||||
if (G1RSScrubVerbose) {
|
||||
gclog_or_tty->print_cr("Scrubbing region %u:", hr()->hrm_index());
|
||||
gclog_or_tty->print_cr("Scrubbing region %u:", _hr->hrm_index());
|
||||
}
|
||||
|
||||
assert(_coarse_map.size() == region_bm->size(), "Precondition");
|
||||
@ -752,7 +738,7 @@ size_t OtherRegionsTable::fl_mem_size() {
|
||||
}
|
||||
|
||||
void OtherRegionsTable::clear_fcc() {
|
||||
FromCardCache::clear(hr()->hrm_index());
|
||||
FromCardCache::clear(_hr->hrm_index());
|
||||
}
|
||||
|
||||
void OtherRegionsTable::clear() {
|
||||
@ -774,27 +760,6 @@ void OtherRegionsTable::clear() {
|
||||
clear_fcc();
|
||||
}
|
||||
|
||||
bool OtherRegionsTable::del_single_region_table(size_t ind,
|
||||
HeapRegion* hr) {
|
||||
assert(0 <= ind && ind < _max_fine_entries, "Preconditions.");
|
||||
PerRegionTable** prev_addr = &_fine_grain_regions[ind];
|
||||
PerRegionTable* prt = *prev_addr;
|
||||
while (prt != NULL && prt->hr() != hr) {
|
||||
prev_addr = prt->collision_list_next_addr();
|
||||
prt = prt->collision_list_next();
|
||||
}
|
||||
if (prt != NULL) {
|
||||
assert(prt->hr() == hr, "Loop postcondition.");
|
||||
*prev_addr = prt->collision_list_next();
|
||||
unlink_from_all(prt);
|
||||
PerRegionTable::free(prt);
|
||||
_n_fine_entries--;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool OtherRegionsTable::contains_reference(OopOrNarrowOopStar from) const {
|
||||
// Cast away const in this case.
|
||||
MutexLockerEx x((Mutex*)_m, Mutex::_no_safepoint_check_flag);
|
||||
@ -975,7 +940,7 @@ HeapRegionRemSetIterator:: HeapRegionRemSetIterator(HeapRegionRemSet* hrrs) :
|
||||
_hrrs(hrrs),
|
||||
_g1h(G1CollectedHeap::heap()),
|
||||
_coarse_map(&hrrs->_other_regions._coarse_map),
|
||||
_bosa(hrrs->bosa()),
|
||||
_bosa(hrrs->_bosa),
|
||||
_is(Sparse),
|
||||
// Set these values so that we increment to the first region.
|
||||
_coarse_cur_region_index(-1),
|
||||
|
@ -162,32 +162,36 @@ class OtherRegionsTable VALUE_OBJ_CLASS_SPEC {
|
||||
// to hold _m, and the fine-grain table to be full.
|
||||
PerRegionTable* delete_region_table();
|
||||
|
||||
// If a PRT for "hr" is in the bucket list indicated by "ind" (which must
|
||||
// be the correct index for "hr"), delete it and return true; else return
|
||||
// false.
|
||||
bool del_single_region_table(size_t ind, HeapRegion* hr);
|
||||
|
||||
// link/add the given fine grain remembered set into the "all" list
|
||||
void link_to_all(PerRegionTable * prt);
|
||||
// unlink/remove the given fine grain remembered set into the "all" list
|
||||
void unlink_from_all(PerRegionTable * prt);
|
||||
|
||||
public:
|
||||
OtherRegionsTable(HeapRegion* hr, Mutex* m);
|
||||
bool contains_reference_locked(OopOrNarrowOopStar from) const;
|
||||
|
||||
HeapRegion* hr() const { return _hr; }
|
||||
// Clear the from_card_cache entries for this region.
|
||||
void clear_fcc();
|
||||
public:
|
||||
// Create a new remembered set for the given heap region. The given mutex should
|
||||
// be used to ensure consistency.
|
||||
OtherRegionsTable(HeapRegion* hr, Mutex* m);
|
||||
|
||||
// For now. Could "expand" some tables in the future, so that this made
|
||||
// sense.
|
||||
void add_reference(OopOrNarrowOopStar from, uint tid);
|
||||
|
||||
// Returns whether the remembered set contains the given reference.
|
||||
bool contains_reference(OopOrNarrowOopStar from) const;
|
||||
|
||||
// Removes any entries shown by the given bitmaps to contain only dead
|
||||
// objects.
|
||||
// objects. Not thread safe.
|
||||
// Set bits in the bitmaps indicate that the given region or card is live.
|
||||
void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm);
|
||||
|
||||
// Returns whether this remembered set (and all sub-sets) contain no entries.
|
||||
// Returns whether this remembered set (and all sub-sets) does not contain any entry.
|
||||
bool is_empty() const;
|
||||
|
||||
// Returns the number of cards contained in this remembered set.
|
||||
size_t occupied() const;
|
||||
size_t occ_fine() const;
|
||||
size_t occ_coarse() const;
|
||||
@ -195,31 +199,17 @@ public:
|
||||
|
||||
static jint n_coarsenings() { return _n_coarsenings; }
|
||||
|
||||
// Returns size in bytes.
|
||||
// Not const because it takes a lock.
|
||||
// Returns size of the actual remembered set containers in bytes.
|
||||
size_t mem_size() const;
|
||||
// Returns the size of static data in bytes.
|
||||
static size_t static_mem_size();
|
||||
// Returns the size of the free list content in bytes.
|
||||
static size_t fl_mem_size();
|
||||
|
||||
bool contains_reference(OopOrNarrowOopStar from) const;
|
||||
bool contains_reference_locked(OopOrNarrowOopStar from) const;
|
||||
|
||||
// Clear the entire contents of this remembered set.
|
||||
void clear();
|
||||
|
||||
// Specifically clear the from_card_cache.
|
||||
void clear_fcc();
|
||||
|
||||
void do_cleanup_work(HRRSCleanupTask* hrrs_cleanup_task);
|
||||
|
||||
// Declare the heap size (in # of regions) to the OtherRegionsTable.
|
||||
// (Uses it to initialize from_card_cache).
|
||||
static void initialize(uint max_regions);
|
||||
|
||||
// Declares that regions between start_idx <= i < start_idx + num_regions are
|
||||
// not in use. Make sure that any entries for these regions are invalid.
|
||||
static void invalidate(uint start_idx, size_t num_regions);
|
||||
|
||||
static void print_from_card_cache();
|
||||
};
|
||||
|
||||
class HeapRegionRemSet : public CHeapObj<mtGC> {
|
||||
@ -233,7 +223,6 @@ public:
|
||||
|
||||
private:
|
||||
G1BlockOffsetSharedArray* _bosa;
|
||||
G1BlockOffsetSharedArray* bosa() const { return _bosa; }
|
||||
|
||||
// A set of code blobs (nmethods) whose code contains pointers into
|
||||
// the region that owns this RSet.
|
||||
@ -268,10 +257,6 @@ public:
|
||||
static uint num_par_rem_sets();
|
||||
static void setup_remset_size();
|
||||
|
||||
HeapRegion* hr() const {
|
||||
return _other_regions.hr();
|
||||
}
|
||||
|
||||
bool is_empty() const {
|
||||
return (strong_code_roots_list_length() == 0) && _other_regions.is_empty();
|
||||
}
|
||||
@ -305,8 +290,9 @@ public:
|
||||
_other_regions.add_reference(from, tid);
|
||||
}
|
||||
|
||||
// Removes any entries shown by the given bitmaps to contain only dead
|
||||
// objects.
|
||||
// Removes any entries in the remembered set shown by the given bitmaps to
|
||||
// contain only dead objects. Not thread safe.
|
||||
// One bits in the bitmaps indicate that the given region or card is live.
|
||||
void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm);
|
||||
|
||||
// The region is being reclaimed; clear its remset, and any mention of
|
||||
@ -397,16 +383,16 @@ public:
|
||||
// Declare the heap size (in # of regions) to the HeapRegionRemSet(s).
|
||||
// (Uses it to initialize from_card_cache).
|
||||
static void init_heap(uint max_regions) {
|
||||
OtherRegionsTable::initialize(max_regions);
|
||||
FromCardCache::initialize(num_par_rem_sets(), max_regions);
|
||||
}
|
||||
|
||||
static void invalidate(uint start_idx, uint num_regions) {
|
||||
OtherRegionsTable::invalidate(start_idx, num_regions);
|
||||
static void invalidate_from_card_cache(uint start_idx, size_t num_regions) {
|
||||
FromCardCache::invalidate(start_idx, num_regions);
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
static void print_from_card_cache() {
|
||||
OtherRegionsTable::print_from_card_cache();
|
||||
FromCardCache::print();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -172,6 +172,27 @@ void YoungGCTracer::report_tenuring_threshold(const uint tenuring_threshold) {
|
||||
_tenuring_threshold = tenuring_threshold;
|
||||
}
|
||||
|
||||
bool YoungGCTracer::should_report_promotion_in_new_plab_event() const {
|
||||
return should_send_promotion_in_new_plab_event();
|
||||
}
|
||||
|
||||
bool YoungGCTracer::should_report_promotion_outside_plab_event() const {
|
||||
return should_send_promotion_outside_plab_event();
|
||||
}
|
||||
|
||||
void YoungGCTracer::report_promotion_in_new_plab_event(Klass* klass, size_t obj_size,
|
||||
uint age, bool tenured,
|
||||
size_t plab_size) const {
|
||||
assert_set_gc_id();
|
||||
send_promotion_in_new_plab_event(klass, obj_size, age, tenured, plab_size);
|
||||
}
|
||||
|
||||
void YoungGCTracer::report_promotion_outside_plab_event(Klass* klass, size_t obj_size,
|
||||
uint age, bool tenured) const {
|
||||
assert_set_gc_id();
|
||||
send_promotion_outside_plab_event(klass, obj_size, age, tenured);
|
||||
}
|
||||
|
||||
void OldGCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
|
||||
assert_set_gc_id();
|
||||
|
||||
|
@ -156,9 +156,38 @@ class YoungGCTracer : public GCTracer {
|
||||
void report_promotion_failed(const PromotionFailedInfo& pf_info);
|
||||
void report_tenuring_threshold(const uint tenuring_threshold);
|
||||
|
||||
/*
|
||||
* Methods for reporting Promotion in new or outside PLAB Events.
|
||||
*
|
||||
* The object age is always required as it is not certain that the mark word
|
||||
* of the oop can be trusted at this stage.
|
||||
*
|
||||
* obj_size is the size of the promoted object in bytes.
|
||||
*
|
||||
* tenured should be true if the object has been promoted to the old
|
||||
* space during this GC, if the object is copied to survivor space
|
||||
* from young space or survivor space (aging) tenured should be false.
|
||||
*
|
||||
* plab_size is the size of the newly allocated PLAB in bytes.
|
||||
*/
|
||||
bool should_report_promotion_in_new_plab_event() const;
|
||||
bool should_report_promotion_outside_plab_event() const;
|
||||
void report_promotion_in_new_plab_event(Klass* klass, size_t obj_size,
|
||||
uint age, bool tenured,
|
||||
size_t plab_size) const;
|
||||
void report_promotion_outside_plab_event(Klass* klass, size_t obj_size,
|
||||
uint age, bool tenured) const;
|
||||
|
||||
private:
|
||||
void send_young_gc_event() const;
|
||||
void send_promotion_failed_event(const PromotionFailedInfo& pf_info) const;
|
||||
bool should_send_promotion_in_new_plab_event() const;
|
||||
bool should_send_promotion_outside_plab_event() const;
|
||||
void send_promotion_in_new_plab_event(Klass* klass, size_t obj_size,
|
||||
uint age, bool tenured,
|
||||
size_t plab_size) const;
|
||||
void send_promotion_outside_plab_event(Klass* klass, size_t obj_size,
|
||||
uint age, bool tenured) const;
|
||||
};
|
||||
|
||||
class OldGCTracer : public GCTracer {
|
||||
|
@ -111,6 +111,44 @@ void YoungGCTracer::send_young_gc_event() const {
|
||||
}
|
||||
}
|
||||
|
||||
bool YoungGCTracer::should_send_promotion_in_new_plab_event() const {
|
||||
return EventPromoteObjectInNewPLAB::is_enabled();
|
||||
}
|
||||
|
||||
bool YoungGCTracer::should_send_promotion_outside_plab_event() const {
|
||||
return EventPromoteObjectOutsidePLAB::is_enabled();
|
||||
}
|
||||
|
||||
void YoungGCTracer::send_promotion_in_new_plab_event(Klass* klass, size_t obj_size,
|
||||
uint age, bool tenured,
|
||||
size_t plab_size) const {
|
||||
|
||||
EventPromoteObjectInNewPLAB event;
|
||||
if (event.should_commit()) {
|
||||
event.set_gcId(_shared_gc_info.gc_id().id());
|
||||
event.set_class(klass);
|
||||
event.set_objectSize(obj_size);
|
||||
event.set_tenured(tenured);
|
||||
event.set_tenuringAge(age);
|
||||
event.set_plabSize(plab_size);
|
||||
event.commit();
|
||||
}
|
||||
}
|
||||
|
||||
void YoungGCTracer::send_promotion_outside_plab_event(Klass* klass, size_t obj_size,
|
||||
uint age, bool tenured) const {
|
||||
|
||||
EventPromoteObjectOutsidePLAB event;
|
||||
if (event.should_commit()) {
|
||||
event.set_gcId(_shared_gc_info.gc_id().id());
|
||||
event.set_class(klass);
|
||||
event.set_objectSize(obj_size);
|
||||
event.set_tenured(tenured);
|
||||
event.set_tenuringAge(age);
|
||||
event.commit();
|
||||
}
|
||||
}
|
||||
|
||||
void OldGCTracer::send_old_gc_event() const {
|
||||
EventGCOldGarbageCollection e(UNTIMED);
|
||||
if (e.should_commit()) {
|
||||
|
@ -385,6 +385,18 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea
|
||||
int handler_bci;
|
||||
int current_bci = bci(thread);
|
||||
|
||||
if (thread->frames_to_pop_failed_realloc() > 0) {
|
||||
// Allocation of scalar replaced object used in this frame
|
||||
// failed. Unconditionally pop the frame.
|
||||
thread->dec_frames_to_pop_failed_realloc();
|
||||
thread->set_vm_result(h_exception());
|
||||
// If the method is synchronized we already unlocked the monitor
|
||||
// during deoptimization so the interpreter needs to skip it when
|
||||
// the frame is popped.
|
||||
thread->set_do_not_unlock_if_synchronized(true);
|
||||
return Interpreter::remove_activation_entry();
|
||||
}
|
||||
|
||||
// Need to do this check first since when _do_not_unlock_if_synchronized
|
||||
// is set, we don't want to trigger any classloading which may make calls
|
||||
// into java, or surprisingly find a matching exception handler for bci 0
|
||||
|
360
hotspot/src/share/vm/memory/cardGeneration.cpp
Normal file
360
hotspot/src/share/vm/memory/cardGeneration.cpp
Normal file
@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "memory/blockOffsetTable.inline.hpp"
|
||||
#include "memory/cardGeneration.inline.hpp"
|
||||
#include "memory/gcLocker.hpp"
|
||||
#include "memory/generationSpec.hpp"
|
||||
#include "memory/genOopClosures.inline.hpp"
|
||||
#include "memory/genRemSet.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
#include "memory/memRegion.hpp"
|
||||
#include "memory/space.inline.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
|
||||
CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size,
|
||||
int level,
|
||||
GenRemSet* remset) :
|
||||
Generation(rs, initial_byte_size, level), _rs(remset),
|
||||
_shrink_factor(0), _min_heap_delta_bytes(), _capacity_at_prologue(),
|
||||
_used_at_prologue()
|
||||
{
|
||||
HeapWord* start = (HeapWord*)rs.base();
|
||||
size_t reserved_byte_size = rs.size();
|
||||
assert((uintptr_t(start) & 3) == 0, "bad alignment");
|
||||
assert((reserved_byte_size & 3) == 0, "bad alignment");
|
||||
MemRegion reserved_mr(start, heap_word_size(reserved_byte_size));
|
||||
_bts = new BlockOffsetSharedArray(reserved_mr,
|
||||
heap_word_size(initial_byte_size));
|
||||
MemRegion committed_mr(start, heap_word_size(initial_byte_size));
|
||||
_rs->resize_covered_region(committed_mr);
|
||||
if (_bts == NULL) {
|
||||
vm_exit_during_initialization("Could not allocate a BlockOffsetArray");
|
||||
}
|
||||
|
||||
// Verify that the start and end of this generation is the start of a card.
|
||||
// If this wasn't true, a single card could span more than on generation,
|
||||
// which would cause problems when we commit/uncommit memory, and when we
|
||||
// clear and dirty cards.
|
||||
guarantee(_rs->is_aligned(reserved_mr.start()), "generation must be card aligned");
|
||||
if (reserved_mr.end() != Universe::heap()->reserved_region().end()) {
|
||||
// Don't check at the very end of the heap as we'll assert that we're probing off
|
||||
// the end if we try.
|
||||
guarantee(_rs->is_aligned(reserved_mr.end()), "generation must be card aligned");
|
||||
}
|
||||
_min_heap_delta_bytes = MinHeapDeltaBytes;
|
||||
_capacity_at_prologue = initial_byte_size;
|
||||
_used_at_prologue = 0;
|
||||
}
|
||||
|
||||
bool CardGeneration::grow_by(size_t bytes) {
|
||||
assert_correct_size_change_locking();
|
||||
bool result = _virtual_space.expand_by(bytes);
|
||||
if (result) {
|
||||
size_t new_word_size =
|
||||
heap_word_size(_virtual_space.committed_size());
|
||||
MemRegion mr(space()->bottom(), new_word_size);
|
||||
// Expand card table
|
||||
Universe::heap()->barrier_set()->resize_covered_region(mr);
|
||||
// Expand shared block offset array
|
||||
_bts->resize(new_word_size);
|
||||
|
||||
// Fix for bug #4668531
|
||||
if (ZapUnusedHeapArea) {
|
||||
MemRegion mangle_region(space()->end(),
|
||||
(HeapWord*)_virtual_space.high());
|
||||
SpaceMangler::mangle_region(mangle_region);
|
||||
}
|
||||
|
||||
// Expand space -- also expands space's BOT
|
||||
// (which uses (part of) shared array above)
|
||||
space()->set_end((HeapWord*)_virtual_space.high());
|
||||
|
||||
// update the space and generation capacity counters
|
||||
update_counters();
|
||||
|
||||
if (Verbose && PrintGC) {
|
||||
size_t new_mem_size = _virtual_space.committed_size();
|
||||
size_t old_mem_size = new_mem_size - bytes;
|
||||
gclog_or_tty->print_cr("Expanding %s from " SIZE_FORMAT "K by "
|
||||
SIZE_FORMAT "K to " SIZE_FORMAT "K",
|
||||
name(), old_mem_size/K, bytes/K, new_mem_size/K);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CardGeneration::expand(size_t bytes, size_t expand_bytes) {
|
||||
assert_locked_or_safepoint(Heap_lock);
|
||||
if (bytes == 0) {
|
||||
return true; // That's what grow_by(0) would return
|
||||
}
|
||||
size_t aligned_bytes = ReservedSpace::page_align_size_up(bytes);
|
||||
if (aligned_bytes == 0){
|
||||
// The alignment caused the number of bytes to wrap. An expand_by(0) will
|
||||
// return true with the implication that an expansion was done when it
|
||||
// was not. A call to expand implies a best effort to expand by "bytes"
|
||||
// but not a guarantee. Align down to give a best effort. This is likely
|
||||
// the most that the generation can expand since it has some capacity to
|
||||
// start with.
|
||||
aligned_bytes = ReservedSpace::page_align_size_down(bytes);
|
||||
}
|
||||
size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
|
||||
bool success = false;
|
||||
if (aligned_expand_bytes > aligned_bytes) {
|
||||
success = grow_by(aligned_expand_bytes);
|
||||
}
|
||||
if (!success) {
|
||||
success = grow_by(aligned_bytes);
|
||||
}
|
||||
if (!success) {
|
||||
success = grow_to_reserved();
|
||||
}
|
||||
if (PrintGC && Verbose) {
|
||||
if (success && GC_locker::is_active_and_needs_gc()) {
|
||||
gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead");
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool CardGeneration::grow_to_reserved() {
|
||||
assert_correct_size_change_locking();
|
||||
bool success = true;
|
||||
const size_t remaining_bytes = _virtual_space.uncommitted_size();
|
||||
if (remaining_bytes > 0) {
|
||||
success = grow_by(remaining_bytes);
|
||||
DEBUG_ONLY(if (!success) warning("grow to reserved failed");)
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void CardGeneration::shrink(size_t bytes) {
|
||||
assert_correct_size_change_locking();
|
||||
|
||||
size_t size = ReservedSpace::page_align_size_down(bytes);
|
||||
if (size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Shrink committed space
|
||||
_virtual_space.shrink_by(size);
|
||||
// Shrink space; this also shrinks the space's BOT
|
||||
space()->set_end((HeapWord*) _virtual_space.high());
|
||||
size_t new_word_size = heap_word_size(space()->capacity());
|
||||
// Shrink the shared block offset array
|
||||
_bts->resize(new_word_size);
|
||||
MemRegion mr(space()->bottom(), new_word_size);
|
||||
// Shrink the card table
|
||||
Universe::heap()->barrier_set()->resize_covered_region(mr);
|
||||
|
||||
if (Verbose && PrintGC) {
|
||||
size_t new_mem_size = _virtual_space.committed_size();
|
||||
size_t old_mem_size = new_mem_size + size;
|
||||
gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K",
|
||||
name(), old_mem_size/K, new_mem_size/K);
|
||||
}
|
||||
}
|
||||
|
||||
// No young generation references, clear this generation's cards.
|
||||
void CardGeneration::clear_remembered_set() {
|
||||
_rs->clear(reserved());
|
||||
}
|
||||
|
||||
// Objects in this generation may have moved, invalidate this
|
||||
// generation's cards.
|
||||
void CardGeneration::invalidate_remembered_set() {
|
||||
_rs->invalidate(used_region());
|
||||
}
|
||||
|
||||
void CardGeneration::compute_new_size() {
|
||||
assert(_shrink_factor <= 100, "invalid shrink factor");
|
||||
size_t current_shrink_factor = _shrink_factor;
|
||||
_shrink_factor = 0;
|
||||
|
||||
// We don't have floating point command-line arguments
|
||||
// Note: argument processing ensures that MinHeapFreeRatio < 100.
|
||||
const double minimum_free_percentage = MinHeapFreeRatio / 100.0;
|
||||
const double maximum_used_percentage = 1.0 - minimum_free_percentage;
|
||||
|
||||
// Compute some numbers about the state of the heap.
|
||||
const size_t used_after_gc = used();
|
||||
const size_t capacity_after_gc = capacity();
|
||||
|
||||
const double min_tmp = used_after_gc / maximum_used_percentage;
|
||||
size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx));
|
||||
// Don't shrink less than the initial generation size
|
||||
minimum_desired_capacity = MAX2(minimum_desired_capacity,
|
||||
spec()->init_size());
|
||||
assert(used_after_gc <= minimum_desired_capacity, "sanity check");
|
||||
|
||||
if (PrintGC && Verbose) {
|
||||
const size_t free_after_gc = free();
|
||||
const double free_percentage = ((double)free_after_gc) / capacity_after_gc;
|
||||
gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: ");
|
||||
gclog_or_tty->print_cr(" "
|
||||
" minimum_free_percentage: %6.2f"
|
||||
" maximum_used_percentage: %6.2f",
|
||||
minimum_free_percentage,
|
||||
maximum_used_percentage);
|
||||
gclog_or_tty->print_cr(" "
|
||||
" free_after_gc : %6.1fK"
|
||||
" used_after_gc : %6.1fK"
|
||||
" capacity_after_gc : %6.1fK",
|
||||
free_after_gc / (double) K,
|
||||
used_after_gc / (double) K,
|
||||
capacity_after_gc / (double) K);
|
||||
gclog_or_tty->print_cr(" "
|
||||
" free_percentage: %6.2f",
|
||||
free_percentage);
|
||||
}
|
||||
|
||||
if (capacity_after_gc < minimum_desired_capacity) {
|
||||
// If we have less free space than we want then expand
|
||||
size_t expand_bytes = minimum_desired_capacity - capacity_after_gc;
|
||||
// Don't expand unless it's significant
|
||||
if (expand_bytes >= _min_heap_delta_bytes) {
|
||||
expand(expand_bytes, 0); // safe if expansion fails
|
||||
}
|
||||
if (PrintGC && Verbose) {
|
||||
gclog_or_tty->print_cr(" expanding:"
|
||||
" minimum_desired_capacity: %6.1fK"
|
||||
" expand_bytes: %6.1fK"
|
||||
" _min_heap_delta_bytes: %6.1fK",
|
||||
minimum_desired_capacity / (double) K,
|
||||
expand_bytes / (double) K,
|
||||
_min_heap_delta_bytes / (double) K);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// No expansion, now see if we want to shrink
|
||||
size_t shrink_bytes = 0;
|
||||
// We would never want to shrink more than this
|
||||
size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity;
|
||||
|
||||
if (MaxHeapFreeRatio < 100) {
|
||||
const double maximum_free_percentage = MaxHeapFreeRatio / 100.0;
|
||||
const double minimum_used_percentage = 1.0 - maximum_free_percentage;
|
||||
const double max_tmp = used_after_gc / minimum_used_percentage;
|
||||
size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));
|
||||
maximum_desired_capacity = MAX2(maximum_desired_capacity,
|
||||
spec()->init_size());
|
||||
if (PrintGC && Verbose) {
|
||||
gclog_or_tty->print_cr(" "
|
||||
" maximum_free_percentage: %6.2f"
|
||||
" minimum_used_percentage: %6.2f",
|
||||
maximum_free_percentage,
|
||||
minimum_used_percentage);
|
||||
gclog_or_tty->print_cr(" "
|
||||
" _capacity_at_prologue: %6.1fK"
|
||||
" minimum_desired_capacity: %6.1fK"
|
||||
" maximum_desired_capacity: %6.1fK",
|
||||
_capacity_at_prologue / (double) K,
|
||||
minimum_desired_capacity / (double) K,
|
||||
maximum_desired_capacity / (double) K);
|
||||
}
|
||||
assert(minimum_desired_capacity <= maximum_desired_capacity,
|
||||
"sanity check");
|
||||
|
||||
if (capacity_after_gc > maximum_desired_capacity) {
|
||||
// Capacity too large, compute shrinking size
|
||||
shrink_bytes = capacity_after_gc - maximum_desired_capacity;
|
||||
// We don't want shrink all the way back to initSize if people call
|
||||
// System.gc(), because some programs do that between "phases" and then
|
||||
// we'd just have to grow the heap up again for the next phase. So we
|
||||
// damp the shrinking: 0% on the first call, 10% on the second call, 40%
|
||||
// on the third call, and 100% by the fourth call. But if we recompute
|
||||
// size without shrinking, it goes back to 0%.
|
||||
shrink_bytes = shrink_bytes / 100 * current_shrink_factor;
|
||||
assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
|
||||
if (current_shrink_factor == 0) {
|
||||
_shrink_factor = 10;
|
||||
} else {
|
||||
_shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);
|
||||
}
|
||||
if (PrintGC && Verbose) {
|
||||
gclog_or_tty->print_cr(" "
|
||||
" shrinking:"
|
||||
" initSize: %.1fK"
|
||||
" maximum_desired_capacity: %.1fK",
|
||||
spec()->init_size() / (double) K,
|
||||
maximum_desired_capacity / (double) K);
|
||||
gclog_or_tty->print_cr(" "
|
||||
" shrink_bytes: %.1fK"
|
||||
" current_shrink_factor: " SIZE_FORMAT
|
||||
" new shrink factor: " SIZE_FORMAT
|
||||
" _min_heap_delta_bytes: %.1fK",
|
||||
shrink_bytes / (double) K,
|
||||
current_shrink_factor,
|
||||
_shrink_factor,
|
||||
_min_heap_delta_bytes / (double) K);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (capacity_after_gc > _capacity_at_prologue) {
|
||||
// We might have expanded for promotions, in which case we might want to
|
||||
// take back that expansion if there's room after GC. That keeps us from
|
||||
// stretching the heap with promotions when there's plenty of room.
|
||||
size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue;
|
||||
expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes);
|
||||
// We have two shrinking computations, take the largest
|
||||
shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion);
|
||||
assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
|
||||
if (PrintGC && Verbose) {
|
||||
gclog_or_tty->print_cr(" "
|
||||
" aggressive shrinking:"
|
||||
" _capacity_at_prologue: %.1fK"
|
||||
" capacity_after_gc: %.1fK"
|
||||
" expansion_for_promotion: %.1fK"
|
||||
" shrink_bytes: %.1fK",
|
||||
capacity_after_gc / (double) K,
|
||||
_capacity_at_prologue / (double) K,
|
||||
expansion_for_promotion / (double) K,
|
||||
shrink_bytes / (double) K);
|
||||
}
|
||||
}
|
||||
// Don't shrink unless it's significant
|
||||
if (shrink_bytes >= _min_heap_delta_bytes) {
|
||||
shrink(shrink_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Currently nothing to do.
|
||||
void CardGeneration::prepare_for_verify() {}
|
||||
|
||||
void CardGeneration::space_iterate(SpaceClosure* blk,
|
||||
bool usedOnly) {
|
||||
blk->do_space(space());
|
||||
}
|
||||
|
||||
void CardGeneration::younger_refs_iterate(OopsInGenClosure* blk) {
|
||||
blk->set_generation(this);
|
||||
younger_refs_in_space_iterate(space(), blk);
|
||||
blk->reset_generation();
|
||||
}
|
99
hotspot/src/share/vm/memory/cardGeneration.hpp
Normal file
99
hotspot/src/share/vm/memory/cardGeneration.hpp
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_MEMORY_CARDGENERATION_HPP
|
||||
#define SHARE_VM_MEMORY_CARDGENERATION_HPP
|
||||
|
||||
// Class CardGeneration is a generation that is covered by a card table,
|
||||
// and uses a card-size block-offset array to implement block_start.
|
||||
|
||||
#include "memory/generation.hpp"
|
||||
|
||||
class BlockOffsetSharedArray;
|
||||
class CompactibleSpace;
|
||||
|
||||
class CardGeneration: public Generation {
|
||||
friend class VMStructs;
|
||||
protected:
|
||||
// This is shared with other generations.
|
||||
GenRemSet* _rs;
|
||||
// This is local to this generation.
|
||||
BlockOffsetSharedArray* _bts;
|
||||
|
||||
// Current shrinking effect: this damps shrinking when the heap gets empty.
|
||||
size_t _shrink_factor;
|
||||
|
||||
size_t _min_heap_delta_bytes; // Minimum amount to expand.
|
||||
|
||||
// Some statistics from before gc started.
|
||||
// These are gathered in the gc_prologue (and should_collect)
|
||||
// to control growing/shrinking policy in spite of promotions.
|
||||
size_t _capacity_at_prologue;
|
||||
size_t _used_at_prologue;
|
||||
|
||||
CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level,
|
||||
GenRemSet* remset);
|
||||
|
||||
virtual void assert_correct_size_change_locking() = 0;
|
||||
|
||||
virtual CompactibleSpace* space() const = 0;
|
||||
|
||||
public:
|
||||
|
||||
// Attempt to expand the generation by "bytes". Expand by at a
|
||||
// minimum "expand_bytes". Return true if some amount (not
|
||||
// necessarily the full "bytes") was done.
|
||||
virtual bool expand(size_t bytes, size_t expand_bytes);
|
||||
|
||||
// Shrink generation with specified size
|
||||
virtual void shrink(size_t bytes);
|
||||
|
||||
virtual void compute_new_size();
|
||||
|
||||
virtual void clear_remembered_set();
|
||||
|
||||
virtual void invalidate_remembered_set();
|
||||
|
||||
virtual void prepare_for_verify();
|
||||
|
||||
// Grow generation with specified size (returns false if unable to grow)
|
||||
bool grow_by(size_t bytes);
|
||||
// Grow generation to reserved size.
|
||||
bool grow_to_reserved();
|
||||
|
||||
size_t capacity() const;
|
||||
size_t used() const;
|
||||
size_t free() const;
|
||||
MemRegion used_region() const;
|
||||
|
||||
void space_iterate(SpaceClosure* blk, bool usedOnly = false);
|
||||
|
||||
void younger_refs_iterate(OopsInGenClosure* blk);
|
||||
|
||||
bool is_in(const void* p) const;
|
||||
|
||||
CompactibleSpace* first_compaction_space() const;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_MEMORY_CARDGENERATION_HPP
|
55
hotspot/src/share/vm/memory/cardGeneration.inline.hpp
Normal file
55
hotspot/src/share/vm/memory/cardGeneration.inline.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_MEMORY_CARDGENERATION_INLINE_HPP
|
||||
#define SHARE_VM_MEMORY_CARDGENERATION_INLINE_HPP
|
||||
|
||||
#include "memory/cardGeneration.hpp"
|
||||
#include "memory/space.hpp"
|
||||
|
||||
inline size_t CardGeneration::capacity() const {
|
||||
return space()->capacity();
|
||||
}
|
||||
|
||||
inline size_t CardGeneration::used() const {
|
||||
return space()->used();
|
||||
}
|
||||
|
||||
inline size_t CardGeneration::free() const {
|
||||
return space()->free();
|
||||
}
|
||||
|
||||
inline MemRegion CardGeneration::used_region() const {
|
||||
return space()->used_region();
|
||||
}
|
||||
|
||||
inline bool CardGeneration::is_in(const void* p) const {
|
||||
return space()->is_in(p);
|
||||
}
|
||||
|
||||
inline CompactibleSpace* CardGeneration::first_compaction_space() const {
|
||||
return space();
|
||||
}
|
||||
|
||||
#endif // SHARE_VM_MEMORY_CARDGENERATION_INLINE_HPP
|
@ -275,29 +275,26 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) {
|
||||
// the new_end_aligned does not intrude onto the committed
|
||||
// space of another region.
|
||||
int ri = 0;
|
||||
for (ri = 0; ri < _cur_covered_regions; ri++) {
|
||||
if (ri != ind) {
|
||||
if (_committed[ri].contains(new_end_aligned)) {
|
||||
// The prior check included in the assert
|
||||
// (new_end_aligned >= _committed[ri].start())
|
||||
// is redundant with the "contains" test.
|
||||
// Any region containing the new end
|
||||
// should start at or beyond the region found (ind)
|
||||
// for the new end (committed regions are not expected to
|
||||
// be proper subsets of other committed regions).
|
||||
assert(_committed[ri].start() >= _committed[ind].start(),
|
||||
"New end of committed region is inconsistent");
|
||||
new_end_aligned = _committed[ri].start();
|
||||
// new_end_aligned can be equal to the start of its
|
||||
// committed region (i.e., of "ind") if a second
|
||||
// region following "ind" also start at the same location
|
||||
// as "ind".
|
||||
assert(new_end_aligned >= _committed[ind].start(),
|
||||
"New end of committed region is before start");
|
||||
debug_only(collided = true;)
|
||||
// Should only collide with 1 region
|
||||
break;
|
||||
}
|
||||
for (ri = ind + 1; ri < _cur_covered_regions; ri++) {
|
||||
if (new_end_aligned > _committed[ri].start()) {
|
||||
assert(new_end_aligned <= _committed[ri].end(),
|
||||
"An earlier committed region can't cover a later committed region");
|
||||
// Any region containing the new end
|
||||
// should start at or beyond the region found (ind)
|
||||
// for the new end (committed regions are not expected to
|
||||
// be proper subsets of other committed regions).
|
||||
assert(_committed[ri].start() >= _committed[ind].start(),
|
||||
"New end of committed region is inconsistent");
|
||||
new_end_aligned = _committed[ri].start();
|
||||
// new_end_aligned can be equal to the start of its
|
||||
// committed region (i.e., of "ind") if a second
|
||||
// region following "ind" also start at the same location
|
||||
// as "ind".
|
||||
assert(new_end_aligned >= _committed[ind].start(),
|
||||
"New end of committed region is before start");
|
||||
debug_only(collided = true;)
|
||||
// Should only collide with 1 region
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef ASSERT
|
||||
|
@ -361,244 +361,3 @@ void Generation::compact() {
|
||||
sp = sp->next_compaction_space();
|
||||
}
|
||||
}
|
||||
|
||||
CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size,
|
||||
int level,
|
||||
GenRemSet* remset) :
|
||||
Generation(rs, initial_byte_size, level), _rs(remset),
|
||||
_shrink_factor(0), _min_heap_delta_bytes(), _capacity_at_prologue(),
|
||||
_used_at_prologue()
|
||||
{
|
||||
HeapWord* start = (HeapWord*)rs.base();
|
||||
size_t reserved_byte_size = rs.size();
|
||||
assert((uintptr_t(start) & 3) == 0, "bad alignment");
|
||||
assert((reserved_byte_size & 3) == 0, "bad alignment");
|
||||
MemRegion reserved_mr(start, heap_word_size(reserved_byte_size));
|
||||
_bts = new BlockOffsetSharedArray(reserved_mr,
|
||||
heap_word_size(initial_byte_size));
|
||||
MemRegion committed_mr(start, heap_word_size(initial_byte_size));
|
||||
_rs->resize_covered_region(committed_mr);
|
||||
if (_bts == NULL)
|
||||
vm_exit_during_initialization("Could not allocate a BlockOffsetArray");
|
||||
|
||||
// Verify that the start and end of this generation is the start of a card.
|
||||
// If this wasn't true, a single card could span more than on generation,
|
||||
// which would cause problems when we commit/uncommit memory, and when we
|
||||
// clear and dirty cards.
|
||||
guarantee(_rs->is_aligned(reserved_mr.start()), "generation must be card aligned");
|
||||
if (reserved_mr.end() != Universe::heap()->reserved_region().end()) {
|
||||
// Don't check at the very end of the heap as we'll assert that we're probing off
|
||||
// the end if we try.
|
||||
guarantee(_rs->is_aligned(reserved_mr.end()), "generation must be card aligned");
|
||||
}
|
||||
_min_heap_delta_bytes = MinHeapDeltaBytes;
|
||||
_capacity_at_prologue = initial_byte_size;
|
||||
_used_at_prologue = 0;
|
||||
}
|
||||
|
||||
bool CardGeneration::expand(size_t bytes, size_t expand_bytes) {
|
||||
assert_locked_or_safepoint(Heap_lock);
|
||||
if (bytes == 0) {
|
||||
return true; // That's what grow_by(0) would return
|
||||
}
|
||||
size_t aligned_bytes = ReservedSpace::page_align_size_up(bytes);
|
||||
if (aligned_bytes == 0){
|
||||
// The alignment caused the number of bytes to wrap. An expand_by(0) will
|
||||
// return true with the implication that an expansion was done when it
|
||||
// was not. A call to expand implies a best effort to expand by "bytes"
|
||||
// but not a guarantee. Align down to give a best effort. This is likely
|
||||
// the most that the generation can expand since it has some capacity to
|
||||
// start with.
|
||||
aligned_bytes = ReservedSpace::page_align_size_down(bytes);
|
||||
}
|
||||
size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
|
||||
bool success = false;
|
||||
if (aligned_expand_bytes > aligned_bytes) {
|
||||
success = grow_by(aligned_expand_bytes);
|
||||
}
|
||||
if (!success) {
|
||||
success = grow_by(aligned_bytes);
|
||||
}
|
||||
if (!success) {
|
||||
success = grow_to_reserved();
|
||||
}
|
||||
if (PrintGC && Verbose) {
|
||||
if (success && GC_locker::is_active_and_needs_gc()) {
|
||||
gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead");
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
// No young generation references, clear this generation's cards.
|
||||
void CardGeneration::clear_remembered_set() {
|
||||
_rs->clear(reserved());
|
||||
}
|
||||
|
||||
|
||||
// Objects in this generation may have moved, invalidate this
|
||||
// generation's cards.
|
||||
void CardGeneration::invalidate_remembered_set() {
|
||||
_rs->invalidate(used_region());
|
||||
}
|
||||
|
||||
|
||||
void CardGeneration::compute_new_size() {
|
||||
assert(_shrink_factor <= 100, "invalid shrink factor");
|
||||
size_t current_shrink_factor = _shrink_factor;
|
||||
_shrink_factor = 0;
|
||||
|
||||
// We don't have floating point command-line arguments
|
||||
// Note: argument processing ensures that MinHeapFreeRatio < 100.
|
||||
const double minimum_free_percentage = MinHeapFreeRatio / 100.0;
|
||||
const double maximum_used_percentage = 1.0 - minimum_free_percentage;
|
||||
|
||||
// Compute some numbers about the state of the heap.
|
||||
const size_t used_after_gc = used();
|
||||
const size_t capacity_after_gc = capacity();
|
||||
|
||||
const double min_tmp = used_after_gc / maximum_used_percentage;
|
||||
size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx));
|
||||
// Don't shrink less than the initial generation size
|
||||
minimum_desired_capacity = MAX2(minimum_desired_capacity,
|
||||
spec()->init_size());
|
||||
assert(used_after_gc <= minimum_desired_capacity, "sanity check");
|
||||
|
||||
if (PrintGC && Verbose) {
|
||||
const size_t free_after_gc = free();
|
||||
const double free_percentage = ((double)free_after_gc) / capacity_after_gc;
|
||||
gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: ");
|
||||
gclog_or_tty->print_cr(" "
|
||||
" minimum_free_percentage: %6.2f"
|
||||
" maximum_used_percentage: %6.2f",
|
||||
minimum_free_percentage,
|
||||
maximum_used_percentage);
|
||||
gclog_or_tty->print_cr(" "
|
||||
" free_after_gc : %6.1fK"
|
||||
" used_after_gc : %6.1fK"
|
||||
" capacity_after_gc : %6.1fK",
|
||||
free_after_gc / (double) K,
|
||||
used_after_gc / (double) K,
|
||||
capacity_after_gc / (double) K);
|
||||
gclog_or_tty->print_cr(" "
|
||||
" free_percentage: %6.2f",
|
||||
free_percentage);
|
||||
}
|
||||
|
||||
if (capacity_after_gc < minimum_desired_capacity) {
|
||||
// If we have less free space than we want then expand
|
||||
size_t expand_bytes = minimum_desired_capacity - capacity_after_gc;
|
||||
// Don't expand unless it's significant
|
||||
if (expand_bytes >= _min_heap_delta_bytes) {
|
||||
expand(expand_bytes, 0); // safe if expansion fails
|
||||
}
|
||||
if (PrintGC && Verbose) {
|
||||
gclog_or_tty->print_cr(" expanding:"
|
||||
" minimum_desired_capacity: %6.1fK"
|
||||
" expand_bytes: %6.1fK"
|
||||
" _min_heap_delta_bytes: %6.1fK",
|
||||
minimum_desired_capacity / (double) K,
|
||||
expand_bytes / (double) K,
|
||||
_min_heap_delta_bytes / (double) K);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// No expansion, now see if we want to shrink
|
||||
size_t shrink_bytes = 0;
|
||||
// We would never want to shrink more than this
|
||||
size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity;
|
||||
|
||||
if (MaxHeapFreeRatio < 100) {
|
||||
const double maximum_free_percentage = MaxHeapFreeRatio / 100.0;
|
||||
const double minimum_used_percentage = 1.0 - maximum_free_percentage;
|
||||
const double max_tmp = used_after_gc / minimum_used_percentage;
|
||||
size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));
|
||||
maximum_desired_capacity = MAX2(maximum_desired_capacity,
|
||||
spec()->init_size());
|
||||
if (PrintGC && Verbose) {
|
||||
gclog_or_tty->print_cr(" "
|
||||
" maximum_free_percentage: %6.2f"
|
||||
" minimum_used_percentage: %6.2f",
|
||||
maximum_free_percentage,
|
||||
minimum_used_percentage);
|
||||
gclog_or_tty->print_cr(" "
|
||||
" _capacity_at_prologue: %6.1fK"
|
||||
" minimum_desired_capacity: %6.1fK"
|
||||
" maximum_desired_capacity: %6.1fK",
|
||||
_capacity_at_prologue / (double) K,
|
||||
minimum_desired_capacity / (double) K,
|
||||
maximum_desired_capacity / (double) K);
|
||||
}
|
||||
assert(minimum_desired_capacity <= maximum_desired_capacity,
|
||||
"sanity check");
|
||||
|
||||
if (capacity_after_gc > maximum_desired_capacity) {
|
||||
// Capacity too large, compute shrinking size
|
||||
shrink_bytes = capacity_after_gc - maximum_desired_capacity;
|
||||
// We don't want shrink all the way back to initSize if people call
|
||||
// System.gc(), because some programs do that between "phases" and then
|
||||
// we'd just have to grow the heap up again for the next phase. So we
|
||||
// damp the shrinking: 0% on the first call, 10% on the second call, 40%
|
||||
// on the third call, and 100% by the fourth call. But if we recompute
|
||||
// size without shrinking, it goes back to 0%.
|
||||
shrink_bytes = shrink_bytes / 100 * current_shrink_factor;
|
||||
assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
|
||||
if (current_shrink_factor == 0) {
|
||||
_shrink_factor = 10;
|
||||
} else {
|
||||
_shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100);
|
||||
}
|
||||
if (PrintGC && Verbose) {
|
||||
gclog_or_tty->print_cr(" "
|
||||
" shrinking:"
|
||||
" initSize: %.1fK"
|
||||
" maximum_desired_capacity: %.1fK",
|
||||
spec()->init_size() / (double) K,
|
||||
maximum_desired_capacity / (double) K);
|
||||
gclog_or_tty->print_cr(" "
|
||||
" shrink_bytes: %.1fK"
|
||||
" current_shrink_factor: " SIZE_FORMAT
|
||||
" new shrink factor: " SIZE_FORMAT
|
||||
" _min_heap_delta_bytes: %.1fK",
|
||||
shrink_bytes / (double) K,
|
||||
current_shrink_factor,
|
||||
_shrink_factor,
|
||||
_min_heap_delta_bytes / (double) K);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (capacity_after_gc > _capacity_at_prologue) {
|
||||
// We might have expanded for promotions, in which case we might want to
|
||||
// take back that expansion if there's room after GC. That keeps us from
|
||||
// stretching the heap with promotions when there's plenty of room.
|
||||
size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue;
|
||||
expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes);
|
||||
// We have two shrinking computations, take the largest
|
||||
shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion);
|
||||
assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size");
|
||||
if (PrintGC && Verbose) {
|
||||
gclog_or_tty->print_cr(" "
|
||||
" aggressive shrinking:"
|
||||
" _capacity_at_prologue: %.1fK"
|
||||
" capacity_after_gc: %.1fK"
|
||||
" expansion_for_promotion: %.1fK"
|
||||
" shrink_bytes: %.1fK",
|
||||
capacity_after_gc / (double) K,
|
||||
_capacity_at_prologue / (double) K,
|
||||
expansion_for_promotion / (double) K,
|
||||
shrink_bytes / (double) K);
|
||||
}
|
||||
}
|
||||
// Don't shrink unless it's significant
|
||||
if (shrink_bytes >= _min_heap_delta_bytes) {
|
||||
shrink(shrink_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
// Currently nothing to do.
|
||||
void CardGeneration::prepare_for_verify() {}
|
||||
|
||||
|
@ -584,57 +584,4 @@ public:
|
||||
virtual CollectorCounters* counters() { return _gc_counters; }
|
||||
};
|
||||
|
||||
// Class CardGeneration is a generation that is covered by a card table,
|
||||
// and uses a card-size block-offset array to implement block_start.
|
||||
|
||||
// class BlockOffsetArray;
|
||||
// class BlockOffsetArrayContigSpace;
|
||||
class BlockOffsetSharedArray;
|
||||
|
||||
class CardGeneration: public Generation {
|
||||
friend class VMStructs;
|
||||
protected:
|
||||
// This is shared with other generations.
|
||||
GenRemSet* _rs;
|
||||
// This is local to this generation.
|
||||
BlockOffsetSharedArray* _bts;
|
||||
|
||||
// current shrinking effect: this damps shrinking when the heap gets empty.
|
||||
size_t _shrink_factor;
|
||||
|
||||
size_t _min_heap_delta_bytes; // Minimum amount to expand.
|
||||
|
||||
// Some statistics from before gc started.
|
||||
// These are gathered in the gc_prologue (and should_collect)
|
||||
// to control growing/shrinking policy in spite of promotions.
|
||||
size_t _capacity_at_prologue;
|
||||
size_t _used_at_prologue;
|
||||
|
||||
CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level,
|
||||
GenRemSet* remset);
|
||||
|
||||
public:
|
||||
|
||||
// Attempt to expand the generation by "bytes". Expand by at a
|
||||
// minimum "expand_bytes". Return true if some amount (not
|
||||
// necessarily the full "bytes") was done.
|
||||
virtual bool expand(size_t bytes, size_t expand_bytes);
|
||||
|
||||
// Shrink generation with specified size (returns false if unable to shrink)
|
||||
virtual void shrink(size_t bytes) = 0;
|
||||
|
||||
virtual void compute_new_size();
|
||||
|
||||
virtual void clear_remembered_set();
|
||||
|
||||
virtual void invalidate_remembered_set();
|
||||
|
||||
virtual void prepare_for_verify();
|
||||
|
||||
// Grow generation with specified size (returns false if unable to grow)
|
||||
virtual bool grow_by(size_t bytes) = 0;
|
||||
// Grow generation to reserved size.
|
||||
virtual bool grow_to_reserved() = 0;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_MEMORY_GENERATION_HPP
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -235,34 +235,6 @@ bool TenuredGeneration::expand(size_t bytes, size_t expand_bytes) {
|
||||
return CardGeneration::expand(bytes, expand_bytes);
|
||||
}
|
||||
|
||||
|
||||
void TenuredGeneration::shrink(size_t bytes) {
|
||||
assert_locked_or_safepoint(ExpandHeap_lock);
|
||||
size_t size = ReservedSpace::page_align_size_down(bytes);
|
||||
if (size > 0) {
|
||||
shrink_by(size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t TenuredGeneration::capacity() const {
|
||||
return _the_space->capacity();
|
||||
}
|
||||
|
||||
|
||||
size_t TenuredGeneration::used() const {
|
||||
return _the_space->used();
|
||||
}
|
||||
|
||||
|
||||
size_t TenuredGeneration::free() const {
|
||||
return _the_space->free();
|
||||
}
|
||||
|
||||
MemRegion TenuredGeneration::used_region() const {
|
||||
return the_space()->used_region();
|
||||
}
|
||||
|
||||
size_t TenuredGeneration::unsafe_max_alloc_nogc() const {
|
||||
return _the_space->free();
|
||||
}
|
||||
@ -271,74 +243,8 @@ size_t TenuredGeneration::contiguous_available() const {
|
||||
return _the_space->free() + _virtual_space.uncommitted_size();
|
||||
}
|
||||
|
||||
bool TenuredGeneration::grow_by(size_t bytes) {
|
||||
void TenuredGeneration::assert_correct_size_change_locking() {
|
||||
assert_locked_or_safepoint(ExpandHeap_lock);
|
||||
bool result = _virtual_space.expand_by(bytes);
|
||||
if (result) {
|
||||
size_t new_word_size =
|
||||
heap_word_size(_virtual_space.committed_size());
|
||||
MemRegion mr(_the_space->bottom(), new_word_size);
|
||||
// Expand card table
|
||||
Universe::heap()->barrier_set()->resize_covered_region(mr);
|
||||
// Expand shared block offset array
|
||||
_bts->resize(new_word_size);
|
||||
|
||||
// Fix for bug #4668531
|
||||
if (ZapUnusedHeapArea) {
|
||||
MemRegion mangle_region(_the_space->end(),
|
||||
(HeapWord*)_virtual_space.high());
|
||||
SpaceMangler::mangle_region(mangle_region);
|
||||
}
|
||||
|
||||
// Expand space -- also expands space's BOT
|
||||
// (which uses (part of) shared array above)
|
||||
_the_space->set_end((HeapWord*)_virtual_space.high());
|
||||
|
||||
// update the space and generation capacity counters
|
||||
update_counters();
|
||||
|
||||
if (Verbose && PrintGC) {
|
||||
size_t new_mem_size = _virtual_space.committed_size();
|
||||
size_t old_mem_size = new_mem_size - bytes;
|
||||
gclog_or_tty->print_cr("Expanding %s from " SIZE_FORMAT "K by "
|
||||
SIZE_FORMAT "K to " SIZE_FORMAT "K",
|
||||
name(), old_mem_size/K, bytes/K, new_mem_size/K);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool TenuredGeneration::grow_to_reserved() {
|
||||
assert_locked_or_safepoint(ExpandHeap_lock);
|
||||
bool success = true;
|
||||
const size_t remaining_bytes = _virtual_space.uncommitted_size();
|
||||
if (remaining_bytes > 0) {
|
||||
success = grow_by(remaining_bytes);
|
||||
DEBUG_ONLY(if (!success) warning("grow to reserved failed");)
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void TenuredGeneration::shrink_by(size_t bytes) {
|
||||
assert_locked_or_safepoint(ExpandHeap_lock);
|
||||
// Shrink committed space
|
||||
_virtual_space.shrink_by(bytes);
|
||||
// Shrink space; this also shrinks the space's BOT
|
||||
_the_space->set_end((HeapWord*) _virtual_space.high());
|
||||
size_t new_word_size = heap_word_size(_the_space->capacity());
|
||||
// Shrink the shared block offset array
|
||||
_bts->resize(new_word_size);
|
||||
MemRegion mr(_the_space->bottom(), new_word_size);
|
||||
// Shrink the card table
|
||||
Universe::heap()->barrier_set()->resize_covered_region(mr);
|
||||
|
||||
if (Verbose && PrintGC) {
|
||||
size_t new_mem_size = _virtual_space.committed_size();
|
||||
size_t old_mem_size = new_mem_size + bytes;
|
||||
gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K",
|
||||
name(), old_mem_size/K, new_mem_size/K);
|
||||
}
|
||||
}
|
||||
|
||||
// Currently nothing to do.
|
||||
@ -348,27 +254,14 @@ void TenuredGeneration::object_iterate(ObjectClosure* blk) {
|
||||
_the_space->object_iterate(blk);
|
||||
}
|
||||
|
||||
void TenuredGeneration::space_iterate(SpaceClosure* blk,
|
||||
bool usedOnly) {
|
||||
blk->do_space(_the_space);
|
||||
}
|
||||
|
||||
void TenuredGeneration::younger_refs_iterate(OopsInGenClosure* blk) {
|
||||
blk->set_generation(this);
|
||||
younger_refs_in_space_iterate(_the_space, blk);
|
||||
blk->reset_generation();
|
||||
}
|
||||
|
||||
void TenuredGeneration::save_marks() {
|
||||
_the_space->set_saved_mark();
|
||||
}
|
||||
|
||||
|
||||
void TenuredGeneration::reset_saved_marks() {
|
||||
_the_space->reset_saved_mark();
|
||||
}
|
||||
|
||||
|
||||
bool TenuredGeneration::no_allocs_since_save_marks() {
|
||||
return _the_space->saved_mark_at_top();
|
||||
}
|
||||
@ -387,28 +280,25 @@ ALL_SINCE_SAVE_MARKS_CLOSURES(TenuredGen_SINCE_SAVE_MARKS_ITERATE_DEFN)
|
||||
|
||||
#undef TenuredGen_SINCE_SAVE_MARKS_ITERATE_DEFN
|
||||
|
||||
|
||||
void TenuredGeneration::gc_epilogue(bool full) {
|
||||
_last_gc = WaterMark(the_space(), the_space()->top());
|
||||
|
||||
// update the generation and space performance counters
|
||||
update_counters();
|
||||
if (ZapUnusedHeapArea) {
|
||||
the_space()->check_mangled_unused_area_complete();
|
||||
_the_space->check_mangled_unused_area_complete();
|
||||
}
|
||||
}
|
||||
|
||||
void TenuredGeneration::record_spaces_top() {
|
||||
assert(ZapUnusedHeapArea, "Not mangling unused space");
|
||||
the_space()->set_top_for_allocations();
|
||||
_the_space->set_top_for_allocations();
|
||||
}
|
||||
|
||||
void TenuredGeneration::verify() {
|
||||
the_space()->verify();
|
||||
_the_space->verify();
|
||||
}
|
||||
|
||||
void TenuredGeneration::print_on(outputStream* st) const {
|
||||
Generation::print_on(st);
|
||||
st->print(" the");
|
||||
the_space()->print_on(st);
|
||||
_the_space->print_on(st);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,7 +28,7 @@
|
||||
#include "gc_implementation/shared/cSpaceCounters.hpp"
|
||||
#include "gc_implementation/shared/gcStats.hpp"
|
||||
#include "gc_implementation/shared/generationCounters.hpp"
|
||||
#include "memory/generation.hpp"
|
||||
#include "memory/cardGeneration.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
// TenuredGeneration models the heap containing old (promoted/tenured) objects
|
||||
@ -42,27 +42,18 @@ class TenuredGeneration: public CardGeneration {
|
||||
friend class VM_PopulateDumpSharedSpace;
|
||||
|
||||
protected:
|
||||
ContiguousSpace* _the_space; // actual space holding objects
|
||||
WaterMark _last_gc; // watermark between objects allocated before
|
||||
// and after last GC.
|
||||
ContiguousSpace* _the_space; // Actual space holding objects
|
||||
|
||||
GenerationCounters* _gen_counters;
|
||||
CSpaceCounters* _space_counters;
|
||||
|
||||
// Grow generation with specified size (returns false if unable to grow)
|
||||
virtual bool grow_by(size_t bytes);
|
||||
// Grow generation to reserved size.
|
||||
virtual bool grow_to_reserved();
|
||||
// Shrink generation with specified size (returns false if unable to shrink)
|
||||
void shrink_by(size_t bytes);
|
||||
|
||||
// Allocation failure
|
||||
virtual bool expand(size_t bytes, size_t expand_bytes);
|
||||
void shrink(size_t bytes);
|
||||
|
||||
// Accessing spaces
|
||||
ContiguousSpace* the_space() const { return _the_space; }
|
||||
ContiguousSpace* space() const { return _the_space; }
|
||||
|
||||
void assert_correct_size_change_locking();
|
||||
public:
|
||||
TenuredGeneration(ReservedSpace rs, size_t initial_byte_size,
|
||||
int level, GenRemSet* remset);
|
||||
@ -81,33 +72,15 @@ class TenuredGeneration: public CardGeneration {
|
||||
return !ScavengeBeforeFullGC;
|
||||
}
|
||||
|
||||
inline bool is_in(const void* p) const;
|
||||
|
||||
// Space enquiries
|
||||
size_t capacity() const;
|
||||
size_t used() const;
|
||||
size_t free() const;
|
||||
|
||||
MemRegion used_region() const;
|
||||
|
||||
size_t unsafe_max_alloc_nogc() const;
|
||||
size_t contiguous_available() const;
|
||||
|
||||
// Iteration
|
||||
void object_iterate(ObjectClosure* blk);
|
||||
void space_iterate(SpaceClosure* blk, bool usedOnly = false);
|
||||
|
||||
void younger_refs_iterate(OopsInGenClosure* blk);
|
||||
|
||||
inline CompactibleSpace* first_compaction_space() const;
|
||||
|
||||
virtual inline HeapWord* allocate(size_t word_size, bool is_tlab);
|
||||
virtual inline HeapWord* par_allocate(size_t word_size, bool is_tlab);
|
||||
|
||||
// Accessing marks
|
||||
inline WaterMark top_mark();
|
||||
inline WaterMark bottom_mark();
|
||||
|
||||
#define TenuredGen_SINCE_SAVE_MARKS_DECL(OopClosureType, nv_suffix) \
|
||||
void oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl);
|
||||
TenuredGen_SINCE_SAVE_MARKS_DECL(OopsInGenClosure,_v)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,53 +22,35 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_MEMORY_GENERATION_INLINE_HPP
|
||||
#define SHARE_VM_MEMORY_GENERATION_INLINE_HPP
|
||||
#ifndef SHARE_VM_MEMORY_TENUREDGENERATION_INLINE_HPP
|
||||
#define SHARE_VM_MEMORY_TENUREDGENERATION_INLINE_HPP
|
||||
|
||||
#include "memory/genCollectedHeap.hpp"
|
||||
#include "memory/space.hpp"
|
||||
#include "memory/tenuredGeneration.hpp"
|
||||
|
||||
bool TenuredGeneration::is_in(const void* p) const {
|
||||
return the_space()->is_in(p);
|
||||
}
|
||||
|
||||
|
||||
WaterMark TenuredGeneration::top_mark() {
|
||||
return the_space()->top_mark();
|
||||
}
|
||||
|
||||
CompactibleSpace*
|
||||
TenuredGeneration::first_compaction_space() const {
|
||||
return the_space();
|
||||
}
|
||||
|
||||
HeapWord* TenuredGeneration::allocate(size_t word_size,
|
||||
bool is_tlab) {
|
||||
assert(!is_tlab, "TenuredGeneration does not support TLAB allocation");
|
||||
return the_space()->allocate(word_size);
|
||||
return _the_space->allocate(word_size);
|
||||
}
|
||||
|
||||
HeapWord* TenuredGeneration::par_allocate(size_t word_size,
|
||||
bool is_tlab) {
|
||||
assert(!is_tlab, "TenuredGeneration does not support TLAB allocation");
|
||||
return the_space()->par_allocate(word_size);
|
||||
}
|
||||
|
||||
WaterMark TenuredGeneration::bottom_mark() {
|
||||
return the_space()->bottom_mark();
|
||||
return _the_space->par_allocate(word_size);
|
||||
}
|
||||
|
||||
size_t TenuredGeneration::block_size(const HeapWord* addr) const {
|
||||
if (addr < the_space()->top()) return oop(addr)->size();
|
||||
else {
|
||||
assert(addr == the_space()->top(), "non-block head arg to block_size");
|
||||
return the_space()->end() - the_space()->top();
|
||||
if (addr < _the_space->top()) {
|
||||
return oop(addr)->size();
|
||||
} else {
|
||||
assert(addr == _the_space->top(), "non-block head arg to block_size");
|
||||
return _the_space->end() - _the_space->top();
|
||||
}
|
||||
}
|
||||
|
||||
bool TenuredGeneration::block_is_obj(const HeapWord* addr) const {
|
||||
return addr < the_space()->top();
|
||||
return addr < _the_space ->top();
|
||||
}
|
||||
|
||||
#endif // SHARE_VM_MEMORY_GENERATION_INLINE_HPP
|
||||
#endif // SHARE_VM_MEMORY_TENUREDGENERATION_INLINE_HPP
|
||||
|
@ -120,6 +120,7 @@ oop Universe::_out_of_memory_error_metaspace = NULL;
|
||||
oop Universe::_out_of_memory_error_class_metaspace = NULL;
|
||||
oop Universe::_out_of_memory_error_array_size = NULL;
|
||||
oop Universe::_out_of_memory_error_gc_overhead_limit = NULL;
|
||||
oop Universe::_out_of_memory_error_realloc_objects = NULL;
|
||||
objArrayOop Universe::_preallocated_out_of_memory_error_array = NULL;
|
||||
volatile jint Universe::_preallocated_out_of_memory_error_avail_count = 0;
|
||||
bool Universe::_verify_in_progress = false;
|
||||
@ -191,6 +192,7 @@ void Universe::oops_do(OopClosure* f, bool do_all) {
|
||||
f->do_oop((oop*)&_out_of_memory_error_class_metaspace);
|
||||
f->do_oop((oop*)&_out_of_memory_error_array_size);
|
||||
f->do_oop((oop*)&_out_of_memory_error_gc_overhead_limit);
|
||||
f->do_oop((oop*)&_out_of_memory_error_realloc_objects);
|
||||
f->do_oop((oop*)&_preallocated_out_of_memory_error_array);
|
||||
f->do_oop((oop*)&_null_ptr_exception_instance);
|
||||
f->do_oop((oop*)&_arithmetic_exception_instance);
|
||||
@ -575,7 +577,8 @@ bool Universe::should_fill_in_stack_trace(Handle throwable) {
|
||||
(throwable() != Universe::_out_of_memory_error_metaspace) &&
|
||||
(throwable() != Universe::_out_of_memory_error_class_metaspace) &&
|
||||
(throwable() != Universe::_out_of_memory_error_array_size) &&
|
||||
(throwable() != Universe::_out_of_memory_error_gc_overhead_limit));
|
||||
(throwable() != Universe::_out_of_memory_error_gc_overhead_limit) &&
|
||||
(throwable() != Universe::_out_of_memory_error_realloc_objects));
|
||||
}
|
||||
|
||||
|
||||
@ -1039,6 +1042,7 @@ bool universe_post_init() {
|
||||
Universe::_out_of_memory_error_array_size = k_h->allocate_instance(CHECK_false);
|
||||
Universe::_out_of_memory_error_gc_overhead_limit =
|
||||
k_h->allocate_instance(CHECK_false);
|
||||
Universe::_out_of_memory_error_realloc_objects = k_h->allocate_instance(CHECK_false);
|
||||
|
||||
// Setup preallocated NullPointerException
|
||||
// (this is currently used for a cheap & dirty solution in compiler exception handling)
|
||||
@ -1078,6 +1082,9 @@ bool universe_post_init() {
|
||||
msg = java_lang_String::create_from_str("GC overhead limit exceeded", CHECK_false);
|
||||
java_lang_Throwable::set_message(Universe::_out_of_memory_error_gc_overhead_limit, msg());
|
||||
|
||||
msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK_false);
|
||||
java_lang_Throwable::set_message(Universe::_out_of_memory_error_realloc_objects, msg());
|
||||
|
||||
msg = java_lang_String::create_from_str("/ by zero", CHECK_false);
|
||||
java_lang_Throwable::set_message(Universe::_arithmetic_exception_instance, msg());
|
||||
|
||||
|
@ -157,6 +157,7 @@ class Universe: AllStatic {
|
||||
static oop _out_of_memory_error_class_metaspace;
|
||||
static oop _out_of_memory_error_array_size;
|
||||
static oop _out_of_memory_error_gc_overhead_limit;
|
||||
static oop _out_of_memory_error_realloc_objects;
|
||||
|
||||
static Array<int>* _the_empty_int_array; // Canonicalized int array
|
||||
static Array<u2>* _the_empty_short_array; // Canonicalized short array
|
||||
@ -328,6 +329,7 @@ class Universe: AllStatic {
|
||||
static oop out_of_memory_error_class_metaspace() { return gen_out_of_memory_error(_out_of_memory_error_class_metaspace); }
|
||||
static oop out_of_memory_error_array_size() { return gen_out_of_memory_error(_out_of_memory_error_array_size); }
|
||||
static oop out_of_memory_error_gc_overhead_limit() { return gen_out_of_memory_error(_out_of_memory_error_gc_overhead_limit); }
|
||||
static oop out_of_memory_error_realloc_objects() { return gen_out_of_memory_error(_out_of_memory_error_realloc_objects); }
|
||||
|
||||
// Accessors needed for fast allocation
|
||||
static Klass** boolArrayKlassObj_addr() { return &_boolArrayKlassObj; }
|
||||
|
@ -104,7 +104,8 @@ const Type *CastIINode::Value(PhaseTransform *phase) const {
|
||||
// Try to improve the type of the CastII if we recognize a CmpI/If
|
||||
// pattern.
|
||||
if (_carry_dependency) {
|
||||
if (in(0) != NULL && (in(0)->is_IfFalse() || in(0)->is_IfTrue())) {
|
||||
if (in(0) != NULL && in(0)->in(0) != NULL && in(0)->in(0)->is_If()) {
|
||||
assert(in(0)->is_IfFalse() || in(0)->is_IfTrue(), "should be If proj");
|
||||
Node* proj = in(0);
|
||||
if (proj->in(0)->in(1)->is_Bool()) {
|
||||
Node* b = proj->in(0)->in(1);
|
||||
|
@ -820,6 +820,11 @@ static Node *remove_useless_bool(IfNode *iff, PhaseGVN *phase) {
|
||||
|
||||
static IfNode* idealize_test(PhaseGVN* phase, IfNode* iff);
|
||||
|
||||
struct RangeCheck {
|
||||
Node* ctl;
|
||||
jint off;
|
||||
};
|
||||
|
||||
//------------------------------Ideal------------------------------------------
|
||||
// Return a node which is more "ideal" than the current node. Strip out
|
||||
// control copies
|
||||
@ -861,83 +866,141 @@ Node *IfNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
jint offset1;
|
||||
int flip1 = is_range_check(range1, index1, offset1);
|
||||
if( flip1 ) {
|
||||
Node *first_prev_dom = NULL;
|
||||
|
||||
// Try to remove extra range checks. All 'up_one_dom' gives up at merges
|
||||
// so all checks we inspect post-dominate the top-most check we find.
|
||||
// If we are going to fail the current check and we reach the top check
|
||||
// then we are guaranteed to fail, so just start interpreting there.
|
||||
// We 'expand' the top 2 range checks to include all post-dominating
|
||||
// We 'expand' the top 3 range checks to include all post-dominating
|
||||
// checks.
|
||||
|
||||
// The top 2 range checks seen
|
||||
Node *prev_chk1 = NULL;
|
||||
Node *prev_chk2 = NULL;
|
||||
// The top 3 range checks seen
|
||||
const int NRC =3;
|
||||
RangeCheck prev_checks[NRC];
|
||||
int nb_checks = 0;
|
||||
|
||||
// Low and high offsets seen so far
|
||||
jint off_lo = offset1;
|
||||
jint off_hi = offset1;
|
||||
|
||||
// Scan for the top 2 checks and collect range of offsets
|
||||
for( int dist = 0; dist < 999; dist++ ) { // Range-Check scan limit
|
||||
if( dom->Opcode() == Op_If && // Not same opcode?
|
||||
prev_dom->in(0) == dom ) { // One path of test does dominate?
|
||||
if( dom == this ) return NULL; // dead loop
|
||||
bool found_immediate_dominator = false;
|
||||
|
||||
// Scan for the top checks and collect range of offsets
|
||||
for (int dist = 0; dist < 999; dist++) { // Range-Check scan limit
|
||||
if (dom->Opcode() == Op_If && // Not same opcode?
|
||||
prev_dom->in(0) == dom) { // One path of test does dominate?
|
||||
if (dom == this) return NULL; // dead loop
|
||||
// See if this is a range check
|
||||
Node *index2, *range2;
|
||||
jint offset2;
|
||||
int flip2 = dom->as_If()->is_range_check(range2, index2, offset2);
|
||||
// See if this is a _matching_ range check, checking against
|
||||
// the same array bounds.
|
||||
if( flip2 == flip1 && range2 == range1 && index2 == index1 &&
|
||||
dom->outcnt() == 2 ) {
|
||||
if (flip2 == flip1 && range2 == range1 && index2 == index1 &&
|
||||
dom->outcnt() == 2) {
|
||||
if (nb_checks == 0 && dom->in(1) == in(1)) {
|
||||
// Found an immediately dominating test at the same offset.
|
||||
// This kind of back-to-back test can be eliminated locally,
|
||||
// and there is no need to search further for dominating tests.
|
||||
assert(offset2 == offset1, "Same test but different offsets");
|
||||
found_immediate_dominator = true;
|
||||
break;
|
||||
}
|
||||
// Gather expanded bounds
|
||||
off_lo = MIN2(off_lo,offset2);
|
||||
off_hi = MAX2(off_hi,offset2);
|
||||
// Record top 2 range checks
|
||||
prev_chk2 = prev_chk1;
|
||||
prev_chk1 = prev_dom;
|
||||
// If we match the test exactly, then the top test covers
|
||||
// both our lower and upper bounds.
|
||||
if( dom->in(1) == in(1) )
|
||||
prev_chk2 = prev_chk1;
|
||||
// Record top NRC range checks
|
||||
prev_checks[nb_checks%NRC].ctl = prev_dom;
|
||||
prev_checks[nb_checks%NRC].off = offset2;
|
||||
nb_checks++;
|
||||
}
|
||||
}
|
||||
prev_dom = dom;
|
||||
dom = up_one_dom( dom );
|
||||
if( !dom ) break;
|
||||
dom = up_one_dom(dom);
|
||||
if (!dom) break;
|
||||
}
|
||||
|
||||
if (!found_immediate_dominator) {
|
||||
// Attempt to widen the dominating range check to cover some later
|
||||
// ones. Since range checks "fail" by uncommon-trapping to the
|
||||
// interpreter, widening a check can make us speculatively enter
|
||||
// the interpreter. If we see range-check deopt's, do not widen!
|
||||
if (!phase->C->allow_range_check_smearing()) return NULL;
|
||||
|
||||
// Attempt to widen the dominating range check to cover some later
|
||||
// ones. Since range checks "fail" by uncommon-trapping to the
|
||||
// interpreter, widening a check can make us speculative enter the
|
||||
// interpreter. If we see range-check deopt's, do not widen!
|
||||
if (!phase->C->allow_range_check_smearing()) return NULL;
|
||||
|
||||
// Constant indices only need to check the upper bound.
|
||||
// Non-constance indices must check both low and high.
|
||||
if( index1 ) {
|
||||
// Didn't find 2 prior covering checks, so cannot remove anything.
|
||||
if( !prev_chk2 ) return NULL;
|
||||
// 'Widen' the offsets of the 1st and 2nd covering check
|
||||
adjust_check( prev_chk1, range1, index1, flip1, off_lo, igvn );
|
||||
// Do not call adjust_check twice on the same projection
|
||||
// as the first call may have transformed the BoolNode to a ConI
|
||||
if( prev_chk1 != prev_chk2 ) {
|
||||
adjust_check( prev_chk2, range1, index1, flip1, off_hi, igvn );
|
||||
}
|
||||
// Test is now covered by prior checks, dominate it out
|
||||
prev_dom = prev_chk2;
|
||||
} else {
|
||||
// Didn't find prior covering check, so cannot remove anything.
|
||||
if( !prev_chk1 ) return NULL;
|
||||
// 'Widen' the offset of the 1st and only covering check
|
||||
adjust_check( prev_chk1, range1, index1, flip1, off_hi, igvn );
|
||||
// Test is now covered by prior checks, dominate it out
|
||||
prev_dom = prev_chk1;
|
||||
if (nb_checks == 0) {
|
||||
return NULL;
|
||||
}
|
||||
// Constant indices only need to check the upper bound.
|
||||
// Non-constant indices must check both low and high.
|
||||
int chk0 = (nb_checks - 1) % NRC;
|
||||
if (index1) {
|
||||
if (nb_checks == 1) {
|
||||
return NULL;
|
||||
} else {
|
||||
// If the top range check's constant is the min or max of
|
||||
// all constants we widen the next one to cover the whole
|
||||
// range of constants.
|
||||
RangeCheck rc0 = prev_checks[chk0];
|
||||
int chk1 = (nb_checks - 2) % NRC;
|
||||
RangeCheck rc1 = prev_checks[chk1];
|
||||
if (rc0.off == off_lo) {
|
||||
adjust_check(rc1.ctl, range1, index1, flip1, off_hi, igvn);
|
||||
prev_dom = rc1.ctl;
|
||||
} else if (rc0.off == off_hi) {
|
||||
adjust_check(rc1.ctl, range1, index1, flip1, off_lo, igvn);
|
||||
prev_dom = rc1.ctl;
|
||||
} else {
|
||||
// If the top test's constant is not the min or max of all
|
||||
// constants, we need 3 range checks. We must leave the
|
||||
// top test unchanged because widening it would allow the
|
||||
// accesses it protects to successfully read/write out of
|
||||
// bounds.
|
||||
if (nb_checks == 2) {
|
||||
return NULL;
|
||||
}
|
||||
int chk2 = (nb_checks - 3) % NRC;
|
||||
RangeCheck rc2 = prev_checks[chk2];
|
||||
// The top range check a+i covers interval: -a <= i < length-a
|
||||
// The second range check b+i covers interval: -b <= i < length-b
|
||||
if (rc1.off <= rc0.off) {
|
||||
// if b <= a, we change the second range check to:
|
||||
// -min_of_all_constants <= i < length-min_of_all_constants
|
||||
// Together top and second range checks now cover:
|
||||
// -min_of_all_constants <= i < length-a
|
||||
// which is more restrictive than -b <= i < length-b:
|
||||
// -b <= -min_of_all_constants <= i < length-a <= length-b
|
||||
// The third check is then changed to:
|
||||
// -max_of_all_constants <= i < length-max_of_all_constants
|
||||
// so 2nd and 3rd checks restrict allowed values of i to:
|
||||
// -min_of_all_constants <= i < length-max_of_all_constants
|
||||
adjust_check(rc1.ctl, range1, index1, flip1, off_lo, igvn);
|
||||
adjust_check(rc2.ctl, range1, index1, flip1, off_hi, igvn);
|
||||
} else {
|
||||
// if b > a, we change the second range check to:
|
||||
// -max_of_all_constants <= i < length-max_of_all_constants
|
||||
// Together top and second range checks now cover:
|
||||
// -a <= i < length-max_of_all_constants
|
||||
// which is more restrictive than -b <= i < length-b:
|
||||
// -b < -a <= i < length-max_of_all_constants <= length-b
|
||||
// The third check is then changed to:
|
||||
// -max_of_all_constants <= i < length-max_of_all_constants
|
||||
// so 2nd and 3rd checks restrict allowed values of i to:
|
||||
// -min_of_all_constants <= i < length-max_of_all_constants
|
||||
adjust_check(rc1.ctl, range1, index1, flip1, off_hi, igvn);
|
||||
adjust_check(rc2.ctl, range1, index1, flip1, off_lo, igvn);
|
||||
}
|
||||
prev_dom = rc2.ctl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
RangeCheck rc0 = prev_checks[chk0];
|
||||
// 'Widen' the offset of the 1st and only covering check
|
||||
adjust_check(rc0.ctl, range1, index1, flip1, off_hi, igvn);
|
||||
// Test is now covered by prior checks, dominate it out
|
||||
prev_dom = rc0.ctl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else { // Scan for an equivalent test
|
||||
|
||||
Node *cmp;
|
||||
@ -1019,7 +1082,7 @@ void IfNode::dominated_by( Node *prev_dom, PhaseIterGVN *igvn ) {
|
||||
// for lower and upper bounds.
|
||||
ProjNode* unc_proj = proj_out(1 - prev_dom->as_Proj()->_con)->as_Proj();
|
||||
if (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate))
|
||||
prev_dom = idom;
|
||||
prev_dom = idom;
|
||||
|
||||
// Now walk the current IfNode's projections.
|
||||
// Loop ends when 'this' has no more uses.
|
||||
|
@ -241,8 +241,13 @@ void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff, bool flip, bool exc
|
||||
ProjNode* dp_proj = dp->as_Proj();
|
||||
ProjNode* unc_proj = iff->as_If()->proj_out(1 - dp_proj->_con)->as_Proj();
|
||||
if (exclude_loop_predicate &&
|
||||
unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate))
|
||||
(unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) ||
|
||||
unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_range_check))) {
|
||||
// If this is a range check (IfNode::is_range_check), do not
|
||||
// reorder because Compile::allow_range_check_smearing might have
|
||||
// changed the check.
|
||||
return; // Let IGVN transformation change control dependence.
|
||||
}
|
||||
|
||||
IdealLoopTree *old_loop = get_loop(dp);
|
||||
|
||||
@ -898,23 +903,23 @@ void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) {
|
||||
int n_op = n->Opcode();
|
||||
|
||||
// Check for an IF being dominated by another IF same test
|
||||
if( n_op == Op_If ) {
|
||||
if (n_op == Op_If) {
|
||||
Node *bol = n->in(1);
|
||||
uint max = bol->outcnt();
|
||||
// Check for same test used more than once?
|
||||
if( n_op == Op_If && max > 1 && bol->is_Bool() ) {
|
||||
if (max > 1 && bol->is_Bool()) {
|
||||
// Search up IDOMs to see if this IF is dominated.
|
||||
Node *cutoff = get_ctrl(bol);
|
||||
|
||||
// Now search up IDOMs till cutoff, looking for a dominating test
|
||||
Node *prevdom = n;
|
||||
Node *dom = idom(prevdom);
|
||||
while( dom != cutoff ) {
|
||||
if( dom->req() > 1 && dom->in(1) == bol && prevdom->in(0) == dom ) {
|
||||
while (dom != cutoff) {
|
||||
if (dom->req() > 1 && dom->in(1) == bol && prevdom->in(0) == dom) {
|
||||
// Replace the dominated test with an obvious true or false.
|
||||
// Place it on the IGVN worklist for later cleanup.
|
||||
C->set_major_progress();
|
||||
dominated_by( prevdom, n, false, true );
|
||||
dominated_by(prevdom, n, false, true);
|
||||
#ifndef PRODUCT
|
||||
if( VerifyLoopOptimizations ) verify();
|
||||
#endif
|
||||
|
@ -971,7 +971,11 @@ void PhaseMacroExpand::process_users_of_allocation(CallNode *alloc) {
|
||||
}
|
||||
|
||||
bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) {
|
||||
if (!EliminateAllocations || !alloc->_is_non_escaping) {
|
||||
// Don't do scalar replacement if the frame can be popped by JVMTI:
|
||||
// if reallocation fails during deoptimization we'll pop all
|
||||
// interpreter frames for this compiled frame and that won't play
|
||||
// nice with JVMTI popframe.
|
||||
if (!EliminateAllocations || JvmtiExport::can_pop_frame() || !alloc->_is_non_escaping) {
|
||||
return false;
|
||||
}
|
||||
Node* klass = alloc->in(AllocateNode::KlassNode);
|
||||
|
@ -74,7 +74,7 @@ class WhiteBox : public AllStatic {
|
||||
static JavaThread* create_sweeper_thread(TRAPS);
|
||||
static int get_blob_type(const CodeBlob* code);
|
||||
static CodeHeap* get_code_heap(int blob_type);
|
||||
static CodeBlob* allocate_code_blob(int blob_type, int size);
|
||||
static CodeBlob* allocate_code_blob(int size, int blob_type);
|
||||
static int array_bytes_to_length(size_t bytes);
|
||||
static void register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread,
|
||||
JNINativeMethod* method_array, int method_count);
|
||||
|
@ -125,8 +125,8 @@ char* Arguments::_meta_index_path = NULL;
|
||||
char* Arguments::_meta_index_dir = NULL;
|
||||
char* Arguments::_ext_dirs = NULL;
|
||||
|
||||
// Check if head of 'option' matches 'name', and sets 'tail' remaining part of option string
|
||||
|
||||
// Check if head of 'option' matches 'name', and sets 'tail' to the remaining
|
||||
// part of the option string.
|
||||
static bool match_option(const JavaVMOption *option, const char* name,
|
||||
const char** tail) {
|
||||
int len = (int)strlen(name);
|
||||
@ -138,6 +138,32 @@ static bool match_option(const JavaVMOption *option, const char* name,
|
||||
}
|
||||
}
|
||||
|
||||
// Check if 'option' matches 'name'. No "tail" is allowed.
|
||||
static bool match_option(const JavaVMOption *option, const char* name) {
|
||||
const char* tail = NULL;
|
||||
bool result = match_option(option, name, &tail);
|
||||
if (tail != NULL && *tail == '\0') {
|
||||
return result;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if any of the strings in null-terminated array 'names' matches.
|
||||
// If tail_allowed is true, then the tail must begin with a colon; otherwise,
|
||||
// the option must match exactly.
|
||||
static bool match_option(const JavaVMOption* option, const char** names, const char** tail,
|
||||
bool tail_allowed) {
|
||||
for (/* empty */; *names != NULL; ++names) {
|
||||
if (match_option(option, *names, tail)) {
|
||||
if (**tail == '\0' || tail_allowed && **tail == ':') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void logOption(const char* opt) {
|
||||
if (PrintVMOptions) {
|
||||
jio_fprintf(defaultStream::output_stream(), "VM option '%s'\n", opt);
|
||||
@ -2526,21 +2552,6 @@ static const char* system_assertion_options[] = {
|
||||
"-dsa", "-esa", "-disablesystemassertions", "-enablesystemassertions", 0
|
||||
};
|
||||
|
||||
// Return true if any of the strings in null-terminated array 'names' matches.
|
||||
// If tail_allowed is true, then the tail must begin with a colon; otherwise,
|
||||
// the option must match exactly.
|
||||
static bool match_option(const JavaVMOption* option, const char** names, const char** tail,
|
||||
bool tail_allowed) {
|
||||
for (/* empty */; *names != NULL; ++names) {
|
||||
if (match_option(option, *names, tail)) {
|
||||
if (**tail == '\0' || tail_allowed && **tail == ':') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Arguments::parse_uintx(const char* value,
|
||||
uintx* uintx_arg,
|
||||
uintx min_size) {
|
||||
@ -2782,16 +2793,16 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
}
|
||||
#endif // !INCLUDE_JVMTI
|
||||
// -Xnoclassgc
|
||||
} else if (match_option(option, "-Xnoclassgc", &tail)) {
|
||||
} else if (match_option(option, "-Xnoclassgc")) {
|
||||
FLAG_SET_CMDLINE(bool, ClassUnloading, false);
|
||||
// -Xconcgc
|
||||
} else if (match_option(option, "-Xconcgc", &tail)) {
|
||||
} else if (match_option(option, "-Xconcgc")) {
|
||||
FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, true);
|
||||
// -Xnoconcgc
|
||||
} else if (match_option(option, "-Xnoconcgc", &tail)) {
|
||||
} else if (match_option(option, "-Xnoconcgc")) {
|
||||
FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, false);
|
||||
// -Xbatch
|
||||
} else if (match_option(option, "-Xbatch", &tail)) {
|
||||
} else if (match_option(option, "-Xbatch")) {
|
||||
FLAG_SET_CMDLINE(bool, BackgroundCompilation, false);
|
||||
// -Xmn for compatibility with other JVM vendors
|
||||
} else if (match_option(option, "-Xmn", &tail)) {
|
||||
@ -2936,28 +2947,28 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
}
|
||||
FLAG_SET_CMDLINE(uintx, IncreaseFirstTierCompileThresholdAt, (uintx)uint_IncreaseFirstTierCompileThresholdAt);
|
||||
// -green
|
||||
} else if (match_option(option, "-green", &tail)) {
|
||||
} else if (match_option(option, "-green")) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"Green threads support not available\n");
|
||||
return JNI_EINVAL;
|
||||
// -native
|
||||
} else if (match_option(option, "-native", &tail)) {
|
||||
} else if (match_option(option, "-native")) {
|
||||
// HotSpot always uses native threads, ignore silently for compatibility
|
||||
// -Xsqnopause
|
||||
} else if (match_option(option, "-Xsqnopause", &tail)) {
|
||||
} else if (match_option(option, "-Xsqnopause")) {
|
||||
// EVM option, ignore silently for compatibility
|
||||
// -Xrs
|
||||
} else if (match_option(option, "-Xrs", &tail)) {
|
||||
} else if (match_option(option, "-Xrs")) {
|
||||
// Classic/EVM option, new functionality
|
||||
FLAG_SET_CMDLINE(bool, ReduceSignalUsage, true);
|
||||
} else if (match_option(option, "-Xusealtsigs", &tail)) {
|
||||
} else if (match_option(option, "-Xusealtsigs")) {
|
||||
// change default internal VM signals used - lower case for back compat
|
||||
FLAG_SET_CMDLINE(bool, UseAltSigs, true);
|
||||
// -Xoptimize
|
||||
} else if (match_option(option, "-Xoptimize", &tail)) {
|
||||
} else if (match_option(option, "-Xoptimize")) {
|
||||
// EVM option, ignore silently for compatibility
|
||||
// -Xprof
|
||||
} else if (match_option(option, "-Xprof", &tail)) {
|
||||
} else if (match_option(option, "-Xprof")) {
|
||||
#if INCLUDE_FPROF
|
||||
_has_profile = true;
|
||||
#else // INCLUDE_FPROF
|
||||
@ -2966,7 +2977,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
return JNI_ERR;
|
||||
#endif // INCLUDE_FPROF
|
||||
// -Xconcurrentio
|
||||
} else if (match_option(option, "-Xconcurrentio", &tail)) {
|
||||
} else if (match_option(option, "-Xconcurrentio")) {
|
||||
FLAG_SET_CMDLINE(bool, UseLWPSynchronization, true);
|
||||
FLAG_SET_CMDLINE(bool, BackgroundCompilation, false);
|
||||
FLAG_SET_CMDLINE(intx, DeferThrSuspendLoopCount, 1);
|
||||
@ -2974,13 +2985,13 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
FLAG_SET_CMDLINE(uintx, NewSizeThreadIncrease, 16 * K); // 20Kb per thread added to new generation
|
||||
|
||||
// -Xinternalversion
|
||||
} else if (match_option(option, "-Xinternalversion", &tail)) {
|
||||
} else if (match_option(option, "-Xinternalversion")) {
|
||||
jio_fprintf(defaultStream::output_stream(), "%s\n",
|
||||
VM_Version::internal_vm_info_string());
|
||||
vm_exit(0);
|
||||
#ifndef PRODUCT
|
||||
// -Xprintflags
|
||||
} else if (match_option(option, "-Xprintflags", &tail)) {
|
||||
} else if (match_option(option, "-Xprintflags")) {
|
||||
CommandLineFlags::printFlags(tty, false);
|
||||
vm_exit(0);
|
||||
#endif
|
||||
@ -3014,29 +3025,29 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
#endif
|
||||
}
|
||||
// -Xint
|
||||
} else if (match_option(option, "-Xint", &tail)) {
|
||||
} else if (match_option(option, "-Xint")) {
|
||||
set_mode_flags(_int);
|
||||
// -Xmixed
|
||||
} else if (match_option(option, "-Xmixed", &tail)) {
|
||||
} else if (match_option(option, "-Xmixed")) {
|
||||
set_mode_flags(_mixed);
|
||||
// -Xcomp
|
||||
} else if (match_option(option, "-Xcomp", &tail)) {
|
||||
} else if (match_option(option, "-Xcomp")) {
|
||||
// for testing the compiler; turn off all flags that inhibit compilation
|
||||
set_mode_flags(_comp);
|
||||
// -Xshare:dump
|
||||
} else if (match_option(option, "-Xshare:dump", &tail)) {
|
||||
} else if (match_option(option, "-Xshare:dump")) {
|
||||
FLAG_SET_CMDLINE(bool, DumpSharedSpaces, true);
|
||||
set_mode_flags(_int); // Prevent compilation, which creates objects
|
||||
// -Xshare:on
|
||||
} else if (match_option(option, "-Xshare:on", &tail)) {
|
||||
} else if (match_option(option, "-Xshare:on")) {
|
||||
FLAG_SET_CMDLINE(bool, UseSharedSpaces, true);
|
||||
FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true);
|
||||
// -Xshare:auto
|
||||
} else if (match_option(option, "-Xshare:auto", &tail)) {
|
||||
} else if (match_option(option, "-Xshare:auto")) {
|
||||
FLAG_SET_CMDLINE(bool, UseSharedSpaces, true);
|
||||
FLAG_SET_CMDLINE(bool, RequireSharedSpaces, false);
|
||||
// -Xshare:off
|
||||
} else if (match_option(option, "-Xshare:off", &tail)) {
|
||||
} else if (match_option(option, "-Xshare:off")) {
|
||||
FLAG_SET_CMDLINE(bool, UseSharedSpaces, false);
|
||||
FLAG_SET_CMDLINE(bool, RequireSharedSpaces, false);
|
||||
// -Xverify
|
||||
@ -3054,13 +3065,13 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
return JNI_EINVAL;
|
||||
}
|
||||
// -Xdebug
|
||||
} else if (match_option(option, "-Xdebug", &tail)) {
|
||||
} else if (match_option(option, "-Xdebug")) {
|
||||
// note this flag has been used, then ignore
|
||||
set_xdebug_mode(true);
|
||||
// -Xnoagent
|
||||
} else if (match_option(option, "-Xnoagent", &tail)) {
|
||||
} else if (match_option(option, "-Xnoagent")) {
|
||||
// For compatibility with classic. HotSpot refuses to load the old style agent.dll.
|
||||
} else if (match_option(option, "-Xboundthreads", &tail)) {
|
||||
} else if (match_option(option, "-Xboundthreads")) {
|
||||
// Bind user level threads to kernel threads (Solaris only)
|
||||
FLAG_SET_CMDLINE(bool, UseBoundThreads, true);
|
||||
} else if (match_option(option, "-Xloggc:", &tail)) {
|
||||
@ -3090,14 +3101,14 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
"check")) {
|
||||
return JNI_EINVAL;
|
||||
}
|
||||
} else if (match_option(option, "vfprintf", &tail)) {
|
||||
} else if (match_option(option, "vfprintf")) {
|
||||
_vfprintf_hook = CAST_TO_FN_PTR(vfprintf_hook_t, option->extraInfo);
|
||||
} else if (match_option(option, "exit", &tail)) {
|
||||
} else if (match_option(option, "exit")) {
|
||||
_exit_hook = CAST_TO_FN_PTR(exit_hook_t, option->extraInfo);
|
||||
} else if (match_option(option, "abort", &tail)) {
|
||||
} else if (match_option(option, "abort")) {
|
||||
_abort_hook = CAST_TO_FN_PTR(abort_hook_t, option->extraInfo);
|
||||
// -XX:+AggressiveHeap
|
||||
} else if (match_option(option, "-XX:+AggressiveHeap", &tail)) {
|
||||
} else if (match_option(option, "-XX:+AggressiveHeap")) {
|
||||
|
||||
// This option inspects the machine and attempts to set various
|
||||
// parameters to be optimal for long-running, memory allocation
|
||||
@ -3188,11 +3199,11 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
|
||||
// Need to keep consistency of MaxTenuringThreshold and AlwaysTenure/NeverTenure;
|
||||
// and the last option wins.
|
||||
} else if (match_option(option, "-XX:+NeverTenure", &tail)) {
|
||||
} else if (match_option(option, "-XX:+NeverTenure")) {
|
||||
FLAG_SET_CMDLINE(bool, NeverTenure, true);
|
||||
FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
|
||||
FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, markOopDesc::max_age + 1);
|
||||
} else if (match_option(option, "-XX:+AlwaysTenure", &tail)) {
|
||||
} else if (match_option(option, "-XX:+AlwaysTenure")) {
|
||||
FLAG_SET_CMDLINE(bool, NeverTenure, false);
|
||||
FLAG_SET_CMDLINE(bool, AlwaysTenure, true);
|
||||
FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, 0);
|
||||
@ -3211,17 +3222,17 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
FLAG_SET_CMDLINE(bool, NeverTenure, false);
|
||||
FLAG_SET_CMDLINE(bool, AlwaysTenure, false);
|
||||
}
|
||||
} else if (match_option(option, "-XX:+CMSPermGenSweepingEnabled", &tail) ||
|
||||
match_option(option, "-XX:-CMSPermGenSweepingEnabled", &tail)) {
|
||||
} else if (match_option(option, "-XX:+CMSPermGenSweepingEnabled") ||
|
||||
match_option(option, "-XX:-CMSPermGenSweepingEnabled")) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"Please use CMSClassUnloadingEnabled in place of "
|
||||
"CMSPermGenSweepingEnabled in the future\n");
|
||||
} else if (match_option(option, "-XX:+UseGCTimeLimit", &tail)) {
|
||||
} else if (match_option(option, "-XX:+UseGCTimeLimit")) {
|
||||
FLAG_SET_CMDLINE(bool, UseGCOverheadLimit, true);
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"Please use -XX:+UseGCOverheadLimit in place of "
|
||||
"-XX:+UseGCTimeLimit in the future\n");
|
||||
} else if (match_option(option, "-XX:-UseGCTimeLimit", &tail)) {
|
||||
} else if (match_option(option, "-XX:-UseGCTimeLimit")) {
|
||||
FLAG_SET_CMDLINE(bool, UseGCOverheadLimit, false);
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"Please use -XX:-UseGCOverheadLimit in place of "
|
||||
@ -3231,13 +3242,13 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
// are not to be documented.
|
||||
} else if (match_option(option, "-XX:MaxTLERatio=", &tail)) {
|
||||
// No longer used.
|
||||
} else if (match_option(option, "-XX:+ResizeTLE", &tail)) {
|
||||
} else if (match_option(option, "-XX:+ResizeTLE")) {
|
||||
FLAG_SET_CMDLINE(bool, ResizeTLAB, true);
|
||||
} else if (match_option(option, "-XX:-ResizeTLE", &tail)) {
|
||||
} else if (match_option(option, "-XX:-ResizeTLE")) {
|
||||
FLAG_SET_CMDLINE(bool, ResizeTLAB, false);
|
||||
} else if (match_option(option, "-XX:+PrintTLE", &tail)) {
|
||||
} else if (match_option(option, "-XX:+PrintTLE")) {
|
||||
FLAG_SET_CMDLINE(bool, PrintTLAB, true);
|
||||
} else if (match_option(option, "-XX:-PrintTLE", &tail)) {
|
||||
} else if (match_option(option, "-XX:-PrintTLE")) {
|
||||
FLAG_SET_CMDLINE(bool, PrintTLAB, false);
|
||||
} else if (match_option(option, "-XX:TLEFragmentationRatio=", &tail)) {
|
||||
// No longer used.
|
||||
@ -3253,17 +3264,17 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
FLAG_SET_CMDLINE(uintx, TLABSize, long_tlab_size);
|
||||
} else if (match_option(option, "-XX:TLEThreadRatio=", &tail)) {
|
||||
// No longer used.
|
||||
} else if (match_option(option, "-XX:+UseTLE", &tail)) {
|
||||
} else if (match_option(option, "-XX:+UseTLE")) {
|
||||
FLAG_SET_CMDLINE(bool, UseTLAB, true);
|
||||
} else if (match_option(option, "-XX:-UseTLE", &tail)) {
|
||||
} else if (match_option(option, "-XX:-UseTLE")) {
|
||||
FLAG_SET_CMDLINE(bool, UseTLAB, false);
|
||||
} else if (match_option(option, "-XX:+DisplayVMOutputToStderr", &tail)) {
|
||||
} else if (match_option(option, "-XX:+DisplayVMOutputToStderr")) {
|
||||
FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, false);
|
||||
FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, true);
|
||||
} else if (match_option(option, "-XX:+DisplayVMOutputToStdout", &tail)) {
|
||||
} else if (match_option(option, "-XX:+DisplayVMOutputToStdout")) {
|
||||
FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, false);
|
||||
FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, true);
|
||||
} else if (match_option(option, "-XX:+ExtendedDTraceProbes", &tail)) {
|
||||
} else if (match_option(option, "-XX:+ExtendedDTraceProbes")) {
|
||||
#if defined(DTRACE_ENABLED)
|
||||
FLAG_SET_CMDLINE(bool, ExtendedDTraceProbes, true);
|
||||
FLAG_SET_CMDLINE(bool, DTraceMethodProbes, true);
|
||||
@ -3275,7 +3286,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
return JNI_EINVAL;
|
||||
#endif // defined(DTRACE_ENABLED)
|
||||
#ifdef ASSERT
|
||||
} else if (match_option(option, "-XX:+FullGCALot", &tail)) {
|
||||
} else if (match_option(option, "-XX:+FullGCALot")) {
|
||||
FLAG_SET_CMDLINE(bool, FullGCALot, true);
|
||||
// disable scavenge before parallel mark-compact
|
||||
FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false);
|
||||
@ -3361,7 +3372,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||
}
|
||||
FLAG_SET_CMDLINE(uintx, MaxDirectMemorySize, max_direct_memory_size);
|
||||
#if !INCLUDE_MANAGEMENT
|
||||
} else if (match_option(option, "-XX:+ManagementServer", &tail)) {
|
||||
} else if (match_option(option, "-XX:+ManagementServer")) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"ManagementServer is not supported in this VM.\n");
|
||||
return JNI_ERR;
|
||||
@ -3796,23 +3807,23 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
|
||||
settings_file_specified = true;
|
||||
continue;
|
||||
}
|
||||
if (match_option(option, "-XX:+PrintVMOptions", &tail)) {
|
||||
if (match_option(option, "-XX:+PrintVMOptions")) {
|
||||
PrintVMOptions = true;
|
||||
continue;
|
||||
}
|
||||
if (match_option(option, "-XX:-PrintVMOptions", &tail)) {
|
||||
if (match_option(option, "-XX:-PrintVMOptions")) {
|
||||
PrintVMOptions = false;
|
||||
continue;
|
||||
}
|
||||
if (match_option(option, "-XX:+IgnoreUnrecognizedVMOptions", &tail)) {
|
||||
if (match_option(option, "-XX:+IgnoreUnrecognizedVMOptions")) {
|
||||
IgnoreUnrecognizedVMOptions = true;
|
||||
continue;
|
||||
}
|
||||
if (match_option(option, "-XX:-IgnoreUnrecognizedVMOptions", &tail)) {
|
||||
if (match_option(option, "-XX:-IgnoreUnrecognizedVMOptions")) {
|
||||
IgnoreUnrecognizedVMOptions = false;
|
||||
continue;
|
||||
}
|
||||
if (match_option(option, "-XX:+PrintFlagsInitial", &tail)) {
|
||||
if (match_option(option, "-XX:+PrintFlagsInitial")) {
|
||||
CommandLineFlags::printFlags(tty, false);
|
||||
vm_exit(0);
|
||||
}
|
||||
@ -3838,7 +3849,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
|
||||
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (match_option(option, "-XX:+PrintFlagsWithComments", &tail)) {
|
||||
if (match_option(option, "-XX:+PrintFlagsWithComments")) {
|
||||
CommandLineFlags::printFlags(tty, true);
|
||||
vm_exit(0);
|
||||
}
|
||||
|
@ -176,6 +176,8 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||
assert(vf->is_compiled_frame(), "Wrong frame type");
|
||||
chunk->push(compiledVFrame::cast(vf));
|
||||
|
||||
bool realloc_failures = false;
|
||||
|
||||
#ifdef COMPILER2
|
||||
// Reallocate the non-escaping objects and restore their fields. Then
|
||||
// relock objects if synchronization on them was eliminated.
|
||||
@ -206,19 +208,16 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||
tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, (void *)result, thread);
|
||||
}
|
||||
}
|
||||
bool reallocated = false;
|
||||
if (objects != NULL) {
|
||||
JRT_BLOCK
|
||||
reallocated = realloc_objects(thread, &deoptee, objects, THREAD);
|
||||
realloc_failures = realloc_objects(thread, &deoptee, objects, THREAD);
|
||||
JRT_END
|
||||
}
|
||||
if (reallocated) {
|
||||
reassign_fields(&deoptee, &map, objects);
|
||||
reassign_fields(&deoptee, &map, objects, realloc_failures);
|
||||
#ifndef PRODUCT
|
||||
if (TraceDeoptimization) {
|
||||
ttyLocker ttyl;
|
||||
tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, thread);
|
||||
print_objects(objects);
|
||||
print_objects(objects, realloc_failures);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -236,7 +235,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||
assert (cvf->scope() != NULL,"expect only compiled java frames");
|
||||
GrowableArray<MonitorInfo*>* monitors = cvf->monitors();
|
||||
if (monitors->is_nonempty()) {
|
||||
relock_objects(monitors, thread);
|
||||
relock_objects(monitors, thread, realloc_failures);
|
||||
#ifndef PRODUCT
|
||||
if (TraceDeoptimization) {
|
||||
ttyLocker ttyl;
|
||||
@ -247,7 +246,12 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||
first = false;
|
||||
tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, thread);
|
||||
}
|
||||
tty->print_cr(" object <" INTPTR_FORMAT "> locked", (void *)mi->owner());
|
||||
if (mi->owner_is_scalar_replaced()) {
|
||||
Klass* k = java_lang_Class::as_Klass(mi->owner_klass());
|
||||
tty->print_cr(" failed reallocation for klass %s", k->external_name());
|
||||
} else {
|
||||
tty->print_cr(" object <" INTPTR_FORMAT "> locked", (void *)mi->owner());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -262,9 +266,14 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||
// out the java state residing in the vframeArray will be missed.
|
||||
No_Safepoint_Verifier no_safepoint;
|
||||
|
||||
vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk);
|
||||
vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk, realloc_failures);
|
||||
#ifdef COMPILER2
|
||||
if (realloc_failures) {
|
||||
pop_frames_failed_reallocs(thread, array);
|
||||
}
|
||||
#endif
|
||||
|
||||
assert(thread->vframe_array_head() == NULL, "Pending deopt!");;
|
||||
assert(thread->vframe_array_head() == NULL, "Pending deopt!");
|
||||
thread->set_vframe_array_head(array);
|
||||
|
||||
// Now that the vframeArray has been created if we have any deferred local writes
|
||||
@ -718,6 +727,8 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArra
|
||||
int exception_line = thread->exception_line();
|
||||
thread->clear_pending_exception();
|
||||
|
||||
bool failures = false;
|
||||
|
||||
for (int i = 0; i < objects->length(); i++) {
|
||||
assert(objects->at(i)->is_object(), "invalid debug information");
|
||||
ObjectValue* sv = (ObjectValue*) objects->at(i);
|
||||
@ -727,27 +738,34 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArra
|
||||
|
||||
if (k->oop_is_instance()) {
|
||||
InstanceKlass* ik = InstanceKlass::cast(k());
|
||||
obj = ik->allocate_instance(CHECK_(false));
|
||||
obj = ik->allocate_instance(THREAD);
|
||||
} else if (k->oop_is_typeArray()) {
|
||||
TypeArrayKlass* ak = TypeArrayKlass::cast(k());
|
||||
assert(sv->field_size() % type2size[ak->element_type()] == 0, "non-integral array length");
|
||||
int len = sv->field_size() / type2size[ak->element_type()];
|
||||
obj = ak->allocate(len, CHECK_(false));
|
||||
obj = ak->allocate(len, THREAD);
|
||||
} else if (k->oop_is_objArray()) {
|
||||
ObjArrayKlass* ak = ObjArrayKlass::cast(k());
|
||||
obj = ak->allocate(sv->field_size(), CHECK_(false));
|
||||
obj = ak->allocate(sv->field_size(), THREAD);
|
||||
}
|
||||
|
||||
if (obj == NULL) {
|
||||
failures = true;
|
||||
}
|
||||
|
||||
assert(obj != NULL, "allocation failed");
|
||||
assert(sv->value().is_null(), "redundant reallocation");
|
||||
assert(obj != NULL || HAS_PENDING_EXCEPTION, "allocation should succeed or we should get an exception");
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
sv->set_value(obj);
|
||||
}
|
||||
|
||||
if (pending_exception.not_null()) {
|
||||
if (failures) {
|
||||
THROW_OOP_(Universe::out_of_memory_error_realloc_objects(), failures);
|
||||
} else if (pending_exception.not_null()) {
|
||||
thread->set_pending_exception(pending_exception(), exception_file, exception_line);
|
||||
}
|
||||
|
||||
return true;
|
||||
return failures;
|
||||
}
|
||||
|
||||
// This assumes that the fields are stored in ObjectValue in the same order
|
||||
@ -885,12 +903,15 @@ void Deoptimization::reassign_object_array_elements(frame* fr, RegisterMap* reg_
|
||||
|
||||
|
||||
// restore fields of all eliminated objects and arrays
|
||||
void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects) {
|
||||
void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures) {
|
||||
for (int i = 0; i < objects->length(); i++) {
|
||||
ObjectValue* sv = (ObjectValue*) objects->at(i);
|
||||
KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()()));
|
||||
Handle obj = sv->value();
|
||||
assert(obj.not_null(), "reallocation was missed");
|
||||
assert(obj.not_null() || realloc_failures, "reallocation was missed");
|
||||
if (obj.is_null()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (k->oop_is_instance()) {
|
||||
InstanceKlass* ik = InstanceKlass::cast(k());
|
||||
@ -907,34 +928,36 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr
|
||||
|
||||
|
||||
// relock objects for which synchronization was eliminated
|
||||
void Deoptimization::relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread) {
|
||||
void Deoptimization::relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread, bool realloc_failures) {
|
||||
for (int i = 0; i < monitors->length(); i++) {
|
||||
MonitorInfo* mon_info = monitors->at(i);
|
||||
if (mon_info->eliminated()) {
|
||||
assert(mon_info->owner() != NULL, "reallocation was missed");
|
||||
Handle obj = Handle(mon_info->owner());
|
||||
markOop mark = obj->mark();
|
||||
if (UseBiasedLocking && mark->has_bias_pattern()) {
|
||||
// New allocated objects may have the mark set to anonymously biased.
|
||||
// Also the deoptimized method may called methods with synchronization
|
||||
// where the thread-local object is bias locked to the current thread.
|
||||
assert(mark->is_biased_anonymously() ||
|
||||
mark->biased_locker() == thread, "should be locked to current thread");
|
||||
// Reset mark word to unbiased prototype.
|
||||
markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());
|
||||
obj->set_mark(unbiased_prototype);
|
||||
assert(!mon_info->owner_is_scalar_replaced() || realloc_failures, "reallocation was missed");
|
||||
if (!mon_info->owner_is_scalar_replaced()) {
|
||||
Handle obj = Handle(mon_info->owner());
|
||||
markOop mark = obj->mark();
|
||||
if (UseBiasedLocking && mark->has_bias_pattern()) {
|
||||
// New allocated objects may have the mark set to anonymously biased.
|
||||
// Also the deoptimized method may called methods with synchronization
|
||||
// where the thread-local object is bias locked to the current thread.
|
||||
assert(mark->is_biased_anonymously() ||
|
||||
mark->biased_locker() == thread, "should be locked to current thread");
|
||||
// Reset mark word to unbiased prototype.
|
||||
markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());
|
||||
obj->set_mark(unbiased_prototype);
|
||||
}
|
||||
BasicLock* lock = mon_info->lock();
|
||||
ObjectSynchronizer::slow_enter(obj, lock, thread);
|
||||
assert(mon_info->owner()->is_locked(), "object must be locked now");
|
||||
}
|
||||
BasicLock* lock = mon_info->lock();
|
||||
ObjectSynchronizer::slow_enter(obj, lock, thread);
|
||||
}
|
||||
assert(mon_info->owner()->is_locked(), "object must be locked now");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef PRODUCT
|
||||
// print information about reallocated objects
|
||||
void Deoptimization::print_objects(GrowableArray<ScopeValue*>* objects) {
|
||||
void Deoptimization::print_objects(GrowableArray<ScopeValue*>* objects, bool realloc_failures) {
|
||||
fieldDescriptor fd;
|
||||
|
||||
for (int i = 0; i < objects->length(); i++) {
|
||||
@ -944,10 +967,15 @@ void Deoptimization::print_objects(GrowableArray<ScopeValue*>* objects) {
|
||||
|
||||
tty->print(" object <" INTPTR_FORMAT "> of type ", (void *)sv->value()());
|
||||
k->print_value();
|
||||
tty->print(" allocated (%d bytes)", obj->size() * HeapWordSize);
|
||||
assert(obj.not_null() || realloc_failures, "reallocation was missed");
|
||||
if (obj.is_null()) {
|
||||
tty->print(" allocation failed");
|
||||
} else {
|
||||
tty->print(" allocated (%d bytes)", obj->size() * HeapWordSize);
|
||||
}
|
||||
tty->cr();
|
||||
|
||||
if (Verbose) {
|
||||
if (Verbose && !obj.is_null()) {
|
||||
k->oop_print_on(obj(), tty);
|
||||
}
|
||||
}
|
||||
@ -955,7 +983,7 @@ void Deoptimization::print_objects(GrowableArray<ScopeValue*>* objects) {
|
||||
#endif
|
||||
#endif // COMPILER2
|
||||
|
||||
vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk) {
|
||||
vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures) {
|
||||
Events::log(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, fr.pc(), fr.sp());
|
||||
|
||||
#ifndef PRODUCT
|
||||
@ -998,7 +1026,7 @@ vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, Re
|
||||
// Since the Java thread being deoptimized will eventually adjust it's own stack,
|
||||
// the vframeArray containing the unpacking information is allocated in the C heap.
|
||||
// For Compiler1, the caller of the deoptimized frame is saved for use by unpack_frames().
|
||||
vframeArray* array = vframeArray::allocate(thread, frame_size, chunk, reg_map, sender, caller, fr);
|
||||
vframeArray* array = vframeArray::allocate(thread, frame_size, chunk, reg_map, sender, caller, fr, realloc_failures);
|
||||
|
||||
// Compare the vframeArray to the collected vframes
|
||||
assert(array->structural_compare(thread, chunk), "just checking");
|
||||
@ -1013,6 +1041,33 @@ vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, Re
|
||||
return array;
|
||||
}
|
||||
|
||||
#ifdef COMPILER2
|
||||
void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array) {
|
||||
// Reallocation of some scalar replaced objects failed. Record
|
||||
// that we need to pop all the interpreter frames for the
|
||||
// deoptimized compiled frame.
|
||||
assert(thread->frames_to_pop_failed_realloc() == 0, "missed frames to pop?");
|
||||
thread->set_frames_to_pop_failed_realloc(array->frames());
|
||||
// Unlock all monitors here otherwise the interpreter will see a
|
||||
// mix of locked and unlocked monitors (because of failed
|
||||
// reallocations of synchronized objects) and be confused.
|
||||
for (int i = 0; i < array->frames(); i++) {
|
||||
MonitorChunk* monitors = array->element(i)->monitors();
|
||||
if (monitors != NULL) {
|
||||
for (int j = 0; j < monitors->number_of_monitors(); j++) {
|
||||
BasicObjectLock* src = monitors->at(j);
|
||||
if (src->obj() != NULL) {
|
||||
ObjectSynchronizer::fast_exit(src->obj(), src->lock(), thread);
|
||||
}
|
||||
}
|
||||
array->element(i)->free_monitors(thread);
|
||||
#ifdef ASSERT
|
||||
array->element(i)->set_removed_monitors();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void collect_monitors(compiledVFrame* cvf, GrowableArray<Handle>* objects_to_revoke) {
|
||||
GrowableArray<MonitorInfo*>* monitors = cvf->monitors();
|
||||
|
@ -125,13 +125,14 @@ class Deoptimization : AllStatic {
|
||||
static bool realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS);
|
||||
static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type);
|
||||
static void reassign_object_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, objArrayOop obj);
|
||||
static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects);
|
||||
static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread);
|
||||
NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects);)
|
||||
static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects, bool realloc_failures);
|
||||
static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread, bool realloc_failures);
|
||||
static void pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array);
|
||||
NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects, bool realloc_failures);)
|
||||
#endif // COMPILER2
|
||||
|
||||
public:
|
||||
static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk);
|
||||
static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk, bool realloc_failures);
|
||||
|
||||
// Interface used for unpacking deoptimized frames
|
||||
|
||||
|
@ -456,6 +456,7 @@ JRT_END
|
||||
|
||||
address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* thread, address return_address) {
|
||||
assert(frame::verify_return_pc(return_address), err_msg("must be a return address: " INTPTR_FORMAT, return_address));
|
||||
assert(thread->frames_to_pop_failed_realloc() == 0 || Interpreter::contains(return_address), "missed frames to pop?");
|
||||
|
||||
// Reset method handle flag.
|
||||
thread->set_is_method_handle_return(false);
|
||||
|
@ -1449,6 +1449,7 @@ void JavaThread::initialize() {
|
||||
_popframe_condition = popframe_inactive;
|
||||
_popframe_preserved_args = NULL;
|
||||
_popframe_preserved_args_size = 0;
|
||||
_frames_to_pop_failed_realloc = 0;
|
||||
|
||||
pd_initialize();
|
||||
}
|
||||
|
@ -908,6 +908,12 @@ class JavaThread: public Thread {
|
||||
// This is set to popframe_pending to signal that top Java frame should be popped immediately
|
||||
int _popframe_condition;
|
||||
|
||||
// If reallocation of scalar replaced objects fails, we throw OOM
|
||||
// and during exception propagation, pop the top
|
||||
// _frames_to_pop_failed_realloc frames, the ones that reference
|
||||
// failed reallocations.
|
||||
int _frames_to_pop_failed_realloc;
|
||||
|
||||
#ifndef PRODUCT
|
||||
int _jmp_ring_index;
|
||||
struct {
|
||||
@ -1567,6 +1573,10 @@ class JavaThread: public Thread {
|
||||
void clr_pop_frame_in_process(void) { _popframe_condition &= ~popframe_processing_bit; }
|
||||
#endif
|
||||
|
||||
int frames_to_pop_failed_realloc() const { return _frames_to_pop_failed_realloc; }
|
||||
void set_frames_to_pop_failed_realloc(int nb) { _frames_to_pop_failed_realloc = nb; }
|
||||
void dec_frames_to_pop_failed_realloc() { _frames_to_pop_failed_realloc--; }
|
||||
|
||||
private:
|
||||
// Saved incoming arguments to popped frame.
|
||||
// Used only when popped interpreted frame returns to deoptimized frame.
|
||||
|
@ -57,7 +57,7 @@ void vframeArrayElement::free_monitors(JavaThread* jt) {
|
||||
}
|
||||
}
|
||||
|
||||
void vframeArrayElement::fill_in(compiledVFrame* vf) {
|
||||
void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) {
|
||||
|
||||
// Copy the information from the compiled vframe to the
|
||||
// interpreter frame we will be creating to replace vf
|
||||
@ -65,6 +65,9 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) {
|
||||
_method = vf->method();
|
||||
_bci = vf->raw_bci();
|
||||
_reexecute = vf->should_reexecute();
|
||||
#ifdef ASSERT
|
||||
_removed_monitors = false;
|
||||
#endif
|
||||
|
||||
int index;
|
||||
|
||||
@ -82,11 +85,15 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) {
|
||||
// Migrate the BasicLocks from the stack to the monitor chunk
|
||||
for (index = 0; index < list->length(); index++) {
|
||||
MonitorInfo* monitor = list->at(index);
|
||||
assert(!monitor->owner_is_scalar_replaced(), "object should be reallocated already");
|
||||
assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased");
|
||||
assert(!monitor->owner_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
|
||||
BasicObjectLock* dest = _monitors->at(index);
|
||||
dest->set_obj(monitor->owner());
|
||||
monitor->lock()->move_to(monitor->owner(), dest->lock());
|
||||
if (monitor->owner_is_scalar_replaced()) {
|
||||
dest->set_obj(NULL);
|
||||
} else {
|
||||
assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased");
|
||||
dest->set_obj(monitor->owner());
|
||||
monitor->lock()->move_to(monitor->owner(), dest->lock());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +118,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) {
|
||||
StackValue* value = locs->at(index);
|
||||
switch(value->type()) {
|
||||
case T_OBJECT:
|
||||
assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
|
||||
assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
|
||||
// preserve object type
|
||||
_locals->add( new StackValue(cast_from_oop<intptr_t>((value->get_obj()())), T_OBJECT ));
|
||||
break;
|
||||
@ -136,7 +143,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) {
|
||||
StackValue* value = exprs->at(index);
|
||||
switch(value->type()) {
|
||||
case T_OBJECT:
|
||||
assert(!value->obj_is_scalar_replaced(), "object should be reallocated already");
|
||||
assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already");
|
||||
// preserve object type
|
||||
_expressions->add( new StackValue(cast_from_oop<intptr_t>((value->get_obj()())), T_OBJECT ));
|
||||
break;
|
||||
@ -287,7 +294,7 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters,
|
||||
|
||||
_frame.patch_pc(thread, pc);
|
||||
|
||||
assert (!method()->is_synchronized() || locks > 0, "synchronized methods must have monitors");
|
||||
assert (!method()->is_synchronized() || locks > 0 || _removed_monitors, "synchronized methods must have monitors");
|
||||
|
||||
BasicObjectLock* top = iframe()->interpreter_frame_monitor_begin();
|
||||
for (int index = 0; index < locks; index++) {
|
||||
@ -439,7 +446,8 @@ int vframeArrayElement::on_stack_size(int callee_parameters,
|
||||
|
||||
|
||||
vframeArray* vframeArray::allocate(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk,
|
||||
RegisterMap *reg_map, frame sender, frame caller, frame self) {
|
||||
RegisterMap *reg_map, frame sender, frame caller, frame self,
|
||||
bool realloc_failures) {
|
||||
|
||||
// Allocate the vframeArray
|
||||
vframeArray * result = (vframeArray*) AllocateHeap(sizeof(vframeArray) + // fixed part
|
||||
@ -451,19 +459,20 @@ vframeArray* vframeArray::allocate(JavaThread* thread, int frame_size, GrowableA
|
||||
result->_caller = caller;
|
||||
result->_original = self;
|
||||
result->set_unroll_block(NULL); // initialize it
|
||||
result->fill_in(thread, frame_size, chunk, reg_map);
|
||||
result->fill_in(thread, frame_size, chunk, reg_map, realloc_failures);
|
||||
return result;
|
||||
}
|
||||
|
||||
void vframeArray::fill_in(JavaThread* thread,
|
||||
int frame_size,
|
||||
GrowableArray<compiledVFrame*>* chunk,
|
||||
const RegisterMap *reg_map) {
|
||||
const RegisterMap *reg_map,
|
||||
bool realloc_failures) {
|
||||
// Set owner first, it is used when adding monitor chunks
|
||||
|
||||
_frame_size = frame_size;
|
||||
for(int i = 0; i < chunk->length(); i++) {
|
||||
element(i)->fill_in(chunk->at(i));
|
||||
element(i)->fill_in(chunk->at(i), realloc_failures);
|
||||
}
|
||||
|
||||
// Copy registers for callee-saved registers
|
||||
|
@ -58,6 +58,9 @@ class vframeArrayElement : public _ValueObj {
|
||||
MonitorChunk* _monitors; // active monitors for this vframe
|
||||
StackValueCollection* _locals;
|
||||
StackValueCollection* _expressions;
|
||||
#ifdef ASSERT
|
||||
bool _removed_monitors;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
@ -78,7 +81,7 @@ class vframeArrayElement : public _ValueObj {
|
||||
|
||||
StackValueCollection* expressions(void) const { return _expressions; }
|
||||
|
||||
void fill_in(compiledVFrame* vf);
|
||||
void fill_in(compiledVFrame* vf, bool realloc_failures);
|
||||
|
||||
// Formerly part of deoptimizedVFrame
|
||||
|
||||
@ -99,6 +102,12 @@ class vframeArrayElement : public _ValueObj {
|
||||
bool is_bottom_frame,
|
||||
int exec_mode);
|
||||
|
||||
#ifdef ASSERT
|
||||
void set_removed_monitors() {
|
||||
_removed_monitors = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print(outputStream* st);
|
||||
#endif /* PRODUCT */
|
||||
@ -160,13 +169,14 @@ class vframeArray: public CHeapObj<mtCompiler> {
|
||||
int frames() const { return _frames; }
|
||||
|
||||
static vframeArray* allocate(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk,
|
||||
RegisterMap* reg_map, frame sender, frame caller, frame self);
|
||||
RegisterMap* reg_map, frame sender, frame caller, frame self,
|
||||
bool realloc_failures);
|
||||
|
||||
|
||||
vframeArrayElement* element(int index) { assert(is_within_bounds(index), "Bad index"); return &_elements[index]; }
|
||||
|
||||
// Allocates a new vframe in the array and fills the array with vframe information in chunk
|
||||
void fill_in(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk, const RegisterMap *reg_map);
|
||||
void fill_in(JavaThread* thread, int frame_size, GrowableArray<compiledVFrame*>* chunk, const RegisterMap *reg_map, bool realloc_failures);
|
||||
|
||||
// Returns the owner of this vframeArray
|
||||
JavaThread* owner_thread() const { return _owner_thread; }
|
||||
|
@ -556,9 +556,6 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
|
||||
\
|
||||
nonstatic_field(TenuredGeneration, _min_heap_delta_bytes, size_t) \
|
||||
nonstatic_field(TenuredGeneration, _the_space, ContiguousSpace*) \
|
||||
nonstatic_field(TenuredGeneration, _last_gc, WaterMark) \
|
||||
\
|
||||
\
|
||||
\
|
||||
nonstatic_field(Space, _bottom, HeapWord*) \
|
||||
nonstatic_field(Space, _end, HeapWord*) \
|
||||
|
@ -314,6 +314,28 @@ Declares a structure type that can be used in other events.
|
||||
<value type="BYTES64" field="totalSize" label="Total Size" />
|
||||
</event>
|
||||
|
||||
<!-- Promotion events, Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. -->
|
||||
<event id="PromoteObjectInNewPLAB" path="vm/gc/detailed/object_promotion_in_new_PLAB" label="Promotion in new PLAB"
|
||||
description="Object survived scavenge and was copied to a new Promotion Local Allocation Buffer (PLAB). Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects."
|
||||
has_thread="true" has_stacktrace="false" is_instant="true">
|
||||
<value type="UINT" field="gcId" label="GC ID" relation="GC_ID" description="ID of GC during which the object was promoted"/>
|
||||
<value type="CLASS" field="class" label="Class" description="Class of promoted object"/>
|
||||
<value type="BYTES64" field="objectSize" label="Object Size" description="Size of promoted object"/>
|
||||
<value type="UINT" field="tenuringAge" label="Object Tenuring Age" description="Tenuring age of a surviving object before being copied. The tenuring age of an object is a value between 0-15 and is incremented each scavange the object survives. Newly allocated objects have tenuring age 0."/>
|
||||
<value type="BOOLEAN" field="tenured" label="Tenured" description="True if object was promoted to Old space, otherwise the object was aged and copied to a Survivor space"/>
|
||||
<value type="BYTES64" field="plabSize" label="PLAB Size" description="Size of the allocated PLAB to which the object was copied"/>
|
||||
</event>
|
||||
|
||||
<event id="PromoteObjectOutsidePLAB" path="vm/gc/detailed/object_promotion_outside_PLAB" label="Promotion outside PLAB"
|
||||
description="Object survived scavenge and was copied directly to the heap. Supported GCs are Parallel Scavange, G1 and CMS with Parallel New. Due to promotion being done in parallel an object might be reported multiple times as the GC threads race to copy all objects."
|
||||
has_thread="true" has_stacktrace="false" is_instant="true">
|
||||
<value type="UINT" field="gcId" label="GC ID" relation="GC_ID" description="ID of GC during which the object was promoted"/>
|
||||
<value type="CLASS" field="class" label="Class" description="Class of promoted object"/>
|
||||
<value type="BYTES64" field="objectSize" label="Object Size" description="Size of promoted object"/>
|
||||
<value type="UINT" field="tenuringAge" label="Object Tenuring Age" description="Tenuring age of a surviving object before being copied. The tenuring age of an object is a value between 0-15 and is incremented each scavange the object survives. Newly allocated objects have tenuring age 0."/>
|
||||
<value type="BOOLEAN" field="tenured" label="Tenured" description="True if object was promoted to Old space, otherwise the object was aged and copied to a Survivor space"/>
|
||||
</event>
|
||||
|
||||
<event id="PromotionFailed" path="vm/gc/detailed/promotion_failed" label="Promotion Failed" is_instant="true"
|
||||
description="Promotion of an object failed">
|
||||
<value type="UINT" field="gcId" label="GC ID" relation="GC_ID"/>
|
||||
|
@ -61,6 +61,7 @@ public class TestMonomorphicObjectCall {
|
||||
String[] vmOpts = new String[] {
|
||||
"-Xbootclasspath/p:" + testClasses,
|
||||
"-Xcomp",
|
||||
"-XX:+IgnoreUnrecognizedVMOptions",
|
||||
"-XX:-VerifyDependencies",
|
||||
"-XX:CompileOnly=TestMonomorphicObjectCall::callFinalize",
|
||||
"-XX:CompileOnly=Object::finalizeObject",
|
||||
|
86
hotspot/test/compiler/exceptions/SumTest.java
Normal file
86
hotspot/test/compiler/exceptions/SumTest.java
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8066900
|
||||
* @summary FP registers are not properly restored by C1 when handling exceptions
|
||||
* @run main/othervm -Xbatch SumTest
|
||||
*
|
||||
*/
|
||||
public class SumTest {
|
||||
private static class Sum {
|
||||
|
||||
double[] sums;
|
||||
|
||||
/**
|
||||
* Construct empty Sum
|
||||
*/
|
||||
public Sum() {
|
||||
sums = new double[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sum of all numbers added to this Sum
|
||||
*
|
||||
* @return the sum
|
||||
*/
|
||||
final public double getSum() {
|
||||
double sum = 0;
|
||||
for (final double s : sums) {
|
||||
sum += s;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new number to this Sum
|
||||
*
|
||||
* @param a number to be added.
|
||||
*/
|
||||
final public void add(double a) {
|
||||
try {
|
||||
sums[sums.length] = -1; // Cause IndexOutOfBoundsException
|
||||
} catch (final IndexOutOfBoundsException e) {
|
||||
final double[] oldSums = sums;
|
||||
sums = new double[oldSums.length + 1]; // Extend sums
|
||||
System.arraycopy(oldSums, 0, sums, 0, oldSums.length);
|
||||
sums[oldSums.length] = a; // Append a
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
final Sum sum = new Sum();
|
||||
for (int i = 1; i <= 10000; ++i) {
|
||||
sum.add(1);
|
||||
double ii = sum.getSum();
|
||||
if (i != ii) {
|
||||
throw new Exception("Failure: computed = " + ii + ", expected = " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
436
hotspot/test/compiler/rangechecks/TestRangeCheckSmearing.java
Normal file
436
hotspot/test/compiler/rangechecks/TestRangeCheckSmearing.java
Normal file
@ -0,0 +1,436 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8066103
|
||||
* @summary C2's range check smearing allows out of bound array accesses
|
||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox /testlibrary/com/oracle/java/testlibrary
|
||||
* @build TestRangeCheckSmearing
|
||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run main ClassFileInstaller com.oracle.java.testlibrary.Platform
|
||||
* @run main/othervm -ea -Xmixed -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||
* -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestRangeCheckSmearing
|
||||
*
|
||||
*/
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import sun.hotspot.WhiteBox;
|
||||
import sun.hotspot.code.NMethod;
|
||||
import com.oracle.java.testlibrary.Platform;
|
||||
|
||||
public class TestRangeCheckSmearing {
|
||||
private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface Args { int[] value(); }
|
||||
|
||||
// first range check is i + max of all constants
|
||||
@Args({0, 8})
|
||||
static int m1(int[] array, int i, boolean allaccesses) {
|
||||
int res = 0;
|
||||
res += array[i+9];
|
||||
if (allaccesses) {
|
||||
res += array[i+8];
|
||||
res += array[i+7];
|
||||
res += array[i+6];
|
||||
res += array[i+5];
|
||||
res += array[i+4];
|
||||
res += array[i+3];
|
||||
res += array[i+2];
|
||||
res += array[i+1];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// first range check is i + min of all constants
|
||||
@Args({0, -9})
|
||||
static int m2(int[] array, int i, boolean allaccesses) {
|
||||
int res = 0;
|
||||
res += array[i+1];
|
||||
if (allaccesses) {
|
||||
res += array[i+2];
|
||||
res += array[i+3];
|
||||
res += array[i+4];
|
||||
res += array[i+5];
|
||||
res += array[i+6];
|
||||
res += array[i+7];
|
||||
res += array[i+8];
|
||||
res += array[i+9];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// first range check is not i + min/max of all constants
|
||||
@Args({0, 8})
|
||||
static int m3(int[] array, int i, boolean allaccesses) {
|
||||
int res = 0;
|
||||
res += array[i+3];
|
||||
if (allaccesses) {
|
||||
res += array[i+2];
|
||||
res += array[i+1];
|
||||
res += array[i+4];
|
||||
res += array[i+5];
|
||||
res += array[i+6];
|
||||
res += array[i+7];
|
||||
res += array[i+8];
|
||||
res += array[i+9];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Args({0, -9})
|
||||
static int m4(int[] array, int i, boolean allaccesses) {
|
||||
int res = 0;
|
||||
res += array[i+3];
|
||||
if (allaccesses) {
|
||||
res += array[i+4];
|
||||
res += array[i+1];
|
||||
res += array[i+2];
|
||||
res += array[i+5];
|
||||
res += array[i+6];
|
||||
res += array[i+7];
|
||||
res += array[i+8];
|
||||
res += array[i+9];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Args({0, -3})
|
||||
static int m5(int[] array, int i, boolean allaccesses) {
|
||||
int res = 0;
|
||||
res += array[i+3];
|
||||
res += array[i+2];
|
||||
if (allaccesses) {
|
||||
res += array[i+1];
|
||||
res += array[i+4];
|
||||
res += array[i+5];
|
||||
res += array[i+6];
|
||||
res += array[i+7];
|
||||
res += array[i+8];
|
||||
res += array[i+9];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Args({0, 6})
|
||||
static int m6(int[] array, int i, boolean allaccesses) {
|
||||
int res = 0;
|
||||
res += array[i+3];
|
||||
res += array[i+4];
|
||||
if (allaccesses) {
|
||||
res += array[i+2];
|
||||
res += array[i+1];
|
||||
res += array[i+5];
|
||||
res += array[i+6];
|
||||
res += array[i+7];
|
||||
res += array[i+8];
|
||||
res += array[i+9];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Args({0, 6})
|
||||
static int m7(int[] array, int i, boolean allaccesses) {
|
||||
int res = 0;
|
||||
res += array[i+3];
|
||||
res += array[i+2];
|
||||
res += array[i+4];
|
||||
if (allaccesses) {
|
||||
res += array[i+1];
|
||||
res += array[i+5];
|
||||
res += array[i+6];
|
||||
res += array[i+7];
|
||||
res += array[i+8];
|
||||
res += array[i+9];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Args({0, -3})
|
||||
static int m8(int[] array, int i, boolean allaccesses) {
|
||||
int res = 0;
|
||||
res += array[i+3];
|
||||
res += array[i+4];
|
||||
res += array[i+2];
|
||||
if (allaccesses) {
|
||||
res += array[i+1];
|
||||
res += array[i+5];
|
||||
res += array[i+6];
|
||||
res += array[i+7];
|
||||
res += array[i+8];
|
||||
res += array[i+9];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Args({6, 15})
|
||||
static int m9(int[] array, int i, boolean allaccesses) {
|
||||
int res = 0;
|
||||
res += array[i+3];
|
||||
if (allaccesses) {
|
||||
res += array[i-2];
|
||||
res += array[i-1];
|
||||
res += array[i-4];
|
||||
res += array[i-5];
|
||||
res += array[i-6];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Args({3, 12})
|
||||
static int m10(int[] array, int i, boolean allaccesses) {
|
||||
int res = 0;
|
||||
res += array[i+3];
|
||||
if (allaccesses) {
|
||||
res += array[i-2];
|
||||
res += array[i-1];
|
||||
res += array[i-3];
|
||||
res += array[i+4];
|
||||
res += array[i+5];
|
||||
res += array[i+6];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Args({3, -3})
|
||||
static int m11(int[] array, int i, boolean allaccesses) {
|
||||
int res = 0;
|
||||
res += array[i+3];
|
||||
res += array[i-2];
|
||||
if (allaccesses) {
|
||||
res += array[i+5];
|
||||
res += array[i+6];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Args({3, 6})
|
||||
static int m12(int[] array, int i, boolean allaccesses) {
|
||||
int res = 0;
|
||||
res += array[i+3];
|
||||
res += array[i+6];
|
||||
if (allaccesses) {
|
||||
res += array[i-2];
|
||||
res += array[i-3];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// check that identical range check is replaced by dominating one
|
||||
// only when correct
|
||||
@Args({0})
|
||||
static int m13(int[] array, int i, boolean ignore) {
|
||||
int res = 0;
|
||||
res += array[i+3];
|
||||
res += array[i+3];
|
||||
return res;
|
||||
}
|
||||
|
||||
@Args({2, 0})
|
||||
static int m14(int[] array, int i, boolean ignore) {
|
||||
int res = 0;
|
||||
|
||||
res += array[i];
|
||||
res += array[i-2];
|
||||
res += array[i]; // If range check below were to be removed first this cannot be considered identical to first range check
|
||||
res += array[i-1]; // range check removed so i-1 array access depends on previous check
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int[] m15_dummy = new int[10];
|
||||
@Args({2, 0})
|
||||
static int m15(int[] array, int i, boolean ignore) {
|
||||
int res = 0;
|
||||
res += array[i];
|
||||
|
||||
// When the loop is optimized out we don't want the
|
||||
// array[i-1] access which is dependent on array[i]'s
|
||||
// range check to become dependent on the identical range
|
||||
// check above.
|
||||
|
||||
int[] array2 = m15_dummy;
|
||||
int j = 0;
|
||||
for (; j < 10; j++);
|
||||
if (j == 10) {
|
||||
array2 = array;
|
||||
}
|
||||
|
||||
res += array2[i-2];
|
||||
res += array2[i];
|
||||
res += array2[i-1]; // range check removed so i-1 array access depends on previous check
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Args({2, 0})
|
||||
static int m16(int[] array, int i, boolean ignore) {
|
||||
int res = 0;
|
||||
|
||||
res += array[i];
|
||||
res += array[i-1];
|
||||
res += array[i-1];
|
||||
res += array[i-2];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@Args({2, 0})
|
||||
static int m17(int[] array, int i, boolean ignore) {
|
||||
int res = 0;
|
||||
|
||||
res += array[i];
|
||||
res += array[i-2];
|
||||
res += array[i-2];
|
||||
res += array[i+2];
|
||||
res += array[i+2];
|
||||
res += array[i-1];
|
||||
res += array[i-1];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static public void main(String[] args) {
|
||||
if (WHITE_BOX.getBooleanVMFlag("BackgroundCompilation")) {
|
||||
throw new AssertionError("Background compilation enabled");
|
||||
}
|
||||
new TestRangeCheckSmearing().doTests();
|
||||
}
|
||||
boolean success = true;
|
||||
boolean exception = false;
|
||||
final int[] array = new int[10];
|
||||
final HashMap<String,Method> tests = new HashMap<>();
|
||||
{
|
||||
final Class<?> TEST_PARAM_TYPES[] = { int[].class, int.class, boolean.class };
|
||||
for (Method m : this.getClass().getDeclaredMethods()) {
|
||||
if (m.getName().matches("m[0-9]+")) {
|
||||
assert(Modifier.isStatic(m.getModifiers())) : m;
|
||||
assert(m.getReturnType() == int.class) : m;
|
||||
assert(Arrays.equals(m.getParameterTypes(), TEST_PARAM_TYPES)) : m;
|
||||
tests.put(m.getName(), m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void invokeTest(Method m, int[] array, int index, boolean z) {
|
||||
try {
|
||||
m.invoke(null, array, index, z);
|
||||
} catch (ReflectiveOperationException roe) {
|
||||
Throwable ex = roe.getCause();
|
||||
if (ex instanceof ArrayIndexOutOfBoundsException)
|
||||
throw (ArrayIndexOutOfBoundsException) ex;
|
||||
throw new AssertionError(roe);
|
||||
}
|
||||
}
|
||||
|
||||
void doTest(String name) {
|
||||
Method m = tests.get(name);
|
||||
tests.remove(name);
|
||||
int[] args = m.getAnnotation(Args.class).value();
|
||||
int index0 = args[0], index1;
|
||||
boolean exceptionRequired = true;
|
||||
if (args.length == 2) {
|
||||
index1 = args[1];
|
||||
} else {
|
||||
// no negative test for this one
|
||||
assert(args.length == 1);
|
||||
assert(name.equals("m13"));
|
||||
exceptionRequired = false;
|
||||
index1 = index0;
|
||||
}
|
||||
// Get the method compiled.
|
||||
if (!WHITE_BOX.isMethodCompiled(m)) {
|
||||
// If not, try to compile it with C2
|
||||
if(!WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) {
|
||||
// C2 compiler not available, try to compile with C1
|
||||
WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
|
||||
}
|
||||
}
|
||||
if (!WHITE_BOX.isMethodCompiled(m)) {
|
||||
throw new RuntimeException(m + " not compiled");
|
||||
}
|
||||
|
||||
// valid access
|
||||
invokeTest(m, array, index0, true);
|
||||
|
||||
if (!WHITE_BOX.isMethodCompiled(m)) {
|
||||
throw new RuntimeException(m + " deoptimized on valid array access");
|
||||
}
|
||||
|
||||
exception = false;
|
||||
boolean test_success = true;
|
||||
try {
|
||||
invokeTest(m, array, index1, false);
|
||||
} catch(ArrayIndexOutOfBoundsException aioob) {
|
||||
exception = true;
|
||||
System.out.println("ArrayIndexOutOfBoundsException thrown in "+name);
|
||||
}
|
||||
if (!exception) {
|
||||
System.out.println("ArrayIndexOutOfBoundsException was not thrown in "+name);
|
||||
}
|
||||
|
||||
if (Platform.isServer()) {
|
||||
if (exceptionRequired == WHITE_BOX.isMethodCompiled(m)) {
|
||||
System.out.println((exceptionRequired?"Didn't deoptimized":"deoptimized") + " in "+name);
|
||||
test_success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (exception != exceptionRequired) {
|
||||
System.out.println((exceptionRequired?"exception required but not thrown":"not exception required but thrown") + " in "+name);
|
||||
test_success = false;
|
||||
}
|
||||
|
||||
if (!test_success) {
|
||||
success = false;
|
||||
System.out.println("TEST FAILED: "+name);
|
||||
}
|
||||
|
||||
}
|
||||
void doTests() {
|
||||
doTest("m1");
|
||||
doTest("m2");
|
||||
doTest("m3");
|
||||
doTest("m4");
|
||||
doTest("m5");
|
||||
doTest("m6");
|
||||
doTest("m7");
|
||||
doTest("m8");
|
||||
doTest("m9");
|
||||
doTest("m10");
|
||||
doTest("m11");
|
||||
doTest("m12");
|
||||
doTest("m13");
|
||||
doTest("m14");
|
||||
doTest("m15");
|
||||
doTest("m16");
|
||||
doTest("m17");
|
||||
if (!success) {
|
||||
throw new RuntimeException("Some tests failed");
|
||||
}
|
||||
assert(tests.isEmpty()) : tests;
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8048170
|
||||
* @summary Following range check smearing, range check cannot be replaced by dominating identical test.
|
||||
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestRangeCheckSmearingLoopOpts
|
||||
*
|
||||
*/
|
||||
public class TestRangeCheckSmearingLoopOpts {
|
||||
|
||||
static int dummy;
|
||||
|
||||
static int m1(int[] array, int i) {
|
||||
for (;;) {
|
||||
for (;;) {
|
||||
if (array[i] < 0) { // range check (i+0) dominates equivalent check below
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// A control flow that stops IfNode::up_one_dom()
|
||||
if ((i % 2)== 0) {
|
||||
if ((array[i] % 2) == 0) {
|
||||
dummy = i;
|
||||
}
|
||||
}
|
||||
|
||||
// IfNode::Ideal will rewrite some range checks if Compile::allow_range_check_smearing
|
||||
if (array[i-1] == 9) { // range check (i-1) unchanged
|
||||
int res = array[i-3]; // range check (i-3) unchanged
|
||||
res += array[i]; // range check (i+0) unchanged
|
||||
res += array[i-2]; // removed redundant range check
|
||||
// the previous access might be hoisted by
|
||||
// PhaseIdealLoop::split_if_with_blocks_post because
|
||||
// it appears to have the same guard, but it also
|
||||
// depends on the previous guards
|
||||
return res;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static public void main(String[] args) {
|
||||
int[] array = { 0, 1, 2, -3, 4, 5, -2, 7, 8, 9, -1 };
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
m1(array, 0);
|
||||
}
|
||||
array[0] = -1;
|
||||
try {
|
||||
m1(array, 0);
|
||||
} catch(ArrayIndexOutOfBoundsException aioobe) {}
|
||||
}
|
||||
}
|
426
hotspot/test/compiler/uncommontrap/TestDeoptOOM.java
Normal file
426
hotspot/test/compiler/uncommontrap/TestDeoptOOM.java
Normal file
@ -0,0 +1,426 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6898462
|
||||
* @summary failed reallocations of scalar replaced objects during deoptimization causes crash
|
||||
* @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=exclude,TestDeoptOOM::main -XX:CompileCommand=exclude,TestDeoptOOM::m9_1 -Xmx128M TestDeoptOOM
|
||||
*
|
||||
*/
|
||||
|
||||
public class TestDeoptOOM {
|
||||
|
||||
long f1;
|
||||
long f2;
|
||||
long f3;
|
||||
long f4;
|
||||
long f5;
|
||||
|
||||
static class LinkedList {
|
||||
LinkedList l;
|
||||
long[] array;
|
||||
LinkedList(LinkedList l, int size) {
|
||||
array = new long[size];
|
||||
this.l = l;
|
||||
}
|
||||
}
|
||||
|
||||
static LinkedList ll;
|
||||
|
||||
static void consume_all_memory() {
|
||||
int size = 128 * 1024 * 1024;
|
||||
while(size > 0) {
|
||||
try {
|
||||
while(true) {
|
||||
ll = new LinkedList(ll, size);
|
||||
}
|
||||
} catch(OutOfMemoryError oom) {
|
||||
}
|
||||
size = size / 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void free_memory() {
|
||||
ll = null;
|
||||
}
|
||||
|
||||
static TestDeoptOOM m1(boolean deopt) {
|
||||
try {
|
||||
TestDeoptOOM tdoom = new TestDeoptOOM();
|
||||
if (deopt) {
|
||||
return tdoom;
|
||||
}
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m1");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static TestDeoptOOM m2_1(boolean deopt) {
|
||||
try {
|
||||
TestDeoptOOM tdoom = new TestDeoptOOM();
|
||||
if (deopt) {
|
||||
return tdoom;
|
||||
}
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m2_1");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static TestDeoptOOM m2(boolean deopt) {
|
||||
try {
|
||||
return m2_1(deopt);
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m2");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static TestDeoptOOM m3_3(boolean deopt) {
|
||||
try {
|
||||
TestDeoptOOM tdoom = new TestDeoptOOM();
|
||||
if (deopt) {
|
||||
return tdoom;
|
||||
}
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m3_3");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static boolean m3_2(boolean deopt) {
|
||||
try {
|
||||
return m3_3(deopt) != null;
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m3_2");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static TestDeoptOOM m3_1(boolean deopt) {
|
||||
try {
|
||||
TestDeoptOOM tdoom = new TestDeoptOOM();
|
||||
if (m3_2(deopt)) {
|
||||
return tdoom;
|
||||
}
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m3_1");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static TestDeoptOOM m3(boolean deopt) {
|
||||
try {
|
||||
return m3_1(deopt);
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m3");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static TestDeoptOOM m4(boolean deopt) {
|
||||
try {
|
||||
TestDeoptOOM tdoom = new TestDeoptOOM();
|
||||
if (deopt) {
|
||||
tdoom.f1 = 1l;
|
||||
tdoom.f2 = 2l;
|
||||
tdoom.f3 = 3l;
|
||||
return tdoom;
|
||||
}
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m4");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static TestDeoptOOM m5(boolean deopt) {
|
||||
try {
|
||||
TestDeoptOOM tdoom = new TestDeoptOOM();
|
||||
synchronized(tdoom) {
|
||||
if (deopt) {
|
||||
return tdoom;
|
||||
}
|
||||
}
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m5");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
synchronized TestDeoptOOM m6_1(boolean deopt) {
|
||||
if (deopt) {
|
||||
return this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static TestDeoptOOM m6(boolean deopt) {
|
||||
try {
|
||||
TestDeoptOOM tdoom = new TestDeoptOOM();
|
||||
return tdoom.m6_1(deopt);
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m6");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static TestDeoptOOM m7_1(boolean deopt, Object lock) {
|
||||
try {
|
||||
synchronized(lock) {
|
||||
TestDeoptOOM tdoom = new TestDeoptOOM();
|
||||
if (deopt) {
|
||||
return tdoom;
|
||||
}
|
||||
}
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m7_1");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static TestDeoptOOM m7(boolean deopt, Object lock) {
|
||||
try {
|
||||
return m7_1(deopt, lock);
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m7");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static class A {
|
||||
long f1;
|
||||
long f2;
|
||||
long f3;
|
||||
long f4;
|
||||
long f5;
|
||||
}
|
||||
|
||||
static class B {
|
||||
long f1;
|
||||
long f2;
|
||||
long f3;
|
||||
long f4;
|
||||
long f5;
|
||||
|
||||
A a;
|
||||
}
|
||||
|
||||
static B m8(boolean deopt) {
|
||||
try {
|
||||
A a = new A();
|
||||
B b = new B();
|
||||
b.a = a;
|
||||
if (deopt) {
|
||||
return b;
|
||||
}
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m8");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static void m9_1(int i) {
|
||||
if (i > 90000) {
|
||||
consume_all_memory();
|
||||
}
|
||||
}
|
||||
|
||||
static TestDeoptOOM m9() {
|
||||
try {
|
||||
for (int i = 0; i < 100000; i++) {
|
||||
TestDeoptOOM tdoom = new TestDeoptOOM();
|
||||
m9_1(i);
|
||||
if (i > 90000) {
|
||||
return tdoom;
|
||||
}
|
||||
}
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in m1");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
m1(false);
|
||||
}
|
||||
|
||||
consume_all_memory();
|
||||
|
||||
try {
|
||||
m1(true);
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in main " + oom.getMessage());
|
||||
}
|
||||
|
||||
free_memory();
|
||||
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
m2(false);
|
||||
}
|
||||
|
||||
consume_all_memory();
|
||||
|
||||
try {
|
||||
m2(true);
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in main");
|
||||
}
|
||||
|
||||
free_memory();
|
||||
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
m3(false);
|
||||
}
|
||||
|
||||
consume_all_memory();
|
||||
|
||||
try {
|
||||
m3(true);
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in main");
|
||||
}
|
||||
|
||||
free_memory();
|
||||
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
m4(false);
|
||||
}
|
||||
|
||||
consume_all_memory();
|
||||
|
||||
try {
|
||||
m4(true);
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in main");
|
||||
}
|
||||
|
||||
free_memory();
|
||||
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
m5(false);
|
||||
}
|
||||
|
||||
consume_all_memory();
|
||||
|
||||
try {
|
||||
m5(true);
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in main");
|
||||
}
|
||||
|
||||
free_memory();
|
||||
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
m6(false);
|
||||
}
|
||||
|
||||
consume_all_memory();
|
||||
|
||||
try {
|
||||
m6(true);
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in main");
|
||||
}
|
||||
|
||||
free_memory();
|
||||
|
||||
final Object lock = new Object();
|
||||
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
m7(false, lock);
|
||||
}
|
||||
|
||||
consume_all_memory();
|
||||
|
||||
try {
|
||||
m7(true, lock);
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in main");
|
||||
}
|
||||
|
||||
free_memory();
|
||||
|
||||
Thread thread = new Thread() {
|
||||
public void run() {
|
||||
System.out.println("Acquiring lock");
|
||||
synchronized(lock) {
|
||||
System.out.println("Lock acquired");
|
||||
}
|
||||
System.out.println("Lock released");
|
||||
}
|
||||
};
|
||||
thread.start();
|
||||
try {
|
||||
thread.join();
|
||||
} catch(InterruptedException ie) {
|
||||
}
|
||||
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
m8(false);
|
||||
}
|
||||
|
||||
consume_all_memory();
|
||||
|
||||
try {
|
||||
m8(true);
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in main");
|
||||
}
|
||||
|
||||
free_memory();
|
||||
|
||||
try {
|
||||
m9();
|
||||
} catch(OutOfMemoryError oom) {
|
||||
free_memory();
|
||||
System.out.println("OOM caught in main");
|
||||
}
|
||||
|
||||
free_memory();
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8067144
|
||||
* @summary -XX:+TraceDeoptimization tries to print realloc'ed objects even when there are none
|
||||
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceDeoptimization TraceDeoptimizationNoRealloc
|
||||
*
|
||||
*/
|
||||
|
||||
public class TraceDeoptimizationNoRealloc {
|
||||
|
||||
static void m(boolean some_condition) {
|
||||
if (some_condition) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static public void main(String[] args) {
|
||||
for (int i = 0; i < 20000; i++) {
|
||||
m(false);
|
||||
}
|
||||
m(true);
|
||||
}
|
||||
}
|
49
hotspot/test/gc/TestCardTablePageCommits.java
Normal file
49
hotspot/test/gc/TestCardTablePageCommits.java
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import com.oracle.java.testlibrary.JDKToolFinder;
|
||||
import com.oracle.java.testlibrary.OutputAnalyzer;
|
||||
import com.oracle.java.testlibrary.ProcessTools;
|
||||
import com.oracle.java.testlibrary.Platform;
|
||||
|
||||
/*
|
||||
* @test TestCardTablePageCommits
|
||||
* @key gc
|
||||
* @bug 8059066
|
||||
* @summary Tests that the card table does not commit the same page twice
|
||||
* @library /testlibrary
|
||||
* @run driver TestCardTablePageCommits
|
||||
*/
|
||||
public class TestCardTablePageCommits {
|
||||
public static void main(String args[]) throws Exception {
|
||||
// The test is run with a small heap to make sure all pages in the card
|
||||
// table gets committed. Need 8 MB heap to trigger the bug on SPARC
|
||||
// because of 8kB pages, assume 4 KB pages for all other CPUs.
|
||||
String Xmx = Platform.isSparc() ? "-Xmx8m" : "-Xmx4m";
|
||||
|
||||
String[] opts = {Xmx, "-XX:NativeMemoryTracking=detail", "-XX:+UseParallelGC", "-version"};
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(opts);
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
@ -153,6 +153,14 @@ public class WhiteBox {
|
||||
public native int getMethodEntryBci(Executable method);
|
||||
public native Object[] getNMethod(Executable method, boolean isOsr);
|
||||
public native long allocateCodeBlob(int size, int type);
|
||||
public long allocateCodeBlob(long size, int type) {
|
||||
int intSize = (int) size;
|
||||
if ((long) intSize != size || size < 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"size argument has illegal value " + size);
|
||||
}
|
||||
return allocateCodeBlob( intSize, type);
|
||||
}
|
||||
public native void freeCodeBlob(long addr);
|
||||
public void forceNMethodSweep() {
|
||||
try {
|
||||
|
@ -284,3 +284,4 @@ b9370464572fc663a38956047aa612d6e7854c3d jdk9-b35
|
||||
a12d347f84176200593999f4da91ae2bb86865b2 jdk9-b39
|
||||
3f46e2196498de33e7c65efa7b372e46f1faba01 jdk9-b40
|
||||
71dd8f7649428efd3a56ca5fefc80e59d37b8434 jdk9-b41
|
||||
47b0d3fa4118b9d56870cf4004987438c501f5c0 jdk9-b42
|
||||
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.xml.parsers.ptests;
|
||||
|
||||
import static jaxp.library.JAXPTestUtilities.FILE_SEP;
|
||||
import static jaxp.library.JAXPTestUtilities.USER_DIR;
|
||||
import static jaxp.library.JAXPTestUtilities.compareWithGold;
|
||||
import static jaxp.library.JAXPTestUtilities.failUnexpected;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* This tests DocumentBuilderFactory for namespace processing and no-namespace
|
||||
* processing.
|
||||
*/
|
||||
public class DBFNamespaceTest {
|
||||
|
||||
/**
|
||||
* Provide input for the cases that supporting namespace or not.
|
||||
*/
|
||||
@DataProvider(name = "input-provider")
|
||||
public Object[][] getInput() {
|
||||
DocumentBuilderFactory dbf1 = DocumentBuilderFactory.newInstance();
|
||||
String outputfile1 = USER_DIR + FILE_SEP + "dbfnstest01.out";
|
||||
String goldfile1 = TestUtils.GOLDEN_DIR + FILE_SEP + "dbfnstest01GF.out";
|
||||
|
||||
DocumentBuilderFactory dbf2 = DocumentBuilderFactory.newInstance();
|
||||
dbf2.setNamespaceAware(true);
|
||||
String outputfile2 = USER_DIR + FILE_SEP + "dbfnstest02.out";
|
||||
String goldfile2 = TestUtils.GOLDEN_DIR + FILE_SEP + "dbfnstest02GF.out";
|
||||
return new Object[][] { { dbf1, outputfile1, goldfile1 }, { dbf2, outputfile2, goldfile2 } };
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to parse and transform a document without supporting namespace and
|
||||
* with supporting namespace.
|
||||
*/
|
||||
@Test(dataProvider = "input-provider")
|
||||
public void testNamespaceTest(DocumentBuilderFactory dbf, String outputfile, String goldfile) {
|
||||
try {
|
||||
Document doc = dbf.newDocumentBuilder().parse(new File(TestUtils.XML_DIR, "namespace1.xml"));
|
||||
dummyTransform(doc, outputfile);
|
||||
assertTrue(compareWithGold(goldfile, outputfile));
|
||||
} catch (SAXException | IOException | ParserConfigurationException | TransformerFactoryConfigurationError | TransformerException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method transforms a Node without any xsl file and uses SAXResult to
|
||||
* invoke the callbacks through a ContentHandler. If namespace processing is
|
||||
* not chosen, namespaceURI in callbacks should be an empty string otherwise
|
||||
* it should be namespaceURI.
|
||||
*
|
||||
* @throws TransformerFactoryConfigurationError
|
||||
* @throws TransformerException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void dummyTransform(Document document, String fileName) throws TransformerFactoryConfigurationError, TransformerException, IOException {
|
||||
DOMSource domSource = new DOMSource(document);
|
||||
Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||
File file = new File(fileName);
|
||||
System.out.println("The fileName is " + file.getAbsolutePath());
|
||||
transformer.transform(domSource, new SAXResult(MyCHandler.newInstance(file)));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,451 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.xml.parsers.ptests;
|
||||
|
||||
import static jaxp.library.JAXPTestUtilities.FILE_SEP;
|
||||
import static jaxp.library.JAXPTestUtilities.failUnexpected;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
/**
|
||||
* This checks the methods of DocumentBuilderFactoryImpl
|
||||
*/
|
||||
public class DocumentBuilderFactory01 {
|
||||
/**
|
||||
* Testcase to test the default functionality of schema support method.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckSchemaSupport1() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setValidating(true);
|
||||
dbf.setNamespaceAware(true);
|
||||
dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
|
||||
MyErrorHandler eh = MyErrorHandler.newInstance();
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
db.setErrorHandler(eh);
|
||||
Document doc = db.parse(new File(TestUtils.XML_DIR, "test.xml"));
|
||||
assertFalse(eh.errorOccured);
|
||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the default functionality of schema support method. In
|
||||
* this case the schema source property is set.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckSchemaSupport2() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setValidating(true);
|
||||
dbf.setNamespaceAware(true);
|
||||
dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
|
||||
dbf.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaSource", new InputSource(new FileInputStream(
|
||||
new File(TestUtils.XML_DIR, "test.xsd"))));
|
||||
MyErrorHandler eh = MyErrorHandler.newInstance();
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
db.setErrorHandler(eh);
|
||||
Document doc = db.parse(new File(TestUtils.XML_DIR, "test1.xml"));
|
||||
assertFalse(eh.errorOccured);
|
||||
} catch (IllegalArgumentException | ParserConfigurationException | SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the default functionality of schema support method. In
|
||||
* this case the schema source property is set.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckSchemaSupport3() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
spf.setNamespaceAware(true);
|
||||
spf.setValidating(true);
|
||||
spf.setNamespaceAware(true);
|
||||
SAXParser sp = spf.newSAXParser();
|
||||
sp.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");
|
||||
sp.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource",
|
||||
new InputSource(new FileInputStream(new File(TestUtils.XML_DIR, "test.xsd"))));
|
||||
DefaultHandler dh = new DefaultHandler();
|
||||
sp.parse(new File(TestUtils.XML_DIR, "test1.xml"), dh);
|
||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the default functionality of newInstance method. To test
|
||||
* the isCoalescing method and setCoalescing This checks to see if the CDATA
|
||||
* and text nodes got combined In that case it will print "<xml>This
|
||||
* is not parsed</xml> yet".
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory02() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setCoalescing(true);
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
Document doc = docBuilder.parse(new File(TestUtils.XML_DIR, "DocumentBuilderFactory01.xml"));
|
||||
Element e = (Element) doc.getElementsByTagName("html").item(0);
|
||||
NodeList nl = e.getChildNodes();
|
||||
assertEquals(nl.item(0).getNodeValue().trim(), "<xml>This is not parsed</xml> yet");
|
||||
} catch (IOException | SAXException | ParserConfigurationException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the isIgnoringComments. By default it is false.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory03() {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
assertFalse(dbf.isIgnoringComments());
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the isValidating. By default it is false, set it to true
|
||||
* and then use a document which is not valid. It should throw a warning or
|
||||
* an error at least. The test passes in case retval 0 is set in the error
|
||||
* method .
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory04() {
|
||||
try {
|
||||
MyErrorHandler eh = MyErrorHandler.newInstance();
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setValidating(true);
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
db.setErrorHandler(eh);
|
||||
Document doc = db.parse(new File(TestUtils.XML_DIR, "DocumentBuilderFactory05.xml"));
|
||||
assertTrue(eh.errorOccured);
|
||||
} catch (ParserConfigurationException | IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the setValidating. By default it is false, use a
|
||||
* document which is not valid. It should not throw a warning or an error.
|
||||
* The test passes in case the retval equals 1 .
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory16() {
|
||||
try {
|
||||
MyErrorHandler eh = MyErrorHandler.newInstance();
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
db.setErrorHandler(eh);
|
||||
Document doc = db.parse(new File(TestUtils.XML_DIR, "DocumentBuilderFactory05.xml"));
|
||||
assertFalse(eh.errorOccured);
|
||||
} catch (ParserConfigurationException | IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the setValidating. By default it is false, use a
|
||||
* document which is valid. It should not throw a warning or an error. The
|
||||
* test passes in case the retval equals 1.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory17() {
|
||||
try {
|
||||
MyErrorHandler eh = MyErrorHandler.newInstance();
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
db.setErrorHandler(eh);
|
||||
Document doc = db.parse(new File(TestUtils.XML_DIR, "DocumentBuilderFactory04.xml"));
|
||||
assertFalse(eh.errorOccured);
|
||||
} catch (ParserConfigurationException | IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* To test the isExpandEntityReferences. By default it is true.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory05() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
Document doc = docBuilder.parse(new FileInputStream(new File(TestUtils.XML_DIR, "DocumentBuilderFactory02.xml")));
|
||||
Element e = (Element) doc.getElementsByTagName("title").item(0);
|
||||
NodeList nl = e.getChildNodes();
|
||||
assertTrue(dbf.isExpandEntityReferences());
|
||||
assertEquals(nl.item(0).getNodeValue().trim().charAt(0), 'W');
|
||||
} catch (ParserConfigurationException | IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the default functionality of setValidating method. The
|
||||
* xml file has a DTD which has namespaces defined. The parser takes care to
|
||||
* check if the namespaces using elements and defined attributes are there
|
||||
* or not.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory06() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setValidating(true);
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
MyErrorHandler eh = MyErrorHandler.newInstance();
|
||||
db.setErrorHandler(eh);
|
||||
Document doc = db.parse(new File(TestUtils.XML_DIR, "DocumentBuilderFactory04.xml"));
|
||||
assertTrue(doc instanceof Document);
|
||||
assertFalse(eh.errorOccured);
|
||||
} catch (ParserConfigurationException | IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the setExpandEntityReferences.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory07() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setExpandEntityReferences(true);
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
Document doc = docBuilder.parse(new FileInputStream(new File(TestUtils.XML_DIR, "DocumentBuilderFactory02.xml")));
|
||||
Element e = (Element) doc.getElementsByTagName("title").item(0);
|
||||
NodeList nl = e.getChildNodes();
|
||||
assertTrue(dbf.isExpandEntityReferences());
|
||||
assertEquals(nl.item(0).getNodeValue().trim().charAt(0), 'W');
|
||||
} catch (ParserConfigurationException | IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the setExpandEntityReferences.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory08() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setExpandEntityReferences(false);
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
Document doc = docBuilder.parse(new FileInputStream(new File(TestUtils.XML_DIR, "DocumentBuilderFactory02.xml")));
|
||||
Element e = (Element) doc.getElementsByTagName("title").item(0);
|
||||
NodeList nl = e.getChildNodes();
|
||||
assertNull(nl.item(0).getNodeValue());
|
||||
} catch (ParserConfigurationException | IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the setIgnoringComments. By default it is set to false.
|
||||
* explicitly setting it to false, it recognizes the comment which is in
|
||||
* Element Node Hence the Element's child node is not null.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory09() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setIgnoringComments(false);
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
Document doc = docBuilder.parse(new FileInputStream(new File(TestUtils.XML_DIR, "DocumentBuilderFactory07.xml")));
|
||||
Element e = (Element) doc.getElementsByTagName("body").item(0);
|
||||
NodeList nl = e.getChildNodes();
|
||||
assertNotNull(nl.item(0).getNodeValue());
|
||||
} catch (ParserConfigurationException | IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests for the parse(InputSource).
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory10() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
Document doc = docBuilder.parse(new InputSource(new BufferedReader(new FileReader(new File(TestUtils.XML_DIR, "DocumentBuilderFactory07.xml")))));
|
||||
assertTrue(doc instanceof Document);
|
||||
} catch (IllegalArgumentException | ParserConfigurationException | IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests for the parse InputStream with SystemID as a second parameter.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory11() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
Document doc = docBuilder.parse(new FileInputStream(new File(TestUtils.XML_DIR, "dbf10import.xsl")), new File(TestUtils.XML_DIR).toURI()
|
||||
.toASCIIString());
|
||||
assertTrue(doc instanceof Document);
|
||||
} catch (IllegalArgumentException | ParserConfigurationException | IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests for the parse InputStream with empty SystemID as a second
|
||||
* parameter.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory12() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
Document doc = docBuilder.parse(new FileInputStream(new File(TestUtils.XML_DIR, "dbf10import.xsl")), " ");
|
||||
assertTrue(doc instanceof Document);
|
||||
} catch (IllegalArgumentException | ParserConfigurationException | IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests for the parse(uri).
|
||||
*/
|
||||
@Test
|
||||
public void testCheckDocumentBuilderFactory13() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
Document doc = docBuilder.parse(new File(TestUtils.XML_DIR + FILE_SEP + "dbf10import.xsl").toURI().toASCIIString());
|
||||
assertTrue(doc instanceof Document);
|
||||
} catch (IllegalArgumentException | ParserConfigurationException | IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests for the parse (uri) with empty string as parameter should
|
||||
* throw Sax Exception.
|
||||
*
|
||||
* @throws SAXException
|
||||
* If any parse errors occur.
|
||||
*/
|
||||
@Test(expectedExceptions = SAXException.class)
|
||||
public void testCheckDocumentBuilderFactory14() throws SAXException {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
docBuilder.parse("");
|
||||
} catch (ParserConfigurationException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests for the parse (uri) with null uri as parameter should throw
|
||||
* IllegalArgumentException.
|
||||
*
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testCheckDocumentBuilderFactory15() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
String uri = null;
|
||||
docBuilder.parse(uri);
|
||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the setIgnoringComments. By default it is set to false,
|
||||
* setting this to true, It does not recognize the comment, Here the
|
||||
* nodelist has a length 0 because the ignoring comments is true.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckIgnoringComments() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setIgnoringComments(true);
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
Document doc = docBuilder.parse(new FileInputStream(new File(TestUtils.XML_DIR, "DocumentBuilderFactory08.xml")));
|
||||
Element e = (Element) doc.getElementsByTagName("body").item(0);
|
||||
NodeList nl = e.getChildNodes();
|
||||
assertEquals(nl.getLength(), 0);
|
||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the default behaviour of setIgnoringComments. By default
|
||||
* it is set to false, this is similar to case 9 but not setIgnoringComments
|
||||
* explicitly, it does not recognize the comment.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckIgnoringComments1() {
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
Document doc = docBuilder.parse(new FileInputStream(new File(TestUtils.XML_DIR, "DocumentBuilderFactory07.xml")));
|
||||
Element e = (Element) doc.getElementsByTagName("body").item(0);
|
||||
NodeList nl = e.getChildNodes();
|
||||
assertFalse(dbf.isIgnoringComments());
|
||||
assertNotNull(nl.item(0).getNodeValue());
|
||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.xml.parsers.ptests;
|
||||
|
||||
import static jaxp.library.JAXPTestUtilities.FILE_SEP;
|
||||
import static jaxp.library.JAXPTestUtilities.USER_DIR;
|
||||
import static jaxp.library.JAXPTestUtilities.compareWithGold;
|
||||
import static jaxp.library.JAXPTestUtilities.failUnexpected;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* This tests the setIgnoringElementWhitespace and setIgnoringComments of
|
||||
* DocumentBuilderFactory
|
||||
*/
|
||||
public class DocumentBuilderFactory02 {
|
||||
|
||||
/**
|
||||
* This testcase tests for the isIgnoringElementContentWhitespace and the
|
||||
* setIgnoringElementContentWhitespace. The xml file has all kinds of
|
||||
* whitespace,tab and newline characters, it uses the MyNSContentHandler
|
||||
* which does not invoke the characters callback when this
|
||||
* setIgnoringElementContentWhitespace is set to true.
|
||||
*/
|
||||
@Test
|
||||
public void testCheckElementContentWhitespace() {
|
||||
try {
|
||||
String goldFile = TestUtils.GOLDEN_DIR + FILE_SEP + "dbfactory02GF.out";
|
||||
String outputFile = USER_DIR + FILE_SEP + "dbfactory02.out";
|
||||
MyErrorHandler eh = MyErrorHandler.newInstance();
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
dbf.setValidating(true);
|
||||
assertFalse(dbf.isIgnoringElementContentWhitespace());
|
||||
dbf.setIgnoringElementContentWhitespace(true);
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
db.setErrorHandler(eh);
|
||||
Document doc = db.parse(new File(TestUtils.XML_DIR, "DocumentBuilderFactory06.xml"));
|
||||
assertFalse(eh.errorOccured);
|
||||
DOMSource domSource = new DOMSource(doc);
|
||||
TransformerFactory tfactory = TransformerFactory.newInstance();
|
||||
Transformer transformer = tfactory.newTransformer();
|
||||
SAXResult saxResult = new SAXResult();
|
||||
saxResult.setHandler(MyCHandler.newInstance(new File(outputFile)));
|
||||
transformer.transform(domSource, saxResult);
|
||||
assertTrue(compareWithGold(goldFile, outputFile));
|
||||
} catch (ParserConfigurationException | SAXException | IOException | TransformerException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.xml.parsers.ptests;
|
||||
|
||||
import static jaxp.library.JAXPTestUtilities.FILE_SEP;
|
||||
import static jaxp.library.JAXPTestUtilities.failUnexpected;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* This checks for the methods of DocumentBuilder
|
||||
*/
|
||||
public class DocumentBuilderImpl01 implements EntityResolver {
|
||||
|
||||
/**
|
||||
* Provide DocumentBuilder.
|
||||
*
|
||||
* @throws ParserConfigurationException
|
||||
*/
|
||||
@DataProvider(name = "builder-provider")
|
||||
public Object[][] getBuilder() throws ParserConfigurationException {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder docBuilder = dbf.newDocumentBuilder();
|
||||
return new Object[][] { { docBuilder } };
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the default functionality of isValidation method. Expect
|
||||
* to return false because not setting the validation.
|
||||
*/
|
||||
@Test(dataProvider = "builder-provider")
|
||||
public void testCheckDocumentBuilderImpl01(DocumentBuilder docBuilder) {
|
||||
assertFalse(docBuilder.isValidating());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the default functionality of isNamespaceAware method.
|
||||
*/
|
||||
@Test(dataProvider = "builder-provider")
|
||||
public void testCheckDocumentBuilderImpl02(DocumentBuilder docBuilder) {
|
||||
assertFalse(docBuilder.isNamespaceAware());
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the parse(InputStream).
|
||||
*/
|
||||
@Test(dataProvider = "builder-provider")
|
||||
public void testCheckDocumentBuilderImpl04(DocumentBuilder docBuilder) {
|
||||
try {
|
||||
Document doc = docBuilder.parse(new FileInputStream(new File(TestUtils.XML_DIR, "DocumentBuilderImpl01.xml")));
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the parse(File).
|
||||
*/
|
||||
@Test(dataProvider = "builder-provider")
|
||||
public void testCheckDocumentBuilderImpl05(DocumentBuilder docBuilder) {
|
||||
try {
|
||||
Document doc = docBuilder.parse(new File(TestUtils.XML_DIR, "DocumentBuilderImpl01.xml"));
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the parse(InputStream,systemId).
|
||||
*/
|
||||
@Test(dataProvider = "builder-provider")
|
||||
public void testCheckDocumentBuilderImpl06(DocumentBuilder docBuilder) {
|
||||
try {
|
||||
Document doc = docBuilder.parse(new FileInputStream(new File(TestUtils.XML_DIR, "DocumentBuilderImpl02.xml")), new File(TestUtils.XML_DIR).toURI()
|
||||
.toASCIIString() + FILE_SEP);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the setEntityResolver.
|
||||
*/
|
||||
@Test(dataProvider = "builder-provider")
|
||||
public void testCheckDocumentBuilderImpl07(DocumentBuilder docBuilder) {
|
||||
docBuilder.setEntityResolver(this);
|
||||
resolveEntity("publicId", "http://www.myhost.com/today");
|
||||
}
|
||||
|
||||
public InputSource resolveEntity(String publicId, String systemId) {
|
||||
if (systemId.equals("http://www.myhost.com/today"))
|
||||
return new InputSource(systemId);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.xml.parsers.ptests;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.FactoryConfigurationError;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import org.testng.annotations.AfterTest;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* Class containing the test cases for SAXParserFactory/DocumentBuilderFactory
|
||||
* newInstance methods.
|
||||
*/
|
||||
public class FactoryConfErrorTest {
|
||||
|
||||
/**
|
||||
* Set properties DocumentBuilderFactory and SAXParserFactory to invalid
|
||||
* value before any test run.
|
||||
*/
|
||||
@BeforeTest
|
||||
public void setup() {
|
||||
System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "xx");
|
||||
System.setProperty("javax.xml.parsers.SAXParserFactory", "xx");
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore properties DocumentBuilderFactory and SAXParserFactory to default
|
||||
* value after all tests run.
|
||||
*/
|
||||
@AfterTest
|
||||
public void cleanup() {
|
||||
System.clearProperty("javax.xml.parsers.DocumentBuilderFactory");
|
||||
System.clearProperty("javax.xml.parsers.SAXParserFactory");
|
||||
}
|
||||
|
||||
/**
|
||||
* To test exception thrown if javax.xml.parsers.SAXParserFactory property
|
||||
* is invalid.
|
||||
*/
|
||||
@Test(expectedExceptions = FactoryConfigurationError.class)
|
||||
public void testNewInstance01() {
|
||||
SAXParserFactory.newInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* To test exeception thrown if javax.xml.parsers.DocumentBuilderFactory is
|
||||
* invalid.
|
||||
*/
|
||||
@Test(expectedExceptions = FactoryConfigurationError.class)
|
||||
public void testNewInstance02() {
|
||||
DocumentBuilderFactory.newInstance();
|
||||
}
|
||||
}
|
@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.xml.parsers.ptests;
|
||||
|
||||
import static jaxp.library.JAXPTestUtilities.failUnexpected;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXNotRecognizedException;
|
||||
import org.xml.sax.SAXNotSupportedException;
|
||||
|
||||
/**
|
||||
* Class containing the test cases for SAXParserFactory API
|
||||
*/
|
||||
public class SAXParserFactTest {
|
||||
|
||||
private static final String NAMESPACES = "http://xml.org/sax/features/namespaces";
|
||||
private static final String NAMESPACE_PREFIXES = "http://xml.org/sax/features/namespace-prefixes";
|
||||
private static final String STRING_INTERNING = "http://xml.org/sax/features/string-interning";
|
||||
private static final String VALIDATION = "http://xml.org/sax/features/validation";
|
||||
private static final String EXTERNAL_G_ENTITIES = "http://xml.org/sax/features/external-general-entities";
|
||||
private static final String EXTERNAL_P_ENTITIES = "http://xml.org/sax/features/external-parameter-entities";
|
||||
|
||||
/**
|
||||
* Testcase to test if newSAXParser() method returns SAXParser.
|
||||
*/
|
||||
@Test
|
||||
public void testParser01() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
SAXParser saxparser = spf.newSAXParser();
|
||||
} catch (ParserConfigurationException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the default functionality (No validation) of the parser.
|
||||
*/
|
||||
@Test
|
||||
public void testValidate01() {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
assertFalse(spf.isValidating());
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the functionality of setValidating and isvalidating
|
||||
* methods.
|
||||
*/
|
||||
@Test
|
||||
public void testValidate02() {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
spf.setValidating(true);
|
||||
assertTrue(spf.isValidating());
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser should not be namespaceaware by default.
|
||||
*/
|
||||
@Test
|
||||
public void testNamespace01() {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
assertFalse(spf.isNamespaceAware());
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the functionality of setNamespaceAware and
|
||||
* isNamespaceAware methods.
|
||||
*/
|
||||
@Test
|
||||
public void testNamespace02() {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
spf.setNamespaceAware(true);
|
||||
assertTrue(spf.isNamespaceAware());
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the functionality of setNamespaceAware and getFeature()
|
||||
* methods for namespaces property.
|
||||
*/
|
||||
@Test
|
||||
public void testFeature01() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
assertFalse(spf.getFeature(NAMESPACES));
|
||||
|
||||
spf.setNamespaceAware(true);
|
||||
assertTrue(spf.getFeature(NAMESPACES));
|
||||
} catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the functionality of setFeature and getFeature methods
|
||||
* for namespaces property.
|
||||
*/
|
||||
@Test
|
||||
public void testFeature02() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
|
||||
spf.setFeature(NAMESPACES, true);
|
||||
assertTrue(spf.getFeature(NAMESPACES));
|
||||
|
||||
spf.setFeature(NAMESPACES, false);
|
||||
assertFalse(spf.getFeature(NAMESPACES));
|
||||
} catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the functionality of setFeature and getFeature methods
|
||||
* for namespace-prefixes property.
|
||||
*/
|
||||
@Test
|
||||
public void testFeature03() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
|
||||
spf.setFeature(NAMESPACE_PREFIXES, true);
|
||||
assertTrue(spf.getFeature(NAMESPACE_PREFIXES));
|
||||
|
||||
spf.setFeature(NAMESPACE_PREFIXES, false);
|
||||
assertFalse(spf.getFeature(NAMESPACE_PREFIXES));
|
||||
} catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the functionality of getFeature method for
|
||||
* string-interning property.
|
||||
*/
|
||||
@Test
|
||||
public void testFeature04() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
assertTrue(spf.getFeature(STRING_INTERNING));
|
||||
} catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the functionality of getFeature and setValidating
|
||||
* methods for validation property.
|
||||
*/
|
||||
@Test
|
||||
public void testFeature05() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
assertFalse(spf.getFeature(VALIDATION));
|
||||
spf.setValidating(true);
|
||||
assertTrue(spf.getFeature(VALIDATION));
|
||||
} catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the functionality of setFeature and getFeature methods
|
||||
* for validation property.
|
||||
*/
|
||||
@Test
|
||||
public void testFeature06() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
|
||||
spf.setFeature(VALIDATION, true);
|
||||
assertTrue(spf.getFeature(VALIDATION));
|
||||
|
||||
spf.setFeature(VALIDATION, false);
|
||||
assertFalse(spf.getFeature(VALIDATION));
|
||||
} catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the functionality of getFeature method for
|
||||
* external-general-entities property.
|
||||
*/
|
||||
@Test
|
||||
public void testFeature07() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
assertTrue(spf.getFeature(EXTERNAL_G_ENTITIES));
|
||||
} catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the functionality of setFeature and getFeature methods
|
||||
* for external-general-entities property.
|
||||
*/
|
||||
@Test
|
||||
public void testFeature08() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
spf.setFeature(EXTERNAL_G_ENTITIES, false);
|
||||
assertFalse(spf.getFeature(EXTERNAL_G_ENTITIES));
|
||||
} catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the functionality of getFeature method for
|
||||
* external-parameter-entities property.
|
||||
*/
|
||||
@Test
|
||||
public void testFeature09() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
assertTrue(spf.getFeature(EXTERNAL_P_ENTITIES));
|
||||
} catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the functionality of setFeature method for
|
||||
* external-parameter-entitie property.
|
||||
*/
|
||||
@Test
|
||||
public void testFeature10() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
spf.setFeature(EXTERNAL_P_ENTITIES, false);
|
||||
} catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,559 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.xml.parsers.ptests;
|
||||
|
||||
import static jaxp.library.JAXPTestUtilities.failUnexpected;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
import org.xml.sax.HandlerBase;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
/**
|
||||
* Class contains the test cases for SAXParser API
|
||||
*/
|
||||
public class SAXParserTest {
|
||||
|
||||
/**
|
||||
* Provide SAXParser.
|
||||
*
|
||||
* @throws SAXException
|
||||
* @throws ParserConfigurationException
|
||||
*/
|
||||
@DataProvider(name = "parser-provider")
|
||||
public Object[][] getParser() throws ParserConfigurationException, SAXException {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
SAXParser saxparser = spf.newSAXParser();
|
||||
return new Object[][] { { saxparser } };
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case with FileInputStream null, parsing should fail and throw
|
||||
* IllegalArgumentException.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "parser-provider")
|
||||
public void testParse01(SAXParser saxparser) throws IllegalArgumentException {
|
||||
try {
|
||||
FileInputStream instream = null;
|
||||
HandlerBase handler = new HandlerBase();
|
||||
saxparser.parse(instream, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with an error in xml file, parsing should fail and throw
|
||||
* SAXException.
|
||||
*
|
||||
* @throws SAXException
|
||||
*/
|
||||
@Test(expectedExceptions = SAXException.class, dataProvider = "parser-provider")
|
||||
public void testParse02(SAXParser saxparser) throws SAXException {
|
||||
try {
|
||||
HandlerBase handler = new HandlerBase();
|
||||
FileInputStream instream = new FileInputStream(new File(TestUtils.XML_DIR, "invalid.xml"));
|
||||
saxparser.parse(instream, handler);
|
||||
} catch (IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with a valid in xml file, parser should parse the xml document.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testParse03(SAXParser saxparser) {
|
||||
try {
|
||||
HandlerBase handler = new HandlerBase();
|
||||
saxparser.parse(new File(TestUtils.XML_DIR, "parsertest.xml"), handler);
|
||||
} catch (IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with valid input stream, parser should parse the xml document
|
||||
* successfully.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testParse04(SAXParser saxparser) {
|
||||
try {
|
||||
HandlerBase handler = new HandlerBase();
|
||||
FileInputStream instream = new FileInputStream(new File(TestUtils.XML_DIR, "correct.xml"));
|
||||
saxparser.parse(instream, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with valid input source, parser should parse the xml document
|
||||
* successfully.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testParse05(SAXParser saxparser) {
|
||||
try {
|
||||
HandlerBase handler = new HandlerBase();
|
||||
FileInputStream instream = new FileInputStream(new File(TestUtils.XML_DIR, "parsertest.xml"));
|
||||
saxparser.parse(instream, handler, new File(TestUtils.XML_DIR).toURI().toASCIIString());
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with uri null, parsing should fail and throw
|
||||
* IllegalArgumentException.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "parser-provider")
|
||||
public void testParse07(SAXParser saxparser) throws IllegalArgumentException {
|
||||
try {
|
||||
String uri = null;
|
||||
HandlerBase handler = new HandlerBase();
|
||||
saxparser.parse(uri, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with non-existant uri, parsing should fail and throw
|
||||
* IOException.
|
||||
*
|
||||
* @throws SAXException
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test(expectedExceptions = { SAXException.class, IOException.class }, dataProvider = "parser-provider")
|
||||
public void testParse08(SAXParser saxparser) throws SAXException, IOException {
|
||||
String uri = " ";
|
||||
|
||||
HandlerBase handler = new HandlerBase();
|
||||
saxparser.parse(uri, handler);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with proper uri, parser should parse successfully.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testParse09(SAXParser saxparser) {
|
||||
try {
|
||||
File file = new File(TestUtils.XML_DIR, "correct.xml");
|
||||
HandlerBase handler = new HandlerBase();
|
||||
saxparser.parse(file.toURI().toASCIIString(), handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with File null, parsing should fail and throw
|
||||
* IllegalArgumentException.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "parser-provider")
|
||||
public void testParse10(SAXParser saxparser) throws IllegalArgumentException {
|
||||
try {
|
||||
File file = null;
|
||||
HandlerBase handler = new HandlerBase();
|
||||
saxparser.parse(file, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with empty string as File, parsing should fail and throw
|
||||
* SAXException.
|
||||
*
|
||||
* @throws SAXException
|
||||
*/
|
||||
@Test(expectedExceptions = SAXException.class, dataProvider = "parser-provider")
|
||||
public void testParse11(SAXParser saxparser) throws SAXException {
|
||||
try {
|
||||
HandlerBase handler = new HandlerBase();
|
||||
File file = new File("");
|
||||
saxparser.parse(file, handler);
|
||||
} catch (IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with xml file that has errors parsing should fail and throw
|
||||
* SAXException.
|
||||
*
|
||||
* @throws SAXException
|
||||
*/
|
||||
@Test(expectedExceptions = SAXException.class, dataProvider = "parser-provider")
|
||||
public void testParse12(SAXParser saxparser) throws SAXException {
|
||||
try {
|
||||
HandlerBase handler = new HandlerBase();
|
||||
File file = new File(TestUtils.XML_DIR, "valid.xml");
|
||||
saxparser.parse(file, handler);
|
||||
} catch (IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with xml file that has no errors Parser should successfully
|
||||
* parse the xml document.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testParse13(SAXParser saxparser) {
|
||||
try {
|
||||
HandlerBase handler = new HandlerBase();
|
||||
File file = new File(TestUtils.XML_DIR, "correct.xml");
|
||||
saxparser.parse(file, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with input source null, parsing should fail and throw
|
||||
* IllegalArgumentException.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "parser-provider")
|
||||
public void testParse14(SAXParser saxparser) throws IllegalArgumentException {
|
||||
try {
|
||||
InputSource is = null;
|
||||
HandlerBase handler = new HandlerBase();
|
||||
saxparser.parse(is, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with input source attached an invaild xml, parsing should fail
|
||||
* and throw SAXException.
|
||||
*
|
||||
* @throws SAXException
|
||||
*/
|
||||
@Test(expectedExceptions = SAXException.class, dataProvider = "parser-provider")
|
||||
public void testParse15(SAXParser saxparser) throws SAXException {
|
||||
try {
|
||||
HandlerBase handler = new HandlerBase();
|
||||
FileInputStream instream = new FileInputStream(new File(TestUtils.XML_DIR, "invalid.xml"));
|
||||
InputSource is = new InputSource(instream);
|
||||
saxparser.parse(is, handler);
|
||||
} catch (IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with input source attached an vaild xml, parser should
|
||||
* successfully parse the xml document.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testParse16(SAXParser saxparser) {
|
||||
try {
|
||||
HandlerBase handler = new HandlerBase();
|
||||
FileInputStream instream = new FileInputStream(new File(TestUtils.XML_DIR, "correct.xml"));
|
||||
InputSource is = new InputSource(instream);
|
||||
saxparser.parse(is, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with FileInputStream null, parsing should fail and throw
|
||||
* IllegalArgumentException.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "parser-provider")
|
||||
public void testParse17(SAXParser saxparser) throws IllegalArgumentException {
|
||||
try {
|
||||
FileInputStream instream = null;
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
saxparser.parse(instream, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with an error in xml file, parsing should fail and throw
|
||||
* SAXException.
|
||||
*
|
||||
* @throws SAXException
|
||||
*/
|
||||
@Test(expectedExceptions = SAXException.class, dataProvider = "parser-provider")
|
||||
public void testParse18(SAXParser saxparser) throws SAXException {
|
||||
try {
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
FileInputStream instream = new FileInputStream(new File(TestUtils.XML_DIR, "invalid.xml"));
|
||||
saxparser.parse(instream, handler);
|
||||
} catch (IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with valid input stream, parser should parse the xml document
|
||||
* successfully.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testParse19(SAXParser saxparser) {
|
||||
try {
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
saxparser.parse(new File(TestUtils.XML_DIR, "parsertest.xml"), handler);
|
||||
} catch (IOException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with valid input stream, parser should parse the xml document
|
||||
* successfully.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testParse20(SAXParser saxparser) {
|
||||
try {
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
FileInputStream instream = new FileInputStream(new File(TestUtils.XML_DIR, "correct.xml"));
|
||||
saxparser.parse(instream, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with valid input source, parser should parse the xml document
|
||||
* successfully.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testParse21(SAXParser saxparser) {
|
||||
try {
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
FileInputStream instream = new FileInputStream(new File(TestUtils.XML_DIR, "parsertest.xml"));
|
||||
saxparser.parse(instream, handler, new File(TestUtils.XML_DIR).toURI().toASCIIString());
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with uri null, parsing should fail and throw
|
||||
* IllegalArgumentException.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "parser-provider")
|
||||
public void testParse23(SAXParser saxparser) throws IllegalArgumentException {
|
||||
try {
|
||||
String uri = null;
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
saxparser.parse(uri, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with non-existant uri, parsing should fail and throw
|
||||
* SAXException or IOException.
|
||||
*
|
||||
* @throws SAXException
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test(expectedExceptions = { SAXException.class, IOException.class }, dataProvider = "parser-provider")
|
||||
public void testParse24(SAXParser saxparser) throws SAXException, IOException {
|
||||
String uri = " ";
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
saxparser.parse(uri, handler);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with proper uri, parser should parse successfully.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testParse25(SAXParser saxparser) {
|
||||
try {
|
||||
File file = new File(TestUtils.XML_DIR, "correct.xml");
|
||||
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
saxparser.parse(file.toURI().toASCIIString(), handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with File null, parsing should fail and throw
|
||||
* IllegalArgumentException.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "parser-provider")
|
||||
public void testParse26(SAXParser saxparser) throws IllegalArgumentException {
|
||||
try {
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
saxparser.parse((File) null, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with empty string as File, parsing should fail and throw
|
||||
* SAXException.
|
||||
*
|
||||
* @throws SAXException
|
||||
*/
|
||||
@Test(expectedExceptions = SAXException.class, dataProvider = "parser-provider")
|
||||
public void testParse27(SAXParser saxparser) throws SAXException {
|
||||
try {
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
File file = new File("");
|
||||
saxparser.parse(file, handler);
|
||||
} catch (IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with xml file that has errors, parsing should fail and throw
|
||||
* SAXException.
|
||||
*
|
||||
* @throws SAXException
|
||||
*/
|
||||
@Test(expectedExceptions = SAXException.class, dataProvider = "parser-provider")
|
||||
public void testParse28(SAXParser saxparser) throws SAXException {
|
||||
try {
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
File file = new File(TestUtils.XML_DIR, "valid.xml");
|
||||
saxparser.parse(file, handler);
|
||||
} catch (IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with xml file that has no errors, parser should successfully
|
||||
* parse the xml document.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testParse29(SAXParser saxparser) {
|
||||
try {
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
File file = new File(TestUtils.XML_DIR, "correct.xml");
|
||||
saxparser.parse(file, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with input source null, parsing should fail and throw
|
||||
* IllegalArgumentException.
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "parser-provider")
|
||||
public void testParse30(SAXParser saxparser) throws IllegalArgumentException {
|
||||
try {
|
||||
InputSource is = null;
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
saxparser.parse(is, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase with an invalid xml file, parser should throw SAXException.
|
||||
*
|
||||
* @throws SAXException
|
||||
*/
|
||||
@Test(expectedExceptions = SAXException.class, dataProvider = "parser-provider")
|
||||
public void testParse31(SAXParser saxparser) throws SAXException {
|
||||
try {
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
FileInputStream instream = new FileInputStream(new File(TestUtils.XML_DIR, "invalid.xml"));
|
||||
InputSource is = new InputSource(instream);
|
||||
saxparser.parse(is, handler);
|
||||
} catch (IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case to parse an xml file that not use namespaces.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testParse32(SAXParser saxparser) {
|
||||
try {
|
||||
DefaultHandler handler = new DefaultHandler();
|
||||
FileInputStream instream = new FileInputStream(new File(TestUtils.XML_DIR, "correct.xml"));
|
||||
InputSource is = new InputSource(instream);
|
||||
saxparser.parse(is, handler);
|
||||
} catch (SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case to parse an xml file that uses namespaces.
|
||||
*/
|
||||
@Test
|
||||
public void testParse33() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
spf.setNamespaceAware(true);
|
||||
SAXParser saxparser = spf.newSAXParser();
|
||||
HandlerBase handler = new HandlerBase();
|
||||
FileInputStream instream = new FileInputStream(new File(TestUtils.XML_DIR, "ns4.xml"));
|
||||
saxparser.parse(instream, handler);
|
||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.xml.parsers.ptests;
|
||||
|
||||
import static jaxp.library.JAXPTestUtilities.failUnexpected;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import javax.xml.parsers.FactoryConfigurationError;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
import org.xml.sax.Parser;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXNotRecognizedException;
|
||||
import org.xml.sax.SAXNotSupportedException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.DeclHandler;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* Class contains the test cases for SAXParser API
|
||||
*/
|
||||
public class SAXParserTest02 {
|
||||
final String DOM_NODE = "http://xml.org/sax/properties/dom-node";
|
||||
final String XML_STRING = "http://xml.org/sax/properties/xml-string";
|
||||
final String DECL_HANDLER = "http://xml.org/sax/properties/declaration-handler";
|
||||
final String LEXICAL_HANDLER = "http://xml.org/sax/properties/lexical-handler";
|
||||
|
||||
/**
|
||||
* Provide SAXParser.
|
||||
*
|
||||
* @throws SAXException
|
||||
* @throws ParserConfigurationException
|
||||
*/
|
||||
@DataProvider(name = "parser-provider")
|
||||
public Object[][] getParser() throws ParserConfigurationException, SAXException {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
SAXParser saxparser = spf.newSAXParser();
|
||||
return new Object[][] { { saxparser } };
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the default functionality (No validation) of the parser.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testValidate01(SAXParser saxparser) {
|
||||
try {
|
||||
assertFalse(saxparser.isValidating());
|
||||
} catch (FactoryConfigurationError e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase to test the functionality of setValidating and isvalidating
|
||||
* methods.
|
||||
*/
|
||||
@Test
|
||||
public void testValidate02() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
spf.setValidating(true);
|
||||
spf.newSAXParser();
|
||||
assertTrue(spf.isValidating());
|
||||
} catch (FactoryConfigurationError | ParserConfigurationException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case to test isNamespaceAware() method. By default, namespaces are
|
||||
* not supported.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testNamespace01(SAXParser saxparser) {
|
||||
try {
|
||||
assertFalse(saxparser.isNamespaceAware());
|
||||
} catch (FactoryConfigurationError e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case to test setnamespaceAware() method.
|
||||
*/
|
||||
@Test
|
||||
public void testNamespace02() {
|
||||
try {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
spf.setNamespaceAware(true);
|
||||
SAXParser saxparser = spf.newSAXParser();
|
||||
assertTrue(saxparser.isNamespaceAware());
|
||||
} catch (FactoryConfigurationError | ParserConfigurationException | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case to test if the getParser() method returns instance of Parser.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testParser01(SAXParser saxparser) {
|
||||
try {
|
||||
Parser parser = saxparser.getParser();
|
||||
} catch (FactoryConfigurationError | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case to test if the getXMLReader() method returns instance of
|
||||
* XMLReader.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testXmlReader01(SAXParser saxparser) {
|
||||
try {
|
||||
XMLReader xmlReader = saxparser.getXMLReader();
|
||||
} catch (FactoryConfigurationError | SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the xml-string property is not supported.
|
||||
*
|
||||
* @throws SAXNotSupportedException
|
||||
*/
|
||||
@Test(expectedExceptions = SAXNotSupportedException.class, dataProvider = "parser-provider")
|
||||
public void testProperty01(SAXParser saxparser) throws SAXNotSupportedException {
|
||||
try {
|
||||
Object object = saxparser.getProperty(XML_STRING);
|
||||
} catch (SAXNotRecognizedException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the dom-node property is not supported.
|
||||
*
|
||||
* @throws SAXNotSupportedException
|
||||
*/
|
||||
@Test(expectedExceptions = SAXNotSupportedException.class, dataProvider = "parser-provider")
|
||||
public void testProperty02(SAXParser saxparser) throws SAXNotSupportedException {
|
||||
try {
|
||||
Object object = saxparser.getProperty(DOM_NODE);
|
||||
} catch (SAXNotRecognizedException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the default lexical-handler not exists.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testProperty03(SAXParser saxparser) {
|
||||
try {
|
||||
assertNull(saxparser.getProperty(LEXICAL_HANDLER));
|
||||
} catch (SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the default declaration-handler not exists.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testProperty04(SAXParser saxparser) {
|
||||
|
||||
try {
|
||||
assertNull(saxparser.getProperty(DECL_HANDLER));
|
||||
} catch (SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to set and get the lexical-handler.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testProperty05(SAXParser saxparser) {
|
||||
try {
|
||||
MyLexicalHandler myLexicalHandler = new MyLexicalHandler();
|
||||
saxparser.setProperty(LEXICAL_HANDLER, myLexicalHandler);
|
||||
Object object = saxparser.getProperty(LEXICAL_HANDLER);
|
||||
assertTrue(object instanceof LexicalHandler);
|
||||
} catch (SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to set and get the declaration-handler.
|
||||
*/
|
||||
@Test(dataProvider = "parser-provider")
|
||||
public void testProperty06(SAXParser saxparser) {
|
||||
try {
|
||||
MyDeclHandler myDeclHandler = new MyDeclHandler();
|
||||
saxparser.setProperty(DECL_HANDLER, myDeclHandler);
|
||||
Object object = saxparser.getProperty(DECL_HANDLER);
|
||||
assertTrue(object instanceof DeclHandler);
|
||||
} catch (SAXException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Customized LexicalHandler used for test.
|
||||
*/
|
||||
private class MyLexicalHandler implements LexicalHandler {
|
||||
|
||||
public void comment(char[] ch, int start, int length) {
|
||||
}
|
||||
|
||||
public void endCDATA() {
|
||||
}
|
||||
|
||||
public void endDTD() {
|
||||
}
|
||||
|
||||
public void endEntity(String name) {
|
||||
}
|
||||
|
||||
public void startCDATA() {
|
||||
}
|
||||
|
||||
public void startDTD(String name, String publicId, String systemId) {
|
||||
}
|
||||
|
||||
public void startEntity(String name) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Customized DeclHandler used for test.
|
||||
*/
|
||||
private class MyDeclHandler implements DeclHandler {
|
||||
|
||||
public void attributeDecl(String eName, String aName, String type, String valueDefault, String value) {
|
||||
}
|
||||
|
||||
public void elementDecl(String name, String model) {
|
||||
}
|
||||
|
||||
public void externalEntityDecl(String name, String publicId, String systemId) {
|
||||
}
|
||||
|
||||
public void internalEntityDecl(String name, String value) {
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package javax.xml.parsers.ptests;
|
||||
|
||||
import static jaxp.library.JAXPTestUtilities.failUnexpected;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Class contains the test cases for SAXParser API
|
||||
*/
|
||||
public class SAXParserTest03 {
|
||||
|
||||
/**
|
||||
* Provide SAXParserFactory.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@DataProvider(name = "input-provider")
|
||||
public Object[][] getFactory() {
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
spf.setValidating(true);
|
||||
MyErrorHandler handler = MyErrorHandler.newInstance();
|
||||
return new Object[][] { { spf, handler } };
|
||||
}
|
||||
|
||||
/**
|
||||
* parsertest.xml holds a valid document. This method tests the validating
|
||||
* parser.
|
||||
*/
|
||||
@Test(dataProvider = "input-provider")
|
||||
public void testParseValidate01(SAXParserFactory spf, MyErrorHandler handler) {
|
||||
try {
|
||||
SAXParser saxparser = spf.newSAXParser();
|
||||
saxparser.parse(new File(TestUtils.XML_DIR, "parsertest.xml"), handler);
|
||||
assertFalse(handler.errorOccured);
|
||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* validns.xml holds a valid document with XML namespaces in it. This method
|
||||
* tests the Validating parser with namespace processing on.
|
||||
*/
|
||||
@Test(dataProvider = "input-provider")
|
||||
public void testParseValidate02(SAXParserFactory spf, MyErrorHandler handler) {
|
||||
try {
|
||||
spf.setNamespaceAware(true);
|
||||
SAXParser saxparser = spf.newSAXParser();
|
||||
saxparser.parse(new File(TestUtils.XML_DIR, "validns.xml"), handler);
|
||||
assertFalse(handler.errorOccured);
|
||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||
failUnexpected(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* invalidns.xml holds an invalid document with XML namespaces in it. This
|
||||
* method tests the validating parser with namespace processing on. It
|
||||
* should throw validation error.
|
||||
*/
|
||||
@Test(dataProvider = "input-provider")
|
||||
public void testParseValidate03(SAXParserFactory spf, MyErrorHandler handler) {
|
||||
try {
|
||||
spf.setNamespaceAware(true);
|
||||
SAXParser saxparser = spf.newSAXParser();
|
||||
saxparser.parse(new File(TestUtils.XML_DIR, "invalidns.xml"), handler);
|
||||
failUnexpected(new RuntimeException());
|
||||
} catch (ParserConfigurationException | SAXException | IOException e) {
|
||||
if (e instanceof SAXException) {
|
||||
assertTrue(handler.errorOccured);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package javax.xml.parsers.ptests;
|
||||
|
||||
import static jaxp.library.JAXPTestUtilities.ERROR_MSG_HEADER;
|
||||
import static jaxp.library.JAXPTestUtilities.FILE_SEP;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
import org.xml.sax.helpers.LocatorImpl;
|
||||
|
||||
/**
|
||||
* Utility interface which includes final variables of xml, golden file
|
||||
* directories.
|
||||
*/
|
||||
interface TestUtils {
|
||||
final String XML_DIR = System.getProperty("test.src", ".") + FILE_SEP + "javax/xml/parsers/xmlfiles";
|
||||
final String GOLDEN_DIR = XML_DIR + FILE_SEP + "out";
|
||||
}
|
||||
|
||||
/**
|
||||
* Customized DefaultHandler which writes output document when methods are
|
||||
* called by Transformer. Test may use output document to compare with golden
|
||||
* file for verification.
|
||||
*/
|
||||
class MyCHandler extends DefaultHandler {
|
||||
|
||||
private final BufferedWriter bWriter;
|
||||
private final Locator locator = new LocatorImpl();
|
||||
|
||||
private MyCHandler(File file) throws IOException {
|
||||
bWriter = new BufferedWriter(new FileWriter(file));
|
||||
}
|
||||
|
||||
public static MyCHandler newInstance(File file) throws IOException {
|
||||
MyCHandler handler = new MyCHandler(file);
|
||||
return handler;
|
||||
}
|
||||
|
||||
public void characters(char[] ch, int start, int length) {
|
||||
String s = new String(ch, start, length);
|
||||
String str = String.format("characters...length is:%d\n<%s>", s.length(), s);
|
||||
try {
|
||||
bWriter.write(str, 0, str.length());
|
||||
bWriter.newLine();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(ERROR_MSG_HEADER, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void endDocument() {
|
||||
String str = "endDocument...";
|
||||
try {
|
||||
bWriter.write(str, 0, str.length());
|
||||
bWriter.newLine();
|
||||
bWriter.flush();
|
||||
bWriter.close();
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(ERROR_MSG_HEADER, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void endElement(String namespaceURI, String localName, String qName) {
|
||||
String str = String.format("endElement...\nnamespaceURI: <%s> localName: <%s> qName: <%s>", namespaceURI, localName, qName);
|
||||
try {
|
||||
bWriter.write(str, 0, str.length());
|
||||
bWriter.newLine();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(ERROR_MSG_HEADER, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void endPrefixMapping(String prefix) {
|
||||
String str = String.format("endPrefixMapping...\nprefix: <%s>", prefix);
|
||||
try {
|
||||
bWriter.write(str, 0, str.length());
|
||||
bWriter.newLine();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(ERROR_MSG_HEADER, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void ignorableWhitespace(char[] ch, int start, int length) {
|
||||
String s = new String(ch, start, length);
|
||||
String str = String.format("ignorableWhitespace...\n%s ignorable white space string length: %d", s, s.length());
|
||||
try {
|
||||
bWriter.write(str, 0, str.length());
|
||||
bWriter.newLine();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(ERROR_MSG_HEADER, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void processingInstruction(String target, String data) {
|
||||
String str = String.format("processingInstruction...target:<%s> data: <%s>", target, data);
|
||||
try {
|
||||
bWriter.write(str, 0, str.length());
|
||||
bWriter.newLine();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(ERROR_MSG_HEADER, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void skippedEntity(String name) {
|
||||
String str = String.format("skippedEntity...\nname: <%s>", name);
|
||||
try {
|
||||
bWriter.write(str, 0, str.length());
|
||||
bWriter.newLine();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(ERROR_MSG_HEADER, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void startDocument() {
|
||||
String str = "startDocument...";
|
||||
try {
|
||||
bWriter.write(str, 0, str.length());
|
||||
bWriter.newLine();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(ERROR_MSG_HEADER, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
|
||||
String str = String.format("startElement...\nnamespaceURI: <%s> localName: <%s> qName: <%s> Number of Attributes: <%d> Line# <%d>", namespaceURI,
|
||||
localName, qName, atts.getLength(), locator.getLineNumber());
|
||||
try {
|
||||
bWriter.write(str, 0, str.length());
|
||||
bWriter.newLine();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(ERROR_MSG_HEADER, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void startPrefixMapping(String prefix, String uri) {
|
||||
String str = String.format("startPrefixMapping...\nprefix: <%s> uri: <%s>", prefix, uri);
|
||||
try {
|
||||
bWriter.write(str, 0, str.length());
|
||||
bWriter.newLine();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(ERROR_MSG_HEADER, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Customized DefaultHandler used for SAXParseException testing.
|
||||
*/
|
||||
class MyErrorHandler extends DefaultHandler {
|
||||
boolean errorOccured = false;
|
||||
|
||||
private MyErrorHandler() {
|
||||
}
|
||||
|
||||
public static MyErrorHandler newInstance() {
|
||||
return new MyErrorHandler();
|
||||
}
|
||||
|
||||
public void error(SAXParseException e) {
|
||||
errorOccured = true;
|
||||
}
|
||||
|
||||
public void warning(SAXParseException e) {
|
||||
errorOccured = true;
|
||||
}
|
||||
|
||||
public void fatalError(SAXParseException e) {
|
||||
errorOccured = true;
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0"?>
|
||||
<html>
|
||||
<![CDATA[ <xml>This is not parsed</xml>]]> yet
|
||||
</html>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE document [
|
||||
<!ENTITY ws "Wiliam SHAkespeare">
|
||||
<!ELEMENT document (title)>
|
||||
<!ELEMENT title (#PCDATA)>
|
||||
]>
|
||||
<document>
|
||||
<title>&ws;</title>
|
||||
</document>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE document [
|
||||
<!ENTITY ws "Wiliam SHAkespeare">
|
||||
<!ELEMENT document (name)>
|
||||
<!ELEMENT title (#PCDATA)>
|
||||
]>
|
||||
<document>
|
||||
<title>&ws;</title>
|
||||
</document>
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE note [
|
||||
<!ELEMENT note (#PCDATA|to|ar:from|br:from|heading|body)*>
|
||||
<!ELEMENT to (#PCDATA)>
|
||||
<!ELEMENT ar:from (#PCDATA)>
|
||||
<!ELEMENT br:from (#PCDATA)>
|
||||
<!ELEMENT heading (#PCDATA)>
|
||||
<!ELEMENT body (#PCDATA)>
|
||||
<!ATTLIST note xmlns:ar CDATA #IMPLIED>
|
||||
<!ATTLIST note xmlns:br CDATA #IMPLIED>
|
||||
]>
|
||||
<note xmlns:ar="http://www.xml.com/books">
|
||||
xmlns:br="http://www.abc.com">
|
||||
<to>Tove</to>
|
||||
<ar:from>Jani</ar:from>
|
||||
<br:from>Next</br:from>
|
||||
<heading>Reminder</heading>
|
||||
<body> weekend!</body>
|
||||
</note>
|
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE note [
|
||||
<!ELEMENT note (to,from,heading,body)>
|
||||
<!ELEMENT to (#PCDATA)>
|
||||
<!ELEMENT from (#PCDATA)>
|
||||
<!ELEMENT heading (#PCDATA)>
|
||||
<!ELEMENT body (#PCDATA)>
|
||||
]>
|
||||
<note xmlns:ar="http://www.xml.com/books">
|
||||
xmlns:br="http://www.abc.com">
|
||||
<to>Tove</to>
|
||||
<ar:from>Jani</ar:from>
|
||||
<br:from>Next</br:from>
|
||||
<heading>Reminder</heading>
|
||||
<body> weekend!</body>
|
||||
</note>
|
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE note [
|
||||
<!ELEMENT note (#PCDATA|to|with|ar:from|br:from|heading|body)*>
|
||||
<!ELEMENT to (sender)>
|
||||
<!ELEMENT sender (#PCDATA)>
|
||||
<!ELEMENT with (message)>
|
||||
<!ELEMENT message (#PCDATA)>
|
||||
<!ELEMENT ar:from (tab)>
|
||||
<!ELEMENT tab (#PCDATA)>
|
||||
<!ELEMENT br:from (#PCDATA)>
|
||||
<!ELEMENT heading (#PCDATA)>
|
||||
<!ELEMENT body (#PCDATA)>
|
||||
<!ATTLIST note xmlns:ar CDATA #IMPLIED>
|
||||
<!ATTLIST note xmlns:br CDATA #IMPLIED>
|
||||
]>
|
||||
<note xmlns:ar="http://www.xml.com/books"
|
||||
xmlns:br="http://www.abc.com">
|
||||
<to>
|
||||
|
||||
<!--This is with whitespace-->
|
||||
<sender>John</sender>
|
||||
|
||||
</to>
|
||||
<with> <message>with whitespace</message> </with>
|
||||
<ar:from> <tab>Jani</tab></ar:from>
|
||||
<br:from>Next</br:from>
|
||||
<heading>Reminder</heading>
|
||||
<body> weekend!</body>
|
||||
</note>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE note [
|
||||
<!ELEMENT note (to|heading|body)*>
|
||||
<!ELEMENT body (#PCDATA)>
|
||||
]>
|
||||
<note>
|
||||
<to>Tove</to>
|
||||
<body><!--hello--></body>
|
||||
</note>
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<note>
|
||||
<to>Tove</to>
|
||||
<body><!--hello--></body>
|
||||
</note>
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0"?>
|
||||
<html>
|
||||
<![CDATA[ <xml>This is not parsed</xml>]]> yet
|
||||
</html>
|
@ -0,0 +1,12 @@
|
||||
<!ELEMENT document ANY>
|
||||
<!ELEMENT title (#PCDATA)>
|
||||
<!ELEMENT publisher (#PCDATA)>
|
||||
<!ELEMENT book (#PCDATA)>
|
||||
<!ELEMENT bookurn (#PCDATA)>
|
||||
<!ATTLIST book price CDATA "$100">
|
||||
<!ATTLIST book author CDATA "Herold">
|
||||
<!ATTLIST book number ID #REQUIRED>
|
||||
<!ATTLIST bookurn xmlns CDATA "10">
|
||||
<!ATTLIST bookurn xmlns:isbn CDATA "10">
|
||||
<!ENTITY w "William">
|
||||
<!ENTITY s "Shakespeare">
|
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE document SYSTEM "DocumentBuilderImpl02.dtd">
|
||||
<document>
|
||||
|
||||
Publishers of the Music of New York Women Composers
|
||||
|
||||
<title>The Publishers </title>
|
||||
|
||||
<publisher>
|
||||
Alfred Publishing
|
||||
&w;
|
||||
15535 Morrison
|
||||
South Oaks CA 91403
|
||||
</publisher>
|
||||
|
||||
<book price="$100" author = "Herold" number = "no_11">
|
||||
eXtensible Markup Language
|
||||
</book>
|
||||
|
||||
<bookurn xmlns='urn:loc.gov:books'
|
||||
xmlns:isbn='urn:ISBN:0-395-36341-6'/>
|
||||
|
||||
|
||||
Publishers are not noted in report by time.
|
||||
|
||||
</document>
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" standalone="yes"?>
|
||||
<document>
|
||||
Publishers of the Music of New York Women Composers
|
||||
|
||||
<title>The Publishers </title>
|
||||
|
||||
<publisher>
|
||||
Alfred Publishing
|
||||
15535 Morrison
|
||||
South Oaks CA 91403
|
||||
</publisher>
|
||||
|
||||
<book price="$100" author = "Herold" number = "no_11">
|
||||
eXtensible Markup Language
|
||||
</book>
|
||||
|
||||
<bookurn xmlns='urn:loc.gov:books'
|
||||
xmlns:isbn='urn:ISBN:0-395-36341-6'/>
|
||||
<xmlns:pages />
|
||||
|
||||
Publishers are not noted in report by time.
|
||||
|
||||
</document>
|
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" standalone="yes" ?>
|
||||
<cities>
|
||||
<city name="Paris" country="France"/>
|
||||
<city name="Roma" country="Italia"/>
|
||||
<city name="Nice" country="France"/>
|
||||
<city name="Madrid" country="Espana"/>
|
||||
<city name="Milano" country="Italia"/>
|
||||
<city name="Firenze" country="Italia"/>
|
||||
<city name="Napoli" country="Italia"/>
|
||||
<city name="Lyon" country="France"/>
|
||||
<city name="Barcelona" country="Espana"/>
|
||||
</cities>
|
||||
|
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" ?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:output method="xml" indent="yes"/>
|
||||
<xsl:template match="/">
|
||||
<xsl:variable name="unique-countries"
|
||||
select="/cities
|
||||
/city[not(@country=preceding-sibling::city/@country)]
|
||||
/@country"
|
||||
/>
|
||||
<countries>
|
||||
<xsl:for-each select="$unique-countries">
|
||||
<country name="{.}">
|
||||
<xsl:for-each select="//city[@country=current()]">
|
||||
<city><xsl:value-of select="@name"/></city>
|
||||
</xsl:for-each>
|
||||
</country>
|
||||
</xsl:for-each>
|
||||
</countries>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" ?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:import href="temp/cities.xsl"/>
|
||||
</xsl:stylesheet>
|
||||
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" ?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:include href="temp/cities.xsl"/>
|
||||
</xsl:stylesheet>
|
||||
|
@ -0,0 +1,13 @@
|
||||
<!ELEMENT document ANY>
|
||||
<!ELEMENT title (#PCDATA)>
|
||||
<!ELEMENT publisher (#PCDATA)>
|
||||
<!ELEMENT book (#PCDATA)>
|
||||
<!ELEMENT bookurn (#PCDATA)>
|
||||
<!ELEMENT xmlns:pages (#PCDATA)>
|
||||
<!ATTLIST book price CDATA "$100">
|
||||
<!ATTLIST book author CDATA "Herold">
|
||||
<!ATTLIST book number ID #REQUIRED>
|
||||
<!ATTLIST bookurn xmlns CDATA "10">
|
||||
<!ATTLIST bookurn xmlns:isbn CDATA "10">
|
||||
<!ENTITY mkm "I am Krishna">
|
||||
<!ENTITY km "I am KrishnaMohan">
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" standalone="yes"?>
|
||||
<document>
|
||||
Publishers of the Music of New York Women Composers
|
||||
|
||||
<title>The Publishers </title>
|
||||
|
||||
<publisher>
|
||||
Alfred Publishing
|
||||
&mkm;
|
||||
15535 Morrison
|
||||
South Oaks CA 91403
|
||||
</publisher>
|
||||
|
||||
<book price="$100" author = "Herold" number = "no_11">
|
||||
eXtensible Markup Language
|
||||
</book>
|
||||
|
||||
<bookurn xmlns='urn:loc.gov:books'
|
||||
xmlns:isbn='urn:ISBN:0-395-36341-6'/>
|
||||
<xmlns:pages />
|
||||
|
||||
Publishers are not noted in report by time.
|
||||
|
||||
</document>
|
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE book [
|
||||
<!ELEMENT book (#PCDATA | ar:rating | fr:rating | zr:rating)* >
|
||||
<!ATTLIST ar:rating
|
||||
xmlns:ar CDATA #FIXED "http://www.amazon.com/">
|
||||
<!ATTLIST fr:rating
|
||||
xmlns:fr CDATA #FIXED "http://www.fatbrain.com/">
|
||||
<!ELEMENT ar:rating (#PCDATA)>
|
||||
<!ELEMENT fr:rating (#PCDATA)>
|
||||
<!ELEMENT zr:rating (#PCDATA)>
|
||||
]>
|
||||
<book>
|
||||
<ar:rating>4star</ar:rating>
|
||||
<fr:rating>3star</fr:rating>
|
||||
<zr:rating>2star</zr:rating>
|
||||
</book>
|
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0"?>
|
||||
<html xmlns="http://www.w3.org/TR/REC-html40"
|
||||
xmlns:b="urn:BooksAreUs.org:BookInfo">
|
||||
<head>
|
||||
<title>Typography</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p> Welcome to the world of typography! Here is a book that you may find useful.</p>
|
||||
<b:title style="font-family: sans-serif;">Digital Typography</b:title>
|
||||
<b:author>Donald Knuth</b:author>
|
||||
<?netscape http://www.hotmail.com?>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -0,0 +1,8 @@
|
||||
<section><title>Book-Signing Event</title>
|
||||
<signing>
|
||||
<author title="Mr" name="Vikram Seth" />
|
||||
<book title="A Suitable Boy" price="$22.95" /></signing>
|
||||
<signing>
|
||||
<author title="Dr" name="Oliver Sacks" />
|
||||
<book title="The Island of the Color-Blind" price="$12.95" /></signing>
|
||||
</section>
|
@ -0,0 +1,83 @@
|
||||
startDocument...
|
||||
startPrefixMapping...
|
||||
prefix: <ar> uri: <http://www.xml.com/books>
|
||||
startPrefixMapping...
|
||||
prefix: <br> uri: <http://www.abc.com>
|
||||
startElement...
|
||||
namespaceURI: <> localName: <note> qName: <note> Number of Attributes: <2> Line# <0>
|
||||
characters...length is:1
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <> localName: <to> qName: <to> Number of Attributes: <0> Line# <0>
|
||||
startElement...
|
||||
namespaceURI: <> localName: <sender> qName: <sender> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:4
|
||||
<John>
|
||||
endElement...
|
||||
namespaceURI: <> localName: <sender> qName: <sender>
|
||||
endElement...
|
||||
namespaceURI: <> localName: <to> qName: <to>
|
||||
characters...length is:1
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <> localName: <with> qName: <with> Number of Attributes: <0> Line# <0>
|
||||
startElement...
|
||||
namespaceURI: <> localName: <message> qName: <message> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:15
|
||||
<with whitespace>
|
||||
endElement...
|
||||
namespaceURI: <> localName: <message> qName: <message>
|
||||
endElement...
|
||||
namespaceURI: <> localName: <with> qName: <with>
|
||||
characters...length is:1
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <http://www.xml.com/books> localName: <from> qName: <ar:from> Number of Attributes: <0> Line# <0>
|
||||
startElement...
|
||||
namespaceURI: <> localName: <tab> qName: <tab> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:4
|
||||
<Jani>
|
||||
endElement...
|
||||
namespaceURI: <> localName: <tab> qName: <tab>
|
||||
endElement...
|
||||
namespaceURI: <http://www.xml.com/books> localName: <from> qName: <ar:from>
|
||||
characters...length is:1
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <http://www.abc.com> localName: <from> qName: <br:from> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:4
|
||||
<Next>
|
||||
endElement...
|
||||
namespaceURI: <http://www.abc.com> localName: <from> qName: <br:from>
|
||||
characters...length is:1
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <> localName: <heading> qName: <heading> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:8
|
||||
<Reminder>
|
||||
endElement...
|
||||
namespaceURI: <> localName: <heading> qName: <heading>
|
||||
characters...length is:1
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <> localName: <body> qName: <body> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:9
|
||||
< weekend!>
|
||||
endElement...
|
||||
namespaceURI: <> localName: <body> qName: <body>
|
||||
characters...length is:1
|
||||
<
|
||||
>
|
||||
endElement...
|
||||
namespaceURI: <> localName: <note> qName: <note>
|
||||
endPrefixMapping...
|
||||
prefix: <br>
|
||||
endPrefixMapping...
|
||||
prefix: <ar>
|
||||
endDocument...
|
@ -0,0 +1,79 @@
|
||||
startDocument...
|
||||
startPrefixMapping...
|
||||
prefix: <> uri: <http://www.w3.org/TR/REC-html40>
|
||||
startPrefixMapping...
|
||||
prefix: <b> uri: <urn:BooksAreUs.org:BookInfo>
|
||||
startElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <html> qName: <html> Number of Attributes: <2> Line# <0>
|
||||
characters...length is:3
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <head> qName: <head> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:5
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <title> qName: <title> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:10
|
||||
<Typography>
|
||||
endElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <title> qName: <title>
|
||||
characters...length is:3
|
||||
<
|
||||
>
|
||||
endElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <head> qName: <head>
|
||||
characters...length is:4
|
||||
<
|
||||
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <body> qName: <body> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:5
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <p> qName: <p> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:77
|
||||
< Welcome to the world of typography! Here is a book that you may find useful.>
|
||||
endElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <p> qName: <p>
|
||||
characters...length is:5
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <urn:BooksAreUs.org:BookInfo> localName: <title> qName: <b:title> Number of Attributes: <1> Line# <0>
|
||||
characters...length is:18
|
||||
<Digital Typography>
|
||||
endElement...
|
||||
namespaceURI: <urn:BooksAreUs.org:BookInfo> localName: <title> qName: <b:title>
|
||||
characters...length is:6
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <urn:BooksAreUs.org:BookInfo> localName: <author> qName: <b:author> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:12
|
||||
<Donald Knuth>
|
||||
endElement...
|
||||
namespaceURI: <urn:BooksAreUs.org:BookInfo> localName: <author> qName: <b:author>
|
||||
characters...length is:5
|
||||
<
|
||||
>
|
||||
processingInstruction...target:<netscape> data: <http://www.hotmail.com>
|
||||
characters...length is:3
|
||||
<
|
||||
>
|
||||
endElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <body> qName: <body>
|
||||
characters...length is:2
|
||||
<
|
||||
|
||||
>
|
||||
endElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <html> qName: <html>
|
||||
endPrefixMapping...
|
||||
prefix: <b>
|
||||
endPrefixMapping...
|
||||
prefix: <>
|
||||
endDocument...
|
@ -0,0 +1,79 @@
|
||||
startDocument...
|
||||
startPrefixMapping...
|
||||
prefix: <> uri: <http://www.w3.org/TR/REC-html40>
|
||||
startPrefixMapping...
|
||||
prefix: <b> uri: <urn:BooksAreUs.org:BookInfo>
|
||||
startElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <html> qName: <html> Number of Attributes: <2> Line# <0>
|
||||
characters...length is:3
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <head> qName: <head> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:5
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <title> qName: <title> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:10
|
||||
<Typography>
|
||||
endElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <title> qName: <title>
|
||||
characters...length is:3
|
||||
<
|
||||
>
|
||||
endElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <head> qName: <head>
|
||||
characters...length is:4
|
||||
<
|
||||
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <body> qName: <body> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:5
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <p> qName: <p> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:77
|
||||
< Welcome to the world of typography! Here is a book that you may find useful.>
|
||||
endElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <p> qName: <p>
|
||||
characters...length is:5
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <urn:BooksAreUs.org:BookInfo> localName: <title> qName: <b:title> Number of Attributes: <1> Line# <0>
|
||||
characters...length is:18
|
||||
<Digital Typography>
|
||||
endElement...
|
||||
namespaceURI: <urn:BooksAreUs.org:BookInfo> localName: <title> qName: <b:title>
|
||||
characters...length is:6
|
||||
<
|
||||
>
|
||||
startElement...
|
||||
namespaceURI: <urn:BooksAreUs.org:BookInfo> localName: <author> qName: <b:author> Number of Attributes: <0> Line# <0>
|
||||
characters...length is:12
|
||||
<Donald Knuth>
|
||||
endElement...
|
||||
namespaceURI: <urn:BooksAreUs.org:BookInfo> localName: <author> qName: <b:author>
|
||||
characters...length is:5
|
||||
<
|
||||
>
|
||||
processingInstruction...target:<netscape> data: <http://www.hotmail.com>
|
||||
characters...length is:3
|
||||
<
|
||||
>
|
||||
endElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <body> qName: <body>
|
||||
characters...length is:2
|
||||
<
|
||||
|
||||
>
|
||||
endElement...
|
||||
namespaceURI: <http://www.w3.org/TR/REC-html40> localName: <html> qName: <html>
|
||||
endPrefixMapping...
|
||||
prefix: <b>
|
||||
endPrefixMapping...
|
||||
prefix: <>
|
||||
endDocument...
|
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE document SYSTEM "firstdtd.dtd">
|
||||
<document>
|
||||
Publishers of the Music of New York Women Composers
|
||||
|
||||
<title>The Publishers </title>
|
||||
|
||||
<publisher>
|
||||
Alfred Publishing
|
||||
&mkm;
|
||||
15535 Morrison
|
||||
South Oaks CA 91403
|
||||
</publisher>
|
||||
|
||||
<book price="$100" author = "Herold" number = "no_11">
|
||||
eXtensible Markup Language
|
||||
</book>
|
||||
|
||||
<bookurn xmlns='urn:loc.gov:books'
|
||||
xmlns:isbn='urn:ISBN:0-395-36341-6'/>
|
||||
<xmlns:pages />
|
||||
|
||||
Publishers are not noted in report by time.
|
||||
|
||||
</document>
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<contact xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test.xsd">
|
||||
<name> John </name>
|
||||
<phone>444-121-3434</phone>
|
||||
</contact>
|
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="contact">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="name" type="xs:string"/>
|
||||
<xs:element name="phone" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<contact xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="junk.xsd">
|
||||
<name> John </name>
|
||||
<phone>444-121-3434</phone>
|
||||
</contact>
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" standalone="yes"?>
|
||||
<document>
|
||||
Publishers of the Music of New York Women Composers
|
||||
|
||||
<title>The Publishers </title>
|
||||
|
||||
<publisher>
|
||||
Alfred Publishing
|
||||
&mkm;
|
||||
15535 Morrison
|
||||
South Oaks CA 91403
|
||||
</publisher>
|
||||
|
||||
<book price="$100" author = "Herold" number = "no_11">
|
||||
eXtensible Markup Language
|
||||
</book>
|
||||
|
||||
<bookurn xmlns='urn:loc.gov:books'
|
||||
xmlns:isbn='urn:ISBN:0-395-36341-6'/>
|
||||
<xmlns:pages />
|
||||
|
||||
Publishers are not noted in report by time.
|
||||
|
||||
</document>
|
@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE book [
|
||||
<!ELEMENT book (#PCDATA| ar:rating| fr:rating)* >
|
||||
<!ATTLIST ar:rating
|
||||
xmlns:ar CDATA #FIXED "http://www.amazon.com/">
|
||||
<!ATTLIST fr:rating
|
||||
xmlns:fr CDATA #FIXED "http://www.fatbrain.com/">
|
||||
<!ELEMENT ar:rating (#PCDATA)>
|
||||
<!ELEMENT fr:rating (#PCDATA)>
|
||||
]>
|
||||
<book>
|
||||
<ar:rating>4star</ar:rating>
|
||||
<fr:rating>3star</fr:rating>
|
||||
</book>
|
@ -61,33 +61,25 @@ public class TransformerFactoryTest {
|
||||
String xmlFile = XML_DIR + "TransformerFactoryTest.xml";
|
||||
String xmlURI = "file:///" + XML_DIR;
|
||||
|
||||
try {
|
||||
try (FileInputStream fis = new FileInputStream(xmlFile);
|
||||
FileOutputStream fos = new FileOutputStream(outputFile);) {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
Document doc = db.parse(new FileInputStream(xmlFile), xmlURI);
|
||||
Document doc = db.parse(fis, xmlURI);
|
||||
DOMSource domSource = new DOMSource(doc);
|
||||
domSource.setSystemId(xmlURI);
|
||||
StreamResult streamResult =new StreamResult(
|
||||
new FileOutputStream(outputFile));
|
||||
StreamResult streamResult = new StreamResult(fos);
|
||||
TransformerFactory tFactory = TransformerFactory.newInstance();
|
||||
|
||||
Source s = tFactory.getAssociatedStylesheet(domSource,"screen",
|
||||
"Modern",null);
|
||||
Source s = tFactory.getAssociatedStylesheet(domSource, "screen",
|
||||
"Modern", null);
|
||||
Transformer t = tFactory.newTransformer();
|
||||
t.transform(s,streamResult);
|
||||
t.transform(s, streamResult);
|
||||
assertTrue(compareWithGold(goldFile, outputFile));
|
||||
}catch (IOException | ParserConfigurationException
|
||||
} catch (IOException | ParserConfigurationException
|
||||
| TransformerException | SAXException ex) {
|
||||
failUnexpected(ex);
|
||||
} finally {
|
||||
try {
|
||||
Path outputPath = Paths.get(outputFile);
|
||||
if(Files.exists(outputPath))
|
||||
Files.delete(outputPath);
|
||||
} catch (IOException ex) {
|
||||
failCleanup(ex, outputFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -287,3 +287,4 @@ dd4ba422dba858b1c3c4b38f49a3e514be4e2790 jdk9-b38
|
||||
381bad1174c7c27352bee604535332da4ee2c556 jdk9-b39
|
||||
5455969de31f3083bcfd779b7acc3ab758ecb308 jdk9-b40
|
||||
4f785187377fe4c7ff388a7026dd72fcccdcfe7a jdk9-b41
|
||||
301ddb4478fb36d1f025d14e7e48c2a434e9e6ff jdk9-b42
|
||||
|
@ -284,3 +284,4 @@ d2d745313c81d1fc01f426983b9f784ab1f750e8 jdk9-b38
|
||||
ca6edf957fe1c6ea818530b503578e872cea7239 jdk9-b39
|
||||
f1ed1540da70a066527fd043413107e47721edbf jdk9-b40
|
||||
e336cbd8b15e959e70ed02f0f5e93fa76ebd4c07 jdk9-b41
|
||||
6b2314173433467245261364a52fb8e347fe6342 jdk9-b42
|
||||
|
@ -46,8 +46,7 @@ $(eval $(call SetupJavaCompilation,BUILD_INTERIM_RMIC, \
|
||||
SRC := $(JDK_TOPDIR)/src/jdk.rmic/share/classes, \
|
||||
INCLUDES := $(RMIC_PKGS), \
|
||||
BIN := $(BUILDTOOLS_OUTPUTDIR)/interim_rmic_classes, \
|
||||
COPY := .properties, \
|
||||
JAVAC_SOURCE_PATH_OVERRIDE := $(addprefix $(JDK_TOPDIR)/src/jdk.rmic/share/classes/, $(RMIC_PKGS))))
|
||||
COPY := .properties))
|
||||
|
||||
##########################################################################################
|
||||
|
||||
|
@ -221,8 +221,13 @@ $(JDK_OUTPUTDIR)/modules/jdk.hotspot.agent/_the.sa.jar.unpacked: $(HOTSPOT_DIST)
|
||||
# even if zip is already unpacked.
|
||||
$(SUPPORT_OUTPUTDIR)/gensrc/jdk.hotspot.agent/_the.sa.services: $(HOTSPOT_DIST)/lib/sa-jdi.jar
|
||||
|
||||
SA_TARGETS += $(JDK_OUTPUTDIR)/modules/jdk.hotspot.agent/_the.sa.jar.unpacked \
|
||||
$(SUPPORT_OUTPUTDIR)/gensrc/jdk.hotspot.agent/_the.sa.services
|
||||
# Some platforms don't have the serviceability agent
|
||||
ifeq (, $(filter $(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU), aix-ppc64))
|
||||
ifneq ($(JVM_VARIANT_ZERO), true)
|
||||
SA_TARGETS += $(JDK_OUTPUTDIR)/modules/jdk.hotspot.agent/_the.sa.jar.unpacked \
|
||||
$(SUPPORT_OUTPUTDIR)/gensrc/jdk.hotspot.agent/_the.sa.services
|
||||
endif
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user