alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (verificationType.hpp)

This example Java source code file (verificationType.hpp) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

bitsperbyte, boolean, category1, category1query, category2, category2_2nd, category2_2ndquery, category2flag, must, primitive, traps, typequery, uninitialized, verificationtype

The verificationType.hpp Java example source code

/*
 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef SHARE_VM_CLASSFILE_VERIFICATIONTYPE_HPP
#define SHARE_VM_CLASSFILE_VERIFICATIONTYPE_HPP

#include "classfile/systemDictionary.hpp"
#include "memory/allocation.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "runtime/handles.hpp"
#include "runtime/signature.hpp"

enum {
  // As specifed in the JVM spec
  ITEM_Top = 0,
  ITEM_Integer = 1,
  ITEM_Float = 2,
  ITEM_Double = 3,
  ITEM_Long = 4,
  ITEM_Null = 5,
  ITEM_UninitializedThis = 6,
  ITEM_Object = 7,
  ITEM_Uninitialized = 8,
  ITEM_Bogus = (uint)-1
};

class ClassVerifier;

class VerificationType VALUE_OBJ_CLASS_SPEC {
  private:
    // Least significant bits of _handle are always 0, so we use these as
    // the indicator that the _handle is valid.  Otherwise, the _data field
    // contains encoded data (as specified below).  Should the VM change
    // and the lower bits on oops aren't 0, the assert in the constructor
    // will catch this and we'll have to add a descriminator tag to this
    // structure.
    union {
      Symbol*   _sym;
      uintptr_t _data;
    } _u;

    enum {
      // These rest are not found in classfiles, but used by the verifier
      ITEM_Boolean = 9, ITEM_Byte, ITEM_Short, ITEM_Char,
      ITEM_Long_2nd, ITEM_Double_2nd
    };

    // Enum for the _data field
    enum {
      // Bottom two bits determine if the type is a reference, primitive,
      // uninitialized or a query-type.
      TypeMask           = 0x00000003,

      // Topmost types encoding
      Reference          = 0x0,        // _sym contains the name
      Primitive          = 0x1,        // see below for primitive list
      Uninitialized      = 0x2,        // 0x00ffff00 contains bci
      TypeQuery          = 0x3,        // Meta-types used for category testing

      // Utility flags
      ReferenceFlag      = 0x00,       // For reference query types
      Category1Flag      = 0x01,       // One-word values
      Category2Flag      = 0x02,       // First word of a two-word value
      Category2_2ndFlag  = 0x04,       // Second word of a two-word value

      // special reference values
      Null               = 0x00000000, // A reference with a 0 sym is null

      // Primitives categories (the second byte determines the category)
      Category1          = (Category1Flag     << 1 * BitsPerByte) | Primitive,
      Category2          = (Category2Flag     << 1 * BitsPerByte) | Primitive,
      Category2_2nd      = (Category2_2ndFlag << 1 * BitsPerByte) | Primitive,

      // Primitive values (type descriminator stored in most-signifcant bytes)
      Bogus              = (ITEM_Bogus      << 2 * BitsPerByte) | Category1,
      Boolean            = (ITEM_Boolean    << 2 * BitsPerByte) | Category1,
      Byte               = (ITEM_Byte       << 2 * BitsPerByte) | Category1,
      Short              = (ITEM_Short      << 2 * BitsPerByte) | Category1,
      Char               = (ITEM_Char       << 2 * BitsPerByte) | Category1,
      Integer            = (ITEM_Integer    << 2 * BitsPerByte) | Category1,
      Float              = (ITEM_Float      << 2 * BitsPerByte) | Category1,
      Long               = (ITEM_Long       << 2 * BitsPerByte) | Category2,
      Double             = (ITEM_Double     << 2 * BitsPerByte) | Category2,
      Long_2nd           = (ITEM_Long_2nd   << 2 * BitsPerByte) | Category2_2nd,
      Double_2nd         = (ITEM_Double_2nd << 2 * BitsPerByte) | Category2_2nd,

      // Used by Uninitialized (second and third bytes hold the bci)
      BciMask            = 0xffff << 1 * BitsPerByte,
      BciForThis         = ((u2)-1),   // A bci of -1 is an Unintialized-This

      // Query values
      ReferenceQuery     = (ReferenceFlag     << 1 * BitsPerByte) | TypeQuery,
      Category1Query     = (Category1Flag     << 1 * BitsPerByte) | TypeQuery,
      Category2Query     = (Category2Flag     << 1 * BitsPerByte) | TypeQuery,
      Category2_2ndQuery = (Category2_2ndFlag << 1 * BitsPerByte) | TypeQuery
    };

  VerificationType(uintptr_t raw_data) {
    _u._data = raw_data;
  }

 public:

  VerificationType() { *this = bogus_type(); }

  // Create verification types
  static VerificationType bogus_type() { return VerificationType(Bogus); }
  static VerificationType top_type() { return bogus_type(); } // alias
  static VerificationType null_type() { return VerificationType(Null); }
  static VerificationType integer_type() { return VerificationType(Integer); }
  static VerificationType float_type() { return VerificationType(Float); }
  static VerificationType long_type() { return VerificationType(Long); }
  static VerificationType long2_type() { return VerificationType(Long_2nd); }
  static VerificationType double_type() { return VerificationType(Double); }
  static VerificationType boolean_type() { return VerificationType(Boolean); }
  static VerificationType byte_type() { return VerificationType(Byte); }
  static VerificationType char_type() { return VerificationType(Char); }
  static VerificationType short_type() { return VerificationType(Short); }
  static VerificationType double2_type()
    { return VerificationType(Double_2nd); }

  // "check" types are used for queries.  A "check" type is not assignable
  // to anything, but the specified types are assignable to a "check".  For
  // example, any category1 primitive is assignable to category1_check and
  // any reference is assignable to reference_check.
  static VerificationType reference_check()
    { return VerificationType(ReferenceQuery); }
  static VerificationType category1_check()
    { return VerificationType(Category1Query); }
  static VerificationType category2_check()
    { return VerificationType(Category2Query); }
  static VerificationType category2_2nd_check()
    { return VerificationType(Category2_2ndQuery); }

  // For reference types, store the actual Symbol
  static VerificationType reference_type(Symbol* sh) {
      assert(((uintptr_t)sh & 0x3) == 0, "Symbols must be aligned");
      // If the above assert fails in the future because oop* isn't aligned,
      // then this type encoding system will have to change to have a tag value
      // to descriminate between oops and primitives.
      return VerificationType((uintptr_t)sh);
  }
  static VerificationType uninitialized_type(u2 bci)
    { return VerificationType(bci << 1 * BitsPerByte | Uninitialized); }
  static VerificationType uninitialized_this_type()
    { return uninitialized_type(BciForThis); }

  // Create based on u1 read from classfile
  static VerificationType from_tag(u1 tag);

  bool is_bogus() const     { return (_u._data == Bogus); }
  bool is_null() const      { return (_u._data == Null); }
  bool is_boolean() const   { return (_u._data == Boolean); }
  bool is_byte() const      { return (_u._data == Byte); }
  bool is_char() const      { return (_u._data == Char); }
  bool is_short() const     { return (_u._data == Short); }
  bool is_integer() const   { return (_u._data == Integer); }
  bool is_long() const      { return (_u._data == Long); }
  bool is_float() const     { return (_u._data == Float); }
  bool is_double() const    { return (_u._data == Double); }
  bool is_long2() const     { return (_u._data == Long_2nd); }
  bool is_double2() const   { return (_u._data == Double_2nd); }
  bool is_reference() const { return ((_u._data & TypeMask) == Reference); }
  bool is_category1() const {
    // This should return true for all one-word types, which are category1
    // primitives, and references (including uninitialized refs).  Though
    // the 'query' types should technically return 'false' here, if we
    // allow this to return true, we can perform the test using only
    // 2 operations rather than 8 (3 masks, 3 compares and 2 logical 'ands').
    // Since noone should call this on a query type anyway, this is ok.
    assert(!is_check(), "Must not be a check type (wrong value returned)");
    return ((_u._data & Category1) != Primitive);
    // should only return false if it's a primitive, and the category1 flag
    // is not set.
  }
  bool is_category2() const { return ((_u._data & Category2) == Category2); }
  bool is_category2_2nd() const {
    return ((_u._data & Category2_2nd) == Category2_2nd);
  }
  bool is_reference_check() const { return _u._data == ReferenceQuery; }
  bool is_category1_check() const { return _u._data == Category1Query; }
  bool is_category2_check() const { return _u._data == Category2Query; }
  bool is_category2_2nd_check() const { return _u._data == Category2_2ndQuery; }
  bool is_check() const { return (_u._data & TypeQuery) == TypeQuery; }

  bool is_x_array(char sig) const {
    return is_null() || (is_array() && (name()->byte_at(1) == sig));
  }
  bool is_int_array() const { return is_x_array('I'); }
  bool is_byte_array() const { return is_x_array('B'); }
  bool is_bool_array() const { return is_x_array('Z'); }
  bool is_char_array() const { return is_x_array('C'); }
  bool is_short_array() const { return is_x_array('S'); }
  bool is_long_array() const { return is_x_array('J'); }
  bool is_float_array() const { return is_x_array('F'); }
  bool is_double_array() const { return is_x_array('D'); }
  bool is_object_array() const { return is_x_array('L'); }
  bool is_array_array() const { return is_x_array('['); }
  bool is_reference_array() const
    { return is_object_array() || is_array_array(); }
  bool is_object() const
    { return (is_reference() && !is_null() && name()->utf8_length() >= 1 &&
              name()->byte_at(0) != '['); }
  bool is_array() const
    { return (is_reference() && !is_null() && name()->utf8_length() >= 2 &&
              name()->byte_at(0) == '['); }
  bool is_uninitialized() const
    { return ((_u._data & Uninitialized) == Uninitialized); }
  bool is_uninitialized_this() const
    { return is_uninitialized() && bci() == BciForThis; }

  VerificationType to_category2_2nd() const {
    assert(is_category2(), "Must be a double word");
    return VerificationType(is_long() ? Long_2nd : Double_2nd);
  }

  u2 bci() const {
    assert(is_uninitialized(), "Must be uninitialized type");
    return ((_u._data & BciMask) >> 1 * BitsPerByte);
  }

  Symbol* name() const {
    assert(is_reference() && !is_null(), "Must be a non-null reference");
    return _u._sym;
  }

  bool equals(const VerificationType& t) const {
    return (_u._data == t._u._data ||
      (is_reference() && t.is_reference() && !is_null() && !t.is_null() &&
       name() == t.name()));
  }

  bool operator ==(const VerificationType& t) const {
    return equals(t);
  }

  bool operator !=(const VerificationType& t) const {
    return !equals(t);
  }

  // The whole point of this type system - check to see if one type
  // is assignable to another.  Returns true if one can assign 'from' to
  // this.
  bool is_assignable_from(
      const VerificationType& from, ClassVerifier* context, TRAPS) const {
    if (equals(from) || is_bogus()) {
      return true;
    } else {
      switch(_u._data) {
        case Category1Query:
          return from.is_category1();
        case Category2Query:
          return from.is_category2();
        case Category2_2ndQuery:
          return from.is_category2_2nd();
        case ReferenceQuery:
          return from.is_reference() || from.is_uninitialized();
        case Boolean:
        case Byte:
        case Char:
        case Short:
          // An int can be assigned to boolean, byte, char or short values.
          return from.is_integer();
        default:
          if (is_reference() && from.is_reference()) {
            return is_reference_assignable_from(from, context, CHECK_false);
          } else {
            return false;
          }
      }
    }
  }

  VerificationType get_component(ClassVerifier* context, TRAPS) const;

  int dimensions() const {
    assert(is_array(), "Must be an array");
    int index = 0;
    while (name()->byte_at(index++) == '[');
    return index;
  }

  void print_on(outputStream* st) const;

 private:

  bool is_reference_assignable_from(
    const VerificationType&, ClassVerifier*, TRAPS) const;
};

#endif // SHARE_VM_CLASSFILE_VERIFICATIONTYPE_HPP

Other Java examples (source code examples)

Here is a short list of links related to this Java verificationType.hpp source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.