1 /*
 2  * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
 3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 4  *
 5  * This code is free software; you can redistribute it and/or modify it
 6  * under the terms of the GNU General Public License version 2 only, as
 7  * published by the Free Software Foundation.
 8  *
 9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 #ifndef SHARE_OOPS_SYMBOLHANDLE_HPP
26 #define SHARE_OOPS_SYMBOLHANDLE_HPP
27 
28 #include "memory/allocation.hpp"
29 #include "oops/symbol.hpp"
30 
31 // TempNewSymbol acts as a handle class in a handle/body idiom and is
32 // responsible for proper resource management of the body (which is a Symbol*).
33 // The body is resource managed by a reference counting scheme.
34 // TempNewSymbol can therefore be used to properly hold a newly created or referenced
35 // Symbol* temporarily in scope.
36 //
37 // Routines in SymbolTable will initialize the reference count of a Symbol* before
38 // it becomes "managed" by TempNewSymbol instances. As a handle class, TempNewSymbol
39 // needs to maintain proper reference counting in context of copy semantics.
40 //
41 // In SymbolTable, new_symbol() will create a Symbol* if not already in the
42 // symbol table and add to the symbol's reference count.
43 // probe() and lookup_only() will increment the refcount if symbol is found.
44 template <bool TEMP>
45 class SymbolHandleBase : public StackObj {
46   Symbol* _temp;
47 
48 public:
49   SymbolHandleBase() : _temp(nullptr) { }
50 
51   // Conversion from a Symbol* to a SymbolHandleBase.
52   // Does not increment the current reference count if temporary.
53   SymbolHandleBase(Symbol *s) : _temp(s) {
54     if (!TEMP) {
55       Symbol::maybe_increment_refcount(_temp);
56     }
57   }
58 
59   // Copy constructor increments reference count.
60   SymbolHandleBase(const SymbolHandleBase& rhs) : _temp(rhs._temp) {
61     Symbol::maybe_increment_refcount(_temp);
62   }
63 
64   // Assignment operator uses a c++ trick called copy and swap idiom.
65   // rhs is passed by value so within the scope of this method it is a copy.
66   // At method exit it contains the former value of _temp, triggering the correct refcount
67   // decrement upon destruction.
68   void operator=(SymbolHandleBase rhs) {
69     Symbol* tmp = rhs._temp;
70     rhs._temp = _temp;
71     _temp = tmp;
72   }
73 
74   // Decrement reference counter so it can go away if it's unused
75   ~SymbolHandleBase() {
76     Symbol::maybe_decrement_refcount(_temp);
77   }
78 
79   // Symbol* conversion operators
80   Symbol* operator -> () const                   { return _temp; }
81   bool    operator == (Symbol* o) const          { return _temp == o; }
82   operator Symbol*() const                       { return _temp; }
83 
84   static unsigned int compute_hash(const SymbolHandleBase& name) {
85     return (unsigned int) name->identity_hash();
86   }
87 };
88 
89 // TempNewSymbol is a temporary holder for a newly created symbol
90 using TempNewSymbol = SymbolHandleBase<true>;
91 
92 // SymbolHandle is a non-temp symbol used to hold a symbol in a semi permanent place,
93 // like in a hashtable. The only difference is that the constructor increments the refcount.
94 using SymbolHandle = SymbolHandleBase<false>;
95 
96 #endif // SHARE_OOPS_SYMBOLHANDLE_HPP