Path: blob/master/src/hotspot/share/classfile/metadataOnStackMark.cpp
40949 views
/*1* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "classfile/metadataOnStackMark.hpp"26#include "code/codeCache.hpp"27#include "compiler/compileBroker.hpp"28#include "oops/metadata.hpp"29#include "prims/jvmtiImpl.hpp"30#include "runtime/synchronizer.hpp"31#include "runtime/thread.hpp"32#include "services/threadService.hpp"33#include "utilities/chunkedList.hpp"34#if INCLUDE_JVMCI35#include "jvmci/jvmci.hpp"36#endif3738MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL;39MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL;4041MetadataOnStackBuffer* MetadataOnStackMark::_current_buffer = NULL;42NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)4344class MetadataOnStackClosure : public MetadataClosure {45void do_metadata(Metadata* m) { Metadata::mark_on_stack(m); }46};4748// Walk metadata on the stack and mark it so that redefinition doesn't delete49// it. Class unloading only deletes in-error class files, methods created by50// the relocator and dummy constant pools. None of these appear anywhere except51// in metadata Handles.52MetadataOnStackMark::MetadataOnStackMark(bool walk_all_metadata, bool redefinition_walk) {53assert(SafepointSynchronize::is_at_safepoint(), "sanity check");54assert(_used_buffers == NULL, "sanity check");55assert(!_is_active, "MetadataOnStackMarks do not nest");56assert(!redefinition_walk || walk_all_metadata,57"walk_all_metadata must be true for redefinition_walk");58NOT_PRODUCT(_is_active = true;)5960Threads::metadata_handles_do(Metadata::mark_on_stack);6162if (walk_all_metadata) {63MetadataOnStackClosure md_on_stack;64Threads::metadata_do(&md_on_stack);65if (redefinition_walk) {66// We have to walk the whole code cache during redefinition.67CodeCache::metadata_do(&md_on_stack);68} else {69CodeCache::old_nmethods_do(&md_on_stack);70}71CompileBroker::mark_on_stack();72ThreadService::metadata_do(Metadata::mark_on_stack);73#if INCLUDE_JVMCI74JVMCI::metadata_do(Metadata::mark_on_stack);75#endif76}77}7879MetadataOnStackMark::~MetadataOnStackMark() {80assert(SafepointSynchronize::is_at_safepoint(), "sanity check");81// Unmark everything that was marked. Can't do the same walk because82// redefine classes messes up the code cache so the set of methods83// might not be the same.84retire_current_buffer();8586MetadataOnStackBuffer* buffer = _used_buffers;87while (buffer != NULL) {88// Clear on stack state for all metadata.89size_t size = buffer->size();90for (size_t i = 0; i < size; i++) {91Metadata* md = buffer->at(i);92md->set_on_stack(false);93}9495MetadataOnStackBuffer* next = buffer->next_used();9697// Move the buffer to the free list.98buffer->clear();99buffer->set_next_used(NULL);100buffer->set_next_free(_free_buffers);101_free_buffers = buffer;102103// Step to next used buffer.104buffer = next;105}106107_used_buffers = NULL;108109NOT_PRODUCT(_is_active = false;)110}111112void MetadataOnStackMark::retire_buffer(MetadataOnStackBuffer* buffer) {113if (buffer == NULL) {114return;115}116buffer->set_next_used(_used_buffers);117_used_buffers = buffer;118}119120// Current buffer is full or we're ready to walk them, add it to the used list.121void MetadataOnStackMark::retire_current_buffer() {122retire_buffer(_current_buffer);123_current_buffer = NULL;124}125126// Get buffer off free list.127MetadataOnStackBuffer* MetadataOnStackMark::allocate_buffer() {128MetadataOnStackBuffer* allocated = _free_buffers;129130if (allocated != NULL) {131_free_buffers = allocated->next_free();132}133134if (allocated == NULL) {135allocated = new MetadataOnStackBuffer();136}137138assert(!allocated->is_full(), "Should not be full: " PTR_FORMAT, p2i(allocated));139140return allocated;141}142143// Record which objects are marked so we can unmark the same objects.144void MetadataOnStackMark::record(Metadata* m) {145assert(_is_active, "metadata on stack marking is active");146147MetadataOnStackBuffer* buffer = _current_buffer;148149if (buffer != NULL && buffer->is_full()) {150retire_buffer(buffer);151buffer = NULL;152}153154if (buffer == NULL) {155buffer = allocate_buffer();156_current_buffer = buffer;157}158159buffer->push(m);160}161162163