1 /*
   2  * Copyright (c) 2015, 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 VALUE_OBJ_CLASS_SPEC {
  53 public:
  54   // Construct with the indicated concrete tag, and include the
  55   // concrete tag in the associated tag set.
  56   explicit FakeRttiSupport(TagType concrete_tag) :
  57     _tag_set(tag_bit(concrete_tag)), _ctag(concrete_tag) { }
  58 
  59   // Construct with the indicated concrete tag and tag set.
  60   // Note: This constructor is public only to allow clients to set up
  61   // "unusual" (or perhaps buggy) fake RTTI configurations.
  62   FakeRttiSupport(TagType concrete_tag, uintx tag_set) :
  63     _tag_set(tag_set), _ctag(validate_tag(concrete_tag)) { }
  64 
  65   // Get the concrete tag.
  66   TagType concrete_tag() const { return _ctag; }
  67 
  68   // Test whether tag is in the tag set.
  69   bool has_tag(TagType tag) const {
  70     return (_tag_set & tag_bit(tag)) != 0;
  71   }
  72 
  73   // Return a new support object which is the same as this, except tag
  74   // has been added to the tag set.  The tag must not already be
  75   // present in the tag set.
  76   FakeRttiSupport add_tag(TagType tag) const {
  77     uintx tbit = tag_bit(tag);
  78     assert((_tag_set & tbit) == 0,
  79            err_msg("Tag " UINTX_FORMAT " is already present in tag set: " UINTX_FORMAT,
  80                    (uintx)tag, _tag_set));
  81     return FakeRttiSupport(_ctag, _tag_set | tbit);
  82   }
  83 
  84 private:
  85   uintx _tag_set;
  86   TagType _ctag;
  87 
  88   static uintx tag_bit(TagType tag) {
  89     return ((uintx)1) << validate_tag(tag);
  90   }
  91 
  92   static TagType validate_tag(uintx tag) {
  93     // Type of tag is not TagType to dodge useless MacOSX compiler warning.
  94     assert(tag < (sizeof(uintx) * BitsPerByte),
  95            err_msg("Tag " UINTX_FORMAT " is too large", tag));
  96     return static_cast<TagType>(tag);
  97   }
  98 };
  99 
 100 #endif // include guard