# HG changeset patch # User Michael Haupt # Date 1430296140 -7200 # Node ID 2b03d4ce9bcee6b0078bcacd3910a46610052485 # Parent 33ff6b03fad183d12f76cebcc160982d8a47fcec# Parent 4c3cc6a12df28868994ec3cb9a344d75fa10b797 merge diff -r 33ff6b03fad1 -r 2b03d4ce9bce graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/LoadJavaMirrorWithKlassTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/LoadJavaMirrorWithKlassTest.java Wed Apr 29 08:31:28 2015 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/LoadJavaMirrorWithKlassTest.java Wed Apr 29 10:29:00 2015 +0200 @@ -64,8 +64,8 @@ @Override protected boolean checkLowTierGraph(StructuredGraph graph) { for (ConstantNode constantNode : graph.getNodes().filter(ConstantNode.class)) { - assert constantNode.asJavaConstant() == null || constantNode.asJavaConstant().getKind() != Kind.Object : "Found unexpected object constant " + constantNode + - ", this should have been removed by the LoadJavaMirrorWithKlassPhase."; + assert constantNode.asJavaConstant() == null || constantNode.asJavaConstant().getKind() != Kind.Object || constantNode.asJavaConstant().isDefaultForKind() : "Found unexpected object constant " + + constantNode + ", this should have been removed by the LoadJavaMirrorWithKlassPhase."; } return true; } diff -r 33ff6b03fad1 -r 2b03d4ce9bce graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Wed Apr 29 08:31:28 2015 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Wed Apr 29 10:29:00 2015 +0200 @@ -427,7 +427,7 @@ } public static BytecodePosition processSimpleInfopoint(Invoke invoke, SimpleInfopointNode infopointNode, BytecodePosition incomingPos) { - BytecodePosition pos = incomingPos != null ? incomingPos : new BytecodePosition(toBytecodePosition(invoke.stateAfter()).getCaller(), invoke.asNode().graph().method(), invoke.bci()); + BytecodePosition pos = incomingPos != null ? incomingPos : new BytecodePosition(toBytecodePosition(invoke.stateAfter().outerFrameState()), invoke.asNode().graph().method(), invoke.bci()); infopointNode.addCaller(pos); return pos; } diff -r 33ff6b03fad1 -r 2b03d4ce9bce src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Wed Apr 29 08:31:28 2015 +0200 +++ b/src/share/vm/code/nmethod.cpp Wed Apr 29 10:29:00 2015 +0200 @@ -1463,16 +1463,6 @@ _method = NULL; // Clear the method of this dead nmethod } -#ifdef GRAAL - // The method can only be unloaded after the pointer to the installed code - // Java wrapper is no longer alive. Here we need to clear out this weak - // reference to the dead object. - if (_graal_installed_code != NULL) { - InstalledCode::set_address(_graal_installed_code, 0); - _graal_installed_code = NULL; - } -#endif - // Make the class unloaded - i.e., change state and notify sweeper assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); if (is_in_use()) { @@ -1485,6 +1475,18 @@ // Unregister must be done before the state change Universe::heap()->unregister_nmethod(this); +#ifdef GRAAL + // The method can only be unloaded after the pointer to the installed code + // Java wrapper is no longer alive. Here we need to clear out this weak + // reference to the dead object. Nulling out the reference has to happen + // after the method is unregistered since the original value may be still + // tracked by the rset. + if (_graal_installed_code != NULL) { + InstalledCode::set_address(_graal_installed_code, 0); + _graal_installed_code = NULL; + } +#endif + _state = unloaded; // Log the unloading. @@ -1916,27 +1918,6 @@ unloading_occurred = true; } -#ifdef GRAAL - // Follow Graal method - if (_graal_installed_code != NULL) { - if (_graal_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_graal_installed_code)) { - if (!is_alive->do_object_b(_graal_installed_code)) { - _graal_installed_code = NULL; - } - } else { - if (can_unload(is_alive, (oop*)&_graal_installed_code, unloading_occurred)) { - return; - } - } - } - - if (_speculation_log != NULL) { - if (!is_alive->do_object_b(_speculation_log)) { - _speculation_log = NULL; - } - } -#endif - // Exception cache clean_exception_cache(is_alive); @@ -1983,6 +1964,33 @@ } } +#ifdef GRAAL + // Follow Graal method + BarrierSet* bs = Universe::heap()->barrier_set(); + if (_graal_installed_code != NULL) { + if (_graal_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_graal_installed_code)) { + if (!is_alive->do_object_b(_graal_installed_code)) { + bs->write_ref_nmethod_pre(&_graal_installed_code, this); + _graal_installed_code = NULL; + bs->write_ref_nmethod_post(&_graal_installed_code, this); + } + } else { + if (can_unload(is_alive, (oop*)&_graal_installed_code, unloading_occurred)) { + return; + } + } + } + + if (_speculation_log != NULL) { + if (!is_alive->do_object_b(_speculation_log)) { + bs->write_ref_nmethod_pre(&_speculation_log, this); + _speculation_log = NULL; + bs->write_ref_nmethod_post(&_speculation_log, this); + } + } +#endif + + // Ensure that all metadata is still alive verify_metadata_loaders(low_boundary, is_alive); } @@ -2182,6 +2190,32 @@ return postponed; } +#ifdef GRAAL + // Follow Graal method + BarrierSet* bs = Universe::heap()->barrier_set(); + if (_graal_installed_code != NULL) { + if (_graal_installed_code->is_a(HotSpotNmethod::klass()) && HotSpotNmethod::isDefault(_graal_installed_code)) { + if (!is_alive->do_object_b(_graal_installed_code)) { + bs->write_ref_nmethod_pre(&_graal_installed_code, this); + _graal_installed_code = NULL; + bs->write_ref_nmethod_post(&_graal_installed_code, this); + } + } else { + if (can_unload(is_alive, (oop*)&_graal_installed_code, unloading_occurred)) { + is_unloaded = true; + } + } + } + + if (_speculation_log != NULL) { + if (!is_alive->do_object_b(_speculation_log)) { + bs->write_ref_nmethod_pre(&_speculation_log, this); + _speculation_log = NULL; + bs->write_ref_nmethod_post(&_speculation_log, this); + } + } +#endif + // Ensure that all metadata is still alive verify_metadata_loaders(low_boundary, is_alive); diff -r 33ff6b03fad1 -r 2b03d4ce9bce src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Apr 29 08:31:28 2015 +0200 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Apr 29 10:29:00 2015 +0200 @@ -4830,11 +4830,14 @@ bool during_im = _g1h->g1_policy()->during_initial_mark_pause(); bool trace_metadata = during_im && ClassUnloadingWithConcurrentMark; + // Without eager nmethod unloading, we need to treat all oops in code cache as strong during the initial mark + bool trace_codecache = during_im && !ClassUnloadingWithConcurrentMark; + BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots); BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots); process_roots(false, // no scoping; this is parallel code - SharedHeap::SO_None, + trace_codecache ? SharedHeap::SO_AllCodeCache : SharedHeap::SO_None, &buf_scan_non_heap_roots, &buf_scan_non_heap_weak_roots, scan_strong_clds, diff -r 33ff6b03fad1 -r 2b03d4ce9bce src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp --- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Wed Apr 29 08:31:28 2015 +0200 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Wed Apr 29 10:29:00 2015 +0200 @@ -255,3 +255,60 @@ } } } + +void G1SATBCardTableModRefBS::write_ref_nmethod_pre(oop* dst, nmethod* nm) { + oop obj = oopDesc::load_heap_oop(dst); + if (obj != NULL) { + G1CollectedHeap* g1h = (G1CollectedHeap*)Universe::heap(); + HeapRegion* hr = g1h->heap_region_containing(obj); + assert(!hr->continuesHumongous(), + err_msg("trying to add code root "INTPTR_FORMAT" in continuation of humongous region "HR_FORMAT + " starting at "HR_FORMAT, + (intptr_t)nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region()))); + hr->add_strong_code_root(nm); + } +} + +class G1EnsureLastRefToRegion : public OopClosure { + G1CollectedHeap* _g1h; + HeapRegion* _hr; + oop* _dst; + + bool _value; +public: + G1EnsureLastRefToRegion(G1CollectedHeap* g1h, HeapRegion* hr, oop* dst) : + _g1h(g1h), _hr(hr), _dst(dst), _value(true) {} + + void do_oop(oop* p) { + if (_value && p != _dst) { + oop obj = oopDesc::load_heap_oop(p); + if (obj != NULL) { + HeapRegion* hr = _g1h->heap_region_containing(obj); + if (hr == _hr) { + // Another reference to the same region. + _value = false; + } + } + } + } + void do_oop(narrowOop* p) { ShouldNotReachHere(); } + bool value() const { return _value; } +}; + +void G1SATBCardTableModRefBS::write_ref_nmethod_post(oop* dst, nmethod* nm) { + oop obj = oopDesc::load_heap_oop(dst); + if (obj != NULL) { + G1CollectedHeap* g1h = (G1CollectedHeap*)Universe::heap(); + HeapRegion* hr = g1h->heap_region_containing(obj); + assert(!hr->continuesHumongous(), + err_msg("trying to remove code root "INTPTR_FORMAT" in continuation of humongous region "HR_FORMAT + " starting at "HR_FORMAT, + (intptr_t)nm, HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region()))); + G1EnsureLastRefToRegion ensure_last_ref(g1h, hr, dst); + nm->oops_do(&ensure_last_ref); + if (ensure_last_ref.value()) { + // Last reference to this region, remove the nmethod from the rset. + hr->remove_strong_code_root(nm); + } + } +} diff -r 33ff6b03fad1 -r 2b03d4ce9bce src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp --- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Wed Apr 29 08:31:28 2015 +0200 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Wed Apr 29 10:29:00 2015 +0200 @@ -126,6 +126,9 @@ jbyte val = _byte_map[card_index]; return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val(); } + void write_ref_nmethod_pre(oop* dst, nmethod* nm); + void write_ref_nmethod_post(oop* dst, nmethod* nm); + }; class G1SATBCardTableLoggingModRefBSChangedListener : public G1MappingChangedListener { diff -r 33ff6b03fad1 -r 2b03d4ce9bce src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Wed Apr 29 08:31:28 2015 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Wed Apr 29 10:29:00 2015 +0200 @@ -509,7 +509,12 @@ HotSpotInstalledCode::set_codeSize(installed_code_handle, cb->code_size()); } nmethod* nm = cb->as_nmethod_or_null(); - assert(nm == NULL || !installed_code_handle->is_scavengable() || nm->on_scavenge_root_list(), "nm should be scavengable if installed_code is scavengable"); + if (nm != NULL && installed_code_handle->is_scavengable()) { + assert(nm->detect_scavenge_root_oops(), "nm should be scavengable if installed_code is scavengable"); + if (!UseG1GC) { + assert(nm->on_scavenge_root_list(), "nm should be on scavengable list"); + } + } } } return result; diff -r 33ff6b03fad1 -r 2b03d4ce9bce src/share/vm/memory/barrierSet.hpp --- a/src/share/vm/memory/barrierSet.hpp Wed Apr 29 08:31:28 2015 +0200 +++ b/src/share/vm/memory/barrierSet.hpp Wed Apr 29 10:29:00 2015 +0200 @@ -145,6 +145,9 @@ static void static_write_ref_array_pre(HeapWord* start, size_t count); static void static_write_ref_array_post(HeapWord* start, size_t count); + virtual void write_ref_nmethod_pre(oop* dst, nmethod* nm) {} + virtual void write_ref_nmethod_post(oop* dst, nmethod* nm) {} + protected: virtual void write_ref_array_work(MemRegion mr) = 0; public: