jaxp/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java
author chegar
Sun, 17 Aug 2014 15:51:56 +0100
changeset 25868 686eef1e7a79
parent 12457 jaxp/src/com/sun/org/apache/bcel/internal/generic/ReferenceType.java@c348e06f0e82
child 44797 8b3b3b911b8a
permissions -rw-r--r--
8054834: Modular Source Code Reviewed-by: alanb, chegar, ihse, mduigou Contributed-by: alan.bateman@oracle.com, alex.buckley@oracle.com, chris.hegarty@oracle.com, erik.joelsson@oracle.com, jonathan.gibbons@oracle.com, karen.kinnear@oracle.com, magnus.ihse.bursie@oracle.com, mandy.chung@oracle.com, mark.reinhold@oracle.com, paul.sandoz@oracle.com
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6
7f561c08de6b Initial load
duke
parents:
diff changeset
     1
/*
7f561c08de6b Initial load
duke
parents:
diff changeset
     2
 * reserved comment block
7f561c08de6b Initial load
duke
parents:
diff changeset
     3
 * DO NOT REMOVE OR ALTER!
7f561c08de6b Initial load
duke
parents:
diff changeset
     4
 */
7f561c08de6b Initial load
duke
parents:
diff changeset
     5
package com.sun.org.apache.bcel.internal.generic;
7f561c08de6b Initial load
duke
parents:
diff changeset
     6
7f561c08de6b Initial load
duke
parents:
diff changeset
     7
/* ====================================================================
7f561c08de6b Initial load
duke
parents:
diff changeset
     8
 * The Apache Software License, Version 1.1
7f561c08de6b Initial load
duke
parents:
diff changeset
     9
 *
7f561c08de6b Initial load
duke
parents:
diff changeset
    10
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
7f561c08de6b Initial load
duke
parents:
diff changeset
    11
 * reserved.
7f561c08de6b Initial load
duke
parents:
diff changeset
    12
 *
7f561c08de6b Initial load
duke
parents:
diff changeset
    13
 * Redistribution and use in source and binary forms, with or without
7f561c08de6b Initial load
duke
parents:
diff changeset
    14
 * modification, are permitted provided that the following conditions
7f561c08de6b Initial load
duke
parents:
diff changeset
    15
 * are met:
7f561c08de6b Initial load
duke
parents:
diff changeset
    16
 *
7f561c08de6b Initial load
duke
parents:
diff changeset
    17
 * 1. Redistributions of source code must retain the above copyright
7f561c08de6b Initial load
duke
parents:
diff changeset
    18
 *    notice, this list of conditions and the following disclaimer.
7f561c08de6b Initial load
duke
parents:
diff changeset
    19
 *
7f561c08de6b Initial load
duke
parents:
diff changeset
    20
 * 2. Redistributions in binary form must reproduce the above copyright
7f561c08de6b Initial load
duke
parents:
diff changeset
    21
 *    notice, this list of conditions and the following disclaimer in
7f561c08de6b Initial load
duke
parents:
diff changeset
    22
 *    the documentation and/or other materials provided with the
7f561c08de6b Initial load
duke
parents:
diff changeset
    23
 *    distribution.
7f561c08de6b Initial load
duke
parents:
diff changeset
    24
 *
7f561c08de6b Initial load
duke
parents:
diff changeset
    25
 * 3. The end-user documentation included with the redistribution,
7f561c08de6b Initial load
duke
parents:
diff changeset
    26
 *    if any, must include the following acknowledgment:
7f561c08de6b Initial load
duke
parents:
diff changeset
    27
 *       "This product includes software developed by the
7f561c08de6b Initial load
duke
parents:
diff changeset
    28
 *        Apache Software Foundation (http://www.apache.org/)."
7f561c08de6b Initial load
duke
parents:
diff changeset
    29
 *    Alternately, this acknowledgment may appear in the software itself,
7f561c08de6b Initial load
duke
parents:
diff changeset
    30
 *    if and wherever such third-party acknowledgments normally appear.
7f561c08de6b Initial load
duke
parents:
diff changeset
    31
 *
7f561c08de6b Initial load
duke
parents:
diff changeset
    32
 * 4. The names "Apache" and "Apache Software Foundation" and
7f561c08de6b Initial load
duke
parents:
diff changeset
    33
 *    "Apache BCEL" must not be used to endorse or promote products
7f561c08de6b Initial load
duke
parents:
diff changeset
    34
 *    derived from this software without prior written permission. For
7f561c08de6b Initial load
duke
parents:
diff changeset
    35
 *    written permission, please contact apache@apache.org.
7f561c08de6b Initial load
duke
parents:
diff changeset
    36
 *
7f561c08de6b Initial load
duke
parents:
diff changeset
    37
 * 5. Products derived from this software may not be called "Apache",
7f561c08de6b Initial load
duke
parents:
diff changeset
    38
 *    "Apache BCEL", nor may "Apache" appear in their name, without
7f561c08de6b Initial load
duke
parents:
diff changeset
    39
 *    prior written permission of the Apache Software Foundation.
7f561c08de6b Initial load
duke
parents:
diff changeset
    40
 *
7f561c08de6b Initial load
duke
parents:
diff changeset
    41
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
7f561c08de6b Initial load
duke
parents:
diff changeset
    42
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
7f561c08de6b Initial load
duke
parents:
diff changeset
    43
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
7f561c08de6b Initial load
duke
parents:
diff changeset
    44
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
7f561c08de6b Initial load
duke
parents:
diff changeset
    45
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
7f561c08de6b Initial load
duke
parents:
diff changeset
    46
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
7f561c08de6b Initial load
duke
parents:
diff changeset
    47
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
7f561c08de6b Initial load
duke
parents:
diff changeset
    48
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
7f561c08de6b Initial load
duke
parents:
diff changeset
    49
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
7f561c08de6b Initial load
duke
parents:
diff changeset
    50
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
7f561c08de6b Initial load
duke
parents:
diff changeset
    51
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7f561c08de6b Initial load
duke
parents:
diff changeset
    52
 * SUCH DAMAGE.
7f561c08de6b Initial load
duke
parents:
diff changeset
    53
 * ====================================================================
7f561c08de6b Initial load
duke
parents:
diff changeset
    54
 *
7f561c08de6b Initial load
duke
parents:
diff changeset
    55
 * This software consists of voluntary contributions made by many
7f561c08de6b Initial load
duke
parents:
diff changeset
    56
 * individuals on behalf of the Apache Software Foundation.  For more
7f561c08de6b Initial load
duke
parents:
diff changeset
    57
 * information on the Apache Software Foundation, please see
7f561c08de6b Initial load
duke
parents:
diff changeset
    58
 * <http://www.apache.org/>.
7f561c08de6b Initial load
duke
parents:
diff changeset
    59
 */
7f561c08de6b Initial load
duke
parents:
diff changeset
    60
7f561c08de6b Initial load
duke
parents:
diff changeset
    61
import com.sun.org.apache.bcel.internal.Constants;
7f561c08de6b Initial load
duke
parents:
diff changeset
    62
import com.sun.org.apache.bcel.internal.Repository;
7f561c08de6b Initial load
duke
parents:
diff changeset
    63
import com.sun.org.apache.bcel.internal.classfile.JavaClass;
7f561c08de6b Initial load
duke
parents:
diff changeset
    64
7f561c08de6b Initial load
duke
parents:
diff changeset
    65
/**
7f561c08de6b Initial load
duke
parents:
diff changeset
    66
 * Super class for object and array types.
7f561c08de6b Initial load
duke
parents:
diff changeset
    67
 *
7f561c08de6b Initial load
duke
parents:
diff changeset
    68
 * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
7f561c08de6b Initial load
duke
parents:
diff changeset
    69
 */
7f561c08de6b Initial load
duke
parents:
diff changeset
    70
public abstract class ReferenceType extends Type {
7f561c08de6b Initial load
duke
parents:
diff changeset
    71
  protected ReferenceType(byte t, String s) {
7f561c08de6b Initial load
duke
parents:
diff changeset
    72
    super(t, s);
7f561c08de6b Initial load
duke
parents:
diff changeset
    73
  }
7f561c08de6b Initial load
duke
parents:
diff changeset
    74
7f561c08de6b Initial load
duke
parents:
diff changeset
    75
  /** Class is non-abstract but not instantiable from the outside
7f561c08de6b Initial load
duke
parents:
diff changeset
    76
   */
7f561c08de6b Initial load
duke
parents:
diff changeset
    77
  ReferenceType() {
7f561c08de6b Initial load
duke
parents:
diff changeset
    78
    super(Constants.T_OBJECT, "<null object>");
7f561c08de6b Initial load
duke
parents:
diff changeset
    79
  }
7f561c08de6b Initial load
duke
parents:
diff changeset
    80
7f561c08de6b Initial load
duke
parents:
diff changeset
    81
  /**
7f561c08de6b Initial load
duke
parents:
diff changeset
    82
   * Return true iff this type is castable to another type t as defined in
7f561c08de6b Initial load
duke
parents:
diff changeset
    83
   * the JVM specification.  The case where this is Type.NULL is not
7f561c08de6b Initial load
duke
parents:
diff changeset
    84
   * defined (see the CHECKCAST definition in the JVM specification).
7f561c08de6b Initial load
duke
parents:
diff changeset
    85
   * However, because e.g. CHECKCAST doesn't throw a
7f561c08de6b Initial load
duke
parents:
diff changeset
    86
   * ClassCastException when casting a null reference to any Object,
7f561c08de6b Initial load
duke
parents:
diff changeset
    87
   * true is returned in this case.
7f561c08de6b Initial load
duke
parents:
diff changeset
    88
   */
7f561c08de6b Initial load
duke
parents:
diff changeset
    89
  public boolean isCastableTo(Type t) {
7f561c08de6b Initial load
duke
parents:
diff changeset
    90
    if (this.equals(Type.NULL))
7f561c08de6b Initial load
duke
parents:
diff changeset
    91
      return true;              // If this is ever changed in isAssignmentCompatible()
7f561c08de6b Initial load
duke
parents:
diff changeset
    92
7f561c08de6b Initial load
duke
parents:
diff changeset
    93
    return isAssignmentCompatibleWith(t);
7f561c08de6b Initial load
duke
parents:
diff changeset
    94
    /* Yes, it's true: It's the same definition.
7f561c08de6b Initial load
duke
parents:
diff changeset
    95
     * See vmspec2 AASTORE / CHECKCAST definitions.
7f561c08de6b Initial load
duke
parents:
diff changeset
    96
     */
7f561c08de6b Initial load
duke
parents:
diff changeset
    97
  }
7f561c08de6b Initial load
duke
parents:
diff changeset
    98
7f561c08de6b Initial load
duke
parents:
diff changeset
    99
  /**
7f561c08de6b Initial load
duke
parents:
diff changeset
   100
   * Return true iff this is assignment compatible with another type t
7f561c08de6b Initial load
duke
parents:
diff changeset
   101
   * as defined in the JVM specification; see the AASTORE definition
7f561c08de6b Initial load
duke
parents:
diff changeset
   102
   * there.
7f561c08de6b Initial load
duke
parents:
diff changeset
   103
   */
7f561c08de6b Initial load
duke
parents:
diff changeset
   104
  public boolean isAssignmentCompatibleWith(Type t) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   105
    if (!(t instanceof ReferenceType))
7f561c08de6b Initial load
duke
parents:
diff changeset
   106
      return false;
7f561c08de6b Initial load
duke
parents:
diff changeset
   107
7f561c08de6b Initial load
duke
parents:
diff changeset
   108
    ReferenceType T = (ReferenceType) t;
7f561c08de6b Initial load
duke
parents:
diff changeset
   109
7f561c08de6b Initial load
duke
parents:
diff changeset
   110
    if (this.equals(Type.NULL))
7f561c08de6b Initial load
duke
parents:
diff changeset
   111
      return true; // This is not explicitely stated, but clear. Isn't it?
7f561c08de6b Initial load
duke
parents:
diff changeset
   112
7f561c08de6b Initial load
duke
parents:
diff changeset
   113
    /* If this is a class type then
7f561c08de6b Initial load
duke
parents:
diff changeset
   114
     */
7f561c08de6b Initial load
duke
parents:
diff changeset
   115
    if ((this instanceof ObjectType) && (((ObjectType) this).referencesClass())) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   116
      /* If T is a class type, then this must be the same class as T,
7f561c08de6b Initial load
duke
parents:
diff changeset
   117
         or this must be a subclass of T;
7f561c08de6b Initial load
duke
parents:
diff changeset
   118
      */
7f561c08de6b Initial load
duke
parents:
diff changeset
   119
      if ((T instanceof ObjectType) && (((ObjectType) T).referencesClass())) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   120
        if (this.equals(T))
7f561c08de6b Initial load
duke
parents:
diff changeset
   121
          return true;
7f561c08de6b Initial load
duke
parents:
diff changeset
   122
7f561c08de6b Initial load
duke
parents:
diff changeset
   123
        if (Repository.instanceOf(((ObjectType) this).getClassName(),
7f561c08de6b Initial load
duke
parents:
diff changeset
   124
                                  ((ObjectType) T).getClassName()))
7f561c08de6b Initial load
duke
parents:
diff changeset
   125
          return true;
7f561c08de6b Initial load
duke
parents:
diff changeset
   126
      }
7f561c08de6b Initial load
duke
parents:
diff changeset
   127
7f561c08de6b Initial load
duke
parents:
diff changeset
   128
      /* If T is an interface type, this must implement interface T.
7f561c08de6b Initial load
duke
parents:
diff changeset
   129
       */
7f561c08de6b Initial load
duke
parents:
diff changeset
   130
      if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterface())) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   131
        if (Repository.implementationOf(((ObjectType) this).getClassName(),
7f561c08de6b Initial load
duke
parents:
diff changeset
   132
                                        ((ObjectType) T).getClassName()))
7f561c08de6b Initial load
duke
parents:
diff changeset
   133
          return true;
7f561c08de6b Initial load
duke
parents:
diff changeset
   134
      }
7f561c08de6b Initial load
duke
parents:
diff changeset
   135
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
   136
7f561c08de6b Initial load
duke
parents:
diff changeset
   137
    /* If this is an interface type, then:
7f561c08de6b Initial load
duke
parents:
diff changeset
   138
     */
7f561c08de6b Initial load
duke
parents:
diff changeset
   139
    if ((this instanceof ObjectType) && (((ObjectType) this).referencesInterface())) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   140
      /* If T is a class type, then T must be Object (2.4.7).
7f561c08de6b Initial load
duke
parents:
diff changeset
   141
       */
7f561c08de6b Initial load
duke
parents:
diff changeset
   142
      if ((T instanceof ObjectType) && (((ObjectType) T).referencesClass())) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   143
        if (T.equals(Type.OBJECT)) return true;
7f561c08de6b Initial load
duke
parents:
diff changeset
   144
      }
7f561c08de6b Initial load
duke
parents:
diff changeset
   145
7f561c08de6b Initial load
duke
parents:
diff changeset
   146
      /* If T is an interface type, then T must be the same interface
7f561c08de6b Initial load
duke
parents:
diff changeset
   147
       * as this or a superinterface of this (2.13.2).
7f561c08de6b Initial load
duke
parents:
diff changeset
   148
       */
7f561c08de6b Initial load
duke
parents:
diff changeset
   149
      if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterface())) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   150
        if (this.equals(T)) return true;
7f561c08de6b Initial load
duke
parents:
diff changeset
   151
        if (Repository.implementationOf(((ObjectType) this).getClassName(),
7f561c08de6b Initial load
duke
parents:
diff changeset
   152
                                        ((ObjectType) T).getClassName()))
7f561c08de6b Initial load
duke
parents:
diff changeset
   153
          return true;
7f561c08de6b Initial load
duke
parents:
diff changeset
   154
      }
7f561c08de6b Initial load
duke
parents:
diff changeset
   155
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
   156
7f561c08de6b Initial load
duke
parents:
diff changeset
   157
    /* If this is an array type, namely, the type SC[], that is, an
7f561c08de6b Initial load
duke
parents:
diff changeset
   158
     * array of components of type SC, then:
7f561c08de6b Initial load
duke
parents:
diff changeset
   159
     */
7f561c08de6b Initial load
duke
parents:
diff changeset
   160
    if (this instanceof ArrayType) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   161
      /* If T is a class type, then T must be Object (2.4.7).
7f561c08de6b Initial load
duke
parents:
diff changeset
   162
       */
7f561c08de6b Initial load
duke
parents:
diff changeset
   163
      if ((T instanceof ObjectType) && (((ObjectType) T).referencesClass())) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   164
        if (T.equals(Type.OBJECT)) return true;
7f561c08de6b Initial load
duke
parents:
diff changeset
   165
      }
7f561c08de6b Initial load
duke
parents:
diff changeset
   166
7f561c08de6b Initial load
duke
parents:
diff changeset
   167
      /* If T is an array type TC[], that is, an array of components
7f561c08de6b Initial load
duke
parents:
diff changeset
   168
       * of type TC, then one of the following must be true:
7f561c08de6b Initial load
duke
parents:
diff changeset
   169
       */
7f561c08de6b Initial load
duke
parents:
diff changeset
   170
      if (T instanceof ArrayType) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   171
        /* TC and SC are the same primitive type (2.4.1).
7f561c08de6b Initial load
duke
parents:
diff changeset
   172
         */
7f561c08de6b Initial load
duke
parents:
diff changeset
   173
        Type sc = ((ArrayType) this).getElementType();
7f561c08de6b Initial load
duke
parents:
diff changeset
   174
        Type tc = ((ArrayType) this).getElementType();
7f561c08de6b Initial load
duke
parents:
diff changeset
   175
7f561c08de6b Initial load
duke
parents:
diff changeset
   176
        if (sc instanceof BasicType && tc instanceof BasicType && sc.equals(tc))
7f561c08de6b Initial load
duke
parents:
diff changeset
   177
          return true;
7f561c08de6b Initial load
duke
parents:
diff changeset
   178
7f561c08de6b Initial load
duke
parents:
diff changeset
   179
        /* TC and SC are reference types (2.4.6), and type SC is
7f561c08de6b Initial load
duke
parents:
diff changeset
   180
         * assignable to TC by these runtime rules.
7f561c08de6b Initial load
duke
parents:
diff changeset
   181
         */
7f561c08de6b Initial load
duke
parents:
diff changeset
   182
        if (tc instanceof ReferenceType && sc instanceof ReferenceType &&
7f561c08de6b Initial load
duke
parents:
diff changeset
   183
            ((ReferenceType) sc).isAssignmentCompatibleWith((ReferenceType) tc))
7f561c08de6b Initial load
duke
parents:
diff changeset
   184
          return true;
7f561c08de6b Initial load
duke
parents:
diff changeset
   185
      }
7f561c08de6b Initial load
duke
parents:
diff changeset
   186
7f561c08de6b Initial load
duke
parents:
diff changeset
   187
      /* If T is an interface type, T must be one of the interfaces implemented by arrays (2.15). */
7f561c08de6b Initial load
duke
parents:
diff changeset
   188
      // TODO: Check if this is still valid or find a way to dynamically find out which
7f561c08de6b Initial load
duke
parents:
diff changeset
   189
      // interfaces arrays implement. However, as of the JVM specification edition 2, there
7f561c08de6b Initial load
duke
parents:
diff changeset
   190
      // are at least two different pages where assignment compatibility is defined and
7f561c08de6b Initial load
duke
parents:
diff changeset
   191
      // on one of them "interfaces implemented by arrays" is exchanged with "'Cloneable' or
7f561c08de6b Initial load
duke
parents:
diff changeset
   192
      // 'java.io.Serializable'"
7f561c08de6b Initial load
duke
parents:
diff changeset
   193
      if ((T instanceof ObjectType) && (((ObjectType) T).referencesInterface())) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   194
        for (int ii = 0; ii < Constants.INTERFACES_IMPLEMENTED_BY_ARRAYS.length; ii++) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   195
          if (T.equals(new ObjectType(Constants.INTERFACES_IMPLEMENTED_BY_ARRAYS[ii]))) return true;
7f561c08de6b Initial load
duke
parents:
diff changeset
   196
        }
7f561c08de6b Initial load
duke
parents:
diff changeset
   197
      }
7f561c08de6b Initial load
duke
parents:
diff changeset
   198
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
   199
    return false; // default.
7f561c08de6b Initial load
duke
parents:
diff changeset
   200
  }
7f561c08de6b Initial load
duke
parents:
diff changeset
   201
7f561c08de6b Initial load
duke
parents:
diff changeset
   202
  /**
7f561c08de6b Initial load
duke
parents:
diff changeset
   203
   * This commutative operation returns the first common superclass (narrowest ReferenceType
7f561c08de6b Initial load
duke
parents:
diff changeset
   204
   * referencing a class, not an interface).
7f561c08de6b Initial load
duke
parents:
diff changeset
   205
   * If one of the types is a superclass of the other, the former is returned.
7f561c08de6b Initial load
duke
parents:
diff changeset
   206
   * If "this" is Type.NULL, then t is returned.
7f561c08de6b Initial load
duke
parents:
diff changeset
   207
   * If t is Type.NULL, then "this" is returned.
7f561c08de6b Initial load
duke
parents:
diff changeset
   208
   * If "this" equals t ['this.equals(t)'] "this" is returned.
7f561c08de6b Initial load
duke
parents:
diff changeset
   209
   * If "this" or t is an ArrayType, then Type.OBJECT is returned;
7f561c08de6b Initial load
duke
parents:
diff changeset
   210
   * unless their dimensions match. Then an ArrayType of the same
7f561c08de6b Initial load
duke
parents:
diff changeset
   211
   * number of dimensions is returned, with its basic type being the
7f561c08de6b Initial load
duke
parents:
diff changeset
   212
   * first common super class of the basic types of "this" and t.
7f561c08de6b Initial load
duke
parents:
diff changeset
   213
   * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned.
7f561c08de6b Initial load
duke
parents:
diff changeset
   214
   * If not all of the two classes' superclasses cannot be found, "null" is returned.
7f561c08de6b Initial load
duke
parents:
diff changeset
   215
   * See the JVM specification edition 2, "4.9.2 The Bytecode Verifier".
7f561c08de6b Initial load
duke
parents:
diff changeset
   216
   */
7f561c08de6b Initial load
duke
parents:
diff changeset
   217
  public ReferenceType getFirstCommonSuperclass(ReferenceType t) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   218
    if (this.equals(Type.NULL)) return t;
7f561c08de6b Initial load
duke
parents:
diff changeset
   219
    if (t.equals(Type.NULL)) return this;
7f561c08de6b Initial load
duke
parents:
diff changeset
   220
    if (this.equals(t)) return this;
7f561c08de6b Initial load
duke
parents:
diff changeset
   221
    /*
7f561c08de6b Initial load
duke
parents:
diff changeset
   222
     * TODO: Above sounds a little arbitrary. On the other hand, there is
7f561c08de6b Initial load
duke
parents:
diff changeset
   223
     * no object referenced by Type.NULL so we can also say all the objects
7f561c08de6b Initial load
duke
parents:
diff changeset
   224
     * referenced by Type.NULL were derived from java.lang.Object.
7f561c08de6b Initial load
duke
parents:
diff changeset
   225
     * However, the Java Language's "instanceof" operator proves us wrong:
7f561c08de6b Initial load
duke
parents:
diff changeset
   226
     * "null" is not referring to an instance of java.lang.Object :)
7f561c08de6b Initial load
duke
parents:
diff changeset
   227
     */
7f561c08de6b Initial load
duke
parents:
diff changeset
   228
7f561c08de6b Initial load
duke
parents:
diff changeset
   229
    /* This code is from a bug report by Konstantin Shagin <konst@cs.technion.ac.il> */
7f561c08de6b Initial load
duke
parents:
diff changeset
   230
7f561c08de6b Initial load
duke
parents:
diff changeset
   231
    if ((this instanceof ArrayType) && (t instanceof ArrayType)) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   232
      ArrayType arrType1 = (ArrayType) this;
7f561c08de6b Initial load
duke
parents:
diff changeset
   233
      ArrayType arrType2 = (ArrayType) t;
7f561c08de6b Initial load
duke
parents:
diff changeset
   234
      if (
7f561c08de6b Initial load
duke
parents:
diff changeset
   235
          (arrType1.getDimensions() == arrType2.getDimensions()) &&
7f561c08de6b Initial load
duke
parents:
diff changeset
   236
          arrType1.getBasicType() instanceof ObjectType &&
7f561c08de6b Initial load
duke
parents:
diff changeset
   237
          arrType2.getBasicType() instanceof ObjectType) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   238
        return new ArrayType(
7f561c08de6b Initial load
duke
parents:
diff changeset
   239
                             ((ObjectType) arrType1.getBasicType()).getFirstCommonSuperclass((ObjectType) arrType2.getBasicType()),
7f561c08de6b Initial load
duke
parents:
diff changeset
   240
                             arrType1.getDimensions()
7f561c08de6b Initial load
duke
parents:
diff changeset
   241
                             );
7f561c08de6b Initial load
duke
parents:
diff changeset
   242
7f561c08de6b Initial load
duke
parents:
diff changeset
   243
      }
7f561c08de6b Initial load
duke
parents:
diff changeset
   244
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
   245
7f561c08de6b Initial load
duke
parents:
diff changeset
   246
    if ((this instanceof ArrayType) || (t instanceof ArrayType))
7f561c08de6b Initial load
duke
parents:
diff changeset
   247
      return Type.OBJECT;
7f561c08de6b Initial load
duke
parents:
diff changeset
   248
    // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
7f561c08de6b Initial load
duke
parents:
diff changeset
   249
7f561c08de6b Initial load
duke
parents:
diff changeset
   250
    if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterface()) ||
7f561c08de6b Initial load
duke
parents:
diff changeset
   251
        ((t instanceof ObjectType) && ((ObjectType) t).referencesInterface()))
7f561c08de6b Initial load
duke
parents:
diff changeset
   252
      return Type.OBJECT;
7f561c08de6b Initial load
duke
parents:
diff changeset
   253
    // TODO: The above line is correct comparing to the vmspec2. But one could
7f561c08de6b Initial load
duke
parents:
diff changeset
   254
    // make class file verification a bit stronger here by using the notion of
7f561c08de6b Initial load
duke
parents:
diff changeset
   255
    // superinterfaces or even castability or assignment compatibility.
7f561c08de6b Initial load
duke
parents:
diff changeset
   256
7f561c08de6b Initial load
duke
parents:
diff changeset
   257
7f561c08de6b Initial load
duke
parents:
diff changeset
   258
    // this and t are ObjectTypes, see above.
7f561c08de6b Initial load
duke
parents:
diff changeset
   259
    ObjectType thiz = (ObjectType) this;
7f561c08de6b Initial load
duke
parents:
diff changeset
   260
    ObjectType other = (ObjectType) t;
7f561c08de6b Initial load
duke
parents:
diff changeset
   261
    JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName());
7f561c08de6b Initial load
duke
parents:
diff changeset
   262
    JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName());
7f561c08de6b Initial load
duke
parents:
diff changeset
   263
7f561c08de6b Initial load
duke
parents:
diff changeset
   264
    if ((thiz_sups == null) || (other_sups == null)) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   265
      return null;
7f561c08de6b Initial load
duke
parents:
diff changeset
   266
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
   267
7f561c08de6b Initial load
duke
parents:
diff changeset
   268
    // Waaahh...
7f561c08de6b Initial load
duke
parents:
diff changeset
   269
    JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1];
7f561c08de6b Initial load
duke
parents:
diff changeset
   270
    JavaClass[] t_sups = new JavaClass[other_sups.length + 1];
7f561c08de6b Initial load
duke
parents:
diff changeset
   271
    System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length);
7f561c08de6b Initial load
duke
parents:
diff changeset
   272
    System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length);
7f561c08de6b Initial load
duke
parents:
diff changeset
   273
    this_sups[0] = Repository.lookupClass(thiz.getClassName());
7f561c08de6b Initial load
duke
parents:
diff changeset
   274
    t_sups[0] = Repository.lookupClass(other.getClassName());
7f561c08de6b Initial load
duke
parents:
diff changeset
   275
7f561c08de6b Initial load
duke
parents:
diff changeset
   276
    for (int i = 0; i < t_sups.length; i++) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   277
      for (int j = 0; j < this_sups.length; j++) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   278
        if (this_sups[j].equals(t_sups[i])) return new ObjectType(this_sups[j].getClassName());
7f561c08de6b Initial load
duke
parents:
diff changeset
   279
      }
7f561c08de6b Initial load
duke
parents:
diff changeset
   280
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
   281
7f561c08de6b Initial load
duke
parents:
diff changeset
   282
    // Huh? Did you ask for Type.OBJECT's superclass??
7f561c08de6b Initial load
duke
parents:
diff changeset
   283
    return null;
7f561c08de6b Initial load
duke
parents:
diff changeset
   284
  }
7f561c08de6b Initial load
duke
parents:
diff changeset
   285
7f561c08de6b Initial load
duke
parents:
diff changeset
   286
  /**
7f561c08de6b Initial load
duke
parents:
diff changeset
   287
   * This commutative operation returns the first common superclass (narrowest ReferenceType
7f561c08de6b Initial load
duke
parents:
diff changeset
   288
   * referencing a class, not an interface).
7f561c08de6b Initial load
duke
parents:
diff changeset
   289
   * If one of the types is a superclass of the other, the former is returned.
7f561c08de6b Initial load
duke
parents:
diff changeset
   290
   * If "this" is Type.NULL, then t is returned.
7f561c08de6b Initial load
duke
parents:
diff changeset
   291
   * If t is Type.NULL, then "this" is returned.
7f561c08de6b Initial load
duke
parents:
diff changeset
   292
   * If "this" equals t ['this.equals(t)'] "this" is returned.
7f561c08de6b Initial load
duke
parents:
diff changeset
   293
   * If "this" or t is an ArrayType, then Type.OBJECT is returned.
7f561c08de6b Initial load
duke
parents:
diff changeset
   294
   * If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned.
7f561c08de6b Initial load
duke
parents:
diff changeset
   295
   * If not all of the two classes' superclasses cannot be found, "null" is returned.
7f561c08de6b Initial load
duke
parents:
diff changeset
   296
   * See the JVM specification edition 2, "4.9.2 The Bytecode Verifier".
7f561c08de6b Initial load
duke
parents:
diff changeset
   297
   *
7f561c08de6b Initial load
duke
parents:
diff changeset
   298
   * @deprecated use getFirstCommonSuperclass(ReferenceType t) which has
7f561c08de6b Initial load
duke
parents:
diff changeset
   299
   *             slightly changed semantics.
7f561c08de6b Initial load
duke
parents:
diff changeset
   300
   */
7f561c08de6b Initial load
duke
parents:
diff changeset
   301
  public ReferenceType firstCommonSuperclass(ReferenceType t) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   302
    if (this.equals(Type.NULL)) return t;
7f561c08de6b Initial load
duke
parents:
diff changeset
   303
    if (t.equals(Type.NULL)) return this;
7f561c08de6b Initial load
duke
parents:
diff changeset
   304
    if (this.equals(t)) return this;
7f561c08de6b Initial load
duke
parents:
diff changeset
   305
    /*
7f561c08de6b Initial load
duke
parents:
diff changeset
   306
     * TODO: Above sounds a little arbitrary. On the other hand, there is
7f561c08de6b Initial load
duke
parents:
diff changeset
   307
     * no object referenced by Type.NULL so we can also say all the objects
7f561c08de6b Initial load
duke
parents:
diff changeset
   308
     * referenced by Type.NULL were derived from java.lang.Object.
7f561c08de6b Initial load
duke
parents:
diff changeset
   309
     * However, the Java Language's "instanceof" operator proves us wrong:
7f561c08de6b Initial load
duke
parents:
diff changeset
   310
     * "null" is not referring to an instance of java.lang.Object :)
7f561c08de6b Initial load
duke
parents:
diff changeset
   311
     */
7f561c08de6b Initial load
duke
parents:
diff changeset
   312
7f561c08de6b Initial load
duke
parents:
diff changeset
   313
    if ((this instanceof ArrayType) || (t instanceof ArrayType))
7f561c08de6b Initial load
duke
parents:
diff changeset
   314
      return Type.OBJECT;
7f561c08de6b Initial load
duke
parents:
diff changeset
   315
    // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
7f561c08de6b Initial load
duke
parents:
diff changeset
   316
7f561c08de6b Initial load
duke
parents:
diff changeset
   317
    if (((this instanceof ObjectType) && ((ObjectType) this).referencesInterface()) ||
7f561c08de6b Initial load
duke
parents:
diff changeset
   318
        ((t instanceof ObjectType) && ((ObjectType) t).referencesInterface()))
7f561c08de6b Initial load
duke
parents:
diff changeset
   319
      return Type.OBJECT;
7f561c08de6b Initial load
duke
parents:
diff changeset
   320
    // TODO: The above line is correct comparing to the vmspec2. But one could
7f561c08de6b Initial load
duke
parents:
diff changeset
   321
    // make class file verification a bit stronger here by using the notion of
7f561c08de6b Initial load
duke
parents:
diff changeset
   322
    // superinterfaces or even castability or assignment compatibility.
7f561c08de6b Initial load
duke
parents:
diff changeset
   323
7f561c08de6b Initial load
duke
parents:
diff changeset
   324
7f561c08de6b Initial load
duke
parents:
diff changeset
   325
    // this and t are ObjectTypes, see above.
7f561c08de6b Initial load
duke
parents:
diff changeset
   326
    ObjectType thiz = (ObjectType) this;
7f561c08de6b Initial load
duke
parents:
diff changeset
   327
    ObjectType other = (ObjectType) t;
7f561c08de6b Initial load
duke
parents:
diff changeset
   328
    JavaClass[] thiz_sups = Repository.getSuperClasses(thiz.getClassName());
7f561c08de6b Initial load
duke
parents:
diff changeset
   329
    JavaClass[] other_sups = Repository.getSuperClasses(other.getClassName());
7f561c08de6b Initial load
duke
parents:
diff changeset
   330
7f561c08de6b Initial load
duke
parents:
diff changeset
   331
    if ((thiz_sups == null) || (other_sups == null)) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   332
      return null;
7f561c08de6b Initial load
duke
parents:
diff changeset
   333
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
   334
7f561c08de6b Initial load
duke
parents:
diff changeset
   335
    // Waaahh...
7f561c08de6b Initial load
duke
parents:
diff changeset
   336
    JavaClass[] this_sups = new JavaClass[thiz_sups.length + 1];
7f561c08de6b Initial load
duke
parents:
diff changeset
   337
    JavaClass[] t_sups = new JavaClass[other_sups.length + 1];
7f561c08de6b Initial load
duke
parents:
diff changeset
   338
    System.arraycopy(thiz_sups, 0, this_sups, 1, thiz_sups.length);
7f561c08de6b Initial load
duke
parents:
diff changeset
   339
    System.arraycopy(other_sups, 0, t_sups, 1, other_sups.length);
7f561c08de6b Initial load
duke
parents:
diff changeset
   340
    this_sups[0] = Repository.lookupClass(thiz.getClassName());
7f561c08de6b Initial load
duke
parents:
diff changeset
   341
    t_sups[0] = Repository.lookupClass(other.getClassName());
7f561c08de6b Initial load
duke
parents:
diff changeset
   342
7f561c08de6b Initial load
duke
parents:
diff changeset
   343
    for (int i = 0; i < t_sups.length; i++) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   344
      for (int j = 0; j < this_sups.length; j++) {
7f561c08de6b Initial load
duke
parents:
diff changeset
   345
        if (this_sups[j].equals(t_sups[i])) return new ObjectType(this_sups[j].getClassName());
7f561c08de6b Initial load
duke
parents:
diff changeset
   346
      }
7f561c08de6b Initial load
duke
parents:
diff changeset
   347
    }
7f561c08de6b Initial load
duke
parents:
diff changeset
   348
7f561c08de6b Initial load
duke
parents:
diff changeset
   349
    // Huh? Did you ask for Type.OBJECT's superclass??
7f561c08de6b Initial load
duke
parents:
diff changeset
   350
    return null;
7f561c08de6b Initial load
duke
parents:
diff changeset
   351
  }
7f561c08de6b Initial load
duke
parents:
diff changeset
   352
}