Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp
32285 views
/*1* Copyright (c) 2013, 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"3435volatile MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL;36volatile MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL;3738NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)3940// Walk metadata on the stack and mark it so that redefinition doesn't delete41// it. Class unloading also walks the previous versions and might try to42// delete it, so this class is used by class unloading also.43MetadataOnStackMark::MetadataOnStackMark(bool has_redefined_a_class) {44assert(SafepointSynchronize::is_at_safepoint(), "sanity check");45assert(_used_buffers == NULL, "sanity check");46NOT_PRODUCT(_is_active = true;)4748Threads::metadata_do(Metadata::mark_on_stack);49if (has_redefined_a_class) {50CodeCache::alive_nmethods_do(nmethod::mark_on_stack);51}52CompileBroker::mark_on_stack();53JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);54ThreadService::metadata_do(Metadata::mark_on_stack);55}5657MetadataOnStackMark::~MetadataOnStackMark() {58assert(SafepointSynchronize::is_at_safepoint(), "sanity check");59// Unmark everything that was marked. Can't do the same walk because60// redefine classes messes up the code cache so the set of methods61// might not be the same.6263retire_buffer_for_thread(Thread::current());6465MetadataOnStackBuffer* buffer = const_cast<MetadataOnStackBuffer* >(_used_buffers);66while (buffer != NULL) {67// Clear on stack state for all metadata.68size_t size = buffer->size();69for (size_t i = 0; i < size; i++) {70Metadata* md = buffer->at(i);71md->set_on_stack(false);72}7374MetadataOnStackBuffer* next = buffer->next_used();7576// Move the buffer to the free list.77buffer->clear();78buffer->set_next_used(NULL);79buffer->set_next_free(const_cast<MetadataOnStackBuffer*>(_free_buffers));80_free_buffers = buffer;8182// Step to next used buffer.83buffer = next;84}8586_used_buffers = NULL;8788NOT_PRODUCT(_is_active = false;)89}9091void MetadataOnStackMark::retire_buffer(MetadataOnStackBuffer* buffer) {92if (buffer == NULL) {93return;94}9596MetadataOnStackBuffer* old_head;9798do {99old_head = const_cast<MetadataOnStackBuffer*>(_used_buffers);100buffer->set_next_used(old_head);101} while (Atomic::cmpxchg_ptr(buffer, &_used_buffers, old_head) != old_head);102}103104void MetadataOnStackMark::retire_buffer_for_thread(Thread* thread) {105retire_buffer(thread->metadata_on_stack_buffer());106thread->set_metadata_on_stack_buffer(NULL);107}108109bool MetadataOnStackMark::has_buffer_for_thread(Thread* thread) {110return thread->metadata_on_stack_buffer() != NULL;111}112113MetadataOnStackBuffer* MetadataOnStackMark::allocate_buffer() {114MetadataOnStackBuffer* allocated;115MetadataOnStackBuffer* new_head;116117do {118allocated = const_cast<MetadataOnStackBuffer*>(_free_buffers);119if (allocated == NULL) {120break;121}122new_head = allocated->next_free();123} while (Atomic::cmpxchg_ptr(new_head, &_free_buffers, allocated) != allocated);124125if (allocated == NULL) {126allocated = new MetadataOnStackBuffer();127}128129assert(!allocated->is_full(), err_msg("Should not be full: " PTR_FORMAT, p2i(allocated)));130131return allocated;132}133134// Record which objects are marked so we can unmark the same objects.135void MetadataOnStackMark::record(Metadata* m, Thread* thread) {136assert(_is_active, "metadata on stack marking is active");137138MetadataOnStackBuffer* buffer = thread->metadata_on_stack_buffer();139140if (buffer != NULL && buffer->is_full()) {141retire_buffer(buffer);142buffer = NULL;143}144145if (buffer == NULL) {146buffer = allocate_buffer();147thread->set_metadata_on_stack_buffer(buffer);148}149150buffer->push(m);151}152153154