--- old/src/hotspot/share/gc/z/zNMethodTable.cpp 2019-02-20 21:52:15.887933058 +0100 +++ new/src/hotspot/share/gc/z/zNMethodTable.cpp 2019-02-20 21:52:15.303923109 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, 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,16 +27,16 @@ #include "code/icBuffer.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetNMethod.hpp" -#include "gc/z/zArray.inline.hpp" #include "gc/z/zGlobals.hpp" #include "gc/z/zHash.inline.hpp" #include "gc/z/zLock.inline.hpp" +#include "gc/z/zNMethodAllocator.hpp" #include "gc/z/zNMethodTable.hpp" #include "gc/z/zOopClosures.inline.hpp" #include "gc/z/zTask.hpp" #include "gc/z/zWorkers.hpp" #include "logging/log.hpp" -#include "memory/allocation.inline.hpp" +#include "memory/allocation.hpp" #include "memory/resourceArea.hpp" #include "runtime/atomic.hpp" #include "runtime/orderAccess.hpp" @@ -72,12 +72,12 @@ // Allocate memory for the ZNMethodDataOops object // plus the immediate oop* array that follows right after. const size_t size = ZNMethodDataOops::header_size() + (sizeof(oop*) * immediates.length()); - void* const data = NEW_C_HEAP_ARRAY(uint8_t, size, mtGC); - return ::new (data) ZNMethodDataOops(immediates, has_non_immediates); + void* const mem = ZNMethodAllocator::allocate(size); + return ::new (mem) ZNMethodDataOops(immediates, has_non_immediates); } void ZNMethodDataOops::destroy(ZNMethodDataOops* oops) { - ZNMethodTable::safe_delete(oops); + ZNMethodAllocator::free(oops); } ZNMethodDataOops::ZNMethodDataOops(const GrowableArray& immediates, bool has_non_immediates) : @@ -124,13 +124,13 @@ }; ZNMethodData* ZNMethodData::create(nmethod* nm) { - void* const method = NEW_C_HEAP_ARRAY(uint8_t, sizeof(ZNMethodData), mtGC); - return ::new (method) ZNMethodData(nm); + void* const mem = ZNMethodAllocator::allocate(sizeof(ZNMethodData)); + return ::new (mem) ZNMethodData(nm); } void ZNMethodData::destroy(ZNMethodData* data) { - ZNMethodDataOops::destroy(data->oops()); - ZNMethodTable::safe_delete(data); + ZNMethodAllocator::free(data->oops()); + ZNMethodAllocator::free(data); } ZNMethodData::ZNMethodData(nmethod* nm) : @@ -161,27 +161,10 @@ size_t ZNMethodTable::_size = 0; ZNMethodTableEntry* ZNMethodTable::_iter_table = NULL; size_t ZNMethodTable::_iter_table_size = 0; -ZArray ZNMethodTable::_iter_deferred_deletes; size_t ZNMethodTable::_nregistered = 0; size_t ZNMethodTable::_nunregistered = 0; volatile size_t ZNMethodTable::_claimed = 0; -void ZNMethodTable::safe_delete(void* data) { - assert(CodeCache_lock->owned_by_self(), "Lock must be held"); - - if (data == NULL) { - return; - } - - if (_iter_table != NULL) { - // Iteration in progress, defer delete - _iter_deferred_deletes.add(data); - } else { - // Iteration not in progress, delete now - FREE_C_HEAP_ARRAY(uint8_t, data); - } -} - void ZNMethodTable::attach_gc_data(nmethod* nm) { GrowableArray immediate_oops; bool non_immediate_oops = false; @@ -479,11 +462,13 @@ void ZNMethodTable::nmethods_do_begin() { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + // Make sure we don't free data while iterating + ZNMethodAllocator::activate_deferred_frees(); + // Prepare iteration _iter_table = _table; _iter_table_size = _size; _claimed = 0; - assert(_iter_deferred_deletes.is_empty(), "Should be emtpy"); } void ZNMethodTable::nmethods_do_end() { @@ -497,12 +482,8 @@ assert(_claimed >= _iter_table_size, "Failed to claim all table entries"); - // Process deferred deletes - ZArrayIterator iter(&_iter_deferred_deletes); - for (void* data; iter.next(&data);) { - FREE_C_HEAP_ARRAY(uint8_t, data); - } - _iter_deferred_deletes.clear(); + // Process deferred frees + ZNMethodAllocator::deactivate_and_process_deferred_frees(); // Notify iteration done CodeCache_lock->notify_all(); --- old/src/hotspot/share/gc/z/zNMethodTable.hpp 2019-02-20 21:52:16.627945664 +0100 +++ new/src/hotspot/share/gc/z/zNMethodTable.hpp 2019-02-20 21:52:16.035935579 +0100 @@ -30,6 +30,8 @@ #include "gc/z/zNMethodTableEntry.hpp" #include "memory/allocation.hpp" +class ZNMethodData; +class ZNMethodDataOops; class ZWorkers; class ZNMethodClosure { @@ -43,7 +45,6 @@ static size_t _size; static ZNMethodTableEntry* _iter_table; static size_t _iter_table_size; - static ZArray _iter_deferred_deletes; static size_t _nregistered; static size_t _nunregistered; static volatile size_t _claimed ATTRIBUTE_ALIGNED(ZCacheLineSize); @@ -66,8 +67,6 @@ static void log_unregister(const nmethod* nm); public: - static void safe_delete(void* data); - static size_t registered_nmethods(); static size_t unregistered_nmethods(); --- /dev/null 2019-02-14 11:31:37.500399000 +0100 +++ new/src/hotspot/share/gc/z/zNMethodAllocator.cpp 2019-02-20 21:52:16.759947913 +0100 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/z/zArray.inline.hpp" +#include "gc/z/zNMethodAllocator.hpp" +#include "memory/allocation.hpp" + +ZArray ZNMethodAllocator::_deferred_frees; +bool ZNMethodAllocator::_defer_frees(false); + +void ZNMethodAllocator::immediate_free(void* data) { + FREE_C_HEAP_ARRAY(uint8_t, data); +} + +void ZNMethodAllocator::deferred_free(void* data) { + _deferred_frees.add(data); +} + +void* ZNMethodAllocator::allocate(size_t size) { + return NEW_C_HEAP_ARRAY(uint8_t, size, mtGC); +} + +void ZNMethodAllocator::free(void* data) { + if (data == NULL) { + return; + } + + if (_defer_frees) { + deferred_free(data); + } else { + immediate_free(data); + } +} + +void ZNMethodAllocator::activate_deferred_frees() { + assert(_deferred_frees.is_empty(), "precondition"); + _defer_frees = true; +} + +void ZNMethodAllocator::deactivate_and_process_deferred_frees() { + _defer_frees = false; + + ZArrayIterator iter(&_deferred_frees); + for (void* data; iter.next(&data);) { + immediate_free(data); + } + _deferred_frees.clear(); +} --- /dev/null 2019-02-14 11:31:37.500399000 +0100 +++ new/src/hotspot/share/gc/z/zNMethodAllocator.hpp 2019-02-20 21:52:17.511960723 +0100 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_GC_Z_ZNMETHODALLOCATOR_HPP +#define SHARE_GC_Z_ZNMETHODALLOCATOR_HPP + +#include "memory/allocation.hpp" +#include "gc/z/zArray.hpp" + +class ZNMethodAllocator : AllStatic { +private: + static ZArray _deferred_frees; + static bool _defer_frees; + + static void immediate_free(void* data); + static void deferred_free(void* data); + +public: + static void* allocate(size_t size); + static void free(void* data); + + static void activate_deferred_frees(); + static void deactivate_and_process_deferred_frees(); +}; + +#endif // SHARE_GC_Z_ZNMETHODALLOCATOR_HPP