# HG changeset patch # User amurillo # Date 1430431133 25200 # Node ID 1f0d760ccac1ff82a03a9b7d6bd5c697ef0a7c4a # Parent b0f52462883d96f11453870cafa82fb1a4a30291# Parent 9041e030d11f37c7d9ddc017a0b852d8c589daae Merge diff -r b0f52462883d -r 1f0d760ccac1 .hgtags --- a/.hgtags Wed Apr 29 12:16:38 2015 -0700 +++ b/.hgtags Thu Apr 30 14:58:53 2015 -0700 @@ -636,3 +636,4 @@ 4390345de45c7768c04bfafabf006a401824c5b5 hs25.60-b12 ccca7162738eee1be74890342c67d3b26540dcf6 jdk8u60-b12 ced08ed4924fc6581626c7ce2d769fc18d7b23e0 jdk8u60-b13 +30e04eba9e298cc5094793e279306535239187cc hs25.60-b13 \ No newline at end of file diff -r b0f52462883d -r 1f0d760ccac1 make/hotspot_version --- a/make/hotspot_version Wed Apr 29 12:16:38 2015 -0700 +++ b/make/hotspot_version Thu Apr 30 14:58:53 2015 -0700 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=60 -HS_BUILD_NUMBER=12 +HS_BUILD_NUMBER=14 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r b0f52462883d -r 1f0d760ccac1 src/cpu/ppc/vm/interpreter_ppc.cpp --- a/src/cpu/ppc/vm/interpreter_ppc.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/cpu/ppc/vm/interpreter_ppc.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2014 SAP AG. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2015 SAP AG. 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 @@ -459,7 +459,8 @@ // This is not a leaf but we have a JavaFrameAnchor now and we will // check (create) exceptions afterward so this is ok. - __ call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError)); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError), + R16_thread); // Pop the C frame and restore LR. __ pop_frame(); diff -r b0f52462883d -r 1f0d760ccac1 src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/os/linux/vm/os_linux.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -5929,14 +5929,6 @@ extern char** environ; -#ifndef __NR_fork -#define __NR_fork IA32_ONLY(2) IA64_ONLY(not defined) AMD64_ONLY(57) -#endif - -#ifndef __NR_execve -#define __NR_execve IA32_ONLY(11) IA64_ONLY(1033) AMD64_ONLY(59) -#endif - // Run the specified command in a separate process. Return its exit value, // or -1 on failure (e.g. can't fork a new process). // Unlike system(), this function can be called from signal handler. It @@ -5944,13 +5936,7 @@ int os::fork_and_exec(char* cmd) { const char * argv[4] = {"sh", "-c", cmd, NULL}; - // fork() in LinuxThreads/NPTL is not async-safe. It needs to run - // pthread_atfork handlers and reset pthread library. All we need is a - // separate process to execve. Make a direct syscall to fork process. - // On IA64 there's no fork syscall, we have to use fork() and hope for - // the best... - pid_t pid = NOT_IA64(syscall(__NR_fork);) - IA64_ONLY(fork();) + pid_t pid = fork(); if (pid < 0) { // fork failed @@ -5959,15 +5945,7 @@ } else if (pid == 0) { // child process - // execve() in LinuxThreads will call pthread_kill_other_threads_np() - // first to kill every thread on the thread list. Because this list is - // not reset by fork() (see notes above), execve() will instead kill - // every thread in the parent process. We know this is the only thread - // in the new process, so make a system call directly. - // IA64 should use normal execve() from glibc to match the glibc fork() - // above. - NOT_IA64(syscall(__NR_execve, "/bin/sh", argv, environ);) - IA64_ONLY(execve("/bin/sh", (char* const*)argv, environ);) + execve("/bin/sh", (char* const*)argv, environ); // execve failed _exit(-1); diff -r b0f52462883d -r 1f0d760ccac1 src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/os/solaris/vm/os_solaris.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -2696,29 +2696,30 @@ } } +size_t os::Solaris::page_size_for_alignment(size_t alignment) { + assert(is_size_aligned(alignment, (size_t) vm_page_size()), + err_msg(SIZE_FORMAT " is not aligned to " SIZE_FORMAT, + alignment, (size_t) vm_page_size())); + + for (int i = 0; _page_sizes[i] != 0; i++) { + if (is_size_aligned(alignment, _page_sizes[i])) { + return _page_sizes[i]; + } + } + + return (size_t) vm_page_size(); +} + int os::Solaris::commit_memory_impl(char* addr, size_t bytes, size_t alignment_hint, bool exec) { int err = Solaris::commit_memory_impl(addr, bytes, exec); - if (err == 0) { - if (UseLargePages && (alignment_hint > (size_t)vm_page_size())) { - // If the large page size has been set and the VM - // is using large pages, use the large page size - // if it is smaller than the alignment hint. This is - // a case where the VM wants to use a larger alignment size - // for its own reasons but still want to use large pages - // (which is what matters to setting the mpss range. - size_t page_size = 0; - if (large_page_size() < alignment_hint) { - assert(UseLargePages, "Expected to be here for large page use only"); - page_size = large_page_size(); - } else { - // If the alignment hint is less than the large page - // size, the VM wants a particular alignment (thus the hint) - // for internal reasons. Try to set the mpss range using - // the alignment_hint. - page_size = alignment_hint; - } - // Since this is a hint, ignore any failures. + if (err == 0 && UseLargePages && alignment_hint > 0) { + assert(is_size_aligned(bytes, alignment_hint), + err_msg(SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, alignment_hint)); + + // The syscall memcntl requires an exact page size (see man memcntl for details). + size_t page_size = page_size_for_alignment(alignment_hint); + if (page_size > (size_t) vm_page_size()) { (void)Solaris::setup_large_pages(addr, bytes, page_size); } } @@ -3251,7 +3252,22 @@ } } +bool os::Solaris::is_valid_page_size(size_t bytes) { + for (int i = 0; _page_sizes[i] != 0; i++) { + if (_page_sizes[i] == bytes) { + return true; + } + } + return false; +} + bool os::Solaris::setup_large_pages(caddr_t start, size_t bytes, size_t align) { + assert(is_valid_page_size(align), err_msg(SIZE_FORMAT " is not a valid page size", align)); + assert(is_ptr_aligned((void*) start, align), + err_msg(PTR_FORMAT " is not aligned to " SIZE_FORMAT, p2i((void*) start), align)); + assert(is_size_aligned(bytes, align), + err_msg(SIZE_FORMAT " is not aligned to " SIZE_FORMAT, bytes, align)); + // Signal to OS that we want large pages for addresses // from addr, addr + bytes struct memcntl_mha mpss_struct; diff -r b0f52462883d -r 1f0d760ccac1 src/os/solaris/vm/os_solaris.hpp --- a/src/os/solaris/vm/os_solaris.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/os/solaris/vm/os_solaris.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -110,6 +110,8 @@ static meminfo_func_t _meminfo; // Large Page Support + static bool is_valid_page_size(size_t bytes); + static size_t page_size_for_alignment(size_t alignment); static bool setup_large_pages(caddr_t start, size_t bytes, size_t align); static void init_thread_fpu_state(void); diff -r b0f52462883d -r 1f0d760ccac1 src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp --- a/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2014 SAP AG. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2015 SAP AG. 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 @@ -290,6 +290,7 @@ goto report_and_die; } + CodeBlob *cb = NULL; // Handle signal from NativeJump::patch_verified_entry(). if (( TrapBasedNotEntrantChecks && sig == SIGTRAP && nativeInstruction_at(pc)->is_sigtrap_zombie_not_entrant()) || (!TrapBasedNotEntrantChecks && sig == SIGILL && nativeInstruction_at(pc)->is_sigill_zombie_not_entrant())) { @@ -305,7 +306,10 @@ // especially when we try to read from the safepoint polling page. So the check // (address)info->si_addr == os::get_standard_polling_page() // doesn't work for us. We use: - ((NativeInstruction*)pc)->is_safepoint_poll()) { + ((NativeInstruction*)pc)->is_safepoint_poll() && + CodeCache::contains((void*) pc) && + ((cb = CodeCache::find_blob(pc)) != NULL) && + cb->is_nmethod()) { if (TraceTraps) { tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", p2i(pc)); } diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/ci/ciMethod.cpp --- a/src/share/vm/ci/ciMethod.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/ci/ciMethod.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -70,7 +70,8 @@ // Loaded method. ciMethod::ciMethod(methodHandle h_m, ciInstanceKlass* holder) : ciMetadata(h_m()), - _holder(holder) + _holder(holder), + _has_injected_profile(false) { assert(h_m() != NULL, "no null method"); @@ -167,7 +168,8 @@ _liveness( NULL), _can_be_statically_bound(false), _method_blocks( NULL), - _method_data( NULL) + _method_data( NULL), + _has_injected_profile( false) #if defined(COMPILER2) || defined(SHARK) , _flow( NULL), @@ -689,7 +691,8 @@ // via assert_unique_concrete_method or assert_leaf_type. ciMethod* ciMethod::find_monomorphic_target(ciInstanceKlass* caller, ciInstanceKlass* callee_holder, - ciInstanceKlass* actual_recv) { + ciInstanceKlass* actual_recv, + bool check_access) { check_is_loaded(); if (actual_recv->is_interface()) { @@ -697,7 +700,7 @@ return NULL; } - ciMethod* root_m = resolve_invoke(caller, actual_recv); + ciMethod* root_m = resolve_invoke(caller, actual_recv, check_access); if (root_m == NULL) { // Something went wrong looking up the actual receiver method. return NULL; @@ -776,7 +779,7 @@ // // Given a known receiver klass, find the target for the call. // Return NULL if the call has no target or the target is abstract. -ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver) { +ciMethod* ciMethod::resolve_invoke(ciKlass* caller, ciKlass* exact_receiver, bool check_access) { check_is_loaded(); VM_ENTRY_MARK; @@ -793,9 +796,9 @@ || InstanceKlass::cast(h_recv())->is_linked() && !exact_receiver->is_interface()) { if (holder()->is_interface()) { - m = LinkResolver::resolve_interface_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass); + m = LinkResolver::resolve_interface_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass, check_access); } else { - m = LinkResolver::resolve_virtual_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass); + m = LinkResolver::resolve_virtual_call_or_null(h_recv, h_resolved, h_name, h_signature, caller_klass, check_access); } } diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/ci/ciMethod.hpp --- a/src/share/vm/ci/ciMethod.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/ci/ciMethod.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -78,6 +78,7 @@ bool _is_c1_compilable; bool _is_c2_compilable; bool _can_be_statically_bound; + bool _has_injected_profile; // Lazy fields, filled in on demand address _code; @@ -248,11 +249,12 @@ // its calling environment. ciMethod* find_monomorphic_target(ciInstanceKlass* caller, ciInstanceKlass* callee_holder, - ciInstanceKlass* actual_receiver); + ciInstanceKlass* actual_receiver, + bool check_access = true); // Given a known receiver klass, find the target for the call. // Return NULL if the call has no target or is abstract. - ciMethod* resolve_invoke(ciKlass* caller, ciKlass* exact_receiver); + ciMethod* resolve_invoke(ciKlass* caller, ciKlass* exact_receiver, bool check_access = true); // Find the proper vtable index to invoke this method. int resolve_vtable_index(ciKlass* caller, ciKlass* receiver); @@ -281,6 +283,9 @@ int instructions_size(); int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC + bool has_injected_profile() const { return _has_injected_profile; } + void set_injected_profile(bool x) { _has_injected_profile = x; } + // Stack walking support bool is_ignored_by_security_stack_walk() const; diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/classfile/javaClasses.cpp --- a/src/share/vm/classfile/javaClasses.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/classfile/javaClasses.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -124,7 +124,7 @@ tty->print_cr(" name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int()); } #endif //PRODUCT - fatal("Invalid layout of preloaded class"); + vm_exit_during_initialization("Invalid layout of preloaded class: use -XX:+TraceClassLoading to see the origin of the problem class"); } dest_offset = fd.offset(); } @@ -2801,33 +2801,6 @@ return (flags(mname) & (MN_IS_METHOD | MN_IS_CONSTRUCTOR)) > 0; } -#if INCLUDE_JVMTI -// Can be executed on VM thread only -void java_lang_invoke_MemberName::adjust_vmtarget(oop mname, Method* old_method, - Method* new_method, bool* trace_name_printed) { - assert(is_method(mname), "wrong type"); - assert(Thread::current()->is_VM_thread(), "not VM thread"); - - Method* target = (Method*)mname->address_field(_vmtarget_offset); - if (target == old_method) { - mname->address_field_put(_vmtarget_offset, (address)new_method); - - if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { - if (!(*trace_name_printed)) { - // RC_TRACE_MESG macro has an embedded ResourceMark - RC_TRACE_MESG(("adjust: name=%s", - old_method->method_holder()->external_name())); - *trace_name_printed = true; - } - // RC_TRACE macro has an embedded ResourceMark - RC_TRACE(0x00400000, ("MemberName method update: %s(%s)", - new_method->name()->as_C_string(), - new_method->signature()->as_C_string())); - } - } -} -#endif // INCLUDE_JVMTI - void java_lang_invoke_MemberName::set_vmtarget(oop mname, Metadata* ref) { assert(is_instance(mname), "wrong type"); // check the type of the vmtarget @@ -3601,7 +3574,7 @@ tty->print_cr(" name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int()); } #endif //PRODUCT - fatal("Invalid layout of preloaded class"); + vm_exit_during_initialization("Invalid layout of preloaded class: use -XX:+TraceClassLoading to see the origin of the problem class"); return -1; } diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/classfile/javaClasses.hpp --- a/src/share/vm/classfile/javaClasses.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/classfile/javaClasses.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -1096,10 +1096,6 @@ static Metadata* vmtarget(oop mname); static void set_vmtarget(oop mname, Metadata* target); -#if INCLUDE_JVMTI - static void adjust_vmtarget(oop mname, Method* old_method, Method* new_method, - bool* trace_name_printed); -#endif // INCLUDE_JVMTI static intptr_t vmindex(oop mname); static void set_vmindex(oop mname, intptr_t index); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -244,7 +244,6 @@ template(returnType_name, "returnType") \ template(signature_name, "signature") \ template(slot_name, "slot") \ - template(selectAlternative_name, "selectAlternative") \ \ /* Support for annotations (JDK 1.5 and above) */ \ \ @@ -296,8 +295,7 @@ template(setTarget_signature, "(Ljava/lang/invoke/MethodHandle;)V") \ NOT_LP64( do_alias(intptr_signature, int_signature) ) \ LP64_ONLY( do_alias(intptr_signature, long_signature) ) \ - template(selectAlternative_signature, "(ZLjava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/MethodHandle;") \ - \ + \ /* common method and field names */ \ template(object_initializer_name, "") \ template(class_initializer_name, "") \ @@ -868,6 +866,12 @@ do_name( fullFence_name, "fullFence") \ do_alias( fullFence_signature, void_method_signature) \ \ + /* Custom branch frequencies profiling support for JSR292 */ \ + do_class(java_lang_invoke_MethodHandleImpl, "java/lang/invoke/MethodHandleImpl") \ + do_intrinsic(_profileBoolean, java_lang_invoke_MethodHandleImpl, profileBoolean_name, profileBoolean_signature, F_S) \ + do_name( profileBoolean_name, "profileBoolean") \ + do_signature(profileBoolean_signature, "(Z[I)Z") \ + \ /* unsafe memory references (there are a lot of them...) */ \ do_signature(getObject_signature, "(Ljava/lang/Object;J)Ljava/lang/Object;") \ do_signature(putObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)V") \ diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -114,7 +114,7 @@ } size_t CMBitMap::compute_size(size_t heap_size) { - return heap_size / mark_distance(); + return ReservedSpace::allocation_align_size_up(heap_size / mark_distance()); } size_t CMBitMap::mark_distance() { diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -1904,6 +1904,26 @@ guarantee(_task_queues != NULL, "task_queues allocation failure."); } +G1RegionToSpaceMapper* G1CollectedHeap::create_aux_memory_mapper(const char* description, + size_t size, + size_t translation_factor) { + size_t preferred_page_size = os::page_size_for_region_unaligned(size, 1); + // Allocate a new reserved space, preferring to use large pages. + ReservedSpace rs(size, preferred_page_size); + G1RegionToSpaceMapper* result = + G1RegionToSpaceMapper::create_mapper(rs, + size, + rs.alignment(), + HeapRegion::GrainBytes, + translation_factor, + mtGC); + if (TracePageSizes) { + gclog_or_tty->print_cr("G1 '%s': pg_sz=" SIZE_FORMAT " base=" PTR_FORMAT " size=" SIZE_FORMAT " alignment=" SIZE_FORMAT " reqsize=" SIZE_FORMAT, + description, preferred_page_size, p2i(rs.base()), rs.size(), rs.alignment(), size); + } + return result; +} + jint G1CollectedHeap::initialize() { CollectedHeap::pre_initialize(); os::enable_vtime(); @@ -1977,57 +1997,35 @@ ReservedSpace g1_rs = heap_rs.first_part(max_byte_size); G1RegionToSpaceMapper* heap_storage = G1RegionToSpaceMapper::create_mapper(g1_rs, + g1_rs.size(), UseLargePages ? os::large_page_size() : os::vm_page_size(), HeapRegion::GrainBytes, 1, mtJavaHeap); heap_storage->set_mapping_changed_listener(&_listener); - // Reserve space for the block offset table. We do not support automatic uncommit - // for the card table at this time. BOT only. - ReservedSpace bot_rs(G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize)); + // Create storage for the BOT, card table, card counts table (hot card cache) and the bitmaps. G1RegionToSpaceMapper* bot_storage = - G1RegionToSpaceMapper::create_mapper(bot_rs, - os::vm_page_size(), - HeapRegion::GrainBytes, - G1BlockOffsetSharedArray::N_bytes, - mtGC); + create_aux_memory_mapper("Block offset table", + G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize), + G1BlockOffsetSharedArray::N_bytes); ReservedSpace cardtable_rs(G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize)); G1RegionToSpaceMapper* cardtable_storage = - G1RegionToSpaceMapper::create_mapper(cardtable_rs, - os::vm_page_size(), - HeapRegion::GrainBytes, - G1BlockOffsetSharedArray::N_bytes, - mtGC); - - // Reserve space for the card counts table. - ReservedSpace card_counts_rs(G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize)); + create_aux_memory_mapper("Card table", + G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize), + G1BlockOffsetSharedArray::N_bytes); + G1RegionToSpaceMapper* card_counts_storage = - G1RegionToSpaceMapper::create_mapper(card_counts_rs, - os::vm_page_size(), - HeapRegion::GrainBytes, - G1BlockOffsetSharedArray::N_bytes, - mtGC); - - // Reserve space for prev and next bitmap. + create_aux_memory_mapper("Card counts table", + G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize), + G1BlockOffsetSharedArray::N_bytes); + size_t bitmap_size = CMBitMap::compute_size(g1_rs.size()); - - ReservedSpace prev_bitmap_rs(ReservedSpace::allocation_align_size_up(bitmap_size)); G1RegionToSpaceMapper* prev_bitmap_storage = - G1RegionToSpaceMapper::create_mapper(prev_bitmap_rs, - os::vm_page_size(), - HeapRegion::GrainBytes, - CMBitMap::mark_distance(), - mtGC); - - ReservedSpace next_bitmap_rs(ReservedSpace::allocation_align_size_up(bitmap_size)); + create_aux_memory_mapper("Prev Bitmap", bitmap_size, CMBitMap::mark_distance()); G1RegionToSpaceMapper* next_bitmap_storage = - G1RegionToSpaceMapper::create_mapper(next_bitmap_rs, - os::vm_page_size(), - HeapRegion::GrainBytes, - CMBitMap::mark_distance(), - mtGC); + create_aux_memory_mapper("Next Bitmap", bitmap_size, CMBitMap::mark_distance()); _hrm.initialize(heap_storage, prev_bitmap_storage, next_bitmap_storage, bot_storage, cardtable_storage, card_counts_storage); g1_barrier_set()->initialize(cardtable_storage); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -367,6 +367,12 @@ // heap after a compaction. void print_hrm_post_compaction(); + // Create a memory mapper for auxiliary data structures of the given size and + // translation factor. + static G1RegionToSpaceMapper* create_aux_memory_mapper(const char* description, + size_t size, + size_t translation_factor); + double verify(bool guard, const char* msg); void verify_before_gc(); void verify_after_gc(); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp --- a/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -44,20 +44,29 @@ #endif #include "utilities/bitMap.inline.hpp" -G1PageBasedVirtualSpace::G1PageBasedVirtualSpace() : _low_boundary(NULL), - _high_boundary(NULL), _committed(), _page_size(0), _special(false), +G1PageBasedVirtualSpace::G1PageBasedVirtualSpace(ReservedSpace rs, size_t used_size, size_t page_size) : + _low_boundary(NULL), _high_boundary(NULL), _committed(), _page_size(0), _special(false), _dirty(), _executable(false) { + initialize_with_page_size(rs, used_size, page_size); } -bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t page_size) { - if (!rs.is_reserved()) { - return false; // Allocation failed. - } +void G1PageBasedVirtualSpace::initialize_with_page_size(ReservedSpace rs, size_t used_size, size_t page_size) { + guarantee(rs.is_reserved(), "Given reserved space must have been reserved already."); + assert(_low_boundary == NULL, "VirtualSpace already initialized"); - assert(page_size > 0, "Granularity must be non-zero."); + assert(page_size > 0, "Page size must be non-zero."); + + guarantee(is_ptr_aligned(rs.base(), page_size), + err_msg("Reserved space base " PTR_FORMAT " is not aligned to requested page size " SIZE_FORMAT, p2i(rs.base()), page_size)); + guarantee(is_size_aligned(used_size, os::vm_page_size()), + err_msg("Given used reserved space size needs to be OS page size aligned (%d bytes) but is " SIZE_FORMAT, os::vm_page_size(), used_size)); + guarantee(used_size <= rs.size(), + err_msg("Used size of reserved space " SIZE_FORMAT " bytes is smaller than reservation at " SIZE_FORMAT " bytes", used_size, rs.size())); + guarantee(is_size_aligned(rs.size(), page_size), + err_msg("Expected that the virtual space is size aligned, but " SIZE_FORMAT " is not aligned to page size " SIZE_FORMAT, rs.size(), page_size)); _low_boundary = rs.base(); - _high_boundary = _low_boundary + rs.size(); + _high_boundary = _low_boundary + used_size; _special = rs.special(); _executable = rs.executable(); @@ -65,16 +74,15 @@ _page_size = page_size; assert(_committed.size() == 0, "virtual space initialized more than once"); - uintx size_in_bits = rs.size() / page_size; - _committed.resize(size_in_bits, /* in_resource_area */ false); + BitMap::idx_t size_in_pages = rs.size() / page_size; + _committed.resize(size_in_pages, /* in_resource_area */ false); if (_special) { - _dirty.resize(size_in_bits, /* in_resource_area */ false); + _dirty.resize(size_in_pages, /* in_resource_area */ false); } - return true; + _tail_size = used_size % _page_size; } - G1PageBasedVirtualSpace::~G1PageBasedVirtualSpace() { release(); } @@ -87,12 +95,18 @@ _special = false; _executable = false; _page_size = 0; + _tail_size = 0; _committed.resize(0, false); _dirty.resize(0, false); } size_t G1PageBasedVirtualSpace::committed_size() const { - return _committed.count_one_bits() * _page_size; + size_t result = _committed.count_one_bits() * _page_size; + // The last page might not be in full. + if (is_last_page_partial() && _committed.at(_committed.size() - 1)) { + result -= _page_size - _tail_size; + } + return result; } size_t G1PageBasedVirtualSpace::reserved_size() const { @@ -103,62 +117,134 @@ return reserved_size() - committed_size(); } -uintptr_t G1PageBasedVirtualSpace::addr_to_page_index(char* addr) const { +size_t G1PageBasedVirtualSpace::addr_to_page_index(char* addr) const { return (addr - _low_boundary) / _page_size; } -bool G1PageBasedVirtualSpace::is_area_committed(uintptr_t start, size_t size_in_pages) const { - uintptr_t end = start + size_in_pages; - return _committed.get_next_zero_offset(start, end) >= end; +bool G1PageBasedVirtualSpace::is_area_committed(size_t start_page, size_t size_in_pages) const { + size_t end_page = start_page + size_in_pages; + return _committed.get_next_zero_offset(start_page, end_page) >= end_page; } -bool G1PageBasedVirtualSpace::is_area_uncommitted(uintptr_t start, size_t size_in_pages) const { - uintptr_t end = start + size_in_pages; - return _committed.get_next_one_offset(start, end) >= end; +bool G1PageBasedVirtualSpace::is_area_uncommitted(size_t start_page, size_t size_in_pages) const { + size_t end_page = start_page + size_in_pages; + return _committed.get_next_one_offset(start_page, end_page) >= end_page; } -char* G1PageBasedVirtualSpace::page_start(uintptr_t index) { +char* G1PageBasedVirtualSpace::page_start(size_t index) const { return _low_boundary + index * _page_size; } -size_t G1PageBasedVirtualSpace::byte_size_for_pages(size_t num) { - return num * _page_size; +bool G1PageBasedVirtualSpace::is_after_last_page(size_t index) const { + guarantee(index <= _committed.size(), + err_msg("Given boundary page " SIZE_FORMAT " is beyond managed page count " SIZE_FORMAT, index, _committed.size())); + return index == _committed.size(); +} + +void G1PageBasedVirtualSpace::commit_preferred_pages(size_t start, size_t num_pages) { + assert(num_pages > 0, "No full pages to commit"); + assert(start + num_pages <= _committed.size(), + err_msg("Tried to commit area from page " SIZE_FORMAT " to page " SIZE_FORMAT " " + "that is outside of managed space of " SIZE_FORMAT " pages", + start, start + num_pages, _committed.size())); + + char* start_addr = page_start(start); + size_t size = num_pages * _page_size; + + os::commit_memory_or_exit(start_addr, size, _page_size, _executable, + err_msg("Failed to commit area from " PTR_FORMAT " to " PTR_FORMAT " of length " SIZE_FORMAT ".", + p2i(start_addr), p2i(start_addr + size), size)); +} + +void G1PageBasedVirtualSpace::commit_tail() { + assert(_tail_size > 0, "The size of the tail area must be > 0 when reaching here"); + + char* const aligned_end_address = (char*)align_ptr_down(_high_boundary, _page_size); + os::commit_memory_or_exit(aligned_end_address, _tail_size, os::vm_page_size(), _executable, + err_msg("Failed to commit tail area from " PTR_FORMAT " to " PTR_FORMAT " of length " SIZE_FORMAT ".", + p2i(aligned_end_address), p2i(_high_boundary), _tail_size)); } -bool G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) { +void G1PageBasedVirtualSpace::commit_internal(size_t start_page, size_t end_page) { + guarantee(start_page < end_page, + err_msg("Given start page " SIZE_FORMAT " is larger or equal to end page " SIZE_FORMAT, start_page, end_page)); + guarantee(end_page <= _committed.size(), + err_msg("Given end page " SIZE_FORMAT " is beyond end of managed page amount of " SIZE_FORMAT, end_page, _committed.size())); + + size_t pages = end_page - start_page; + bool need_to_commit_tail = is_after_last_page(end_page) && is_last_page_partial(); + + // If we have to commit some (partial) tail area, decrease the amount of pages to avoid + // committing that in the full-page commit code. + if (need_to_commit_tail) { + pages--; + } + + if (pages > 0) { + commit_preferred_pages(start_page, pages); + } + + if (need_to_commit_tail) { + commit_tail(); + } +} + +char* G1PageBasedVirtualSpace::bounded_end_addr(size_t end_page) const { + return MIN2(_high_boundary, page_start(end_page)); +} + +void G1PageBasedVirtualSpace::pretouch_internal(size_t start_page, size_t end_page) { + guarantee(start_page < end_page, + err_msg("Given start page " SIZE_FORMAT " is larger or equal to end page " SIZE_FORMAT, start_page, end_page)); + + os::pretouch_memory(page_start(start_page), bounded_end_addr(end_page)); +} + +bool G1PageBasedVirtualSpace::commit(size_t start_page, size_t size_in_pages) { // We need to make sure to commit all pages covered by the given area. - guarantee(is_area_uncommitted(start, size_in_pages), "Specified area is not uncommitted"); + guarantee(is_area_uncommitted(start_page, size_in_pages), "Specified area is not uncommitted"); bool zero_filled = true; - uintptr_t end = start + size_in_pages; + size_t end_page = start_page + size_in_pages; if (_special) { // Check for dirty pages and update zero_filled if any found. - if (_dirty.get_next_one_offset(start,end) < end) { + if (_dirty.get_next_one_offset(start_page, end_page) < end_page) { zero_filled = false; - _dirty.clear_range(start, end); + _dirty.clear_range(start_page, end_page); } } else { - os::commit_memory_or_exit(page_start(start), byte_size_for_pages(size_in_pages), _executable, - err_msg("Failed to commit pages from "SIZE_FORMAT" of length "SIZE_FORMAT, start, size_in_pages)); + commit_internal(start_page, end_page); } - _committed.set_range(start, end); + _committed.set_range(start_page, end_page); + if (AlwaysPreTouch) { + pretouch_internal(start_page, end_page); + } return zero_filled; } -void G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) { - guarantee(is_area_committed(start, size_in_pages), "checking"); +void G1PageBasedVirtualSpace::uncommit_internal(size_t start_page, size_t end_page) { + guarantee(start_page < end_page, + err_msg("Given start page " SIZE_FORMAT " is larger or equal to end page " SIZE_FORMAT, start_page, end_page)); + char* start_addr = page_start(start_page); + os::uncommit_memory(start_addr, pointer_delta(bounded_end_addr(end_page), start_addr, sizeof(char))); +} + +void G1PageBasedVirtualSpace::uncommit(size_t start_page, size_t size_in_pages) { + guarantee(is_area_committed(start_page, size_in_pages), "checking"); + + size_t end_page = start_page + size_in_pages; if (_special) { // Mark that memory is dirty. If committed again the memory might // need to be cleared explicitly. - _dirty.set_range(start, start + size_in_pages); + _dirty.set_range(start_page, end_page); } else { - os::uncommit_memory(page_start(start), byte_size_for_pages(size_in_pages)); + uncommit_internal(start_page, end_page); } - _committed.clear_range(start, start + size_in_pages); + _committed.clear_range(start_page, end_page); } bool G1PageBasedVirtualSpace::contains(const void* p) const { @@ -172,7 +258,8 @@ out->cr(); out->print_cr(" - committed: " SIZE_FORMAT, committed_size()); out->print_cr(" - reserved: " SIZE_FORMAT, reserved_size()); - out->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", p2i(_low_boundary), p2i(_high_boundary)); + out->print_cr(" - preferred page size: " SIZE_FORMAT, _page_size); + out->print_cr(" - [low_b, high_b]: [" PTR_FORMAT ", " PTR_FORMAT "]", p2i(_low_boundary), p2i(_high_boundary)); } void G1PageBasedVirtualSpace::print() { diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp --- a/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -34,6 +34,12 @@ // granularity. // (De-)Allocation requests are always OS page aligned by passing a page index // and multiples of pages. +// For systems that only commits of memory in a given size (always greater than +// page size) the base address is required to be aligned to that page size. +// The actual size requested need not be aligned to that page size, but the size +// of the reservation passed may be rounded up to this page size. Any fragment +// (less than the page size) of the actual size at the tail of the request will +// be committed using OS small pages. // The implementation gives an error when trying to commit or uncommit pages that // have already been committed or uncommitted. class G1PageBasedVirtualSpace VALUE_OBJ_CLASS_SPEC { @@ -43,7 +49,11 @@ char* _low_boundary; char* _high_boundary; - // The commit/uncommit granularity in bytes. + // The size of the tail in bytes of the handled space that needs to be committed + // using small pages. + size_t _tail_size; + + // The preferred page size used for commit/uncommit in bytes. size_t _page_size; // Bitmap used for verification of commit/uncommit operations. @@ -62,30 +72,55 @@ // Indicates whether the committed space should be executable. bool _executable; + // Helper function for committing memory. Commit the given memory range by using + // _page_size pages as much as possible and the remainder with small sized pages. + void commit_internal(size_t start_page, size_t end_page); + // Commit num_pages pages of _page_size size starting from start. All argument + // checking has been performed. + void commit_preferred_pages(size_t start_page, size_t end_page); + // Commit space at the high end of the space that needs to be committed with small + // sized pages. + void commit_tail(); + + // Uncommit the given memory range. + void uncommit_internal(size_t start_page, size_t end_page); + + // Pretouch the given memory range. + void pretouch_internal(size_t start_page, size_t end_page); + // Returns the index of the page which contains the given address. uintptr_t addr_to_page_index(char* addr) const; // Returns the address of the given page index. - char* page_start(uintptr_t index); - // Returns the byte size of the given number of pages. - size_t byte_size_for_pages(size_t num); + char* page_start(size_t index) const; + + // Is the given page index the last page? + bool is_last_page(size_t index) const { return index == (_committed.size() - 1); } + // Is the given page index the first after last page? + bool is_after_last_page(size_t index) const; + // Is the last page only partially covered by this space? + bool is_last_page_partial() const { return !is_ptr_aligned(_high_boundary, _page_size); } + // Returns the end address of the given page bounded by the reserved space. + char* bounded_end_addr(size_t end_page) const; // Returns true if the entire area is backed by committed memory. - bool is_area_committed(uintptr_t start, size_t size_in_pages) const; + bool is_area_committed(size_t start_page, size_t size_in_pages) const; // Returns true if the entire area is not backed by committed memory. - bool is_area_uncommitted(uintptr_t start, size_t size_in_pages) const; + bool is_area_uncommitted(size_t start_page, size_t size_in_pages) const; + void initialize_with_page_size(ReservedSpace rs, size_t used_size, size_t page_size); public: // Commit the given area of pages starting at start being size_in_pages large. // Returns true if the given area is zero filled upon completion. - bool commit(uintptr_t start, size_t size_in_pages); + bool commit(size_t start_page, size_t size_in_pages); // Uncommit the given area of pages starting at start being size_in_pages large. - void uncommit(uintptr_t start, size_t size_in_pages); + void uncommit(size_t start_page, size_t size_in_pages); - // Initialization - G1PageBasedVirtualSpace(); - bool initialize_with_granularity(ReservedSpace rs, size_t page_size); + // Initialize the given reserved space with the given base address and the size + // actually used. + // Prefer to commit in page_size chunks. + G1PageBasedVirtualSpace(ReservedSpace rs, size_t used_size, size_t page_size); // Destruction ~G1PageBasedVirtualSpace(); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp --- a/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, 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 @@ -31,17 +31,16 @@ #include "utilities/bitMap.inline.hpp" G1RegionToSpaceMapper::G1RegionToSpaceMapper(ReservedSpace rs, - size_t commit_granularity, + size_t used_size, + size_t page_size, size_t region_granularity, MemoryType type) : - _storage(), - _commit_granularity(commit_granularity), + _storage(rs, used_size, page_size), _region_granularity(region_granularity), _listener(NULL), _commit_map() { - guarantee(is_power_of_2(commit_granularity), "must be"); + guarantee(is_power_of_2(page_size), "must be"); guarantee(is_power_of_2(region_granularity), "must be"); - _storage.initialize_with_granularity(rs, commit_granularity); MemTracker::record_virtual_memory_type((address)rs.base(), type); } @@ -55,25 +54,26 @@ public: G1RegionsLargerThanCommitSizeMapper(ReservedSpace rs, - size_t os_commit_granularity, + size_t actual_size, + size_t page_size, size_t alloc_granularity, size_t commit_factor, MemoryType type) : - G1RegionToSpaceMapper(rs, os_commit_granularity, alloc_granularity, type), - _pages_per_region(alloc_granularity / (os_commit_granularity * commit_factor)) { + G1RegionToSpaceMapper(rs, actual_size, page_size, alloc_granularity, type), + _pages_per_region(alloc_granularity / (page_size * commit_factor)) { - guarantee(alloc_granularity >= os_commit_granularity, "allocation granularity smaller than commit granularity"); + guarantee(alloc_granularity >= page_size, "allocation granularity smaller than commit granularity"); _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false); } - virtual void commit_regions(uintptr_t start_idx, size_t num_regions) { - bool zero_filled = _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region); + virtual void commit_regions(uint start_idx, size_t num_regions) { + bool zero_filled = _storage.commit((size_t)start_idx * _pages_per_region, num_regions * _pages_per_region); _commit_map.set_range(start_idx, start_idx + num_regions); fire_on_commit(start_idx, num_regions, zero_filled); } - virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) { - _storage.uncommit(start_idx * _pages_per_region, num_regions * _pages_per_region); + virtual void uncommit_regions(uint start_idx, size_t num_regions) { + _storage.uncommit((size_t)start_idx * _pages_per_region, num_regions * _pages_per_region); _commit_map.clear_range(start_idx, start_idx + num_regions); } }; @@ -98,22 +98,23 @@ public: G1RegionsSmallerThanCommitSizeMapper(ReservedSpace rs, - size_t os_commit_granularity, + size_t actual_size, + size_t page_size, size_t alloc_granularity, size_t commit_factor, MemoryType type) : - G1RegionToSpaceMapper(rs, os_commit_granularity, alloc_granularity, type), - _regions_per_page((os_commit_granularity * commit_factor) / alloc_granularity), _refcounts() { + G1RegionToSpaceMapper(rs, actual_size, page_size, alloc_granularity, type), + _regions_per_page((page_size * commit_factor) / alloc_granularity), _refcounts() { - guarantee((os_commit_granularity * commit_factor) >= alloc_granularity, "allocation granularity smaller than commit granularity"); - _refcounts.initialize((HeapWord*)rs.base(), (HeapWord*)(rs.base() + rs.size()), os_commit_granularity); + guarantee((page_size * commit_factor) >= alloc_granularity, "allocation granularity smaller than commit granularity"); + _refcounts.initialize((HeapWord*)rs.base(), (HeapWord*)(rs.base() + align_size_up(rs.size(), page_size)), page_size); _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false); } - virtual void commit_regions(uintptr_t start_idx, size_t num_regions) { - for (uintptr_t i = start_idx; i < start_idx + num_regions; i++) { - assert(!_commit_map.at(i), err_msg("Trying to commit storage at region "INTPTR_FORMAT" that is already committed", i)); - uintptr_t idx = region_idx_to_page_idx(i); + virtual void commit_regions(uint start_idx, size_t num_regions) { + for (uint i = start_idx; i < start_idx + num_regions; i++) { + assert(!_commit_map.at(i), err_msg("Trying to commit storage at region %u that is already committed", i)); + size_t idx = region_idx_to_page_idx(i); uint old_refcount = _refcounts.get_by_index(idx); bool zero_filled = false; if (old_refcount == 0) { @@ -125,10 +126,10 @@ } } - virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) { - for (uintptr_t i = start_idx; i < start_idx + num_regions; i++) { - assert(_commit_map.at(i), err_msg("Trying to uncommit storage at region "INTPTR_FORMAT" that is not committed", i)); - uintptr_t idx = region_idx_to_page_idx(i); + virtual void uncommit_regions(uint start_idx, size_t num_regions) { + for (uint i = start_idx; i < start_idx + num_regions; i++) { + assert(_commit_map.at(i), err_msg("Trying to uncommit storage at region %u that is not committed", i)); + size_t idx = region_idx_to_page_idx(i); uint old_refcount = _refcounts.get_by_index(idx); assert(old_refcount > 0, "must be"); if (old_refcount == 1) { @@ -147,14 +148,15 @@ } G1RegionToSpaceMapper* G1RegionToSpaceMapper::create_mapper(ReservedSpace rs, - size_t os_commit_granularity, + size_t actual_size, + size_t page_size, size_t region_granularity, size_t commit_factor, MemoryType type) { - if (region_granularity >= (os_commit_granularity * commit_factor)) { - return new G1RegionsLargerThanCommitSizeMapper(rs, os_commit_granularity, region_granularity, commit_factor, type); + if (region_granularity >= (page_size * commit_factor)) { + return new G1RegionsLargerThanCommitSizeMapper(rs, actual_size, page_size, region_granularity, commit_factor, type); } else { - return new G1RegionsSmallerThanCommitSizeMapper(rs, os_commit_granularity, region_granularity, commit_factor, type); + return new G1RegionsSmallerThanCommitSizeMapper(rs, actual_size, page_size, region_granularity, commit_factor, type); } } diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.hpp --- a/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -46,12 +46,12 @@ protected: // Backing storage. G1PageBasedVirtualSpace _storage; - size_t _commit_granularity; + size_t _region_granularity; // Mapping management BitMap _commit_map; - G1RegionToSpaceMapper(ReservedSpace rs, size_t commit_granularity, size_t region_granularity, MemoryType type); + G1RegionToSpaceMapper(ReservedSpace rs, size_t used_size, size_t page_size, size_t region_granularity, MemoryType type); void fire_on_commit(uint start_idx, size_t num_regions, bool zero_filled); public: @@ -67,16 +67,20 @@ return _commit_map.at(idx); } - virtual void commit_regions(uintptr_t start_idx, size_t num_regions = 1) = 0; - virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions = 1) = 0; + virtual void commit_regions(uint start_idx, size_t num_regions = 1) = 0; + virtual void uncommit_regions(uint start_idx, size_t num_regions = 1) = 0; // Creates an appropriate G1RegionToSpaceMapper for the given parameters. + // The actual space to be used within the given reservation is given by actual_size. + // This is because some OSes need to round up the reservation size to guarantee + // alignment of page_size. // The byte_translation_factor defines how many bytes in a region correspond to // a single byte in the data structure this mapper is for. // Eg. in the card table, this value corresponds to the size a single card - // table entry corresponds to. + // table entry corresponds to in the heap. static G1RegionToSpaceMapper* create_mapper(ReservedSpace rs, - size_t os_commit_granularity, + size_t actual_size, + size_t page_size, size_t region_granularity, size_t byte_translation_factor, MemoryType type); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/gc_implementation/g1/heapRegionSet.cpp --- a/src/share/vm/gc_implementation/g1/heapRegionSet.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/gc_implementation/g1/heapRegionSet.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -420,6 +420,7 @@ ReservedSpace bot_rs(G1BlockOffsetSharedArray::compute_size(heap.word_size())); G1RegionToSpaceMapper* bot_storage = G1RegionToSpaceMapper::create_mapper(bot_rs, + bot_rs.size(), os::vm_page_size(), HeapRegion::GrainBytes, G1BlockOffsetSharedArray::N_bytes, diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -66,9 +66,10 @@ void GenerationSizer::initialize_size_info() { trace_gen_sizes("ps heap raw"); - const size_t page_sz = os::page_size_for_region(_min_heap_byte_size, - _max_heap_byte_size, - 8); + const size_t max_page_sz = os::page_size_for_region_aligned(_max_heap_byte_size, 8); + const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old + const size_t min_page_sz = os::page_size_for_region_aligned(_min_heap_byte_size, min_pages); + const size_t page_sz = MIN2(max_page_sz, min_page_sz); // Can a page size be something else than a power of two? assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2"); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -55,7 +55,7 @@ const size_t words = bits / BitsPerWord; const size_t raw_bytes = words * sizeof(idx_t); - const size_t page_sz = os::page_size_for_region(raw_bytes, raw_bytes, 10); + const size_t page_sz = os::page_size_for_region_aligned(raw_bytes, 10); const size_t granularity = os::vm_allocation_granularity(); _reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity)); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -401,7 +401,7 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size) { const size_t raw_bytes = count * element_size; - const size_t page_sz = os::page_size_for_region(raw_bytes, raw_bytes, 10); + const size_t page_sz = os::page_size_for_region_aligned(raw_bytes, 10); const size_t granularity = os::vm_allocation_granularity(); _reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity)); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/gc_implementation/shared/mutableSpace.cpp --- a/src/share/vm/gc_implementation/shared/mutableSpace.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/gc_implementation/shared/mutableSpace.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -62,9 +62,7 @@ } void MutableSpace::pretouch_pages(MemRegion mr) { - for (volatile char *p = (char*)mr.start(); p < (char*)mr.end(); p += os::vm_page_size()) { - char t = *p; *p = t; - } + os::pretouch_memory((char*)mr.start(), (char*)mr.end()); } void MutableSpace::initialize(MemRegion mr, diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/interpreter/linkResolver.cpp --- a/src/share/vm/interpreter/linkResolver.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/interpreter/linkResolver.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -1410,10 +1410,11 @@ KlassHandle resolved_klass, Symbol* name, Symbol* signature, - KlassHandle current_klass) { + KlassHandle current_klass, + bool check_access) { EXCEPTION_MARK; CallInfo info; - resolve_virtual_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, true, false, THREAD); + resolve_virtual_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, check_access, false, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return methodHandle(); @@ -1426,10 +1427,11 @@ KlassHandle resolved_klass, Symbol* name, Symbol* signature, - KlassHandle current_klass) { + KlassHandle current_klass, + bool check_access) { EXCEPTION_MARK; CallInfo info; - resolve_interface_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, true, false, THREAD); + resolve_interface_call(info, Handle(), receiver_klass, resolved_klass, name, signature, current_klass, check_access, false, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return methodHandle(); @@ -1457,10 +1459,11 @@ KlassHandle resolved_klass, Symbol* name, Symbol* signature, - KlassHandle current_klass) { + KlassHandle current_klass, + bool check_access) { EXCEPTION_MARK; CallInfo info; - resolve_static_call(info, resolved_klass, name, signature, current_klass, true, false, THREAD); + resolve_static_call(info, resolved_klass, name, signature, current_klass, check_access, false, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return methodHandle(); @@ -1468,11 +1471,15 @@ return info.selected_method(); } -methodHandle LinkResolver::resolve_special_call_or_null(KlassHandle resolved_klass, Symbol* name, Symbol* signature, - KlassHandle current_klass) { +methodHandle LinkResolver::resolve_special_call_or_null( + KlassHandle resolved_klass, + Symbol* name, + Symbol* signature, + KlassHandle current_klass, + bool check_access) { EXCEPTION_MARK; CallInfo info; - resolve_special_call(info, resolved_klass, name, signature, current_klass, true, THREAD); + resolve_special_call(info, resolved_klass, name, signature, current_klass, check_access, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; return methodHandle(); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/interpreter/linkResolver.hpp --- a/src/share/vm/interpreter/linkResolver.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/interpreter/linkResolver.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -181,10 +181,10 @@ // same as above for compile-time resolution; but returns null handle instead of throwing an exception on error // also, does not initialize klass (i.e., no side effects) - static methodHandle resolve_virtual_call_or_null (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass); - static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass); - static methodHandle resolve_static_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass); - static methodHandle resolve_special_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass); + static methodHandle resolve_virtual_call_or_null (KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true); + static methodHandle resolve_interface_call_or_null(KlassHandle receiver_klass, KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true); + static methodHandle resolve_static_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true); + static methodHandle resolve_special_call_or_null (KlassHandle resolved_klass, Symbol* method_name, Symbol* method_signature, KlassHandle current_klass, bool check_access = true); static int vtable_index_of_interface_method(KlassHandle klass, methodHandle resolved_method); // same as above for compile-time resolution; returns vtable_index if current_klass if linked diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/memory/heap.cpp --- a/src/share/vm/memory/heap.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/memory/heap.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -97,9 +97,13 @@ _log2_segment_size = exact_log2(segment_size); // Reserve and initialize space for _memory. - const size_t page_size = os::can_execute_large_page_memory() ? - os::page_size_for_region(committed_size, reserved_size, 8) : - os::vm_page_size(); + size_t page_size = os::vm_page_size(); + if (os::can_execute_large_page_memory()) { + const size_t min_pages = 8; + page_size = MIN2(os::page_size_for_region_aligned(committed_size, min_pages), + os::page_size_for_region_aligned(reserved_size, min_pages)); + } + const size_t granularity = os::vm_allocation_granularity(); const size_t r_align = MAX2(page_size, granularity); const size_t r_size = align_size_up(reserved_size, r_align); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/oops/cpCache.cpp --- a/src/share/vm/oops/cpCache.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/oops/cpCache.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -604,44 +604,6 @@ // RedefineClasses() API support: // If any entry of this ConstantPoolCache points to any of // old_methods, replace it with the corresponding new_method. -void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new_methods, - int methods_length, bool * trace_name_printed) { - - if (methods_length == 0) { - // nothing to do if there are no methods - return; - } - - // get shorthand for the interesting class - Klass* old_holder = old_methods[0]->method_holder(); - - for (int i = 0; i < length(); i++) { - if (entry_at(i)->get_interesting_method_entry(old_holder) == NULL) { - // skip uninteresting methods - continue; - } - - // The ConstantPoolCache contains entries for several different - // things, but we only care about methods. In fact, we only care - // about methods in the same class as the one that contains the - // old_methods. At this point, we have an interesting entry. - - for (int j = 0; j < methods_length; j++) { - Method* old_method = old_methods[j]; - Method* new_method = new_methods[j]; - - if (entry_at(i)->adjust_method_entry(old_method, new_method, - trace_name_printed)) { - // current old_method matched this entry and we updated it so - // break out and get to the next interesting entry if there one - break; - } - } - } -} - -// If any entry of this ConstantPoolCache points to any of -// old_methods, replace it with the corresponding new_method. void ConstantPoolCache::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) { for (int i = 0; i < length(); i++) { ConstantPoolCacheEntry* entry = entry_at(i); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/oops/cpCache.hpp --- a/src/share/vm/oops/cpCache.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/oops/cpCache.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -476,8 +476,6 @@ // trace_name_printed is set to true if the current call has // printed the klass name so that other routines in the adjust_* // group don't print the klass name. - void adjust_method_entries(Method** old_methods, Method** new_methods, - int methods_length, bool* trace_name_printed); void adjust_method_entries(InstanceKlass* holder, bool* trace_name_printed); bool check_no_old_or_obsolete_entries(); void dump_cache(); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/opto/callGenerator.cpp --- a/src/share/vm/opto/callGenerator.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/opto/callGenerator.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -859,7 +859,8 @@ // Parse::do_call()) target = C->optimize_virtual_call(caller, jvms->bci(), klass, klass, target, receiver_type, is_virtual, - call_does_dispatch, vtable_index); // out-parameters + call_does_dispatch, vtable_index, // out-parameters + /*check_access=*/false); // We lack profiling at this call but type speculation may // provide us with a type speculative_receiver_type = (receiver_type != NULL) ? receiver_type->speculative_type() : NULL; diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/opto/classes.hpp --- a/src/share/vm/opto/classes.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/opto/classes.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -199,6 +199,7 @@ macro(Opaque1) macro(Opaque2) macro(Opaque3) +macro(ProfileBoolean) macro(OrI) macro(OrL) macro(OverflowAddI) diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/opto/compile.cpp --- a/src/share/vm/opto/compile.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/opto/compile.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -3075,6 +3075,7 @@ default: assert( !n->is_Call(), "" ); assert( !n->is_Mem(), "" ); + assert( nop != Op_ProfileBoolean, "should be eliminated during IGVN"); break; } @@ -3291,6 +3292,9 @@ bool Compile::too_many_traps(ciMethod* method, int bci, Deoptimization::DeoptReason reason) { + if (method->has_injected_profile()) { + return false; + } ciMethodData* md = method->method_data(); if (md->is_empty()) { // Assume the trap has not occurred, or that it occurred only @@ -3340,6 +3344,9 @@ bool Compile::too_many_recompiles(ciMethod* method, int bci, Deoptimization::DeoptReason reason) { + if (method->has_injected_profile()) { + return false; + } ciMethodData* md = method->method_data(); if (md->is_empty()) { // Assume the trap has not occurred, or that it occurred only diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/opto/compile.hpp --- a/src/share/vm/opto/compile.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/opto/compile.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -861,9 +861,11 @@ ciMethod* optimize_virtual_call(ciMethod* caller, int bci, ciInstanceKlass* klass, ciKlass* holder, ciMethod* callee, const TypeOopPtr* receiver_type, bool is_virtual, - bool &call_does_dispatch, int &vtable_index); + bool &call_does_dispatch, int &vtable_index, + bool check_access = true); ciMethod* optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass* klass, - ciMethod* callee, const TypeOopPtr* receiver_type); + ciMethod* callee, const TypeOopPtr* receiver_type, + bool check_access = true); // Report if there were too many traps at a current method and bci. // Report if a trap was recorded, and/or PerMethodTrapLimit was exceeded. diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/opto/connode.cpp --- a/src/share/vm/opto/connode.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/opto/connode.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -1338,6 +1338,30 @@ return (&n == this); // Always fail except on self } +//============================================================================= + +uint ProfileBooleanNode::hash() const { return NO_HASH; } +uint ProfileBooleanNode::cmp( const Node &n ) const { + return (&n == this); +} + +Node *ProfileBooleanNode::Ideal(PhaseGVN *phase, bool can_reshape) { + if (can_reshape && _delay_removal) { + _delay_removal = false; + return this; + } else { + return NULL; + } +} + +Node *ProfileBooleanNode::Identity( PhaseTransform *phase ) { + if (_delay_removal) { + return this; + } else { + assert(_consumed, "profile should be consumed before elimination"); + return in(1); + } +} //------------------------------Value------------------------------------------ const Type *MoveL2DNode::Value( PhaseTransform *phase ) const { diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/opto/connode.hpp --- a/src/share/vm/opto/connode.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/opto/connode.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -669,6 +669,31 @@ bool rtm_opt() const { return (_opt == RTM_OPT); } }; +//------------------------------ProfileBooleanNode------------------------------- +// A node represents value profile for a boolean during parsing. +// Once parsing is over, the node goes away (during IGVN). +// It is used to override branch frequencies from MDO (see has_injected_profile in parse2.cpp). +class ProfileBooleanNode : public Node { + uint _false_cnt; + uint _true_cnt; + bool _consumed; + bool _delay_removal; + virtual uint hash() const ; // { return NO_HASH; } + virtual uint cmp( const Node &n ) const; + public: + ProfileBooleanNode(Node *n, uint false_cnt, uint true_cnt) : Node(0, n), + _false_cnt(false_cnt), _true_cnt(true_cnt), _delay_removal(true), _consumed(false) {} + + uint false_count() const { return _false_cnt; } + uint true_count() const { return _true_cnt; } + + void consume() { _consumed = true; } + + virtual int Opcode() const; + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual Node *Identity(PhaseTransform *phase); + virtual const Type *bottom_type() const { return TypeInt::BOOL; } +}; //----------------------PartialSubtypeCheckNode-------------------------------- // The 2nd slow-half of a subtype check. Scan the subklass's 2ndary superklass diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/opto/doCall.cpp --- a/src/share/vm/opto/doCall.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/opto/doCall.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -956,13 +956,15 @@ ciMethod* Compile::optimize_virtual_call(ciMethod* caller, int bci, ciInstanceKlass* klass, ciKlass* holder, ciMethod* callee, const TypeOopPtr* receiver_type, bool is_virtual, - bool& call_does_dispatch, int& vtable_index) { + bool& call_does_dispatch, int& vtable_index, + bool check_access) { // Set default values for out-parameters. call_does_dispatch = true; vtable_index = Method::invalid_vtable_index; // Choose call strategy. - ciMethod* optimized_virtual_method = optimize_inlining(caller, bci, klass, callee, receiver_type); + ciMethod* optimized_virtual_method = optimize_inlining(caller, bci, klass, callee, + receiver_type, check_access); // Have the call been sufficiently improved such that it is no longer a virtual? if (optimized_virtual_method != NULL) { @@ -977,7 +979,8 @@ // Identify possible target method and inlining style ciMethod* Compile::optimize_inlining(ciMethod* caller, int bci, ciInstanceKlass* klass, - ciMethod* callee, const TypeOopPtr* receiver_type) { + ciMethod* callee, const TypeOopPtr* receiver_type, + bool check_access) { // only use for virtual or interface calls // If it is obviously final, do not bother to call find_monomorphic_target, @@ -1017,7 +1020,7 @@ } ciInstanceKlass* calling_klass = caller->holder(); - ciMethod* cha_monomorphic_target = callee->find_monomorphic_target(calling_klass, klass, actual_receiver); + ciMethod* cha_monomorphic_target = callee->find_monomorphic_target(calling_klass, klass, actual_receiver, check_access); if (cha_monomorphic_target != NULL) { assert(!cha_monomorphic_target->is_abstract(), ""); // Look at the method-receiver type. Does it add "too much information"? diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/opto/graphKit.cpp --- a/src/share/vm/opto/graphKit.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/opto/graphKit.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -1980,6 +1980,11 @@ Deoptimization::trap_request_index(trap_request) < 0 && too_many_recompiles(reason)) { // This BCI is causing too many recompilations. + if (C->log() != NULL) { + C->log()->elem("observe that='trap_action_change' reason='%s' from='%s' to='none'", + Deoptimization::trap_reason_name(reason), + Deoptimization::trap_action_name(action)); + } action = Deoptimization::Action_none; trap_request = Deoptimization::make_trap_request(reason, action); } else { @@ -2742,7 +2747,7 @@ Deoptimization::DeoptReason reason = spec_klass == NULL ? Deoptimization::Reason_class_check : Deoptimization::Reason_speculate_class_check; // Make sure we haven't already deoptimized from this tactic. - if (too_many_traps(reason)) + if (too_many_traps(reason) || too_many_recompiles(reason)) return NULL; // (No, this isn't a call, but it's enough like a virtual call @@ -2764,8 +2769,7 @@ &exact_obj); { PreserveJVMState pjvms(this); set_control(slow_ctl); - uncommon_trap(reason, - Deoptimization::Action_maybe_recompile); + uncommon_trap_exact(reason, Deoptimization::Action_maybe_recompile); } if (safe_for_replace) { replace_in_map(not_null_obj, exact_obj); @@ -2793,8 +2797,8 @@ if (type != NULL) { Deoptimization::DeoptReason class_reason = Deoptimization::Reason_speculate_class_check; Deoptimization::DeoptReason null_reason = Deoptimization::Reason_null_check; - if (!too_many_traps(null_reason) && - !too_many_traps(class_reason)) { + if (!too_many_traps(null_reason) && !too_many_recompiles(null_reason) && + !too_many_traps(class_reason) && !too_many_recompiles(class_reason)) { Node* not_null_obj = NULL; // not_null is true if we know the object is not null and // there's no need for a null check @@ -2813,14 +2817,14 @@ { PreserveJVMState pjvms(this); set_control(slow_ctl); - uncommon_trap(class_reason, - Deoptimization::Action_maybe_recompile); + uncommon_trap_exact(class_reason, Deoptimization::Action_maybe_recompile); } replace_in_map(not_null_obj, exact_obj); obj = exact_obj; } } else { - if (!too_many_traps(Deoptimization::Reason_null_assert)) { + if (!too_many_traps(Deoptimization::Reason_null_assert) && + !too_many_recompiles(Deoptimization::Reason_null_assert)) { Node* exact_obj = null_assert(obj); replace_in_map(obj, exact_obj); obj = exact_obj; diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/opto/graphKit.hpp --- a/src/share/vm/opto/graphKit.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/opto/graphKit.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -708,6 +708,15 @@ klass, reason_string, must_throw, keep_exact_action); } + // Bail out to the interpreter and keep exact action (avoid switching to Action_none). + void uncommon_trap_exact(Deoptimization::DeoptReason reason, + Deoptimization::DeoptAction action, + ciKlass* klass = NULL, const char* reason_string = NULL, + bool must_throw = false) { + uncommon_trap(Deoptimization::make_trap_request(reason, action), + klass, reason_string, must_throw, /*keep_exact_action=*/true); + } + // SP when bytecode needs to be reexecuted. virtual int reexecute_sp() { return sp(); } diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/opto/library_call.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -31,6 +31,7 @@ #include "opto/addnode.hpp" #include "opto/callGenerator.hpp" #include "opto/cfgnode.hpp" +#include "opto/connode.hpp" #include "opto/idealKit.hpp" #include "opto/mathexactnode.hpp" #include "opto/mulnode.hpp" @@ -323,6 +324,8 @@ bool inline_updateBytesCRC32(); bool inline_updateByteBufferCRC32(); bool inline_multiplyToLen(); + + bool inline_profileBoolean(); }; @@ -934,6 +937,9 @@ case vmIntrinsics::_updateByteBufferCRC32: return inline_updateByteBufferCRC32(); + case vmIntrinsics::_profileBoolean: + return inline_profileBoolean(); + default: // If you get here, it may be that someone has added a new intrinsic // to the list in vmSymbols.hpp without implementing it here. @@ -6544,3 +6550,81 @@ return instof_false; // even if it is NULL } + +bool LibraryCallKit::inline_profileBoolean() { + Node* counts = argument(1); + const TypeAryPtr* ary = NULL; + ciArray* aobj = NULL; + if (counts->is_Con() + && (ary = counts->bottom_type()->isa_aryptr()) != NULL + && (aobj = ary->const_oop()->as_array()) != NULL + && (aobj->length() == 2)) { + // Profile is int[2] where [0] and [1] correspond to false and true value occurrences respectively. + jint false_cnt = aobj->element_value(0).as_int(); + jint true_cnt = aobj->element_value(1).as_int(); + + method()->set_injected_profile(true); + + if (C->log() != NULL) { + C->log()->elem("observe source='profileBoolean' false='%d' true='%d'", + false_cnt, true_cnt); + } + + if (false_cnt + true_cnt == 0) { + // According to profile, never executed. + uncommon_trap_exact(Deoptimization::Reason_intrinsic, + Deoptimization::Action_reinterpret); + return true; + } + + // result is a boolean (0 or 1) and its profile (false_cnt & true_cnt) + // is a number of each value occurrences. + Node* result = argument(0); + if (false_cnt == 0 || true_cnt == 0) { + // According to profile, one value has been never seen. + int expected_val = (false_cnt == 0) ? 1 : 0; + + Node* cmp = _gvn.transform(new (C) CmpINode(result, intcon(expected_val))); + Node* test = _gvn.transform(new (C) BoolNode(cmp, BoolTest::eq)); + + IfNode* check = create_and_map_if(control(), test, PROB_ALWAYS, COUNT_UNKNOWN); + Node* fast_path = _gvn.transform(new (C) IfTrueNode(check)); + Node* slow_path = _gvn.transform(new (C) IfFalseNode(check)); + + { // Slow path: uncommon trap for never seen value and then reexecute + // MethodHandleImpl::profileBoolean() to bump the count, so JIT knows + // the value has been seen at least once. + PreserveJVMState pjvms(this); + PreserveReexecuteState preexecs(this); + jvms()->set_should_reexecute(true); + + set_control(slow_path); + set_i_o(i_o()); + + uncommon_trap_exact(Deoptimization::Reason_intrinsic, + Deoptimization::Action_reinterpret); + } + // The guard for never seen value enables sharpening of the result and + // returning a constant. It allows to eliminate branches on the same value + // later on. + set_control(fast_path); + result = intcon(expected_val); + } + // Stop profiling. + // MethodHandleImpl::profileBoolean() has profiling logic in its bytecode. + // By replacing method body with profile data (represented as ProfileBooleanNode + // on IR level) we effectively disable profiling. + // It enables full speed execution once optimized code is generated. + Node* profile = _gvn.transform(new (C) ProfileBooleanNode(result, false_cnt, true_cnt)); + C->record_for_igvn(profile); + set_result(profile); + return true; + } else { + // Continue profiling. + // Profile data isn't available at the moment. So, execute method's bytecode version. + // Usually, when GWT LambdaForms are profiled it means that a stand-alone nmethod + // is compiled and counters aren't available since corresponding MethodHandle + // isn't a compile-time constant. + return false; + } +} diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/opto/parse.hpp --- a/src/share/vm/opto/parse.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/opto/parse.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -549,8 +549,8 @@ void do_jsr(); void do_ret(); - float dynamic_branch_prediction(float &cnt); - float branch_prediction(float &cnt, BoolTest::mask btest, int target_bci); + float dynamic_branch_prediction(float &cnt, BoolTest::mask btest, Node* test); + float branch_prediction(float &cnt, BoolTest::mask btest, int target_bci, Node* test); bool seems_never_taken(float prob) const; bool path_is_suitable_for_uncommon_trap(float prob) const; bool seems_stable_comparison() const; diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/opto/parse2.cpp --- a/src/share/vm/opto/parse2.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/opto/parse2.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -761,35 +761,64 @@ merge_common(target, pnum); } +static bool has_injected_profile(BoolTest::mask btest, Node* test, int& taken, int& not_taken) { + if (btest != BoolTest::eq && btest != BoolTest::ne) { + // Only ::eq and ::ne are supported for profile injection. + return false; + } + if (test->is_Cmp() && + test->in(1)->Opcode() == Op_ProfileBoolean) { + ProfileBooleanNode* profile = (ProfileBooleanNode*)test->in(1); + int false_cnt = profile->false_count(); + int true_cnt = profile->true_count(); + + // Counts matching depends on the actual test operation (::eq or ::ne). + // No need to scale the counts because profile injection was designed + // to feed exact counts into VM. + taken = (btest == BoolTest::eq) ? false_cnt : true_cnt; + not_taken = (btest == BoolTest::eq) ? true_cnt : false_cnt; + + profile->consume(); + return true; + } + return false; +} //--------------------------dynamic_branch_prediction-------------------------- // Try to gather dynamic branch prediction behavior. Return a probability // of the branch being taken and set the "cnt" field. Returns a -1.0 // if we need to use static prediction for some reason. -float Parse::dynamic_branch_prediction(float &cnt) { +float Parse::dynamic_branch_prediction(float &cnt, BoolTest::mask btest, Node* test) { ResourceMark rm; cnt = COUNT_UNKNOWN; - // Use MethodData information if it is available - // FIXME: free the ProfileData structure - ciMethodData* methodData = method()->method_data(); - if (!methodData->is_mature()) return PROB_UNKNOWN; - ciProfileData* data = methodData->bci_to_data(bci()); - if (!data->is_JumpData()) return PROB_UNKNOWN; + int taken = 0; + int not_taken = 0; + + bool use_mdo = !has_injected_profile(btest, test, taken, not_taken); - // get taken and not taken values - int taken = data->as_JumpData()->taken(); - int not_taken = 0; - if (data->is_BranchData()) { - not_taken = data->as_BranchData()->not_taken(); + if (use_mdo) { + // Use MethodData information if it is available + // FIXME: free the ProfileData structure + ciMethodData* methodData = method()->method_data(); + if (!methodData->is_mature()) return PROB_UNKNOWN; + ciProfileData* data = methodData->bci_to_data(bci()); + if (!data->is_JumpData()) return PROB_UNKNOWN; + + // get taken and not taken values + taken = data->as_JumpData()->taken(); + not_taken = 0; + if (data->is_BranchData()) { + not_taken = data->as_BranchData()->not_taken(); + } + + // scale the counts to be commensurate with invocation counts: + taken = method()->scale_count(taken); + not_taken = method()->scale_count(not_taken); } - // scale the counts to be commensurate with invocation counts: - taken = method()->scale_count(taken); - not_taken = method()->scale_count(not_taken); - // Give up if too few (or too many, in which case the sum will overflow) counts to be meaningful. - // We also check that individual counters are positive first, overwise the sum can become positive. + // We also check that individual counters are positive first, otherwise the sum can become positive. if (taken < 0 || not_taken < 0 || taken + not_taken < 40) { if (C->log() != NULL) { C->log()->elem("branch target_bci='%d' taken='%d' not_taken='%d'", iter().get_dest(), taken, not_taken); @@ -839,8 +868,9 @@ //-----------------------------branch_prediction------------------------------- float Parse::branch_prediction(float& cnt, BoolTest::mask btest, - int target_bci) { - float prob = dynamic_branch_prediction(cnt); + int target_bci, + Node* test) { + float prob = dynamic_branch_prediction(cnt, btest, test); // If prob is unknown, switch to static prediction if (prob != PROB_UNKNOWN) return prob; @@ -930,7 +960,7 @@ Block* next_block = successor_for_bci(iter().next_bci()); float cnt; - float prob = branch_prediction(cnt, btest, target_bci); + float prob = branch_prediction(cnt, btest, target_bci, c); if (prob == PROB_UNKNOWN) { // (An earlier version of do_ifnull omitted this trap for OSR methods.) #ifndef PRODUCT @@ -1011,7 +1041,7 @@ Block* next_block = successor_for_bci(iter().next_bci()); float cnt; - float prob = branch_prediction(cnt, btest, target_bci); + float prob = branch_prediction(cnt, btest, target_bci, c); float untaken_prob = 1.0 - prob; if (prob == PROB_UNKNOWN) { diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/prims/jni.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -5071,6 +5071,7 @@ unit_test_function_call // Forward declaration +void TestOS_test(); void TestReservedSpace_test(); void TestReserveMemorySpecial_test(); void TestVirtualSpace_test(); @@ -5092,6 +5093,7 @@ void execute_internal_vm_tests() { if (ExecuteInternalVMTests) { tty->print_cr("Running internal VM tests"); + run_unit_test(TestOS_test()); run_unit_test(TestReservedSpace_test()); run_unit_test(TestReserveMemorySpecial_test()); run_unit_test(TestVirtualSpace_test()); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -3433,10 +3433,7 @@ other_cp = pv_node->prev_constant_pool(); cp_cache = other_cp->cache(); if (cp_cache != NULL) { - cp_cache->adjust_method_entries(_matching_old_methods, - _matching_new_methods, - _matching_methods_length, - &trace_name_printed); + cp_cache->adjust_method_entries(other_cp->pool_holder(), &trace_name_printed); } } } @@ -4071,10 +4068,7 @@ MemberNameTable* mnt = the_class->member_names(); if (mnt != NULL) { bool trace_name_printed = false; - mnt->adjust_method_entries(_matching_old_methods, - _matching_new_methods, - _matching_methods_length, - &trace_name_printed); + mnt->adjust_method_entries(the_class(), &trace_name_printed); } // Fix Resolution Error table also to remove old constant pools diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/prims/methodHandles.cpp --- a/src/share/vm/prims/methodHandles.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/prims/methodHandles.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -30,6 +30,7 @@ #include "memory/allocation.inline.hpp" #include "memory/oopFactory.hpp" #include "prims/methodHandles.hpp" +#include "prims/jvmtiRedefineClassesTrace.hpp" #include "runtime/compilationPolicy.hpp" #include "runtime/javaCalls.hpp" #include "runtime/reflection.hpp" @@ -955,21 +956,41 @@ #if INCLUDE_JVMTI // It is called at safepoint only for RedefineClasses -void MemberNameTable::adjust_method_entries(Method** old_methods, Method** new_methods, - int methods_length, bool *trace_name_printed) { +void MemberNameTable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) { assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint"); // For each redefined method - for (int j = 0; j < methods_length; j++) { - Method* old_method = old_methods[j]; - Method* new_method = new_methods[j]; + for (int idx = 0; idx < length(); idx++) { + oop mem_name = JNIHandles::resolve(this->at(idx)); + if (mem_name == NULL) { + continue; + } + Method* old_method = (Method*)java_lang_invoke_MemberName::vmtarget(mem_name); + + if (old_method == NULL || !old_method->is_old()) { + continue; // skip uninteresting entries + } + if (old_method->is_deleted()) { + // skip entries with deleted methods + continue; + } + Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum()); - // search the MemberNameTable for uses of either obsolete or EMCP methods - for (int idx = 0; idx < length(); idx++) { - oop mem_name = JNIHandles::resolve(this->at(idx)); - if (mem_name != NULL) { - java_lang_invoke_MemberName::adjust_vmtarget(mem_name, old_method, new_method, - trace_name_printed); + assert(new_method != NULL, "method_with_idnum() should not be NULL"); + assert(old_method != new_method, "sanity check"); + + java_lang_invoke_MemberName::set_vmtarget(mem_name, new_method); + + if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) { + if (!(*trace_name_printed)) { + // RC_TRACE_MESG macro has an embedded ResourceMark + RC_TRACE_MESG(("adjust: name=%s", + old_method->method_holder()->external_name())); + *trace_name_printed = true; } + // RC_TRACE macro has an embedded ResourceMark + RC_TRACE(0x00400000, ("MemberName method update: %s(%s)", + new_method->name()->as_C_string(), + new_method->signature()->as_C_string())); } } } diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/prims/methodHandles.hpp --- a/src/share/vm/prims/methodHandles.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/prims/methodHandles.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -240,10 +240,8 @@ #if INCLUDE_JVMTI // RedefineClasses() API support: - // If a MemberName refers to old_method then update it - // to refer to new_method. - void adjust_method_entries(Method** old_methods, Method** new_methods, - int methods_length, bool *trace_name_printed); + // If a MemberName refers to old_method then update it to refer to new_method. + void adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed); #endif // INCLUDE_JVMTI }; diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/prims/whitebox.cpp --- a/src/share/vm/prims/whitebox.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/prims/whitebox.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -73,6 +73,13 @@ return heapOopSize; WB_END +WB_ENTRY(jint, WB_GetVMPageSize(JNIEnv* env, jobject o)) + return os::vm_page_size(); +WB_END + +WB_ENTRY(jlong, WB_GetVMLargePageSize(JNIEnv* env, jobject o)) + return os::large_page_size(); +WB_END class WBIsKlassAliveClosure : public KlassClosure { Symbol* _name; @@ -884,6 +891,16 @@ return (jlong) MetaspaceGC::capacity_until_GC(); WB_END +WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj)) + oop obj_oop = JNIHandles::resolve(obj); + return (jboolean) obj_oop->mark()->has_monitor(); +WB_END + +WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb)) + VM_ForceSafepoint force_safepoint_op; + VMThread::execute(&force_safepoint_op); +WB_END + //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, Symbol* signature_symbol) { @@ -906,7 +923,7 @@ if (res == NULL) { tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string()); - fatal("Invalid layout of preloaded class"); + vm_exit_during_initialization("Invalid layout of preloaded class: use -XX:+TraceClassLoading to see the origin of the problem class"); } //fetch the field at the offset we've found @@ -972,6 +989,8 @@ {CC"getObjectSize", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectSize }, {CC"isObjectInOldGen", CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen }, {CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize }, + {CC"getVMPageSize", CC"()I", (void*)&WB_GetVMPageSize }, + {CC"getVMLargePageSize", CC"()J", (void*)&WB_GetVMLargePageSize}, {CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive }, {CC"classKnownToNotExist", CC"(Ljava/lang/ClassLoader;Ljava/lang/String;)Z",(void*)&WB_ClassKnownToNotExist}, @@ -1067,6 +1086,8 @@ {CC"getCPUFeatures", CC"()Ljava/lang/String;", (void*)&WB_GetCPUFeatures }, {CC"getNMethod", CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;", (void*)&WB_GetNMethod }, + {CC"isMonitorInflated", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated }, + {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint }, }; #undef CC diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/runtime/os.cpp --- a/src/share/vm/runtime/os.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/runtime/os.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -1315,24 +1315,17 @@ return (sp > (stack_limit + reserved_area)); } -size_t os::page_size_for_region(size_t region_min_size, size_t region_max_size, - uint min_pages) -{ +size_t os::page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned) { assert(min_pages > 0, "sanity"); if (UseLargePages) { - const size_t max_page_size = region_max_size / min_pages; + const size_t max_page_size = region_size / min_pages; - for (unsigned int i = 0; _page_sizes[i] != 0; ++i) { - const size_t sz = _page_sizes[i]; - const size_t mask = sz - 1; - if ((region_min_size & mask) == 0 && (region_max_size & mask) == 0) { - // The largest page size with no fragmentation. - return sz; - } - - if (sz <= max_page_size) { - // The largest page size that satisfies the min_pages requirement. - return sz; + for (size_t i = 0; _page_sizes[i] != 0; ++i) { + const size_t page_size = _page_sizes[i]; + if (page_size <= max_page_size) { + if (!must_be_aligned || is_size_aligned(region_size, page_size)) { + return page_size; + } } } } @@ -1340,6 +1333,14 @@ return vm_page_size(); } +size_t os::page_size_for_region_aligned(size_t region_size, size_t min_pages) { + return page_size_for_region(region_size, min_pages, true); +} + +size_t os::page_size_for_region_unaligned(size_t region_size, size_t min_pages) { + return page_size_for_region(region_size, min_pages, false); +} + #ifndef PRODUCT void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count) { @@ -1513,6 +1514,11 @@ return res; } +void os::pretouch_memory(char* start, char* end) { + for (volatile char *p = start; p < end; p += os::vm_page_size()) { + *p = 0; + } +} char* os::map_memory(int fd, const char* file_name, size_t file_offset, char *addr, size_t bytes, bool read_only, @@ -1569,3 +1575,95 @@ return result; } #endif + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT + +#define assert_eq(a,b) assert(a == b, err_msg(SIZE_FORMAT " != " SIZE_FORMAT, a, b)) + +class TestOS : AllStatic { + static size_t small_page_size() { + return os::vm_page_size(); + } + + static size_t large_page_size() { + const size_t large_page_size_example = 4 * M; + return os::page_size_for_region_aligned(large_page_size_example, 1); + } + + static void test_page_size_for_region_aligned() { + if (UseLargePages) { + const size_t small_page = small_page_size(); + const size_t large_page = large_page_size(); + + if (large_page > small_page) { + size_t num_small_pages_in_large = large_page / small_page; + size_t page = os::page_size_for_region_aligned(large_page, num_small_pages_in_large); + + assert_eq(page, small_page); + } + } + } + + static void test_page_size_for_region_alignment() { + if (UseLargePages) { + const size_t small_page = small_page_size(); + const size_t large_page = large_page_size(); + if (large_page > small_page) { + const size_t unaligned_region = large_page + 17; + size_t page = os::page_size_for_region_aligned(unaligned_region, 1); + assert_eq(page, small_page); + + const size_t num_pages = 5; + const size_t aligned_region = large_page * num_pages; + page = os::page_size_for_region_aligned(aligned_region, num_pages); + assert_eq(page, large_page); + } + } + } + + static void test_page_size_for_region_unaligned() { + if (UseLargePages) { + // Given exact page size, should return that page size. + for (size_t i = 0; os::_page_sizes[i] != 0; i++) { + size_t expected = os::_page_sizes[i]; + size_t actual = os::page_size_for_region_unaligned(expected, 1); + assert_eq(expected, actual); + } + + // Given slightly larger size than a page size, return the page size. + for (size_t i = 0; os::_page_sizes[i] != 0; i++) { + size_t expected = os::_page_sizes[i]; + size_t actual = os::page_size_for_region_unaligned(expected + 17, 1); + assert_eq(expected, actual); + } + + // Given a slightly smaller size than a page size, + // return the next smaller page size. + if (os::_page_sizes[1] > os::_page_sizes[0]) { + size_t expected = os::_page_sizes[0]; + size_t actual = os::page_size_for_region_unaligned(os::_page_sizes[1] - 17, 1); + assert_eq(actual, expected); + } + + // Return small page size for values less than a small page. + size_t small_page = small_page_size(); + size_t actual = os::page_size_for_region_unaligned(small_page - 17, 1); + assert_eq(small_page, actual); + } + } + + public: + static void run_tests() { + test_page_size_for_region_aligned(); + test_page_size_for_region_alignment(); + test_page_size_for_region_unaligned(); + } +}; + +void TestOS_test() { + TestOS::run_tests(); +} + +#endif // PRODUCT diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/runtime/os.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -149,6 +149,7 @@ static void pd_free_memory(char *addr, size_t bytes, size_t alignment_hint); static void pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint); + static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned); public: static void init(void); // Called before command line parsing @@ -265,19 +266,16 @@ // Return the default page size. static int vm_page_size(); - // Return the page size to use for a region of memory. The min_pages argument - // is a hint intended to limit fragmentation; it says the returned page size - // should be <= region_max_size / min_pages. Because min_pages is a hint, - // this routine may return a size larger than region_max_size / min_pages. - // - // The current implementation ignores min_pages if a larger page size is an - // exact multiple of both region_min_size and region_max_size. This allows - // larger pages to be used when doing so would not cause fragmentation; in - // particular, a single page can be used when region_min_size == - // region_max_size == a supported page size. - static size_t page_size_for_region(size_t region_min_size, - size_t region_max_size, - uint min_pages); + // Returns the page size to use for a region of memory. + // region_size / min_pages will always be greater than or equal to the + // returned value. The returned value will divide region_size. + static size_t page_size_for_region_aligned(size_t region_size, size_t min_pages); + + // Returns the page size to use for a region of memory. + // region_size / min_pages will always be greater than or equal to the + // returned value. The returned value might not divide region_size. + static size_t page_size_for_region_unaligned(size_t region_size, size_t min_pages); + // Return the largest page size that can be used static size_t max_page_size() { // The _page_sizes array is sorted in descending order. @@ -319,6 +317,12 @@ static bool uncommit_memory(char* addr, size_t bytes); static bool release_memory(char* addr, size_t bytes); + // Touch memory pages that cover the memory range from start to end (exclusive) + // to make the OS back the memory range with actual memory. + // Current implementation may not touch the last page if unaligned addresses + // are passed. + static void pretouch_memory(char* start, char* end); + enum ProtType { MEM_PROT_NONE, MEM_PROT_READ, MEM_PROT_RW, MEM_PROT_RWX }; static bool protect_memory(char* addr, size_t bytes, ProtType prot, bool is_committed = true); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/runtime/virtualspace.cpp --- a/src/share/vm/runtime/virtualspace.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/runtime/virtualspace.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -52,12 +52,22 @@ _alignment(0), _special(false), _executable(false) { } -ReservedSpace::ReservedSpace(size_t size) { - size_t page_size = os::page_size_for_region(size, size, 1); +ReservedSpace::ReservedSpace(size_t size, size_t preferred_page_size) { + bool has_preferred_page_size = preferred_page_size != 0; + // Want to use large pages where possible and pad with small pages. + size_t page_size = has_preferred_page_size ? preferred_page_size : os::page_size_for_region_unaligned(size, 1); bool large_pages = page_size != (size_t)os::vm_page_size(); - // Don't force the alignment to be large page aligned, - // since that will waste memory. - size_t alignment = os::vm_allocation_granularity(); + size_t alignment; + if (large_pages && has_preferred_page_size) { + alignment = MAX2(page_size, (size_t)os::vm_allocation_granularity()); + // ReservedSpace initialization requires size to be aligned to the given + // alignment. Align the size up. + size = align_size_up(size, alignment); + } else { + // Don't force the alignment to be large page aligned, + // since that will waste memory. + alignment = os::vm_allocation_granularity(); + } initialize(size, alignment, large_pages, NULL, 0, false); } @@ -372,7 +382,7 @@ bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) { - const size_t max_commit_granularity = os::page_size_for_region(rs.size(), rs.size(), 1); + const size_t max_commit_granularity = os::page_size_for_region_unaligned(rs.size(), 1); return initialize_with_granularity(rs, committed_size, max_commit_granularity); } @@ -630,19 +640,7 @@ } if (pre_touch || AlwaysPreTouch) { - int vm_ps = os::vm_page_size(); - for (char* curr = previous_high; - curr < unaligned_new_high; - curr += vm_ps) { - // Note the use of a write here; originally we tried just a read, but - // since the value read was unused, the optimizer removed the read. - // If we ever have a concurrent touchahead thread, we'll want to use - // a read, to avoid the potential of overwriting data (if a mutator - // thread beats the touchahead thread to a page). There are various - // ways of making sure this read is not optimized away: for example, - // generating the code for a read procedure at runtime. - *curr = 0; - } + os::pretouch_memory(previous_high, unaligned_new_high); } _high += bytes; @@ -1007,7 +1005,7 @@ case Disable: return vs.initialize_with_granularity(rs, 0, os::vm_page_size()); case Commit: - return vs.initialize_with_granularity(rs, 0, os::page_size_for_region(rs.size(), rs.size(), 1)); + return vs.initialize_with_granularity(rs, 0, os::page_size_for_region_unaligned(rs.size(), 1)); } } diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/runtime/virtualspace.hpp --- a/src/share/vm/runtime/virtualspace.hpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/runtime/virtualspace.hpp Thu Apr 30 14:58:53 2015 -0700 @@ -54,7 +54,11 @@ public: // Constructor ReservedSpace(); - ReservedSpace(size_t size); + // Initialize the reserved space with the given size. If preferred_page_size + // is set, use this as minimum page size/alignment. This may waste some space + // if the given size is not aligned to that value, as the reservation will be + // aligned up to the final alignment in this case. + ReservedSpace(size_t size, size_t preferred_page_size = 0); ReservedSpace(size_t size, size_t alignment, bool large, char* requested_address = NULL, const size_t noaccess_prefix = 0); diff -r b0f52462883d -r 1f0d760ccac1 src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Wed Apr 29 12:16:38 2015 -0700 +++ b/src/share/vm/utilities/vmError.cpp Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ -1013,7 +1013,9 @@ out.print_raw (cmd); out.print_raw_cr("\" ..."); - os::fork_and_exec(cmd); + if (os::fork_and_exec(cmd) < 0) { + out.print_cr("os::fork_and_exec failed: %s (%d)", strerror(errno), errno); + } } // done with OnError @@ -1098,7 +1100,9 @@ #endif tty->print_cr("\"%s\"...", cmd); - os::fork_and_exec(cmd); + if (os::fork_and_exec(cmd) < 0) { + tty->print_cr("os::fork_and_exec failed: %s (%d)", strerror(errno), errno); + } } } diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/codegen/LoadWithMask.java --- a/test/compiler/codegen/LoadWithMask.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/codegen/LoadWithMask.java Thu Apr 30 14:58:53 2015 -0700 @@ -25,7 +25,7 @@ * @test * @bug 8032207 * @summary Invalid node sizing for loadUS2L_immI16 and loadI2L_immI - * @run main/othervm -server -Xbatch -XX:-TieredCompilation -XX:CompileCommand=compileonly,LoadWithMask.foo LoadWithMask + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,LoadWithMask.foo LoadWithMask * */ public class LoadWithMask { diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/codegen/LoadWithMask2.java --- a/test/compiler/codegen/LoadWithMask2.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/codegen/LoadWithMask2.java Thu Apr 30 14:58:53 2015 -0700 @@ -25,7 +25,7 @@ * @test * @bug 8031743 * @summary loadI2L_immI broken for negative memory values - * @run main/othervm -server -Xbatch -XX:-TieredCompilation -XX:CompileCommand=compileonly,*.foo* LoadWithMask2 + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,*.foo* LoadWithMask2 * */ public class LoadWithMask2 { diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/jsr292/MHInlineTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/jsr292/MHInlineTest.java Thu Apr 30 14:58:53 2015 -0700 @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2015, 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 8062280 + * @summary C2: inlining failure due to access checks being too strict + * @library /testlibrary + * @run main/othervm MHInlineTest + */ +import java.lang.invoke.*; +import com.oracle.java.testlibrary.*; +import static com.oracle.java.testlibrary.Asserts.*; + +public class MHInlineTest { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+IgnoreUnrecognizedVMOptions", "-showversion", + "-server", "-XX:-TieredCompilation", "-Xbatch", + "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining", + "-XX:CompileCommand=dontinline,MHInlineTest::test*", + "MHInlineTest$Launcher"); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); + + // The test is applicable only to C2 (present in Server VM). + if (analyzer.getStderr().contains("Server VM")) { + analyzer.shouldContain("MHInlineTest$B::public_x (3 bytes) inline (hot)"); + analyzer.shouldContain( "MHInlineTest$B::protected_x (3 bytes) inline (hot)"); + analyzer.shouldContain( "MHInlineTest$B::package_x (3 bytes) inline (hot)"); + analyzer.shouldContain("MHInlineTest$A::package_final_x (3 bytes) inline (hot)"); + analyzer.shouldContain("MHInlineTest$B::private_x (3 bytes) inline (hot)"); + analyzer.shouldContain("MHInlineTest$B::private_static_x (3 bytes) inline (hot)"); + analyzer.shouldContain("MHInlineTest$A::package_static_x (3 bytes) inline (hot)"); + + analyzer.shouldNotContain("MHInlineTest$A::protected_x (3 bytes) virtual call"); + analyzer.shouldNotContain("MHInlineTest$A::package_x (3 bytes) virtual call"); + } + } + + static class A { + public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); + + public Class public_x() { return A.class; } + protected Class protected_x() { return A.class; } + Class package_x() { return A.class; } + final Class package_final_x() { return A.class; } + + static Class package_static_x() { return A.class; } + } + + static class B extends A { + public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); + + @Override public Class public_x() { return B.class; } + @Override protected Class protected_x() { return B.class; } + @Override Class package_x() { return B.class; } + + private Class private_x() { return B.class; } + static Class private_static_x() { return B.class; } + } + + static final MethodHandle A_PUBLIC_X; + static final MethodHandle A_PROTECTED_X; + static final MethodHandle A_PACKAGE_X; + static final MethodHandle A_PACKAGE_STATIC_X; + static final MethodHandle A_PACKAGE_FINAL_X; + + static final MethodHandle B_PRIVATE_X; + static final MethodHandle B_PRIVATE_STATIC_X; + + static { + try { + MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); + + A_PUBLIC_X = LOOKUP.findVirtual( + A.class, "public_x", MethodType.methodType(Class.class)); + A_PROTECTED_X = LOOKUP.findVirtual( + A.class, "protected_x", MethodType.methodType(Class.class)); + A_PACKAGE_X = LOOKUP.findVirtual( + A.class, "package_x", MethodType.methodType(Class.class)); + A_PACKAGE_FINAL_X = LOOKUP.findVirtual( + A.class, "package_final_x", MethodType.methodType(Class.class)); + A_PACKAGE_STATIC_X = LOOKUP.findStatic( + A.class, "package_static_x", MethodType.methodType(Class.class)); + + B_PRIVATE_X = B.LOOKUP.findVirtual( + B.class, "private_x", MethodType.methodType(Class.class)); + B_PRIVATE_STATIC_X = B.LOOKUP.findStatic( + B.class, "private_static_x", MethodType.methodType(Class.class)); + } catch (Exception e) { + throw new Error(e); + } + } + + static final A a = new B(); + + private static void testPublicMH() { + try { + Class r = (Class)A_PUBLIC_X.invokeExact(a); + assertEquals(r, B.class); + } catch (Throwable throwable) { + throw new Error(throwable); + } + } + + private static void testProtectedMH() { + try { + Class r = (Class)A_PROTECTED_X.invokeExact(a); + assertEquals(r, B.class); + } catch (Throwable throwable) { + throw new Error(throwable); + } + } + + private static void testPackageMH() { + try { + Class r = (Class)A_PACKAGE_X.invokeExact(a); + assertEquals(r, B.class); + } catch (Throwable throwable) { + throw new Error(throwable); + } + } + + private static void testPackageFinalMH() { + try { + Class r = (Class)A_PACKAGE_FINAL_X.invokeExact(a); + assertEquals(r, A.class); + } catch (Throwable throwable) { + throw new Error(throwable); + } + } + + private static void testPackageStaticMH() { + try { + Class r = (Class)A_PACKAGE_STATIC_X.invokeExact(); + assertEquals(r, A.class); + } catch (Throwable throwable) { + throw new Error(throwable); + } + } + + private static void testPrivateMH() { + try { + Class r = (Class)B_PRIVATE_X.invokeExact((B)a); + assertEquals(r, B.class); + } catch (Throwable throwable) { + throw new Error(throwable); + } + } + + private static void testPrivateStaticMH() { + try { + Class r = (Class)B_PRIVATE_STATIC_X.invokeExact(); + assertEquals(r, B.class); + } catch (Throwable throwable) { + throw new Error(throwable); + } + } + static class Launcher { + public static void main(String[] args) throws Exception { + for (int i = 0; i < 20_000; i++) { + testPublicMH(); + } + for (int i = 0; i < 20_000; i++) { + testProtectedMH(); + } + for (int i = 0; i < 20_000; i++) { + testPackageMH(); + } + for (int i = 0; i < 20_000; i++) { + testPackageFinalMH(); + } + for (int i = 0; i < 20_000; i++) { + testPackageStaticMH(); + } + for (int i = 0; i < 20_000; i++) { + testPrivateMH(); + } + for (int i = 0; i < 20_000; i++) { + testPrivateStaticMH(); + } + } + } +} diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/regalloc/C1ObjectSpillInLogicOp.java --- a/test/compiler/regalloc/C1ObjectSpillInLogicOp.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/regalloc/C1ObjectSpillInLogicOp.java Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -24,6 +24,7 @@ /* * @test * @bug 8027751 + * @requires vm.gc=="G1" | vm.gc=="null" * @summary C1 crashes generating G1 post-barrier in Unsafe.getAndSetObject() intrinsic because of the new value spill * @run main/othervm -XX:+UseG1GC C1ObjectSpillInLogicOp * diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/rtm/locking/TestRTMAbortRatio.java --- a/test/compiler/rtm/locking/TestRTMAbortRatio.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/rtm/locking/TestRTMAbortRatio.java Thu Apr 30 14:58:53 2015 -0700 @@ -126,10 +126,7 @@ @Override public String[] getMethodsToCompileNames() { - return new String[] { - getMethodWithLockName(), - Unsafe.class.getName() + "::addressSize" - }; + return new String[] { getMethodWithLockName() }; } public void lock(boolean abort) { @@ -147,10 +144,12 @@ public static void main(String args[]) throws Throwable { Asserts.assertGTE(args.length, 1, "One argument required."); Test t = new Test(); - if (Boolean.valueOf(args[0])) { + boolean shouldBeInflated = Boolean.valueOf(args[0]); + if (shouldBeInflated) { AbortProvoker.inflateMonitor(t.monitor); } for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) { + AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated); t.lock(i >= Test.WARMUP_ITERATIONS); } } diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java --- a/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java Thu Apr 30 14:58:53 2015 -0700 @@ -156,10 +156,7 @@ @Override public String[] getMethodsToCompileNames() { - return new String[] { - getMethodWithLockName(), - sun.misc.Unsafe.class.getName() + "::forceAbort" - }; + return new String[] { getMethodWithLockName() }; } public void forceAbort(int a[], boolean abort) { @@ -182,13 +179,15 @@ public static void main(String args[]) throws Throwable { Test t = new Test(); - if (Boolean.valueOf(args[0])) { + boolean shouldBeInflated = Boolean.valueOf(args[0]); + if (shouldBeInflated) { AbortProvoker.inflateMonitor(t.monitor); } int tmp[] = new int[1]; for (int i = 0; i < Test.ITERATIONS; i++ ) { + AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated); if (i == Test.RANGE_CHECK_AT) { t.forceAbort(new int[0], false); } else { diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java --- a/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java Thu Apr 30 14:58:53 2015 -0700 @@ -129,10 +129,7 @@ @Override public String[] getMethodsToCompileNames() { - return new String[] { - getMethodWithLockName(), - sun.misc.Unsafe.class.getName() + "::addressSize" - }; + return new String[] { getMethodWithLockName() }; } public void forceAbort(boolean abort) { @@ -150,11 +147,12 @@ public static void main(String args[]) throws Throwable { Asserts.assertGTE(args.length, 1, "One argument required."); Test t = new Test(); - - if (Boolean.valueOf(args[0])) { + boolean shouldBeInflated = Boolean.valueOf(args[0]); + if (shouldBeInflated) { AbortProvoker.inflateMonitor(t.monitor); } for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { + AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated); t.forceAbort( i == TestRTMDeoptOnLowAbortRatio.LOCKING_THRESHOLD); } diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/rtm/locking/TestRTMLockingThreshold.java --- a/test/compiler/rtm/locking/TestRTMLockingThreshold.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/rtm/locking/TestRTMLockingThreshold.java Thu Apr 30 14:58:53 2015 -0700 @@ -142,10 +142,7 @@ @Override public String[] getMethodsToCompileNames() { - return new String[] { - getMethodWithLockName(), - sun.misc.Unsafe.class.getName() + "::addressSize" - }; + return new String[] { getMethodWithLockName() }; } public void lock(boolean abort) { @@ -163,11 +160,12 @@ public static void main(String args[]) throws Throwable { Asserts.assertGTE(args.length, 1, "One argument required."); Test t = new Test(); - - if (Boolean.valueOf(args[0])) { + boolean shouldBeInflated = Boolean.valueOf(args[0]); + if (shouldBeInflated) { AbortProvoker.inflateMonitor(t.monitor); } for (int i = 0; i < Test.TOTAL_ITERATIONS; i++) { + AbortProvoker.verifyMonitorState(t.monitor, shouldBeInflated); t.lock(i % 2 == 1); } } diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java --- a/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Thu Apr 30 14:58:53 2015 -0700 @@ -116,9 +116,7 @@ @Override public String[] getMethodsToCompileNames() { - return new String[] { - getMethodWithLockName() - }; + return new String[] { getMethodWithLockName() }; } public void lock() { @@ -134,11 +132,13 @@ public static void main(String args[]) throws Throwable { Asserts.assertGTE(args.length, 1, "One argument required."); Test test = new Test(); - - if (Boolean.valueOf(args[0])) { + boolean shouldBeInflated = Boolean.valueOf(args[0]); + if (shouldBeInflated) { AbortProvoker.inflateMonitor(test.monitor); } for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) { + AbortProvoker.verifyMonitorState(test.monitor, + shouldBeInflated); test.lock(); } } diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java --- a/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java Thu Apr 30 14:58:53 2015 -0700 @@ -51,7 +51,7 @@ * Compiled method invoked {@code AbortProvoker.DEFAULT_ITERATIONS} times before * lock inflation and the same amount of times after inflation. * As a result total locks count should be equal to - * {@code 2*AbortProvoker.DEFAULT_ITERATIONS}. + * {@code 2 * AbortProvoker.DEFAULT_ITERATIONS}. * It is a pretty strict assertion which could fail if some retriable abort * happened: it could be {@code AbortType.RETRIABLE} or * {@code AbortType.MEM_CONFLICT}, but unfortunately abort can has both these @@ -100,7 +100,6 @@ } public static class Test { - /** * Usage: * Test <provoker type> @@ -112,10 +111,12 @@ AbortProvoker provoker = AbortType.lookup(Integer.valueOf(args[0])).provoker(); for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { + AbortProvoker.verifyMonitorState(provoker, false /*deflated*/); provoker.forceAbort(); } provoker.inflateMonitor(); for (int i = 0; i < AbortProvoker.DEFAULT_ITERATIONS; i++) { + AbortProvoker.verifyMonitorState(provoker, true /*inflated*/); provoker.forceAbort(); } } diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/stable/TestStableBoolean.java --- a/test/compiler/stable/TestStableBoolean.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/stable/TestStableBoolean.java Thu Apr 30 14:58:53 2015 -0700 @@ -53,44 +53,32 @@ * java/lang/invoke/TestStableBoolean$DefaultStaticValue * java/lang/invoke/TestStableBoolean$ObjectArrayLowerDim2 * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableBoolean - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableBoolean * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableBoolean - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableBoolean * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:+FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableBoolean - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:-FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableBoolean */ package java.lang.invoke; diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/stable/TestStableByte.java --- a/test/compiler/stable/TestStableByte.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/stable/TestStableByte.java Thu Apr 30 14:58:53 2015 -0700 @@ -53,44 +53,32 @@ * java/lang/invoke/TestStableByte$DefaultStaticValue * java/lang/invoke/TestStableByte$ObjectArrayLowerDim2 * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableByte - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableByte * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableByte - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableByte * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:+FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableByte - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:-FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableByte */ package java.lang.invoke; diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/stable/TestStableChar.java --- a/test/compiler/stable/TestStableChar.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/stable/TestStableChar.java Thu Apr 30 14:58:53 2015 -0700 @@ -53,44 +53,32 @@ * java/lang/invoke/TestStableChar$DefaultStaticValue * java/lang/invoke/TestStableChar$ObjectArrayLowerDim2 * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableChar - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableChar * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableChar - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableChar * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:+FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableChar - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:-FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableChar */ package java.lang.invoke; diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/stable/TestStableDouble.java --- a/test/compiler/stable/TestStableDouble.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/stable/TestStableDouble.java Thu Apr 30 14:58:53 2015 -0700 @@ -53,44 +53,32 @@ * java/lang/invoke/TestStableDouble$DefaultStaticValue * java/lang/invoke/TestStableDouble$ObjectArrayLowerDim2 * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableDouble - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableDouble * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableDouble - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableDouble * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:+FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableDouble - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:-FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableDouble */ package java.lang.invoke; diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/stable/TestStableFloat.java --- a/test/compiler/stable/TestStableFloat.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/stable/TestStableFloat.java Thu Apr 30 14:58:53 2015 -0700 @@ -53,44 +53,32 @@ * java/lang/invoke/TestStableFloat$DefaultStaticValue * java/lang/invoke/TestStableFloat$ObjectArrayLowerDim2 * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableFloat - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableFloat * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableFloat - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableFloat * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:+FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableFloat - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:-FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableFloat */ package java.lang.invoke; diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/stable/TestStableInt.java --- a/test/compiler/stable/TestStableInt.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/stable/TestStableInt.java Thu Apr 30 14:58:53 2015 -0700 @@ -53,44 +53,32 @@ * java/lang/invoke/TestStableInt$DefaultStaticValue * java/lang/invoke/TestStableInt$ObjectArrayLowerDim2 * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableInt - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableInt * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableInt - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableInt * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:+FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableInt - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:-FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableInt */ package java.lang.invoke; diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/stable/TestStableLong.java --- a/test/compiler/stable/TestStableLong.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/stable/TestStableLong.java Thu Apr 30 14:58:53 2015 -0700 @@ -53,44 +53,32 @@ * java/lang/invoke/TestStableLong$DefaultStaticValue * java/lang/invoke/TestStableLong$ObjectArrayLowerDim2 * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableLong - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableLong * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableLong - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableLong * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:+FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableLong - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:-FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableLong */ package java.lang.invoke; diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/stable/TestStableObject.java --- a/test/compiler/stable/TestStableObject.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/stable/TestStableObject.java Thu Apr 30 14:58:53 2015 -0700 @@ -54,44 +54,32 @@ * java/lang/invoke/TestStableObject$DefaultStaticValue * java/lang/invoke/TestStableObject$ObjectArrayLowerDim2 * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableObject - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableObject * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableObject - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableObject * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:+FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableObject - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:-FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableObject */ package java.lang.invoke; diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/stable/TestStableShort.java --- a/test/compiler/stable/TestStableShort.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/stable/TestStableShort.java Thu Apr 30 14:58:53 2015 -0700 @@ -53,44 +53,32 @@ * java/lang/invoke/TestStableShort$DefaultStaticValue * java/lang/invoke/TestStableShort$ObjectArrayLowerDim2 * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableShort - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:-TieredCompilation + * -XX:-TieredCompilation * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableShort * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:+FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableShort - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions + * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -server -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 * -XX:-FoldStableValues * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 * java.lang.invoke.TestStableShort * - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:+FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableShort - * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp - * -client -XX:-TieredCompilation - * -XX:-FoldStableValues - * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 - * java.lang.invoke.TestStableShort */ package java.lang.invoke; diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/testlibrary/rtm/AbortProvoker.java --- a/test/compiler/testlibrary/rtm/AbortProvoker.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/testlibrary/rtm/AbortProvoker.java Thu Apr 30 14:58:53 2015 -0700 @@ -29,8 +29,7 @@ import java.util.concurrent.CyclicBarrier; import com.oracle.java.testlibrary.Asserts; -import com.oracle.java.testlibrary.Utils; -import sun.misc.Unsafe; +import sun.hotspot.WhiteBox; /** * Base class for different transactional execution abortion @@ -38,6 +37,9 @@ */ public abstract class AbortProvoker implements CompilableTest { public static final long DEFAULT_ITERATIONS = 10000L; + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + @SuppressWarnings("unused") + private static int sharedState = 0; /** * Inflates monitor associated with object {@code monitor}. * Inflation is forced by entering the same monitor from @@ -48,36 +50,76 @@ * @throws Exception if something went wrong. */ public static Object inflateMonitor(Object monitor) throws Exception { - Unsafe unsafe = Utils.getUnsafe(); CyclicBarrier barrier = new CyclicBarrier(2); Runnable inflatingRunnable = () -> { - unsafe.monitorEnter(monitor); - try { - barrier.await(); - barrier.await(); - } catch (InterruptedException | BrokenBarrierException e) { - throw new RuntimeException( - "Synchronization issue occurred.", e); - } finally { - unsafe.monitorExit(monitor); + synchronized (monitor) { + try { + barrier.await(); + } catch (BrokenBarrierException | InterruptedException e) { + throw new RuntimeException( + "Synchronization issue occurred.", e); + } + try { + monitor.wait(); + } catch (InterruptedException e) { + throw new AssertionError("The thread waiting on an" + + " inflated monitor was interrupted, thus test" + + " results may be incorrect.", e); + } } }; Thread t = new Thread(inflatingRunnable); + t.setDaemon(true); t.start(); // Wait until thread t enters the monitor. barrier.await(); - // At this point monitor will be owned by thread t, - // so our attempt to enter the same monitor will force - // monitor inflation. - Asserts.assertFalse(unsafe.tryMonitorEnter(monitor), - "Not supposed to enter the monitor first"); - barrier.await(); - t.join(); + synchronized (monitor) { + // At this point thread t is already waiting on the monitor. + // Modifying static field just to avoid lock's elimination. + sharedState++; + } + verifyMonitorState(monitor, true /* inflated */); return monitor; } + /** + * Verifies that {@code monitor} is a stack-lock or inflated lock depending + * on {@code shouldBeInflated} value. If {@code monitor} is inflated while + * it is expected that it should be a stack-lock, then this method attempts + * to deflate it by forcing a safepoint and then verifies the state once + * again. + * + * @param monitor monitor to be verified. + * @param shouldBeInflated flag indicating whether or not monitor is + * expected to be inflated. + * @throws RuntimeException if the {@code monitor} in a wrong state. + */ + public static void verifyMonitorState(Object monitor, + boolean shouldBeInflated) { + if (!shouldBeInflated && WHITE_BOX.isMonitorInflated(monitor)) { + WHITE_BOX.forceSafepoint(); + } + Asserts.assertEQ(WHITE_BOX.isMonitorInflated(monitor), shouldBeInflated, + "Monitor in a wrong state."); + } + /** + * Verifies that monitor used by the {@code provoker} is a stack-lock or + * inflated lock depending on {@code shouldBeInflated} value. If such + * monitor is inflated while it is expected that it should be a stack-lock, + * then this method attempts to deflate it by forcing a safepoint and then + * verifies the state once again. + * + * @param provoker AbortProvoker whose monitor's state should be verified. + * @param shouldBeInflated flag indicating whether or not monitor is + * expected to be inflated. + * @throws RuntimeException if the {@code monitor} in a wrong state. + */ + public static void verifyMonitorState(AbortProvoker provoker, + boolean shouldBeInflated) { + verifyMonitorState(provoker.monitor, shouldBeInflated); + } /** * Get instance of specified AbortProvoker, inflate associated monitor @@ -120,6 +162,7 @@ } for (long i = 0; i < iterations; i++) { + AbortProvoker.verifyMonitorState(provoker, monitorShouldBeInflated); provoker.forceAbort(); } } diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/testlibrary/rtm/BusyLock.java --- a/test/compiler/testlibrary/rtm/BusyLock.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/testlibrary/rtm/BusyLock.java Thu Apr 30 14:58:53 2015 -0700 @@ -77,7 +77,7 @@ } } - public void test() { + public void syncAndTest() { try { barrier.await(); // wait until monitor is locked by a ::run method @@ -85,6 +85,10 @@ } catch (InterruptedException | BrokenBarrierException e) { throw new RuntimeException("Synchronization error happened.", e); } + test(); + } + + public void test() { synchronized(monitor) { BusyLock.field++; } @@ -130,7 +134,7 @@ Thread t = new Thread(busyLock); t.start(); - busyLock.test(); + busyLock.syncAndTest(); t.join(); } } diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/testlibrary/rtm/MemoryConflictProvoker.java --- a/test/compiler/testlibrary/rtm/MemoryConflictProvoker.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/testlibrary/rtm/MemoryConflictProvoker.java Thu Apr 30 14:58:53 2015 -0700 @@ -69,11 +69,6 @@ * Accesses and modifies memory region from within the transaction. */ public void transactionalRegion() { - try { - barrier.await(); - } catch (InterruptedException | BrokenBarrierException e) { - throw new RuntimeException(e); - } for (int i = 0; i < MemoryConflictProvoker.INNER_ITERATIONS; i++) { synchronized(monitor) { MemoryConflictProvoker.field--; @@ -86,6 +81,11 @@ try { Thread t = new Thread(conflictingThread); t.start(); + try { + barrier.await(); + } catch (InterruptedException | BrokenBarrierException e) { + throw new RuntimeException(e); + } transactionalRegion(); t.join(); } catch (Exception e) { diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/testlibrary/rtm/RTMTestBase.java --- a/test/compiler/testlibrary/rtm/RTMTestBase.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/testlibrary/rtm/RTMTestBase.java Thu Apr 30 14:58:53 2015 -0700 @@ -238,10 +238,10 @@ String[] filteredVMOpts = Utils.getFilteredTestJavaOpts(filters); Collections.addAll(finalVMOpts, filteredVMOpts); Collections.addAll(finalVMOpts, "-Xcomp", "-server", - "-XX:-TieredCompilation", + "-XX:-TieredCompilation", "-XX:+UseRTMLocking", CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMLocking"); + "-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI"); if (test != null) { for (String method : test.getMethodsToCompileNames()) { diff -r b0f52462883d -r 1f0d760ccac1 test/compiler/uncommontrap/UncommonTrapStackBang.java --- a/test/compiler/uncommontrap/UncommonTrapStackBang.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/compiler/uncommontrap/UncommonTrapStackBang.java Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -27,9 +27,7 @@ * @bug 8026775 * @summary Uncommon trap blob did not bang all the stack shadow pages * - * @run main/othervm -server -XX:+IgnoreUnrecognizedVMOptions -XX:+TieredCompilation UncommonTrapStackBang - * @run main/othervm -server -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation UncommonTrapStackBang - * + * @run main/othervm UncommonTrapStackBang * * Note: This test does not reproduce the problem with absolute * certainty. Empirically the bug reproduces on Windows some 80+% of diff -r b0f52462883d -r 1f0d760ccac1 test/gc/6581734/Test6581734.java --- a/test/gc/6581734/Test6581734.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/6581734/Test6581734.java Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -24,6 +24,7 @@ /* * @test Test6581734.java * @bug 6581734 + * @requires vm.gc=="ConcMarkSweep" | vm.gc=="null" * @summary CMS Old Gen's collection usage is zero after GC which is incorrect * @run main/othervm -Xmx512m -verbose:gc -XX:+UseConcMarkSweepGC Test6581734 * diff -r b0f52462883d -r 1f0d760ccac1 test/gc/TestSystemGC.java --- a/test/gc/TestSystemGC.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/TestSystemGC.java Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2013, 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 @@ -24,6 +24,7 @@ /* * @test TestSystemGC * @key gc + * @requires vm.gc=="null" * @summary Runs System.gc() with different flags. * @run main/othervm TestSystemGC * @run main/othervm -XX:+UseSerialGC TestSystemGC diff -r b0f52462883d -r 1f0d760ccac1 test/gc/arguments/TestAlignmentToUseLargePages.java --- a/test/gc/arguments/TestAlignmentToUseLargePages.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/arguments/TestAlignmentToUseLargePages.java Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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,6 +28,7 @@ * @bug 8024396 * @key gc * @key regression + * @requires vm.gc=="null" * @run main/othervm -Xms7M -Xmx9M -XX:+UseParallelGC -XX:-UseParallelOldGC -XX:+UseLargePages TestAlignmentToUseLargePages * @run main/othervm -Xms7M -Xmx9M -XX:+UseParallelGC -XX:-UseParallelOldGC -XX:-UseLargePages TestAlignmentToUseLargePages * @run main/othervm -Xms7M -Xmx9M -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseLargePages TestAlignmentToUseLargePages diff -r b0f52462883d -r 1f0d760ccac1 test/gc/arguments/TestG1HeapRegionSize.java --- a/test/gc/arguments/TestG1HeapRegionSize.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/arguments/TestG1HeapRegionSize.java Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2013, 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 @@ -25,11 +25,12 @@ * @test TestG1HeapRegionSize * @key gc * @bug 8021879 + * @requires vm.gc=="G1" | vm.gc=="null" * @summary Verify that the flag G1HeapRegionSize is updated properly * @run main/othervm -Xmx64m TestG1HeapRegionSize 1048576 - * @run main/othervm -XX:G1HeapRegionSize=2m -Xmx64m TestG1HeapRegionSize 2097152 - * @run main/othervm -XX:G1HeapRegionSize=3m -Xmx64m TestG1HeapRegionSize 2097152 - * @run main/othervm -XX:G1HeapRegionSize=64m -Xmx256m TestG1HeapRegionSize 33554432 + * @run main/othervm -XX:G1HeapRegionSize=2m -Xmx64m -XX:+UseG1GC TestG1HeapRegionSize 2097152 + * @run main/othervm -XX:G1HeapRegionSize=3m -Xmx64m -XX:+UseG1GC TestG1HeapRegionSize 2097152 + * @run main/othervm -XX:G1HeapRegionSize=64m -Xmx256m -XX:+UseG1GC TestG1HeapRegionSize 33554432 */ import sun.management.ManagementFactoryHelper; @@ -41,14 +42,8 @@ public static void main(String[] args) { HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean(); - VMOption option = diagnostic.getVMOption("UseG1GC"); - if (option.getValue().equals("false")) { - System.out.println("Skipping this test. It is only a G1 test."); - return; - } - String expectedValue = getExpectedValue(args); - option = diagnostic.getVMOption("G1HeapRegionSize"); + VMOption option = diagnostic.getVMOption("G1HeapRegionSize"); if (!expectedValue.equals(option.getValue())) { throw new RuntimeException("Wrong value for G1HeapRegionSize. Expected " + expectedValue + " but got " + option.getValue()); } diff -r b0f52462883d -r 1f0d760ccac1 test/gc/concurrentMarkSweep/DisableResizePLAB.java --- a/test/gc/concurrentMarkSweep/DisableResizePLAB.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/concurrentMarkSweep/DisableResizePLAB.java Thu Apr 30 14:58:53 2015 -0700 @@ -26,6 +26,7 @@ * @key gc * @bug 8060467 * @author filipp.zhinkin@oracle.com, john.coomes@oracle.com + * @requires vm.gc=="ConcMarkSweep" | vm.gc=="null" * @summary Run CMS with PLAB resizing disabled and a small OldPLABSize * @run main/othervm -XX:+UseConcMarkSweepGC -XX:-ResizePLAB -XX:OldPLABSize=1k -Xmx256m -XX:+PrintGCDetails DisableResizePLAB */ diff -r b0f52462883d -r 1f0d760ccac1 test/gc/g1/TestHumongousShrinkHeap.java --- a/test/gc/g1/TestHumongousShrinkHeap.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/g1/TestHumongousShrinkHeap.java Thu Apr 30 14:58:53 2015 -0700 @@ -24,6 +24,7 @@ /** * @test TestHumongousShrinkHeap * @bug 8036025 8056043 + * @requires vm.gc=="G1" | vm.gc=="null" * @summary Verify that heap shrinks after GC in the presence of fragmentation * due to humongous objects * @library /testlibrary diff -r b0f52462883d -r 1f0d760ccac1 test/gc/g1/TestLargePageUseForAuxMemory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/g1/TestLargePageUseForAuxMemory.java Thu Apr 30 14:58:53 2015 -0700 @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015, 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 TestLargePageUseForAuxMemory.java + * @bug 8058354 + * @key gc + * @library /testlibrary /testlibrary/whitebox + * @requires (vm.gc=="G1" | vm.gc=="null") + * @build TestLargePageUseForAuxMemory + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @summary Test that auxiliary data structures are allocated using large pages if available. + * @run main/othervm -Xbootclasspath/a:. -XX:+UseG1GC -XX:+WhiteBoxAPI -XX:+IgnoreUnrecognizedVMOptions -XX:+UseLargePages TestLargePageUseForAuxMemory + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class TestLargePageUseForAuxMemory { + static final int HEAP_REGION_SIZE = 4 * 1024 * 1024; + static long largePageSize; + static long smallPageSize; + + static void checkSmallTables(OutputAnalyzer output, long expectedPageSize) throws Exception { + output.shouldContain("G1 'Block offset table': pg_sz=" + expectedPageSize); + output.shouldContain("G1 'Card counts table': pg_sz=" + expectedPageSize); + } + + static void checkBitmaps(OutputAnalyzer output, long expectedPageSize) throws Exception { + output.shouldContain("G1 'Prev Bitmap': pg_sz=" + expectedPageSize); + output.shouldContain("G1 'Next Bitmap': pg_sz=" + expectedPageSize); + } + + static void testVM(long heapsize, boolean cardsShouldUseLargePages, boolean bitmapShouldUseLargePages) throws Exception { + ProcessBuilder pb; + // Test with large page enabled. + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", + "-XX:G1HeapRegionSize=" + HEAP_REGION_SIZE, + "-Xms" + 10 * HEAP_REGION_SIZE, + "-Xmx" + heapsize, + "-XX:+TracePageSizes", + "-XX:+UseLargePages", + "-XX:+IgnoreUnrecognizedVMOptions", // there is on ObjectAlignmentInBytes in 32 bit builds + "-XX:ObjectAlignmentInBytes=8", + "-version"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + checkSmallTables(output, (cardsShouldUseLargePages ? largePageSize : smallPageSize)); + checkBitmaps(output, (bitmapShouldUseLargePages ? largePageSize : smallPageSize)); + output.shouldHaveExitValue(0); + + // Test with large page disabled. + pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", + "-XX:G1HeapRegionSize=" + HEAP_REGION_SIZE, + "-Xms" + 10 * HEAP_REGION_SIZE, + "-Xmx" + heapsize, + "-XX:+TracePageSizes", + "-XX:-UseLargePages", + "-XX:+IgnoreUnrecognizedVMOptions", // there is on ObjectAlignmentInBytes in 32 bit builds + "-XX:ObjectAlignmentInBytes=8", + "-version"); + + output = new OutputAnalyzer(pb.start()); + checkSmallTables(output, smallPageSize); + checkBitmaps(output, smallPageSize); + output.shouldHaveExitValue(0); + } + + public static void main(String[] args) throws Exception { + if (!Platform.isDebugBuild()) { + System.out.println("Skip tests on non-debug builds because the required option TracePageSizes is a debug-only option."); + return; + } + + WhiteBox wb = WhiteBox.getWhiteBox(); + smallPageSize = wb.getVMPageSize(); + largePageSize = wb.getVMLargePageSize(); + + if (largePageSize == 0) { + System.out.println("Skip tests because large page support does not seem to be available on this platform."); + return; + } + + // To get large pages for the card table etc. we need at least a 1G heap (with 4k page size). + // 32 bit systems will have problems reserving such an amount of contiguous space, so skip the + // test there. + if (!Platform.is32bit()) { + // Size that a single card covers. + final int cardSize = 512; + + final long heapSizeForCardTableUsingLargePages = largePageSize * cardSize; + + testVM(heapSizeForCardTableUsingLargePages, true, true); + testVM(heapSizeForCardTableUsingLargePages + HEAP_REGION_SIZE, true, true); + testVM(heapSizeForCardTableUsingLargePages - HEAP_REGION_SIZE, false, true); + } + + // Minimum heap requirement to get large pages for bitmaps is 128M heap. This seems okay to test + // everywhere. + final int bitmapTranslationFactor = 8 * 8; // ObjectAlignmentInBytes * BitsPerByte + final long heapSizeForBitmapUsingLargePages = largePageSize * bitmapTranslationFactor; + + testVM(heapSizeForBitmapUsingLargePages, false, true); + testVM(heapSizeForBitmapUsingLargePages + HEAP_REGION_SIZE, false, true); + testVM(heapSizeForBitmapUsingLargePages - HEAP_REGION_SIZE, false, false); + } +} + diff -r b0f52462883d -r 1f0d760ccac1 test/gc/g1/TestRegionAlignment.java --- a/test/gc/g1/TestRegionAlignment.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/g1/TestRegionAlignment.java Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -24,6 +24,7 @@ /* * @test TestRegionAlignment.java * @bug 8013791 + * @requires vm.gc=="G1" | vm.gc=="null" * @summary Make sure that G1 ergonomics pick a heap size that is aligned with the region size * @run main/othervm -XX:+UseG1GC -XX:G1HeapRegionSize=32m -XX:MaxRAM=555m TestRegionAlignment * diff -r b0f52462883d -r 1f0d760ccac1 test/gc/g1/TestShrinkAuxiliaryData.java --- a/test/gc/g1/TestShrinkAuxiliaryData.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/g1/TestShrinkAuxiliaryData.java Thu Apr 30 14:58:53 2015 -0700 @@ -70,9 +70,7 @@ printTestInfo(maxCacheSize); vmOpts.add("-XX:G1ConcRSLogCacheSize=" + RSetCacheSize); - - vmOpts.addAll(Arrays.asList(Utils.getFilteredTestJavaOpts( - ShrinkAuxiliaryDataTest.prohibitedVmOptions))); + vmOpts.addAll(Arrays.asList(Utils.getTestJavaOpts())); // for 32 bits ObjectAlignmentInBytes is not a option if (Platform.is32bit()) { @@ -272,16 +270,5 @@ private static final int REGIONS_TO_ALLOCATE = 5; private static final int NUM_OBJECTS_PER_REGION = 10; private static final int NUM_LINKS = 20; // how many links create for each object - - private static final String[] prohibitedVmOptions = { - // remove this when @requires option will be on duty - "-XX:\\+UseParallelGC", - "-XX:\\+UseSerialGC", - "-XX:\\+UseConcMarkSweepGC", - "-XX:\\+UseParallelOldGC", - "-XX:\\+UseParNewGC", - "-Xconcgc", - "-Xincgc" - }; } } diff -r b0f52462883d -r 1f0d760ccac1 test/gc/g1/TestShrinkAuxiliaryData05.java --- a/test/gc/g1/TestShrinkAuxiliaryData05.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/g1/TestShrinkAuxiliaryData05.java Thu Apr 30 14:58:53 2015 -0700 @@ -26,6 +26,7 @@ * @bug 8038423 * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values + * @requires vm.gc=="G1" | vm.gc=="null" * @library /testlibrary /testlibrary/whitebox * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData05 * @run driver/timeout=720 TestShrinkAuxiliaryData05 diff -r b0f52462883d -r 1f0d760ccac1 test/gc/g1/TestShrinkAuxiliaryData10.java --- a/test/gc/g1/TestShrinkAuxiliaryData10.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/g1/TestShrinkAuxiliaryData10.java Thu Apr 30 14:58:53 2015 -0700 @@ -26,6 +26,7 @@ * @bug 8038423 * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values + * @requires vm.gc=="G1" | vm.gc=="null" * @library /testlibrary /testlibrary/whitebox * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData10 * @run driver/timeout=720 TestShrinkAuxiliaryData10 diff -r b0f52462883d -r 1f0d760ccac1 test/gc/g1/TestShrinkAuxiliaryData15.java --- a/test/gc/g1/TestShrinkAuxiliaryData15.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/g1/TestShrinkAuxiliaryData15.java Thu Apr 30 14:58:53 2015 -0700 @@ -26,6 +26,7 @@ * @bug 8038423 * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values + * @requires vm.gc=="G1" | vm.gc=="null" * @library /testlibrary /testlibrary/whitebox * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData15 * @run driver/timeout=720 TestShrinkAuxiliaryData15 diff -r b0f52462883d -r 1f0d760ccac1 test/gc/g1/TestShrinkAuxiliaryData20.java --- a/test/gc/g1/TestShrinkAuxiliaryData20.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/g1/TestShrinkAuxiliaryData20.java Thu Apr 30 14:58:53 2015 -0700 @@ -26,6 +26,7 @@ * @bug 8038423 * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values + * @requires vm.gc=="G1" | vm.gc=="null" * @library /testlibrary /testlibrary/whitebox * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData20 * @run driver/timeout=720 TestShrinkAuxiliaryData20 diff -r b0f52462883d -r 1f0d760ccac1 test/gc/g1/TestShrinkAuxiliaryData25.java --- a/test/gc/g1/TestShrinkAuxiliaryData25.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/g1/TestShrinkAuxiliaryData25.java Thu Apr 30 14:58:53 2015 -0700 @@ -26,6 +26,7 @@ * @bug 8038423 * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values + * @requires vm.gc=="G1" | vm.gc=="null" * @library /testlibrary /testlibrary/whitebox * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData25 * @run driver/timeout=720 TestShrinkAuxiliaryData25 diff -r b0f52462883d -r 1f0d760ccac1 test/gc/g1/TestShrinkAuxiliaryData30.java --- a/test/gc/g1/TestShrinkAuxiliaryData30.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/g1/TestShrinkAuxiliaryData30.java Thu Apr 30 14:58:53 2015 -0700 @@ -26,6 +26,7 @@ * @bug 8038423 * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values + * @requires vm.gc=="G1" | vm.gc=="null" * @library /testlibrary /testlibrary/whitebox * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData30 * @run driver/timeout=720 TestShrinkAuxiliaryData30 diff -r b0f52462883d -r 1f0d760ccac1 test/gc/g1/TestShrinkToOneRegion.java --- a/test/gc/g1/TestShrinkToOneRegion.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/g1/TestShrinkToOneRegion.java Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -24,6 +24,7 @@ /* * @test TestShrinkToOneRegion.java * @bug 8013872 + * @requires vm.gc=="G1" | vm.gc=="null" * @summary Shrinking the heap down to one region used to hit an assert * @run main/othervm -XX:+UseG1GC -XX:G1HeapRegionSize=32m -Xmx256m TestShrinkToOneRegion * diff -r b0f52462883d -r 1f0d760ccac1 test/gc/metaspace/G1AddMetaspaceDependency.java --- a/test/gc/metaspace/G1AddMetaspaceDependency.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/metaspace/G1AddMetaspaceDependency.java Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -24,6 +24,7 @@ /* * @test G1AddMetaspaceDependency * @bug 8010196 + * @requires vm.gc=="G1" | vm.gc=="null" * @summary Checks that we don't get locking problems when adding metaspace dependencies with the G1 update buffer monitor * @run main/othervm -XX:+UseG1GC -XX:G1UpdateBufferSize=1 G1AddMetaspaceDependency */ diff -r b0f52462883d -r 1f0d760ccac1 test/gc/metaspace/TestMetaspacePerfCounters.java --- a/test/gc/metaspace/TestMetaspacePerfCounters.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/metaspace/TestMetaspacePerfCounters.java Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -29,6 +29,7 @@ /* @test TestMetaspacePerfCounters * @bug 8014659 + * @requires vm.gc=="null" * @library /testlibrary * @summary Tests that performance counters for metaspace and compressed class * space exists and works. diff -r b0f52462883d -r 1f0d760ccac1 test/gc/metaspace/TestPerfCountersAndMemoryPools.java --- a/test/gc/metaspace/TestPerfCountersAndMemoryPools.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/gc/metaspace/TestPerfCountersAndMemoryPools.java Thu Apr 30 14:58:53 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -30,6 +30,7 @@ /* @test TestPerfCountersAndMemoryPools * @bug 8023476 * @library /testlibrary + * @requires vm.gc=="Serial" | vm.gc=="null" * @summary Tests that a MemoryPoolMXBeans and PerfCounters for metaspace * report the same data. * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedKlassPointers -XX:+UseSerialGC -XX:+UsePerfData -Xint TestPerfCountersAndMemoryPools diff -r b0f52462883d -r 1f0d760ccac1 test/runtime/ErrorHandling/TestOnError.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/ErrorHandling/TestOnError.java Thu Apr 30 14:58:53 2015 -0700 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015, 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 TestOnError + * @summary Test using -XX:OnError= + * @library /testlibrary + * @build TestOnError com.oracle.java.testlibrary.* + * @run main TestOnError + * @bug 8078470 + */ + +import com.oracle.java.testlibrary.*; + +public class TestOnError { + + public static void main(String[] args) throws Exception { + if (!Platform.isDebugBuild()) { + System.out.println("Test requires a non-product build - skipping"); + return; + } + + String msg = "Test Succeeded"; + + // Execute the VM so that a + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:-TransmitErrorReport", + "-XX:ErrorHandlerTest=12", // trigger potential SEGV + "-XX:OnError=echo " + msg, + TestOnError.class.getName()); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + /* Actual output will include: + # + # -XX:OnError="echo Test Succeeded" + # Executing /bin/sh -c "echo Test Succeeded"... + Test Succeeded + + So we don't want to match on the "# Executing ..." line, and they + both get written to stdout. + */ + output.stdoutShouldMatch("^" + msg); // match start of line only + System.out.println("PASSED"); + } +} diff -r b0f52462883d -r 1f0d760ccac1 test/runtime/ErrorHandling/TestOnOutOfMemoryError.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/ErrorHandling/TestOnOutOfMemoryError.java Thu Apr 30 14:58:53 2015 -0700 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015, 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 TestOnOutOfMemoryError + * @summary Test using -XX:OnOutOfMemoryError= + * @library /testlibrary + * @build TestOnOutOfMemoryError com.oracle.java.testlibrary.* + * @run main TestOnOutOfMemoryError + * @bug 8078470 + */ + +import com.oracle.java.testlibrary.*; + +public class TestOnOutOfMemoryError { + + public static void main(String[] args) throws Exception { + if (args.length == 1) { + // This should guarantee to throw: + // java.lang.OutOfMemoryError: Requested array size exceeds VM limit + Object[] oa = new Object[Integer.MAX_VALUE]; + return; + } + + // else this is the main test + String msg = "Test Succeeded"; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:OnOutOfMemoryError=echo " + msg, + TestOnOutOfMemoryError.class.getName(), + "throwOOME"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + /* Actual output should look like this: + # + # java.lang.OutOfMemoryError: Requested array size exceeds VM limit + # -XX:OnOutOfMemoryError="echo Test Succeeded" + # Executing /bin/sh -c "echo Test Succeeded"... + Test Succeeded + Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit + at OOME.main(OOME.java:3) + + So we don't want to match on the "# Executing ..." line, and they + both get written to stdout. + */ + output.shouldContain("Requested array size exceeds VM limit"); + output.stdoutShouldMatch("^" + msg); // match start of line only + System.out.println("PASSED"); + } +} diff -r b0f52462883d -r 1f0d760ccac1 test/runtime/memory/LargePages/TestLargePageSizeInBytes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/memory/LargePages/TestLargePageSizeInBytes.java Thu Apr 30 14:58:53 2015 -0700 @@ -0,0 +1,61 @@ +/* + * 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 TestLargePageSizeInBytes + * @summary Tests that the flag -XX:LargePageSizeInBytes does not cause warnings on Solaris + * @bug 8049536 + * @library /testlibrary + * @run driver TestLargePageSizeInBytes + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.Platform; +import com.oracle.java.testlibrary.ProcessTools; + +public class TestLargePageSizeInBytes { + private static long M = 1024L * 1024L; + private static long G = 1024L * M; + + public static void main(String[] args) throws Exception { + if (!Platform.isSolaris()) { + // We only use the syscall mencntl on Solaris + return; + } + + testLargePageSizeInBytes(4 * M); + testLargePageSizeInBytes(256 * M); + testLargePageSizeInBytes(512 * M); + testLargePageSizeInBytes(2 * G); + } + + private static void testLargePageSizeInBytes(long size) throws Exception { + ProcessBuilder pb = + ProcessTools.createJavaProcessBuilder("-XX:+UseLargePages", + "-XX:LargePageSizeInBytes=" + size, + "-version"); + + OutputAnalyzer out = new OutputAnalyzer(pb.start()); + out.shouldNotContain("Attempt to use MPSS failed."); + out.shouldHaveExitValue(0); + } +} diff -r b0f52462883d -r 1f0d760ccac1 test/runtime/memory/ReadVMPageSize.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/memory/ReadVMPageSize.java Thu Apr 30 14:58:53 2015 -0700 @@ -0,0 +1,46 @@ +/* + * 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 + * @summary Using WhiteBox to get VM page size + * @library /testlibrary /testlibrary/whitebox + * @build ReadVMPageSize + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ReadVMPageSize + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class ReadVMPageSize { + public static void main(String args[]) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + int pageSize = wb.getVMPageSize(); + if (pageSize < 0) { + throw new Exception("pageSize < 0"); + } else { + System.out.println("Page size = " + pageSize); + } + } +} diff -r b0f52462883d -r 1f0d760ccac1 test/testlibrary/com/oracle/java/testlibrary/Platform.java --- a/test/testlibrary/com/oracle/java/testlibrary/Platform.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/testlibrary/com/oracle/java/testlibrary/Platform.java Thu Apr 30 14:58:53 2015 -0700 @@ -23,6 +23,8 @@ package com.oracle.java.testlibrary; +import java.util.regex.Pattern; + import com.oracle.java.testlibrary.Utils; public class Platform { @@ -99,29 +101,31 @@ // Returns true for sparc and sparcv9. public static boolean isSparc() { - return isArch("sparc"); + return isArch("sparc.*"); } public static boolean isARM() { - return isArch("arm"); + return isArch("arm.*"); } public static boolean isPPC() { - return isArch("ppc"); + return isArch("ppc.*"); } public static boolean isX86() { - // On Linux it's 'i386', Windows 'x86' - return (isArch("i386") || isArch("x86")); + // On Linux it's 'i386', Windows 'x86' without '_64' suffix. + return isArch("(i386)|(x86(?!_64))"); } public static boolean isX64() { // On OSX it's 'x86_64' and on other (Linux, Windows and Solaris) platforms it's 'amd64' - return (isArch("amd64") || isArch("x86_64")); + return isArch("(amd64)|(x86_64)"); } - private static boolean isArch(String archname) { - return osArch.toLowerCase().startsWith(archname.toLowerCase()); + private static boolean isArch(String archnameRE) { + return Pattern.compile(archnameRE, Pattern.CASE_INSENSITIVE) + .matcher(osArch) + .matches(); } public static String getOsArch() { diff -r b0f52462883d -r 1f0d760ccac1 test/testlibrary/whitebox/sun/hotspot/WhiteBox.java --- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Wed Apr 29 12:16:38 2015 -0700 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Thu Apr 30 14:58:53 2015 -0700 @@ -75,6 +75,9 @@ // Memory public native long getObjectAddress(Object o); public native int getHeapOopSize(); + public native int getVMPageSize(); + public native long getVMLargePageSize(); + public native boolean isObjectInOldGen(Object o); public native long getObjectSize(Object o); @@ -84,6 +87,8 @@ return isClassAlive0(name.replace('.', '/')); } private native boolean isClassAlive0(String name); + public native boolean isMonitorInflated(Object obj); + public native void forceSafepoint(); // Resource/Class Lookup Cache public native boolean classKnownToNotExist(ClassLoader loader, String name); diff -r b0f52462883d -r 1f0d760ccac1 test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java Thu Apr 30 14:58:53 2015 -0700 @@ -0,0 +1,135 @@ +/* + * 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.Asserts; +import com.oracle.java.testlibrary.Platform; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @test + * @summary Verify that for each group of mutually exclusive predicates defined + * in com.oracle.java.testlibrary.Platform one and only one predicate + * evaluates to true. + * @library /testlibrary + * @run main TestMutuallyExclusivePlatformPredicates + */ +public class TestMutuallyExclusivePlatformPredicates { + private static enum MethodGroup { + ARCH("isARM", "isPPC", "isSparc", "isX86", "isX64"), + BITNESS("is32bit", "is64bit"), + OS("isAix", "isLinux", "isSolaris", "isWindows", "isOSX"), + VM_TYPE("isClient", "isServer", "isGraal", "isMinimal"), + IGNORED("isEmbedded", "isDebugBuild", "shouldSAAttach", + "canPtraceAttachLinux", "canAttachOSX"); + + public final List methodNames; + + private MethodGroup(String... methodNames) { + this.methodNames = Collections.unmodifiableList( + Arrays.asList(methodNames)); + } + } + + public static void main(String args[]) { + EnumSet notIgnoredMethodGroups + = EnumSet.complementOf(EnumSet.of(MethodGroup.IGNORED)); + + notIgnoredMethodGroups.forEach( + TestMutuallyExclusivePlatformPredicates::verifyPredicates); + + TestMutuallyExclusivePlatformPredicates.verifyCoverage(); + } + + /** + * Verifies that one and only one predicate method defined in + * {@link com.oracle.java.testlibrary.Platform}, whose name included into + * methodGroup will return {@code true}. + * @param methodGroup The group of methods that should be tested. + */ + private static void verifyPredicates(MethodGroup methodGroup) { + System.out.println("Verifying method group: " + methodGroup.name()); + long truePredicatesCount = methodGroup.methodNames.stream() + .filter(TestMutuallyExclusivePlatformPredicates + ::evaluatePredicate) + .count(); + + Asserts.assertEQ(truePredicatesCount, 1L, String.format( + "Only one predicate from group %s should be evaluated to true " + + "(Actually %d predicates were evaluated to true).", + methodGroup.name(), truePredicatesCount)); + } + + /** + * Verifies that all predicates defined in + * {@link com.oracle.java.testlibrary.Platform} were either tested or + * explicitly ignored. + */ + private static void verifyCoverage() { + Set allMethods = new HashSet<>(); + for (MethodGroup group : MethodGroup.values()) { + allMethods.addAll(group.methodNames); + } + + for (Method m : Platform.class.getMethods()) { + if (m.getParameterCount() == 0 + && m.getReturnType() == boolean.class) { + Asserts.assertTrue(allMethods.contains(m.getName()), + "All Platform's methods with signature '():Z' should " + + "be tested "); + } + } + } + + /** + * Evaluates predicate method with name {@code name} defined in + * {@link com.oracle.java.testlibrary.Platform}. + * + * @param name The name of a predicate to be evaluated. + * @return evaluated predicate's value. + * @throws java.lang.Error if predicate is not defined or could not be + * evaluated. + */ + private static boolean evaluatePredicate(String name) { + try { + System.out.printf("Trying to evaluate predicate with name %s%n", + name); + boolean value + = (Boolean) Platform.class.getMethod(name).invoke(null); + System.out.printf("Predicate evaluated to: %s%n", value); + return value; + } catch (NoSuchMethodException e) { + throw new Error("Predicate with name " + name + + " is not defined in " + Platform.class.getName(), e); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new Error("Unable to evaluate predicate " + name, e); + } + } +}