src/share/vm/classfile/metadataOnStackMark.cpp

Thu, 12 Oct 2017 21:27:07 +0800

author
aoqi
date
Thu, 12 Oct 2017 21:27:07 +0800
changeset 7535
7ae4e26cb1e0
parent 7333
b12a2a9b05ca
parent 6876
710a3c8b516e
child 9203
53eec13fbaa5
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #include "precompiled.hpp"
aoqi@0 26 #include "classfile/metadataOnStackMark.hpp"
aoqi@0 27 #include "code/codeCache.hpp"
aoqi@0 28 #include "compiler/compileBroker.hpp"
aoqi@0 29 #include "oops/metadata.hpp"
aoqi@0 30 #include "prims/jvmtiImpl.hpp"
aoqi@0 31 #include "runtime/synchronizer.hpp"
aoqi@0 32 #include "runtime/thread.hpp"
aoqi@0 33 #include "services/threadService.hpp"
stefank@7333 34 #include "utilities/chunkedList.hpp"
aoqi@0 35
stefank@7333 36 volatile MetadataOnStackBuffer* MetadataOnStackMark::_used_buffers = NULL;
stefank@7333 37 volatile MetadataOnStackBuffer* MetadataOnStackMark::_free_buffers = NULL;
aoqi@0 38
aoqi@0 39 NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
aoqi@0 40
aoqi@0 41 // Walk metadata on the stack and mark it so that redefinition doesn't delete
aoqi@0 42 // it. Class unloading also walks the previous versions and might try to
aoqi@0 43 // delete it, so this class is used by class unloading also.
stefank@7333 44 MetadataOnStackMark::MetadataOnStackMark(bool visit_code_cache) {
aoqi@0 45 assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
stefank@7333 46 assert(_used_buffers == NULL, "sanity check");
aoqi@0 47 NOT_PRODUCT(_is_active = true;)
stefank@6992 48
sla@6122 49 Threads::metadata_do(Metadata::mark_on_stack);
stefank@7333 50 if (visit_code_cache) {
stefank@6992 51 CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
aoqi@0 52 }
aoqi@0 53 CompileBroker::mark_on_stack();
aoqi@0 54 JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
aoqi@0 55 ThreadService::metadata_do(Metadata::mark_on_stack);
aoqi@0 56 }
aoqi@0 57
aoqi@0 58 MetadataOnStackMark::~MetadataOnStackMark() {
aoqi@0 59 assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
aoqi@0 60 // Unmark everything that was marked. Can't do the same walk because
aoqi@0 61 // redefine classes messes up the code cache so the set of methods
aoqi@0 62 // might not be the same.
stefank@7333 63
stefank@7333 64 retire_buffer_for_thread(Thread::current());
stefank@7333 65
stefank@7333 66 MetadataOnStackBuffer* buffer = const_cast<MetadataOnStackBuffer* >(_used_buffers);
stefank@7333 67 while (buffer != NULL) {
stefank@7333 68 // Clear on stack state for all metadata.
stefank@7333 69 size_t size = buffer->size();
stefank@7333 70 for (size_t i = 0; i < size; i++) {
stefank@7333 71 Metadata* md = buffer->at(i);
stefank@7333 72 md->set_on_stack(false);
stefank@7333 73 }
stefank@7333 74
stefank@7333 75 MetadataOnStackBuffer* next = buffer->next_used();
stefank@7333 76
stefank@7333 77 // Move the buffer to the free list.
stefank@7333 78 buffer->clear();
stefank@7333 79 buffer->set_next_used(NULL);
stefank@7333 80 buffer->set_next_free(const_cast<MetadataOnStackBuffer*>(_free_buffers));
stefank@7333 81 _free_buffers = buffer;
stefank@7333 82
stefank@7333 83 // Step to next used buffer.
stefank@7333 84 buffer = next;
aoqi@0 85 }
stefank@7333 86
stefank@7333 87 _used_buffers = NULL;
stefank@7333 88
aoqi@0 89 NOT_PRODUCT(_is_active = false;)
aoqi@0 90 }
aoqi@0 91
stefank@7333 92 void MetadataOnStackMark::retire_buffer(MetadataOnStackBuffer* buffer) {
stefank@7333 93 if (buffer == NULL) {
stefank@7333 94 return;
stefank@7333 95 }
stefank@7333 96
stefank@7333 97 MetadataOnStackBuffer* old_head;
stefank@7333 98
stefank@7333 99 do {
stefank@7333 100 old_head = const_cast<MetadataOnStackBuffer*>(_used_buffers);
stefank@7333 101 buffer->set_next_used(old_head);
stefank@7333 102 } while (Atomic::cmpxchg_ptr(buffer, &_used_buffers, old_head) != old_head);
stefank@7333 103 }
stefank@7333 104
stefank@7333 105 void MetadataOnStackMark::retire_buffer_for_thread(Thread* thread) {
stefank@7333 106 retire_buffer(thread->metadata_on_stack_buffer());
stefank@7333 107 thread->set_metadata_on_stack_buffer(NULL);
stefank@7333 108 }
stefank@7333 109
stefank@7333 110 bool MetadataOnStackMark::has_buffer_for_thread(Thread* thread) {
stefank@7333 111 return thread->metadata_on_stack_buffer() != NULL;
stefank@7333 112 }
stefank@7333 113
stefank@7333 114 MetadataOnStackBuffer* MetadataOnStackMark::allocate_buffer() {
stefank@7333 115 MetadataOnStackBuffer* allocated;
stefank@7333 116 MetadataOnStackBuffer* new_head;
stefank@7333 117
stefank@7333 118 do {
stefank@7333 119 allocated = const_cast<MetadataOnStackBuffer*>(_free_buffers);
stefank@7333 120 if (allocated == NULL) {
stefank@7333 121 break;
stefank@7333 122 }
stefank@7333 123 new_head = allocated->next_free();
stefank@7333 124 } while (Atomic::cmpxchg_ptr(new_head, &_free_buffers, allocated) != allocated);
stefank@7333 125
stefank@7333 126 if (allocated == NULL) {
stefank@7333 127 allocated = new MetadataOnStackBuffer();
stefank@7333 128 }
stefank@7333 129
stefank@7333 130 assert(!allocated->is_full(), err_msg("Should not be full: " PTR_FORMAT, p2i(allocated)));
stefank@7333 131
stefank@7333 132 return allocated;
stefank@7333 133 }
stefank@7333 134
aoqi@0 135 // Record which objects are marked so we can unmark the same objects.
stefank@7333 136 void MetadataOnStackMark::record(Metadata* m, Thread* thread) {
aoqi@0 137 assert(_is_active, "metadata on stack marking is active");
stefank@7333 138
stefank@7333 139 MetadataOnStackBuffer* buffer = thread->metadata_on_stack_buffer();
stefank@7333 140
stefank@7333 141 if (buffer != NULL && buffer->is_full()) {
stefank@7333 142 retire_buffer(buffer);
stefank@7333 143 buffer = NULL;
stefank@7333 144 }
stefank@7333 145
stefank@7333 146 if (buffer == NULL) {
stefank@7333 147 buffer = allocate_buffer();
stefank@7333 148 thread->set_metadata_on_stack_buffer(buffer);
stefank@7333 149 }
stefank@7333 150
stefank@7333 151 buffer->push(m);
aoqi@0 152 }

mercurial