Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/runtime/handles.hpp
32285 views
/*1* Copyright (c) 1997, 2014, 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#ifndef SHARE_VM_RUNTIME_HANDLES_HPP25#define SHARE_VM_RUNTIME_HANDLES_HPP2627#include "oops/klass.hpp"2829//------------------------------------------------------------------------------------------------------------------------30// In order to preserve oops during garbage collection, they should be31// allocated and passed around via Handles within the VM. A handle is32// simply an extra indirection allocated in a thread local handle area.33//34// A handle is a ValueObj, so it can be passed around as a value, can35// be used as a parameter w/o using &-passing, and can be returned as a36// return value.37//38// oop parameters and return types should be Handles whenever feasible.39//40// Handles are declared in a straight-forward manner, e.g.41//42// oop obj = ...;43// Handle h1(obj); // allocate new handle44// Handle h2(thread, obj); // faster allocation when current thread is known45// Handle h3; // declare handle only, no allocation occurs46// ...47// h3 = h1; // make h3 refer to same indirection as h148// oop obj2 = h2(); // get handle value49// h1->print(); // invoking operation on oop50//51// Handles are specialized for different oop types to provide extra type52// information and avoid unnecessary casting. For each oop type xxxOop53// there is a corresponding handle called xxxHandle, e.g.54//55// oop Handle56// Method* methodHandle57// instanceOop instanceHandle5859//------------------------------------------------------------------------------------------------------------------------60// Base class for all handles. Provides overloading of frequently61// used operators for ease of use.6263class Handle VALUE_OBJ_CLASS_SPEC {64private:65oop* _handle;6667protected:68oop obj() const { return _handle == NULL ? (oop)NULL : *_handle; }69oop non_null_obj() const { assert(_handle != NULL, "resolving NULL handle"); return *_handle; }7071public:72// Constructors73Handle() { _handle = NULL; }74Handle(oop obj);75Handle(Thread* thread, oop obj);7677// General access78oop operator () () const { return obj(); }79oop operator -> () const { return non_null_obj(); }80bool operator == (oop o) const { return obj() == o; }81bool operator == (const Handle& h) const { return obj() == h.obj(); }8283// Null checks84bool is_null() const { return _handle == NULL; }85bool not_null() const { return _handle != NULL; }8687// Debugging88void print() { obj()->print(); }8990// Direct interface, use very sparingly.91// Used by JavaCalls to quickly convert handles and to create handles static data structures.92// Constructor takes a dummy argument to prevent unintentional type conversion in C++.93Handle(oop *handle, bool dummy) { _handle = handle; }9495// Raw handle access. Allows easy duplication of Handles. This can be very unsafe96// since duplicates is only valid as long as original handle is alive.97oop* raw_value() { return _handle; }98static oop raw_resolve(oop *handle) { return handle == NULL ? (oop)NULL : *handle; }99};100101// Specific Handles for different oop types102#define DEF_HANDLE(type, is_a) \103class type##Handle: public Handle { \104protected: \105type##Oop obj() const { return (type##Oop)Handle::obj(); } \106type##Oop non_null_obj() const { return (type##Oop)Handle::non_null_obj(); } \107\108public: \109/* Constructors */ \110type##Handle () : Handle() {} \111type##Handle (type##Oop obj) : Handle((oop)obj) { \112assert(is_null() || ((oop)obj)->is_a(), \113"illegal type"); \114} \115type##Handle (Thread* thread, type##Oop obj) : Handle(thread, (oop)obj) { \116assert(is_null() || ((oop)obj)->is_a(), "illegal type"); \117} \118\119/* Operators for ease of use */ \120type##Oop operator () () const { return obj(); } \121type##Oop operator -> () const { return non_null_obj(); } \122};123124125DEF_HANDLE(instance , is_instance )126DEF_HANDLE(array , is_array )127DEF_HANDLE(objArray , is_objArray )128DEF_HANDLE(typeArray , is_typeArray )129130//------------------------------------------------------------------------------------------------------------------------131132// Metadata Handles. Unlike oop Handles these are needed to prevent metadata133// from being reclaimed by RedefineClasses.134135// Specific Handles for different oop types136#define DEF_METADATA_HANDLE(name, type) \137class name##Handle; \138class name##Handle : public StackObj { \139type* _value; \140Thread* _thread; \141protected: \142type* obj() const { return _value; } \143type* non_null_obj() const { assert(_value != NULL, "resolving NULL _value"); return _value; } \144\145public: \146/* Constructors */ \147name##Handle () : _value(NULL), _thread(NULL) {} \148name##Handle (type* obj); \149name##Handle (Thread* thread, type* obj); \150\151name##Handle (const name##Handle &h); \152name##Handle& operator=(const name##Handle &s); \153\154/* Destructor */ \155~name##Handle (); \156void remove(); \157\158/* Operators for ease of use */ \159type* operator () () const { return obj(); } \160type* operator -> () const { return non_null_obj(); } \161\162bool operator == (type* o) const { return obj() == o; } \163bool operator == (const name##Handle& h) const { return obj() == h.obj(); } \164\165/* Null checks */ \166bool is_null() const { return _value == NULL; } \167bool not_null() const { return _value != NULL; } \168};169170171DEF_METADATA_HANDLE(method, Method)172DEF_METADATA_HANDLE(constantPool, ConstantPool)173174// Writing this class explicitly, since DEF_METADATA_HANDLE(klass) doesn't175// provide the necessary Klass* <-> Klass* conversions. This Klass176// could be removed when we don't have the Klass* typedef anymore.177class KlassHandle : public StackObj {178Klass* _value;179protected:180Klass* obj() const { return _value; }181Klass* non_null_obj() const { assert(_value != NULL, "resolving NULL _value"); return _value; }182183public:184KlassHandle() : _value(NULL) {}185KlassHandle(const Klass* obj) : _value(const_cast<Klass *>(obj)) {};186KlassHandle(Thread* thread, const Klass* obj) : _value(const_cast<Klass *>(obj)) {};187188Klass* operator () () const { return obj(); }189Klass* operator -> () const { return non_null_obj(); }190191bool operator == (Klass* o) const { return obj() == o; }192bool operator == (const KlassHandle& h) const { return obj() == h.obj(); }193194bool is_null() const { return _value == NULL; }195bool not_null() const { return _value != NULL; }196};197198class instanceKlassHandle : public KlassHandle {199public:200/* Constructors */201instanceKlassHandle () : KlassHandle() {}202instanceKlassHandle (const Klass* k) : KlassHandle(k) {203assert(k == NULL || k->oop_is_instance(),204"illegal type");205}206instanceKlassHandle (Thread* thread, const Klass* k) : KlassHandle(thread, k) {207assert(k == NULL || k->oop_is_instance(),208"illegal type");209}210/* Access to klass part */211InstanceKlass* operator () () const { return (InstanceKlass*)obj(); }212InstanceKlass* operator -> () const { return (InstanceKlass*)obj(); }213};214215216//------------------------------------------------------------------------------------------------------------------------217// Thread local handle area218class HandleArea: public Arena {219friend class HandleMark;220friend class NoHandleMark;221friend class ResetNoHandleMark;222#ifdef ASSERT223int _handle_mark_nesting;224int _no_handle_mark_nesting;225#endif226HandleArea* _prev; // link to outer (older) area227public:228// Constructor229HandleArea(HandleArea* prev) : Arena(mtThread, Chunk::tiny_size) {230debug_only(_handle_mark_nesting = 0);231debug_only(_no_handle_mark_nesting = 0);232_prev = prev;233}234235// Handle allocation236private:237oop* real_allocate_handle(oop obj) {238#ifdef ASSERT239oop* handle = (oop*) (UseMallocOnly ? internal_malloc_4(oopSize) : Amalloc_4(oopSize));240#else241oop* handle = (oop*) Amalloc_4(oopSize);242#endif243*handle = obj;244return handle;245}246public:247#ifdef ASSERT248oop* allocate_handle(oop obj);249#else250oop* allocate_handle(oop obj) { return real_allocate_handle(obj); }251#endif252253// Garbage collection support254void oops_do(OopClosure* f);255256// Number of handles in use257size_t used() const { return Arena::used() / oopSize; }258259debug_only(bool no_handle_mark_active() { return _no_handle_mark_nesting > 0; })260};261262263//------------------------------------------------------------------------------------------------------------------------264// Handles are allocated in a (growable) thread local handle area. Deallocation265// is managed using a HandleMark. It should normally not be necessary to use266// HandleMarks manually.267//268// A HandleMark constructor will record the current handle area top, and the269// desctructor will reset the top, destroying all handles allocated in between.270// The following code will therefore NOT work:271//272// Handle h;273// {274// HandleMark hm;275// h = Handle(obj);276// }277// h()->print(); // WRONG, h destroyed by HandleMark destructor.278//279// If h has to be preserved, it can be converted to an oop or a local JNI handle280// across the HandleMark boundary.281282// The base class of HandleMark should have been StackObj but we also heap allocate283// a HandleMark when a thread is created. The operator new is for this special case.284285class HandleMark {286private:287Thread *_thread; // thread that owns this mark288HandleArea *_area; // saved handle area289Chunk *_chunk; // saved arena chunk290char *_hwm, *_max; // saved arena info291size_t _size_in_bytes; // size of handle area292// Link to previous active HandleMark in thread293HandleMark* _previous_handle_mark;294295void initialize(Thread* thread); // common code for constructors296void set_previous_handle_mark(HandleMark* mark) { _previous_handle_mark = mark; }297HandleMark* previous_handle_mark() const { return _previous_handle_mark; }298299size_t size_in_bytes() const { return _size_in_bytes; }300public:301HandleMark(); // see handles_inline.hpp302HandleMark(Thread* thread) { initialize(thread); }303~HandleMark();304305// Functions used by HandleMarkCleaner306// called in the constructor of HandleMarkCleaner307void push();308// called in the destructor of HandleMarkCleaner309void pop_and_restore();310// overloaded operators311void* operator new(size_t size) throw();312void* operator new [](size_t size) throw();313void operator delete(void* p);314void operator delete[](void* p);315};316317//------------------------------------------------------------------------------------------------------------------------318// A NoHandleMark stack object will verify that no handles are allocated319// in its scope. Enabled in debug mode only.320321class NoHandleMark: public StackObj {322public:323#ifdef ASSERT324NoHandleMark();325~NoHandleMark();326#else327NoHandleMark() {}328~NoHandleMark() {}329#endif330};331332333class ResetNoHandleMark: public StackObj {334int _no_handle_mark_nesting;335public:336#ifdef ASSERT337ResetNoHandleMark();338~ResetNoHandleMark();339#else340ResetNoHandleMark() {}341~ResetNoHandleMark() {}342#endif343};344345#endif // SHARE_VM_RUNTIME_HANDLES_HPP346347348