1 /*
2  * Copyright (c) 2015, 2018, 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_VM_UTILITIES_FAKERTTISUPPORT_HPP
26 #define SHARE_VM_UTILITIES_FAKERTTISUPPORT_HPP
27 
28 #include "utilities/globalDefinitions.hpp"
29 #include "utilities/debug.hpp"
30 
31 // Provides support for checked downcasts in a hierarchy of classes.
32 // The base class provides a member of this type, specialized on that
33 // base class and an associated tag type.  Tags are small non-negative
34 // integer values uniquely associated with distinct classes in the
35 // hierarchy.  A tag type is often an enum type.
36 //
37 // The concrete class specifies the concrete tag.
38 //
39 // The tag set specifies the set of classes in the derivation
40 // sequence.  Classes in the derivation sequence add their associated
41 // tag during construction.  Given the tag associated with a class, an
42 // object is an instance of that class if the tag is included in the
43 // object's set of recorded tags.
44 //
45 // A tag T is present in a tag set if the T'th bit of the tag set is
46 // one.
47 //
48 // Note: The representation of a tag set being uintx sets an upper
49 // bound on the size of a class hierarchy this utility can be used
50 // with.
51 template<typename T, typename TagType>
52 class FakeRttiSupport {
53   friend class VMStructs;
54 public:
55   // Construct with the indicated concrete tag, and include the
56   // concrete tag in the associated tag set.
FakeRttiSupport(TagType concrete_tag)57   explicit FakeRttiSupport(TagType concrete_tag) :
58     _tag_set(tag_bit(concrete_tag)), _concrete_tag(concrete_tag) { }
59 
60   // Construct with the indicated concrete tag and tag set.
61   // Note: This constructor is public only to allow clients to set up
62   // "unusual" (or perhaps buggy) fake RTTI configurations.
FakeRttiSupport(TagType concrete_tag,uintx tag_set)63   FakeRttiSupport(TagType concrete_tag, uintx tag_set) :
64     _tag_set(tag_set), _concrete_tag(validate_tag(concrete_tag)) { }
65 
66   // Get the concrete tag.
concrete_tag() const67   TagType concrete_tag() const { return _concrete_tag; }
68 
69   // Test whether tag is in the tag set.
has_tag(TagType tag) const70   bool has_tag(TagType tag) const {
71     return (_tag_set & tag_bit(tag)) != 0;
72   }
73 
74   // Return a new support object which is the same as this, except tag
75   // has been added to the tag set.  The tag must not already be
76   // present in the tag set.
add_tag(TagType tag) const77   FakeRttiSupport add_tag(TagType tag) const {
78     uintx tbit = tag_bit(tag);
79     assert((_tag_set & tbit) == 0,
80            "Tag " UINTX_FORMAT " is already present in tag set: " UINTX_FORMAT,
81            (uintx)tag, _tag_set);
82     return FakeRttiSupport(_concrete_tag, _tag_set | tbit);
83   }
84 
85 private:
86   uintx _tag_set;
87   TagType _concrete_tag;
88 
tag_bit(TagType tag)89   static uintx tag_bit(TagType tag) {
90     return ((uintx)1) << validate_tag(tag);
91   }
92 
validate_tag(TagType tag)93   static TagType validate_tag(TagType tag) {
94     assert(0 <= tag, "Tag " INTX_FORMAT " is negative", (intx)tag);
95     assert(tag < BitsPerWord,
96            "Tag " UINTX_FORMAT " is too large", (uintx)tag);
97     return tag;
98   }
99 };
100 
101 #endif // include guard
102