Path: blob/master/src/hotspot/share/runtime/handles.cpp
40951 views
/*1* Copyright (c) 1997, 2021, 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 "memory/allocation.inline.hpp"26#include "oops/constantPool.hpp"27#include "oops/method.hpp"28#include "oops/oop.inline.hpp"29#include "runtime/handles.inline.hpp"30#include "runtime/thread.inline.hpp"3132#ifdef ASSERT33oop* HandleArea::allocate_handle(oop obj) {34assert(_handle_mark_nesting > 1, "memory leak: allocating handle outside HandleMark");35assert(_no_handle_mark_nesting == 0, "allocating handle inside NoHandleMark");36assert(oopDesc::is_oop(obj), "not an oop: " INTPTR_FORMAT, p2i(obj));37return real_allocate_handle(obj);38}39#endif4041// Copy constructors and destructors for metadata handles42// These do too much to inline.43#define DEF_METADATA_HANDLE_FN_NOINLINE(name, type) \44name##Handle::name##Handle(const name##Handle &h) { \45_value = h._value; \46if (_value != NULL) { \47assert(_value->is_valid(), "obj is valid"); \48if (h._thread != NULL) { \49assert(h._thread == Thread::current(), "thread must be current");\50_thread = h._thread; \51} else { \52_thread = Thread::current(); \53} \54assert(_thread->is_in_live_stack((address)this), "not on stack?"); \55_thread->metadata_handles()->push((Metadata*)_value); \56} else { \57_thread = NULL; \58} \59} \60name##Handle& name##Handle::operator=(const name##Handle &s) { \61remove(); \62_value = s._value; \63if (_value != NULL) { \64assert(_value->is_valid(), "obj is valid"); \65if (s._thread != NULL) { \66assert(s._thread == Thread::current(), "thread must be current");\67_thread = s._thread; \68} else { \69_thread = Thread::current(); \70} \71assert(_thread->is_in_live_stack((address)this), "not on stack?"); \72_thread->metadata_handles()->push((Metadata*)_value); \73} else { \74_thread = NULL; \75} \76return *this; \77} \78inline void name##Handle::remove() { \79if (_value != NULL) { \80int i = _thread->metadata_handles()->find_from_end((Metadata*)_value); \81assert(i!=-1, "not in metadata_handles list"); \82_thread->metadata_handles()->remove_at(i); \83} \84} \85name##Handle::~name##Handle () { remove(); } \8687DEF_METADATA_HANDLE_FN_NOINLINE(method, Method)88DEF_METADATA_HANDLE_FN_NOINLINE(constantPool, ConstantPool)899091static uintx chunk_oops_do(OopClosure* f, Chunk* chunk, char* chunk_top) {92oop* bottom = (oop*) chunk->bottom();93oop* top = (oop*) chunk_top;94uintx handles_visited = top - bottom;95assert(top >= bottom && top <= (oop*) chunk->top(), "just checking");96// during GC phase 3, a handle may be a forward pointer that97// is not yet valid, so loosen the assertion98while (bottom < top) {99f->do_oop(bottom++);100}101return handles_visited;102}103104void HandleArea::oops_do(OopClosure* f) {105uintx handles_visited = 0;106// First handle the current chunk. It is filled to the high water mark.107handles_visited += chunk_oops_do(f, _chunk, _hwm);108// Then handle all previous chunks. They are completely filled.109Chunk* k = _first;110while(k != _chunk) {111handles_visited += chunk_oops_do(f, k, k->top());112k = k->next();113}114115if (_prev != NULL) _prev->oops_do(f);116}117118void HandleMark::initialize(Thread* thread) {119_thread = thread; // Not the current thread during thread creation.120// Save area121_area = thread->handle_area();122// Save current top123_chunk = _area->_chunk;124_hwm = _area->_hwm;125_max = _area->_max;126_size_in_bytes = _area->_size_in_bytes;127debug_only(_area->_handle_mark_nesting++);128assert(_area->_handle_mark_nesting > 0, "must stack allocate HandleMarks");129130// Link this in the thread131set_previous_handle_mark(thread->last_handle_mark());132thread->set_last_handle_mark(this);133}134135HandleMark::~HandleMark() {136assert(_area == _thread->handle_area(), "sanity check");137assert(_area->_handle_mark_nesting > 0, "must stack allocate HandleMarks" );138139pop_and_restore();140#ifdef ASSERT141// clear out first chunk (to detect allocation bugs)142if (ZapVMHandleArea) {143memset(_hwm, badHandleValue, _max - _hwm);144}145#endif146147// Unlink this from the thread148_thread->set_last_handle_mark(previous_handle_mark());149}150151void HandleMark::chop_later_chunks() {152// reset arena size before delete chunks. Otherwise, the total153// arena size could exceed total chunk size154_area->set_size_in_bytes(size_in_bytes());155_chunk->next_chop();156}157158void* HandleMark::operator new(size_t size) throw() {159return AllocateHeap(size, mtThread);160}161162void* HandleMark::operator new [] (size_t size) throw() {163return AllocateHeap(size, mtThread);164}165166void HandleMark::operator delete(void* p) {167FreeHeap(p);168}169170void HandleMark::operator delete[](void* p) {171FreeHeap(p);172}173174#ifdef ASSERT175176NoHandleMark::NoHandleMark() {177HandleArea* area = Thread::current()->handle_area();178area->_no_handle_mark_nesting++;179assert(area->_no_handle_mark_nesting > 0, "must stack allocate NoHandleMark" );180}181182183NoHandleMark::~NoHandleMark() {184HandleArea* area = Thread::current()->handle_area();185assert(area->_no_handle_mark_nesting > 0, "must stack allocate NoHandleMark" );186area->_no_handle_mark_nesting--;187}188189190ResetNoHandleMark::ResetNoHandleMark() {191HandleArea* area = Thread::current()->handle_area();192_no_handle_mark_nesting = area->_no_handle_mark_nesting;193area->_no_handle_mark_nesting = 0;194}195196197ResetNoHandleMark::~ResetNoHandleMark() {198HandleArea* area = Thread::current()->handle_area();199area->_no_handle_mark_nesting = _no_handle_mark_nesting;200}201202#endif // ASSERT203204205