# HG changeset patch # User rkennke # Date 1474460140 -7200 # Wed Sep 21 14:15:40 2016 +0200 # Node ID c5e2b030c63be385cba58799423cac209faed057 # Parent 76938ff28105c38cd975b9a6e925e83af5cce810 Pin regions that contain JNI critical regions, instead of bail-and-retry protocol. diff --git a/make/test/JtregNative.gmk b/make/test/JtregNative.gmk --- a/make/test/JtregNative.gmk +++ b/make/test/JtregNative.gmk @@ -54,6 +54,7 @@ $(HOTSPOT_TOPDIR)/test/testlibrary/jvmti \ $(HOTSPOT_TOPDIR)/test/compiler/jvmci/jdk.vm.ci.code.test \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetModulesInfo \ + $(HOTSPOT_TOPDIR)/test/gc/shenandoah \ # # Add conditional directories here when needed. diff --git a/src/share/vm/gc/shared/collectedHeap.cpp b/src/share/vm/gc/shared/collectedHeap.cpp --- a/src/share/vm/gc/shared/collectedHeap.cpp +++ b/src/share/vm/gc/shared/collectedHeap.cpp @@ -142,6 +142,14 @@ assert_locked_or_safepoint(CodeCache_lock); } +void CollectedHeap::enter_critical(oop o) { + // Defaults to no-op +} + +void CollectedHeap::exit_critical(oop o) { + // Defaults to no-op +} + void CollectedHeap::trace_heap(GCWhen::Type when, const GCTracer* gc_tracer) { const GCHeapSummary& heap_summary = create_heap_summary(); gc_tracer->report_gc_heap_summary(when, heap_summary); diff --git a/src/share/vm/gc/shared/collectedHeap.hpp b/src/share/vm/gc/shared/collectedHeap.hpp --- a/src/share/vm/gc/shared/collectedHeap.hpp +++ b/src/share/vm/gc/shared/collectedHeap.hpp @@ -592,6 +592,9 @@ virtual void register_nmethod(nmethod* nm); virtual void unregister_nmethod(nmethod* nm); + virtual void enter_critical(oop o); + virtual void exit_critical(oop o); + void trace_heap_before_gc(const GCTracer* gc_tracer); void trace_heap_after_gc(const GCTracer* gc_tracer); diff --git a/src/share/vm/gc/shenandoah/shenandoahCollectorPolicy.cpp b/src/share/vm/gc/shenandoah/shenandoahCollectorPolicy.cpp --- a/src/share/vm/gc/shenandoah/shenandoahCollectorPolicy.cpp +++ b/src/share/vm/gc/shenandoah/shenandoahCollectorPolicy.cpp @@ -127,7 +127,7 @@ while (i < end) { ShenandoahHeapRegion* region = sorted_regions->get(i++); - if (region->garbage() > _garbage_threshold && ! region->is_humongous()) { + if (region->garbage() > _garbage_threshold && ! region->is_humongous() && ! region->is_pinned()) { // tty->print("choose region %d with garbage = " SIZE_FORMAT " and live = " SIZE_FORMAT " and _garbage_threshold = " SIZE_FORMAT "\n", // region->region_number(), region->garbage(), region->getLiveData(), _garbage_threshold); @@ -158,7 +158,7 @@ size_t garbage = 0; while (i < end && garbage < min_garbage) { ShenandoahHeapRegion* region = sorted_regions->get(i++); - if (region->garbage() > _garbage_threshold && ! region->is_humongous()) { + if (region->garbage() > _garbage_threshold && ! region->is_humongous() && ! region->is_pinned()) { collection_set->add_region(region); garbage += region->garbage(); region->set_is_in_collection_set(true); @@ -175,7 +175,8 @@ while (i < end) { ShenandoahHeapRegion* region = ordered_regions->get(i++); if ((! region->is_in_collection_set()) - && (! region->is_humongous())) { + && (! region->is_humongous()) + && (! region->is_pinned())) { free_set->add_region(region); } } diff --git a/src/share/vm/gc/shenandoah/shenandoahConcurrentThread.cpp b/src/share/vm/gc/shenandoah/shenandoahConcurrentThread.cpp --- a/src/share/vm/gc/shenandoah/shenandoahConcurrentThread.cpp +++ b/src/share/vm/gc/shenandoah/shenandoahConcurrentThread.cpp @@ -25,7 +25,6 @@ #include "gc/shenandoah/shenandoahConcurrentThread.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" -#include "gc/shenandoah/shenandoahJNICritical.hpp" #include "gc/shenandoah/shenandoahMonitoringSupport.hpp" #include "gc/shenandoah/vm_operations_shenandoah.hpp" #include "memory/iterator.hpp" @@ -66,7 +65,7 @@ TraceCollectorStats tcs(heap->monitoring_support()->full_collection_counters()); TraceMemoryManagerStats tmms(true, _full_gc_cause); VM_ShenandoahFullGC full_gc(_full_gc_cause); - heap->jni_critical()->execute_in_vm_thread(&full_gc); + VMThread::execute(&full_gc); } MonitorLockerEx ml(&_full_gc_lock); _do_full_gc = false; @@ -103,7 +102,7 @@ TraceCollectorStats tcs(heap->monitoring_support()->stw_collection_counters()); VM_ShenandoahStartEvacuation finishMark; heap->shenandoahPolicy()->record_phase_start(ShenandoahCollectorPolicy::final_mark_gross); - heap->jni_critical()->execute_in_vm_thread(&finishMark); + VMThread::execute(&finishMark); heap->shenandoahPolicy()->record_phase_end(ShenandoahCollectorPolicy::final_mark_gross); } diff --git a/src/share/vm/gc/shenandoah/shenandoahHeap.cpp b/src/share/vm/gc/shenandoah/shenandoahHeap.cpp --- a/src/share/vm/gc/shenandoah/shenandoahHeap.cpp +++ b/src/share/vm/gc/shenandoah/shenandoahHeap.cpp @@ -39,7 +39,6 @@ #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahHeapRegionSet.hpp" #include "gc/shenandoah/shenandoahHumongous.hpp" -#include "gc/shenandoah/shenandoahJNICritical.hpp" #include "gc/shenandoah/shenandoahMarkCompact.hpp" #include "gc/shenandoah/shenandoahMonitoringSupport.hpp" #include "gc/shenandoah/shenandoahRootProcessor.hpp" @@ -212,7 +211,6 @@ _need_update_refs(false), _need_reset_bitmaps(false), _growing_heap(0), - _jni_critical(new ShenandoahJNICritical()), _gc_timer(new (ResourceObj::C_HEAP, mtGC) ConcurrentGCTimer()) { @@ -1414,6 +1412,7 @@ } void ShenandoahHeap::collect(GCCause::Cause cause) { + assert(cause != GCCause::_gc_locker, "no JNI critical callback"); if (GCCause::is_user_requested_gc(cause)) { if (! DisableExplicitGC) { cancel_concgc(); @@ -1425,13 +1424,6 @@ collector_policy()->set_should_clear_all_soft_refs(true); _concurrent_gc_thread->do_full_gc(cause); - } else if (cause == GCCause::_gc_locker) { - - if (ShenandoahTraceJNICritical) { - tty->print_cr("Resuming deferred evacuation after JNI critical regions"); - } - - jni_critical()->notify_jni_critical(); } } @@ -2086,10 +2078,6 @@ _need_update_refs = need_update_refs; } -ShenandoahJNICritical* ShenandoahHeap::jni_critical() { - return _jni_critical; -} - //fixme this should be in heapregionset ShenandoahHeapRegion* ShenandoahHeap::next_compaction_region(const ShenandoahHeapRegion* r) { size_t region_idx = r->region_number() + 1; @@ -2221,6 +2209,15 @@ void ShenandoahHeap::unregister_nmethod(nmethod* nm) { } +void ShenandoahHeap::enter_critical(oop o) { + heap_region_containing(o)->enter_critical(); +} + +void ShenandoahHeap::exit_critical(oop o) { + heap_region_containing(o)->exit_critical(); +} + + GCTimer* ShenandoahHeap::gc_timer() const { return _gc_timer; } diff --git a/src/share/vm/gc/shenandoah/shenandoahHeap.hpp b/src/share/vm/gc/shenandoah/shenandoahHeap.hpp --- a/src/share/vm/gc/shenandoah/shenandoahHeap.hpp +++ b/src/share/vm/gc/shenandoah/shenandoahHeap.hpp @@ -37,7 +37,6 @@ class ShenandoahConcurrentMark; class ShenandoahConcurrentThread; class ShenandoahMonitoringSupport; -class ShenandoahJNICritical; class ShenandoahAlwaysTrueClosure : public BoolObjectClosure { public: @@ -127,8 +126,6 @@ bool _cancelled_concgc; - ShenandoahJNICritical* _jni_critical; - jbyte _growing_heap; size_t _bytes_allocated_since_cm; @@ -215,6 +212,8 @@ void register_nmethod(nmethod* nm); void unregister_nmethod(nmethod* nm); + void enter_critical(oop o); + void exit_critical(oop o); static ShenandoahHeap* heap(); static ShenandoahHeap* heap_no_check(); @@ -299,7 +298,6 @@ VirtualSpace* storage() const; ShenandoahMonitoringSupport* monitoring_support(); - ShenandoahJNICritical* jni_critical(); ShenandoahConcurrentMark* concurrentMark() { return _scm;} ReferenceProcessor* ref_processor() { return _ref_processor;} diff --git a/src/share/vm/gc/shenandoah/shenandoahHeapRegion.cpp b/src/share/vm/gc/shenandoah/shenandoahHeapRegion.cpp --- a/src/share/vm/gc/shenandoah/shenandoahHeapRegion.cpp +++ b/src/share/vm/gc/shenandoah/shenandoahHeapRegion.cpp @@ -419,3 +419,18 @@ void ShenandoahHeapRegion::set_top_prev_mark_bitmap(HeapWord* top) { _top_prev_mark_bitmap = top; } + +void ShenandoahHeapRegion::enter_critical() { + assert(_critical_pins >= 0, "sanity"); + Atomic::inc(&_critical_pins); +} + +void ShenandoahHeapRegion::exit_critical() { + Atomic::dec(&_critical_pins); + assert(_critical_pins >= 0, "sanity"); +} + +bool ShenandoahHeapRegion::is_pinned() { + assert(_critical_pins >= 0, "sanity"); + return _critical_pins > 0; +} diff --git a/src/share/vm/gc/shenandoah/shenandoahHeapRegion.hpp b/src/share/vm/gc/shenandoah/shenandoahHeapRegion.hpp --- a/src/share/vm/gc/shenandoah/shenandoahHeapRegion.hpp +++ b/src/share/vm/gc/shenandoah/shenandoahHeapRegion.hpp @@ -51,6 +51,8 @@ HeapWord* _new_top; + jint _critical_pins; + #ifdef ASSERT int _mem_protection_level; #endif @@ -138,6 +140,11 @@ void set_new_top(HeapWord* new_top) { _new_top = new_top; } HeapWord* new_top() const { return _new_top; } + void enter_critical(); + void exit_critical(); + + bool is_pinned(); + private: void do_reset(); diff --git a/src/share/vm/gc/shenandoah/shenandoahJNICritical.cpp b/src/share/vm/gc/shenandoah/shenandoahJNICritical.cpp deleted file mode 100644 --- a/src/share/vm/gc/shenandoah/shenandoahJNICritical.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2015, Red Hat, Inc. and/or its affiliates. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "gc/shenandoah/shenandoahJNICritical.hpp" -#include "gc/shenandoah/shenandoahHeap.hpp" - -#include "gc/shared/gcLocker.hpp" -#include "runtime/mutexLocker.hpp" -#include "runtime/thread.hpp" -#include "runtime/vmThread.hpp" - -class VM_ShenandoahJNICriticalOperation : public VM_Operation { -private: - VM_Operation* _target; -public: - VM_ShenandoahJNICriticalOperation(VM_Operation* target); - VMOp_Type type() const; - bool doit_prologue(); - void doit_epilogue(); - void doit(); - const char* name() const; -}; - -ShenandoahJNICritical::ShenandoahJNICritical() : - _lock(Mutex::leaf, "ShenandoahJNICritical_lock", true, Monitor::_safepoint_check_sometimes), - _op_waiting_for_jni_critical(NULL), - _op_ready_for_execution(NULL) -{ -} - -/* - * This is called by the Java thread who leaves the last JNI critical block. - */ -void ShenandoahJNICritical::notify_jni_critical() { - assert(Thread::current()->is_Java_thread(), "call only from Java thread"); - - assert(_op_waiting_for_jni_critical != NULL, "must be waiting for jni critical notification"); - - if (ShenandoahTraceJNICritical) { - tty->print_cr("Shenandoah JNI critical: waiting until task is ready for re-execution"); - } - - { - MonitorLockerEx ml(&_lock); - while (_op_ready_for_execution == NULL) { - ml.wait(); - } - } - - assert(_op_waiting_for_jni_critical != NULL, "must be waiting for jni critical notification"); - assert(_op_ready_for_execution != NULL, "must be ready for re-execution"); - - if (ShenandoahTraceJNICritical) { - tty->print_cr("Shenandoah JNI critical: re-executing VM task after JNI critical notification"); - } - - VMThread::execute(_op_ready_for_execution); - - { - MonitorLockerEx ml(&_lock, Mutex::_no_safepoint_check_flag); - _op_waiting_for_jni_critical = NULL; - _op_ready_for_execution = NULL; - ml.notify(); - } - - if (ShenandoahTraceJNICritical) { - tty->print_cr("Shenandoah JNI critical: resuming Java thread after VM task re-execution"); - } - -} - -/* - * This is called by the VM thread, if it determines that the task must wait - * for JNI critical regions to be left. - */ -void ShenandoahJNICritical::set_waiting_for_jni_before_gc(VM_Operation* op) { - assert(Thread::current()->is_VM_thread(), "call only from VM thread"); - _op_waiting_for_jni_critical = op; -} - -/** - * This is called by the Shenandoah concurrent thread in order - * to execute a VM_Operation on the VM thread, that needs to perform - * a JNI critical region check. - */ -void ShenandoahJNICritical::execute_in_vm_thread(VM_Operation* op) { - assert(_op_waiting_for_jni_critical == NULL, "start out with no waiting op"); - assert(_op_ready_for_execution == NULL, "start out with no ready op"); - VM_ShenandoahJNICriticalOperation jni_op(op); - VMThread::execute(&jni_op); - - { - MonitorLockerEx ml(&_lock, Mutex::_no_safepoint_check_flag); - - if (_op_waiting_for_jni_critical != NULL) { - if (ShenandoahTraceJNICritical) { - tty->print_cr("Shenandoah JNI critical: make task ready for re-execution"); - } - - _op_ready_for_execution = _op_waiting_for_jni_critical; - ml.notify(); - - if (ShenandoahTraceJNICritical) { - tty->print_cr("Shenandoah JNI critical: waiting for task to get re-executed"); - } - - while (_op_ready_for_execution != NULL) { - ml.wait(Mutex::_no_safepoint_check_flag); - } - - if (ShenandoahTraceJNICritical) { - tty->print_cr("Shenandoah JNI critical: resuming concurrent GC thread after task has been re-executed"); - } - } - } - - assert(_op_waiting_for_jni_critical == NULL, "finish with no waiting op"); - assert(_op_ready_for_execution == NULL, "finish with no ready op"); -} - - -VM_ShenandoahJNICriticalOperation::VM_ShenandoahJNICriticalOperation(VM_Operation* target) - : _target(target) { -} - -VM_Operation::VMOp_Type VM_ShenandoahJNICriticalOperation::type() const { - return _target->type(); -} - -const char* VM_ShenandoahJNICriticalOperation::name() const { - return _target->name(); -} - -bool VM_ShenandoahJNICriticalOperation::doit_prologue() { - return _target->doit_prologue(); -} - -void VM_ShenandoahJNICriticalOperation::doit_epilogue() { - _target->doit_epilogue(); -} - -void VM_ShenandoahJNICriticalOperation::doit() { - if (! GCLocker::check_active_before_gc()) { - _target->doit(); - } else { - - if (ShenandoahTraceJNICritical) { - tty->print_cr("Shenandoah JNI critical: Deferring JNI critical op because of active JNI critical regions"); - } - - // This makes the GC background thread wait, and kick off evacuation as - // soon as JNI notifies us that critical regions have all been left. - ShenandoahHeap *sh = ShenandoahHeap::heap(); - sh->jni_critical()->set_waiting_for_jni_before_gc(this); - } -} diff --git a/src/share/vm/gc/shenandoah/shenandoahJNICritical.hpp b/src/share/vm/gc/shenandoah/shenandoahJNICritical.hpp deleted file mode 100644 --- a/src/share/vm/gc/shenandoah/shenandoahJNICritical.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2015, Red Hat, Inc. and/or its affiliates. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHJNICRITICAL_HPP -#define SHARE_VM_GC_SHENANDOAH_SHENANDOAHJNICRITICAL_HPP - -#include "gc/shared/vmGCOperations.hpp" -#include "memory/allocation.hpp" - -class ShenandoahJNICritical : public CHeapObj { -private: - Monitor _lock; - VM_Operation* _op_waiting_for_jni_critical; - VM_Operation* _op_ready_for_execution; -public: - ShenandoahJNICritical(); - void notify_jni_critical(); - void set_waiting_for_jni_before_gc(VM_Operation* op); - void execute_in_vm_thread(VM_Operation* op); -}; - - -#endif // SHARE_VM_GC_SHENANDOAH_SHENANDOAHJNICRITICAL_HPP diff --git a/src/share/vm/gc/shenandoah/shenandoahMarkCompact.cpp b/src/share/vm/gc/shenandoah/shenandoahMarkCompact.cpp --- a/src/share/vm/gc/shenandoah/shenandoahMarkCompact.cpp +++ b/src/share/vm/gc/shenandoah/shenandoahMarkCompact.cpp @@ -357,12 +357,13 @@ ShenandoahHeapRegion* next_from_region(ShenandoahHeapRegionSet* copy_queue) { ShenandoahHeapRegion* from_region = _from_regions->claim_next(); - while (from_region != NULL && from_region->is_humongous()) { + while (from_region != NULL && (from_region->is_humongous() || from_region->is_pinned())) { from_region = _from_regions->claim_next(); } if (from_region != NULL) { assert(copy_queue != NULL, "sanity"); assert(! from_region->is_humongous(), "must not get humongous regions here"); + assert(! from_region->is_pinned(), "no pinned region in mark-compact"); copy_queue->add_region(from_region); } return from_region; diff --git a/src/share/vm/gc/shenandoah/shenandoah_globals.hpp b/src/share/vm/gc/shenandoah/shenandoah_globals.hpp --- a/src/share/vm/gc/shenandoah/shenandoah_globals.hpp +++ b/src/share/vm/gc/shenandoah/shenandoah_globals.hpp @@ -57,9 +57,6 @@ develop(bool, ShenandoahDumpHeapAfterConcurrentMark, false, \ "Dump the ShenanodahHeap After Each Concurrent Mark") \ \ - develop(bool, ShenandoahTraceJNICritical, false, \ - "Trace Shenandoah stalls for JNI critical regions") \ - \ product(bool, ShenandoahTraceHumongous, false, \ "Trace Shenandoah humongous objects") \ \ diff --git a/src/share/vm/gc/shenandoah/vm_operations_shenandoah.cpp b/src/share/vm/gc/shenandoah/vm_operations_shenandoah.cpp --- a/src/share/vm/gc/shenandoah/vm_operations_shenandoah.cpp +++ b/src/share/vm/gc/shenandoah/vm_operations_shenandoah.cpp @@ -90,8 +90,7 @@ void VM_ShenandoahStartEvacuation::doit() { - // We need to do the finish mark here, so that a JNI critical region - // can't divide it from evacuation start. It is critical that we + // It is critical that we // evacuate roots right after finishing marking, so that we don't // get unmarked objects in the roots. ShenandoahHeap *sh = ShenandoahHeap::heap(); diff --git a/src/share/vm/prims/jni.cpp b/src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp +++ b/src/share/vm/prims/jni.cpp @@ -3184,6 +3184,7 @@ } oop a = JNIHandles::resolve_non_null(array); a = oopDesc::bs()->write_barrier(a); + Universe::heap()->enter_critical(a); assert(a->is_array(), "just checking"); BasicType type; if (a->is_objArray()) { @@ -3201,6 +3202,21 @@ JNIWrapper("ReleasePrimitiveArrayCritical"); HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_ENTRY(env, array, carray, mode); // The array, carray and mode arguments are ignored + oop a = JNIHandles::resolve_non_null(array); + a = oopDesc::bs()->read_barrier(a); +#ifdef ASSERT + assert(a->is_array(), "just checking"); + BasicType type; + if (a->is_objArray()) { + type = T_OBJECT; + } else { + type = TypeArrayKlass::cast(a->klass())->element_type(); + } + void* ret = arrayOop(a)->base(type); + assert(ret == carray, "check array not moved"); +#endif + + Universe::heap()->exit_critical(a); GCLocker::unlock_critical(thread); HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_RETURN(); JNI_END @@ -3211,6 +3227,8 @@ HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY(env, string, (uintptr_t *) isCopy); GCLocker::lock_critical(thread); oop s = JNIHandles::resolve_non_null(string); + s = oopDesc::bs()->write_barrier(s); + Universe::heap()->enter_critical(s); typeArrayOop s_value = java_lang_String::value(s); bool is_latin1 = java_lang_String::is_latin1(s); if (isCopy != NULL) { @@ -3241,6 +3259,8 @@ HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY(env, str, (uint16_t *) chars); // The str and chars arguments are ignored for UTF16 strings oop s = JNIHandles::resolve_non_null(str); + s = oopDesc::bs()->read_barrier(s); + Universe::heap()->exit_critical(s); bool is_latin1 = java_lang_String::is_latin1(s); if (is_latin1) { // For latin1 string, free jchar array allocated by earlier call to GetStringCritical. diff --git a/test/TEST.groups b/test/TEST.groups --- a/test/TEST.groups +++ b/test/TEST.groups @@ -331,6 +331,9 @@ hotspot_fast_compiler_closed = \ sanity/ExecuteInternalVMTests.java +hotspot_fast_gc_shenandoah = \ + gc/shenandoah/ + hotspot_fast_gc_1 = \ gc/g1/ diff --git a/test/gc/shenandoah/ShenandoahJNICritical.java b/test/gc/shenandoah/ShenandoahJNICritical.java new file mode 100644 --- /dev/null +++ b/test/gc/shenandoah/ShenandoahJNICritical.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016 Red Hat, Inc. and/or its affiliates. + * + * 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 test JNI critical arrays support in Shenandoah + * @run main/othervm/native -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive ShenandoahJNICritical + */ + +import java.util.Arrays; + +public class ShenandoahJNICritical { + static { + System.loadLibrary("ShenandoahJNICritical"); + } + + private static final int NUM_RUNS = 10000; + private static final int ARRAY_SIZE=10000; + private static int[] a; + private static int[] b; + private static native void copyAtoB(int[] a, int[] b); + + public static void main(String[] args) { + a = new int[ARRAY_SIZE]; + b = new int[ARRAY_SIZE]; + for (int i = 0; i < NUM_RUNS; i++) { + test(); + } + } + + private static void test() { + int[] a1 = new int[ARRAY_SIZE]; + int[] b1 = new int[ARRAY_SIZE]; + fillArray(a); + copyAtoB(a, b); + copyAtoB(a1, b1); // Don't optimize out garbage arrays. + if (! Arrays.equals(a, b)) { + throw new RuntimeException("arrays not equal"); + } + } + + private static void fillArray(int[] array) { + for (int i = 0; i < ARRAY_SIZE; i++) { + int val = (int) (Math.random() * Integer.MAX_VALUE); + array[i] = val; + } + } +} diff --git a/test/gc/shenandoah/libShenandoahJNICritical.c b/test/gc/shenandoah/libShenandoahJNICritical.c new file mode 100644 --- /dev/null +++ b/test/gc/shenandoah/libShenandoahJNICritical.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016 Red Hat, Inc. and/or its affiliates. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include +#include + +JNIEXPORT void JNICALL +Java_ShenandoahJNICritical_copyAtoB(JNIEnv *env, jclass unused, jintArray a, jintArray b) { + jint len = (*env)->GetArrayLength(env, a); + jint* aa = (*env)->GetPrimitiveArrayCritical(env, a, 0); + jint* bb = (*env)->GetPrimitiveArrayCritical(env, b, 0); + memcpy(bb, aa, len * sizeof(jint)); + (*env)->ReleasePrimitiveArrayCritical(env, b, bb, 0); + (*env)->ReleasePrimitiveArrayCritical(env, a, aa, 0); +}