You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by dl...@apache.org on 2007/08/12 23:11:55 UTC
svn commit: r565152 -
/harmony/enhanced/sandbox/bootjvm/bootJVM/jvm/src/classutil.c
Author: dlydick
Date: Sun Aug 12 14:11:54 2007
New Revision: 565152
URL: http://svn.apache.org/viewvc?view=rev&rev=565152
Log:
Added suite of OO evaluation functions.
Modified:
harmony/enhanced/sandbox/bootjvm/bootJVM/jvm/src/classutil.c
Modified: harmony/enhanced/sandbox/bootjvm/bootJVM/jvm/src/classutil.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/sandbox/bootjvm/bootJVM/jvm/src/classutil.c?view=diff&rev=565152&r1=565151&r2=565152
==============================================================================
--- harmony/enhanced/sandbox/bootjvm/bootJVM/jvm/src/classutil.c (original)
+++ harmony/enhanced/sandbox/bootjvm/bootJVM/jvm/src/classutil.c Sun Aug 12 14:11:54 2007
@@ -1,9 +1,7 @@
/*!
* @file classutil.c
*
- * @brief Utility and glue functions for
- * @link jvm/src/class.c class.c@endlink
- * and @c @b java.lang.Class
+ * @brief Utility and glue functions for manipulating Java classes.
*
*
* @internal Due to the fact that the implementation of the Java class
@@ -60,19 +58,22 @@
#include "jvmcfg.h"
#include "cfmacros.h"
#include "classfile.h"
+#include "field.h"
#include "jvm.h"
#include "jvmclass.h"
#include "linkage.h"
+#include "method.h"
#include "nts.h"
#include "utf.h"
+#include "util.h"
/*!
- * @name Examine class indices for object hierarchy relationships.
+ * @name Examine class contents for object hierarchy relationships.
*
*
* If not already present, all classes examined will be loaded here
- * when their constant_pool[] or interfaced[] information is needed.
+ * when their constant_pool[] or interfaces[] information is needed.
*
* @note <em>There is little runtime check performed</em> to check
* whether the input class indices represent classes, interfaces,
@@ -92,13 +93,13 @@
/*@{ */ /* Begin grouped definitions */
/*!
- * @brief Check is class @b clsidx1 is a subclass of class @b clsidx2 .
+ * @brief Check if class @b clsidx1 is a subclass of class @b clsidx2 .
*
* This effectively asks the OO hierarchy question, "Is @c @b clsidx1
* a @c @b clsidx2 ?" For an @link #rtrue rtrue@endlink comparison,
* class @c @b clsidx1 must be either the same class as class
* @c @b clsidx2 or a subclass of it. In other words, the true
- * comparison affirms "@c @b clsidx1 is a @c @b clsidx2 ."
+ * comparison affirms "@c @b clsidx1 <em>is a</em> @c @b clsidx2 ."
*
* The superclass of all array types @e must be java.lang.Object
* per JVM spec section 2.15. (They "may" be assigned this type, if
@@ -114,10 +115,16 @@
* If both input parameters are identical, then result
* is @link #rtrue rtrue@endlink.
*
+ * @see classutil_direct_superclass_parent_object_of()
+ * @see classutil_class_has_a_method()
+ * @see classutil_class_has_an_interface_method()
+ *
*/
rboolean classutil_class_is_a(jvm_class_index clsidx1,
jvm_class_index clsidx2)
{
+ ARCH_FUNCTION_NAME(classutil_class_is_a);
+
/* Disallow comparison with null class */
if ((jvm_class_index_null == clsidx1) ||
(jvm_class_index_null == clsidx2))
@@ -147,8 +154,8 @@
jvm_class_index clsidxCLS = clsidx1;
/*
- * Will not fail on entering loop, only possible after
- * first time through it because of @c @b clsidx1 test above.
+ * Will not fail on entering loop because of @c @b clsidx1 test
+ * above. This is only possible after the first time through.
*/
while (jvm_class_index_null != clsidxCLS)
{
@@ -164,19 +171,19 @@
}
/*
- * @internal Notice that if this request loads a class, it
- * will also load @e all of its superclasses.
- * Therefore, if it is a superclass that matches,
- * no loading will occur later, but that previously
- * loaded superclass will be found and returned
+ * @internal Could use class_load_from_cp_entry() instead of
+ * using class_find_by_cp_entry(). If this were done,
+ * then notice that if this request loaded a class, it
+ * would also load @e all of its superclasses.
+ * Therefore, if it is a superclass that matched,
+ * no loading would occur later, but that previously
+ * loaded superclass would be found and returned
* immediately.
*
*/
clsidxCLS =
- class_load_from_cp_entry_utf(
- pcfs->constant_pool[pcfs->super_class],
- rfalse,
- (jint *) rnull);
+ class_find_by_cp_entry(
+ PTR_CP1_CLASS_NAME_MEMALIGN(pcfs, pcfs->super_class));
if (clsidx2 == clsidxCLS)
{
@@ -191,6 +198,43 @@
/*!
+ * @brief Check if class of object @b objhash1 is a subclass
+ * of class @b clsidx2 .
+ *
+ *
+ * @returns @link #rtrue rtrue@endlink if class of @c @b objhash1 is
+ * the same class or a subclass of @c @b clsidx2 .
+ * If input parameter @b objhash1 is
+ * @link #jvm_object_hash_null jvm_object_hash_null@endlink, or
+ * if input parameter @b clsidx2 is
+ * @link #jvm_class_index_null jvm_class_index_null@endlink,
+ * then the result is @link #rfalse rfalse@endlink.
+ * If the class of @b objhash1 is exactly the same as
+ * @b clsidx2, then result is @link #rtrue rtrue@endlink.
+ *
+ */
+rboolean classutil_object_is_a(jvm_object_hash objhash1,
+ jvm_class_index clsidx2)
+{
+ ARCH_FUNCTION_NAME(classutil_object_is_a);
+
+ /* Disallow comparison with null class */
+ if ((jvm_object_hash_null == objhash1) ||
+ (jvm_class_index_null == clsidx2))
+ {
+ return(rfalse);
+ }
+
+ /* Retrieve class of requested object */
+ jvm_class_index clsidx1 = OBJECT_CLASS_LINKAGE(objhash1)->clsidx;
+
+ /* Analyze class of requested object */
+ return(classutil_class_is_a(clsidx1, clsidx2));
+
+} /* END of classutil_object_is_a() */
+
+
+/*!
* @brief Check if class @b clsidx1 implements interface @b clsidx2 .
*
* For an @link #rtrue rtrue@endlink comparison, the class @c @b clsidx1
@@ -203,13 +247,15 @@
* @link #jvm_class_index_null jvm_class_index_null@endlink,
* then the result is @link #rfalse rfalse@endlink.
* If both input parameters are identical, then result
- * is @link #rtrue rtrue@endlink.
+ * is @link #rfalse rfalse@endlink.
*
*/
rboolean classutil_class_implements_interface(jvm_class_index clsidx1,
jvm_class_index clsidx2)
{
- ClassFile *pcfs1, *pcfs2, *pcfs3;
+ ARCH_FUNCTION_NAME(classutil_class_implements_interface);
+
+ ClassFile *pcfs1, *pcfs2;
u2 ifidx;
/* Disallow comparison with null class */
@@ -228,23 +274,23 @@
}
/*
- * Cannot be true if comparator class index IS an interface
- * and if comparend class index is NOT an interface.
+ * Comparison is false if both are the same class, i.e. there is
+ * no interface involved.
*/
- pcfs1 = CLASS_OBJECT_LINKAGE(clsidx1)->pcfs;
- pcfs2 = CLASS_OBJECT_LINKAGE(clsidx2)->pcfs;
-
- if ( (pcfs1->access_flags & ACC_INTERFACE) ||
- (!(pcfs2->access_flags & ACC_INTERFACE)))
+ if (clsidx1 == clsidx2)
{
return(rfalse);
}
/*
- * Comparison is false if both are the same class, i.e. there is
- * no interface involved.
+ * Cannot be true if comparator class index IS an interface
+ * or if comparend class index is NOT an interface.
*/
- if (clsidx1 == clsidx2)
+ pcfs1 = CLASS_OBJECT_LINKAGE(clsidx1)->pcfs;
+ pcfs2 = CLASS_OBJECT_LINKAGE(clsidx2)->pcfs;
+
+ if ( (pcfs1->access_flags & ACC_INTERFACE) ||
+ (!(pcfs2->access_flags & ACC_INTERFACE)))
{
return(rfalse);
}
@@ -256,43 +302,17 @@
for (ifidx = 0; ifidx < pcfs1->interfaces_count; ifidx++)
{
jvm_class_index clsidxINTFC =
- class_load_from_cp_entry_utf(
- pcfs1->constant_pool[ifidx],
- rfalse,
- (jint *) rnull);
-
- /* Check if this class index matches requested interface */
- if (clsidx2 == clsidxINTFC)
- {
- return(rtrue);
- }
-
- pcfs3 = CLASS_OBJECT_LINKAGE(clsidxINTFC)->pcfs;
-
- /*
- * If found top of hierarchy, namely java.lang.Object class
- * or highest-level interface, then search cannot succeed.
- */
- if (jvm_constant_pool_index_null == pcfs3->super_class)
- {
- break;
- }
-
- /* Look at superclass of this one */
- clsidxINTFC =
- class_load_from_cp_entry_utf(
- pcfs3->constant_pool
- [pcfs3->super_class],
+ class_load_from_cp_entry_utf(pcfs1->constant_pool[ifidx],
rfalse,
(jint *) rnull);
/*
- * Check if super-hierarchy matches.
+ * Check if this class index matches requested interface
+ * or if super-hierarchy matches.
*
- * WARNING: RECURSIVE CALL!!! Will go as deep as hierarchy.
*/
- if (rtrue == classutil_class_is_superinterface_of(clsidx2,
- clsidxINTFC))
+ if ((clsidx2 == clsidxINTFC) ||
+ (rtrue == classutil_class_is_a(clsidx2, clsidxINTFC)))
{
return(rtrue);
}
@@ -309,8 +329,8 @@
* interface @b clsidx2 .
*
* For an @link #rtrue rtrue@endlink comparison, the class index
- * @c @b clsidx1 must be a valid superinterface of that defined
- * by class @c @b clsidx2 .
+ * @c @b clsidx1 must be a valid superinterface of class @c @b clsidx2
+ * per spec section 2.13.2 .
*
*
* @returns @link #rtrue rtrue@endlink if @c @b clsidx1 is a valid
@@ -325,7 +345,9 @@
rboolean classutil_class_is_superinterface_of(jvm_class_index clsidx1,
jvm_class_index clsidx2)
{
- ClassFile *pcfs1, *pcfs2, *pcfs3;
+ ARCH_FUNCTION_NAME(classutil_class_is_superinterface_of);
+
+ ClassFile *pcfs1, *pcfs2;
u2 ifidx;
/* Disallow comparison with null class */
@@ -350,10 +372,10 @@
return(rfalse);
}
- /* Comparison is true if both are the same class */
+ /* Comparison is false if both are the same class */
if (clsidx1 == clsidx2)
{
- return(rtrue);
+ return(rfalse);
}
/*
@@ -372,74 +394,60 @@
/* If no interfaces, then this loop is skipped */
for (ifidx = 0; ifidx < pcfs2->interfaces_count; ifidx++)
{
+ /* Since 'clsidx1' is valid, this really means 'find_by' */
jvm_class_index clsidxINTFC =
- class_load_from_cp_entry_utf(pcfs2->constant_pool[ifidx],
- rfalse,
- (jint *) rnull);
-
- /* Check if this class index matches requested interface */
- if (clsidx1 == clsidxINTFC)
- {
- return(rtrue);
- }
-
- pcfs3 = CLASS_OBJECT_LINKAGE(clsidxINTFC)->pcfs;
-
- /*
- * If found top of hierarchy, namely java.lang.Object class
- * or highest-level interface, then search cannot succeed.
- */
- if (jvm_constant_pool_index_null == pcfs3->super_class)
- {
- break;
- }
-
- /* Look at superclass of this one */
- clsidxINTFC =
class_load_from_cp_entry_utf(
- pcfs3->constant_pool[pcfs3->super_class],
- rfalse,
- (jint *) rnull);
+ pcfs2->constant_pool[pcfs2->interfaces[ifidx]],
+ rfalse,
+ (jint *) rnull);
/*
- * Check if super-hierarchy matches.
+ * Check if this class index matches requested interface
+ * or if super-hierarchy matches.
*
- * WARNING: RECURSIVE CALL!!! Will go as deep as hierarchy.
*/
- if (rtrue == classutil_class_is_superinterface_of(clsidx1,
- clsidxINTFC))
+ /* Check if this class index matches requested interface */
+ if ((clsidx1 == clsidxINTFC) ||
+ (rtrue == classutil_class_is_a(clsidxINTFC, clsidx1)))
{
return(rtrue);
}
}
- /* Superclass of @c @b clsidx2 not found to be @c @b clsidx1 */
+ /* @c @b clsidx1 not found to be superinterface of @c @b clsidx2 */
return(rfalse);
} /* END of classutil_class_is_superinterface_of() */
/*!
- * @brief Check if class @b clsidx1 is accessible to class @b clsidx2 .
+ * @brief Check if class/interface @b clsidx1 is in the same
+ * runtime package as class/interface @b clsidx2 .
*
- * For an @link #rtrue rtrue@endlink comparison, the class @c @b clsidx1
- * must either be public or must be in the same runtime package
- * as @c @b clsidx2, as defined in the JVM spec section 5.4.4.
+ * This function implements the package visibility logic
+ * defined in the JVM spec section 5.4.4 .
*
*
- * @returns @link #rtrue rtrue@endlink if @c @b clsidx1 is either
- * @link #ACC_PUBLIC ACC_PUBLIC@endlink or must be
- * in the same runtime package as @c @b cldidx2 or is
- * actually the same class index as @c @b clsidx2 .
+ * @returns @link #rtrue rtrue@endlink if @c @b clsidx1 is in the
+ * same runtime package as @c @b clsidx2 , otherwise
+ * @link #rfalse rfalse@endlink.
*
*/
-rboolean classutil_class_is_accessible_to(jvm_class_index clsidx1,
- jvm_class_index clsidx2)
+
+rboolean classutil_class_same_package_as(jvm_class_index clsidx1,
+ jvm_class_index clsidx2)
{
- ClassFile *pcfs1 = CLASS_OBJECT_LINKAGE(clsidx1)->pcfs;
+ ARCH_FUNCTION_NAME(classutil_same_package_as);
- /* Class is accessible if it is public or the same class */
- if ((clsidx1 == clsidx2) || (ACC_PUBLIC & pcfs1->access_flags))
+ /* Disallow navigation of null classes */
+ if ((jvm_class_index_null == clsidx1) ||
+ (jvm_class_index_null == clsidx1))
+ {
+ return(rfalse);
+ }
+
+ /* Class is visible if it is in the same class */
+ if (clsidx1 == clsidx2)
{
return(rtrue);
}
@@ -450,6 +458,9 @@
* in other functions in this source file?
*/
+ ClassFile *pcfs1 = CLASS_OBJECT_LINKAGE(clsidx1)->pcfs;
+ ClassFile *pcfs2 = CLASS_OBJECT_LINKAGE(clsidx2)->pcfs;
+
/*
* Class is accessible if it is in the same runtime package.
* This may be discovered by comparing the first part of the
@@ -459,8 +470,6 @@
CONSTANT_Utf8_info *putfname1 = PTR_CP1_CLASS_NAME(pcfs1,
pcfs1->this_class);
- ClassFile *pcfs2 = CLASS_OBJECT_LINKAGE(clsidx2)->pcfs;
-
CONSTANT_Utf8_info *putfname2 = PTR_CP1_CLASS_NAME(pcfs2,
pcfs2->this_class);
@@ -501,8 +510,8 @@
if (((rnull == pnameonly1) && (rnull != pnameonly2)) ||
((rnull != pnameonly1) && (rnull == pnameonly2)))
{
- HEAP_FREE_DATA(prcharname1);
- HEAP_FREE_DATA(prcharname2);
+ HEAP_FREE_DATA(prcharname1); /* Ignores NULL pointers */
+ HEAP_FREE_DATA(prcharname2); /* Ignores NULL pointers */
return(rfalse);
}
@@ -521,6 +530,58 @@
HEAP_FREE_DATA(prcharname2);
return(rc);
+} /* END of classutil_class_same_package_as() */
+
+
+/*!
+ * @brief Check if class/interface @b clsidx1 is accessible
+ * to class/interface @b clsidx2 .
+ *
+ * This function implements the class accessibility logic
+ * defined in the JVM spec section 5.4.4 .
+ *
+ * For an @link #rtrue rtrue@endlink comparison, the class @c @b clsidx1
+ * must either be:
+ *
+ * <ul>
+ * <li>
+ * <b>(1)</b> a @c @b public class, that is,
+ * @link #ACC_PUBLIC ACC_PUBLIC@endlink, or...
+ * </li>
+ * <li>
+ * <b>(2)</b> in the same runtime package as @c @b clsidx2 .
+ * </li>
+ * </ul>
+ *
+ *
+ * @returns @link #rtrue rtrue@endlink if any of the above conditions
+ * are true, otherwise @link #rfalse rfalse@endlink.
+ *
+ */
+
+rboolean classutil_class_is_accessible_to(jvm_class_index clsidx1,
+ jvm_class_index clsidx2)
+{
+ ARCH_FUNCTION_NAME(classutil_class_is_accessible_to);
+
+ /* Disallow navigation of null classes */
+ if ((jvm_class_index_null == clsidx1) ||
+ (jvm_class_index_null == clsidx2))
+ {
+ return(rfalse);
+ }
+
+ ClassFile *pcfs1 = CLASS_OBJECT_LINKAGE(clsidx1)->pcfs;
+
+ /* Class is accessible if it is public or the same class */
+ if ((clsidx1 == clsidx2) || (ACC_PUBLIC & pcfs1->access_flags))
+ {
+ return(rtrue);
+ }
+
+ /* Check if they are in the same package and report result */
+ return(classutil_class_same_package_as(clsidx1, clsidx2));
+
} /* END of classutil_class_is_accessible_to() */
@@ -544,9 +605,11 @@
* design can properly implement the 'clone' method.
*
*/
-rboolean
- classutil_interface_implemented_by_arrays(jvm_class_index clsidx1)
+rboolean classutil_interface_implemented_by_arrays(
+ jvm_class_index clsidx1)
{
+ ARCH_FUNCTION_NAME(classutil_interface_implemented_by_arrays);
+
/* Disallow evaluation of null class */
if (jvm_class_index_null == clsidx1)
{
@@ -571,6 +634,841 @@
return(rfalse);
} /* END of classutil_interface_implemented_by_arrays() */
+
+/*@} */ /* End of grouped definitions */
+
+
+/*!
+ * @name Check if field/method reference @c @b fldref1 / @c @b mthref1
+ * is accessible to class @b clsidx2 .
+ *
+ * These functions implement the field and method accessibility logic
+ * defined in the JVM spec section 5.4.4 .
+ *
+ * For an @link #rtrue rtrue@endlink comparison,
+ * @c @b fldref1 / @c @b mthref1 must be one of:
+ *
+ * <ul>
+ * <li>
+ * <b>(1)</b> a @c @b public field/method, that is,
+ * @link #ACC_PUBLIC ACC_PUBLIC@endlink, or...
+ * </li>
+ * <li>
+ * <b>(2)</b> a @c @b protected field/method, that is,
+ * @link #ACC_PROTECTED ACC_PROTECTED@endlink, whose class
+ * is either @c @b clsidx2 itself or a
+ * superclass of @c @b clsidx2 , or...
+ * </li>
+ * <li>
+ * <b>(3)</b> a @c @b protected field/method, that is,
+ * @link #ACC_PROTECTED ACC_PROTECTED@endlink, whose class
+ * is in the same runtime package as @c @b clsidx2 .
+ * </li>
+ * <li>
+ * <b>(4)</b> a package private field/method (neither @c @b public
+ * nor @c @b protected nor @c @b private ) whose class
+ * is in the same runtime package as @c @b clsidx2 .
+ * </li>
+ * <li>
+ * <b>(5)</b> a @c @b private field/method, that is,
+ * @link #ACC_PRIVATE ACC_PRIVATE@endlink,
+ * in class @c @b clsidx2 .
+ * </li>
+ * </ul>
+ *
+ * @warning This final condition is @e not testable in this function
+ * since @c @b clsidx1 cannot access @c @b private members
+ * of @c @b clsidx2 . This condition will always return
+ * @link #rfalse rfalse@endlink.
+ *
+ * @param fldref1 Field reference to a class containing a field
+ * to be examined.
+ *
+ * @param mthref1 Method reference to a class containing a method
+ * to be examined.
+ *
+ * @param clsidx1 Class table index of class containing @c @b fldref1
+ * or @c @b mthref1 .
+ *
+ * @param access_flags1 Access flags for member @c @b fldref1 or
+ * @c @b mthref1 .
+ *
+ * @param clsidx2 Class table index of class to compare @c @b fldref1
+ * or @c @b mthref1 against.
+ *
+ *
+ * @returns @link #rtrue rtrue@endlink if any of the above conditions
+ * are true, otherwise @link #rfalse rfalse@endlink.
+ *
+ */
+
+/*@{ */ /* Begin grouped definitions */
+
+/*!
+ * @brief Common code for checking if field or method is accessible
+ * to a certain class.
+ *
+ *
+ */
+static rboolean classutil_member_is_accessible_to(
+ jvm_class_index clsidx1,
+ jvm_access_flags access_flags1,
+ jvm_class_index clsidx2)
+{
+ ARCH_FUNCTION_NAME(classutil_member_is_accessible_to);
+
+ /* Disallow navigation of null classes */
+ if ((jvm_class_index_null == clsidx1) ||
+ (jvm_class_index_null == clsidx2))
+ {
+ return(rfalse);
+ }
+
+ /*
+ * Field/Method is accessible if it is the same class
+ * (Not explicitly stated in requirement, but
+ * implied throughout by its structure.)
+ */
+ if (clsidx1 == clsidx2)
+ {
+ return(rtrue);
+ }
+
+ /* Field/Method is accessible if it is public */
+ if (ACC_PUBLIC & access_flags1)
+ {
+ return(rtrue);
+ }
+
+ /*
+ * Field/Method is accessible if it is protected and its class
+ * is either clsidx2 itself or a superclass of clsidx2
+ * (that is, clsidx2 is the same as or a subclass of
+ * the class of fldref1) or it is in the same runtime
+ * package as clsidx2 .
+ */
+ if (ACC_PROTECTED & access_flags1)
+ {
+ if (rtrue == classutil_class_is_a(clsidx2, clsidx1))
+ {
+ return(rtrue);
+ }
+
+ if (rtrue == classutil_class_same_package_as(clsidx1, clsidx2))
+ {
+ return(rtrue);
+ }
+ }
+
+ /*
+ * Field/Method is accessible if it is package private (neither
+ * public nor protected nor private) and it is in the same runtime
+ * package as clsidx2 .
+ */
+ if (!((ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE) & access_flags1))
+ {
+ if (rtrue == classutil_class_same_package_as(clsidx1, clsidx2))
+ {
+ return(rtrue);
+ }
+ }
+
+ /*
+ * Field/Method is accessible if it is private and its class
+ * is clsidx2 . THIS MUST BE FALSE PER FUNCTION PROTOTYPE
+ * BECAUSE 'clsidx1' CANNOT ACCESS ANYTHING 'private' IN 'clsidx2'
+ */
+ return(rfalse);
+
+} /* END of classutil_member_is_accessible_to() */
+
+
+/*!
+ * @brief Check if field @b fldref1 is accessible to class @b clsidx2 .
+ *
+ */
+rboolean classutil_field_is_accessible_to(
+ CONSTANT_Fieldref_info *fldref1,
+ jvm_class_index clsidx2)
+{
+ ARCH_FUNCTION_NAME(classutil_field_is_accessible_to);
+
+ /* Retrieve access_flags for this field */
+ jvm_class_index clsidx1 = fldref1->LOCAL_Fieldref_binding.clsidxJVM;
+
+ /*
+ * @todo HARMONY-6-jvm-classutil.c-4 Does there need to be a
+ * possible linkage_resolve_class() here? Could
+ * @c @b clsidx1 possibly be
+ * @link #jvm_class_index_null jvm_class_index_null@endlink
+ * here?
+ */
+ ClassFile *pcfs = CLASS_OBJECT_LINKAGE(clsidx1)->pcfs;
+
+ jvm_field_lookup_index
+ fluidx1 = fldref1->LOCAL_Fieldref_binding.fluidxJVM;
+
+ rboolean oiflag1 = fldref1->LOCAL_Fieldref_binding.oiflagJVM;
+
+ field_info *pfld = pcfs
+ ->fields
+ [(rtrue == oiflag1)
+ ? CLASS(clsidx1)
+ .object_instance_field_lookup
+ [fluidx1]
+
+ : CLASS(clsidx1)
+ .class_static_field_lookup
+ [fluidx1]
+ ];
+
+ jvm_access_flags
+ access_flags1 = pfld->access_flags;
+
+ /* Process common portion */
+ return(classutil_member_is_accessible_to(clsidx1,
+ access_flags1,
+ clsidx2));
+
+} /* END of classutil_field_is_accessible_to() */
+
+
+/*!
+ * @brief Check if method @b mthref1 is accessible to class @b clsidx2 .
+ *
+ */
+rboolean classutil_method_is_accessible_to(
+ CONSTANT_Methodref_info *mthref1,
+ jvm_class_index clsidx2)
+{
+ ARCH_FUNCTION_NAME(classutil_method_is_accessible_to);
+
+ /* Retrieve access_flags for this method */
+ jvm_class_index clsidx1 = mthref1
+ ->LOCAL_Methodref_binding
+ .clsidxJVM;
+
+ /*
+ * @todo HARMONY-6-jvm-classutil.c-5 Does there need to be a
+ * possible linkage_resolve_class() here? Could
+ * @c @b clsidx1 possibly be
+ * @link #jvm_class_index_null jvm_class_index_null@endlink
+ * here?
+ */
+ ClassFile *pcfs = CLASS_OBJECT_LINKAGE(clsidx1)->pcfs;
+
+ jvm_method_index
+ mthidx1 = mthref1
+ ->LOCAL_Methodref_binding
+ .mthidxJVM;
+
+ method_info *pmth = pcfs->methods[mthidx1];
+
+ jvm_access_flags
+ access_flags1 = pmth->access_flags;
+
+ /* Process common portion */
+ return(classutil_member_is_accessible_to(clsidx1,
+ access_flags1,
+ clsidx2));
+
+} /* END of classutil_method_is_accessible_to() */
+
+
+/*!
+ * @brief Check if interface method @b mthref1 is accessible
+ * to class @b clsidx2 .
+ *
+ * @bug HARMONY-6-classutil.c-1001 Probably need to adjust
+ * classutil_member_is_accessible_to() to traverse interfaces
+ * to check accessibility of interface methods. Could it be
+ * that this function() should re-implement that one, but check
+ * both class interitance and interface inheritance? Should
+ * that one consider both sometimes or always? Perhaps with
+ * an input parameter flag (suggest CONSTANT_xxx tag)?
+ */
+rboolean classutil_interface_method_is_accessible_to(
+ CONSTANT_InterfaceMethodref_info *mthref1,
+ jvm_class_index clsidx2)
+{
+ ARCH_FUNCTION_NAME(classutil_interface_method_is_accessible_to);
+
+ /* Retrieve access_flags for this interface method */
+
+ jvm_class_index clsidx1 = mthref1
+ ->LOCAL_InterfaceMethodref_binding
+ .clsidxJVM;
+
+ /*
+ * @todo HARMONY-6-jvm-classutil.c-6 Does there need to be a
+ * possible linkage_resolve_class() here? Could
+ * @c @b clsidx1 possibly be
+ * @link #jvm_class_index_null jvm_class_index_null@endlink
+ * here?
+ */
+ ClassFile *pcfs = CLASS_OBJECT_LINKAGE(clsidx1)->pcfs;
+
+ jvm_method_index
+ mthidx1 = mthref1
+ ->LOCAL_InterfaceMethodref_binding
+ .mthidxJVM;
+
+ method_info *pmth = pcfs->methods[mthidx1];
+
+ jvm_access_flags
+ access_flags1 = pmth->access_flags;
+
+ /* Process common portion */
+ return(classutil_member_is_accessible_to(clsidx1,
+ access_flags1,
+ clsidx2));
+
+} /* END of classutil_interface_method_is_accessible_to() */
+
+
+/*@} */ /* End of grouped definitions */
+
+
+/*!
+ * @brief Locate an object of class @b clsidx1 that is a direct
+ * superclass parent object (any ancestor) of object @b objhash2 .
+ *
+ * For choosing @e any superclass object, this effectively performs
+ * the OO hierarchy operation, "Find the parent object of @c @b objhash2
+ * that is either a @c @b clsidx1 or one of its superclasses."
+ *
+ * Another way to put this OO hierarchy operation is, "Find the
+ * parent object of @c @b objhash2 whose class is @e exactly
+ * a @c @b clsidx1 , thus is @e neither a subclass @e nor a superclass
+ * of @c @b clsidx1 ."
+ *
+ * The superclass of all array types @e must be java.lang.Object
+ * per JVM spec section 2.15. (They "may" be assigned this type, if
+ * any at all, but in this implementation, they @e always are so that
+ * they have a definite objct type.)
+ *
+ *
+ * @param clsidx1 Class table index of the class of an object that is
+ * a parent of @c @b objhash2 .
+ *
+ * @param objhash2 Object for which to search for a parent of class
+ * @c @b clsidx1 .
+ *
+ *
+ * @returns matching parent object hash of @c @b objhash2 that is a
+ * class @c @b clsidx1 , but is @e not either a subclass
+ * of @c @b clsidx1 @e nor a superclass of @c @b clsidx1 .
+ * If input parameter @c @b clsidx1 is
+ * @link #jvm_class_index_null jvm_class_index_null@endlink or
+ * if input parameter @c @b objhash2 is
+ * @link #jvm_object_hash_null jvm_object_hash_null@endlink,
+ * then the result is
+ * @link #jvm_object_hash_null jvm_object_hash_null@endlink.
+ * If @c @b objhash2 is exactly of class @c @b clsidx1, then
+ * result is @c @b objhash2 itself.
+ *
+ *
+ * @see classutil_class_is_a()
+ * @see classutil_class_has_a_field()
+ * @see classutil_class_has_a_method()
+ * @see classutil_class_has_an_interface_method()
+ *
+ */
+jvm_object_hash classutil_direct_superclass_parent_object_of(
+ jvm_class_index clsidx1,
+ jvm_object_hash objhash2)
+{
+ ARCH_FUNCTION_NAME(classutil_direct_superclass_parent_object_of);
+
+ /* Disallow trivial class and trivial object cases */
+ if ((jvm_class_index_null == clsidx1) ||
+ (jvm_object_hash_null == objhash2))
+ {
+ return(jvm_object_hash_null);
+ }
+
+ /* Extract class of requested object */
+ jvm_class_index clsidx2 = OBJECT_CLASS_LINKAGE(objhash2)->clsidx;
+
+ /* Disallow comparison with null class (should never happen) */
+ if (jvm_class_index_null == clsidx2)
+ {
+/*NOTREACHED*/
+ return(jvm_object_hash_null);
+ }
+
+ /*
+ * Check arrays for a superclass of _only_ java.lang.Object
+ */
+ if (CLASS(clsidx2).status & CLASS_STATUS_ARRAY)
+ {
+ return((clsidx1 == pjvm->class_java_lang_Object)
+
+ /* Namely, java.lang.Object */
+ ? OBJECT(objhash2).objhash_super_class
+
+ /* Namely, "you can't do this" */
+ : jvm_object_hash_null);
+ }
+
+ /* Comparison is true if object class is same as requested class */
+ if (clsidx1 == clsidx2)
+ {
+ return(objhash2);
+ }
+
+ /*
+ * If any object of class clsidx1 is not accessible
+ * to object objhash2, then the inquiry fails.
+ */
+ if (rfalse == classutil_class_is_accessible_to(clsidx1, clsidx2))
+ {
+ return(jvm_object_hash_null);
+ }
+
+ /*
+ * Scan for superclasses of @c @b objhash2
+ */
+ jvm_object_hash objhashSUPER = objhash2;
+
+ /*
+ * Will never fail while() condition on first iteration unless
+ * searching for superclass of java.lang.Object.
+ *
+ * If found top of hierarchy during search, namely java.lang.Object,
+ * then search fails on second and further iterations.
+ */
+ while (jvm_object_hash_null !=
+ (objhashSUPER = OBJECT(objhashSUPER).objhash_super_class))
+ {
+
+ jvm_class_index clsidxCLS =
+ OBJECT_CLASS_LINKAGE(objhashSUPER)->clsidx;
+
+ ClassFile *pcfs = CLASS_OBJECT_LINKAGE(clsidxCLS)->pcfs;
+
+ /*
+ * @internal Could use class_load_from_cp_entry() instead of
+ * using class_find_by_cp_entry(). If this were done,
+ * then notice that if this request loaded a class, it
+ * would also load @e all of its superclasses.
+ * Therefore, if it is a superclass that matched,
+ * no loading would occur later, but that previously
+ * loaded superclass would be found and returned
+ * immediately.
+ *
+ */
+ clsidxCLS =
+ class_find_by_cp_entry(
+ PTR_CP1_CLASS_NAME_MEMALIGN(pcfs, pcfs->this_class));
+
+ if (clsidx1 == clsidxCLS)
+ {
+ return(objhashSUPER);
+ }
+ }
+
+ /*
+ * Superclass of @c @b objhash2 was
+ * not found to be a @c @b clsidx1
+ */
+ return(jvm_object_hash_null);
+
+} /* END of classutil_direct_superclass_parent_object_of() */
+
+
+/*!
+ * @name Locate in an object or one of its parent objects the class
+ * that <em>has a</em> member field, method, or interface method.
+ *
+ * For object @b objhash1 or and of its parents, this effectively
+ * performs the OO hierarchy operation, "Find the object, either
+ * @c @b objhash1 or one of its parent objects, that <em>has a</em>
+ * field/method/interface method @c @b fldref2 / @c @b mthref2 as
+ * set forth by @c @b pcfs2 that is (optionally) accessible to
+ * @c @b objhash1 ."
+ *
+ * The superclass of all array types @e must be java.lang.Object
+ * per JVM spec section 2.15. (They "may" be assigned this type, if
+ * any at all, but in this implementation, they @e always are so that
+ * they have a definite objct type.)
+ *
+ *
+ * @param rc[out] Result of search. Passed out through this
+ * structure pointer so both the class index and
+ * the field or method index may be easily passed
+ * out. Normally return the matching parent class of
+ * @c @b objhash1 that has a field/method/interface
+ * method @c @b fldref2 / @c @b mthref2 as defined
+ * in @c @b pcfs2 . If input parameter
+ * @c @b objhash1 is @link #jvm_object_hash_null
+ jvm_object_hash_null@endlink or if input
+ * parameter @c @b fldref2 / @c @b mthref2 is a
+ * null pointer, or similarly if input parameter
+ * @c @b pcfs2 is a null pointer, then the result
+ * is @link #jvm_class_index_null
+ jvm_class_index_null@endlink and
+ * @link #jvm_field_index_bad
+ jvm_field_index_bad@endlink /
+ * @link #jvm_method_index_bad
+ jvm_method_index_bad@endlink. If @c @b objhash1
+ * contains @c @b fldref2 / @c @b mthref2 itself,
+ * then result is @c @b objhash1 directly.
+ *
+ * @param objhash1[in] Object for which to search that contains field
+ * / method @c @b fldref2 / @c @b mthref2 .
+ *
+ * @param clsidx1[in] Class index of @c @b objhash1 for which to
+ * search that contains field / method
+ * @c @b fldref2 / @c @b mthref2 .
+ *
+ * @param pcfs2[in] ClassFile structure containing field or method
+ * or interface method reference.
+ *
+ * @param fldref2[in] Field reference from @c @b pcfs2 to locate in
+ * @c @b objhash1 or one of its parent objects.
+ *
+ * @param mthref2[in] Method / interface method reference from
+ * @c @b pcfs2 to locate in @c @b objhash1 or
+ * one of its parent objects.
+ *
+ * @param name_and_type_index2[in]
+ Name and type index from either
+ * method reference or interface method reference,
+ * whichever is available to calling function.
+ *
+ * @param isaccessible[in]
+ When @link #rtrue rtrue@endlink, check that
+ * @c @b fldref2 / @c @b mthref2 is accessible to
+ * @c @b objhash1 . For example, @b INVOKEVIRTUAL
+ * uses this accessibility test where
+ * @b INVOKESPECIAL does not.
+ *
+ * @param member_type One of @link #MEMBER_TYPE_FIELD
+ * MEMBER_TYPE_xxx@endlink to inform common function
+ * which type of class member is being processed,
+ * a @link #MEMBER_TYPE_FIELD field@endlink, a
+ * @link #MEMBER_TYPE_METHOD method@endlink, or an
+ * @link #MEMBER_TYPE_INTERFACE_METHOD
+ interface method@endlink.
+ *
+ *
+ * @see classutil_class_is_a()
+ * @see classutil_direct_superclass_parent_object_of()
+ *
+ */
+
+/*@{ */ /* Begin grouped definitions */
+
+/*!
+ * @brief Set class member resolution status to "not found"
+ *
+ * This is used both in classutil_class_has_a_common_member()
+ * and in its callers when performing their unique tests after a
+ * positive result there.
+ *
+ */
+#define INITIALIZE_CLASS_RESOLVE_MEMBER(rc) \
+ rc->clsidx = jvm_class_index_null; \
+ rc->mthidx = jvm_method_index_bad; \
+ rc->fldidx = jvm_field_index_bad; /* Extra ; */
+
+#define MEMBER_TYPE_FIELD 1 /**< Common member is a field */
+#define MEMBER_TYPE_METHOD 2 /**< Common member is a method */
+#define MEMBER_TYPE_INTERFACE_METHOD 3 /**< Common member is an
+ interface method */
+/*!
+ * @brief Code common to classutil_class_has_a_method() and
+ * classutil_class_has_an_interface_method() and
+ * classutil_class_has_an_field() .
+ *
+ *
+ * @returns @link #rtrue rtrue@endlink if a valid common member was
+ * found, otherwise @link #rfalse rfalse@endlink.
+ *
+ */
+static rboolean classutil_class_has_a_common_member(
+ class_resolve_member *rc,
+ jvm_class_index clsidx1,
+ ClassFile *pcfs2,
+ u2 name_and_type_index2,
+ rboolean isaccessible,
+ rint member_type)
+{
+ ARCH_FUNCTION_NAME(classutil_class_has_a_common_method);
+
+ /* Disallow null result pointer (should never happen) */
+ if (rnull == rc)
+ {
+/*NOTREACHED*/
+ sysErrMsg(arch_function_name, "bad result pointer");
+ return(rfalse);
+ }
+
+ /* Initialize result to "class not found with matching member" */
+ INITIALIZE_CLASS_RESOLVE_MEMBER(rc);
+
+ /* Disallow trivial class parameter case */
+ if (rnull == pcfs2)
+ {
+ sysErrMsg(arch_function_name, "bad class file struct pointer");
+ return(rfalse);
+ }
+
+ /* Point to constant_pool method name and type descriptor */
+ CONSTANT_NameAndType_info *pcpma_NameAndType =
+ PTR_THIS_CP_NameAndType(
+ pcfs2->constant_pool[name_and_type_index2]);
+
+ /*
+ * Comparison is true if class is same as resolved member
+ * (on first time through) or of a superclass of @c @b clsidx1
+ * (on second through final time)
+ */
+ jvm_class_index clsidxCLS = clsidx1;
+
+ while (jvm_class_index_null != clsidxCLS)
+ {
+ jvm_field_index fldidxCLS;
+ jvm_method_index mthidxCLS;
+
+ /* Process for the varils member types */
+ switch (member_type)
+ {
+ case MEMBER_TYPE_FIELD:
+ fldidxCLS =
+ field_find_by_cp_entry(
+ clsidxCLS,
+
+ pcfs2->constant_pool
+ [pcpma_NameAndType->name_index],
+
+ pcfs2->constant_pool
+ [pcpma_NameAndType->descriptor_index]);
+
+ /*
+ * Match found if field has same name and type
+ * as name_and_type_index2
+ */
+ if (jvm_field_index_bad != fldidxCLS)
+ {
+ if ((rfalse == isaccessible) ||
+ /*
+ * Call classutil_field_is_accessible_to()
+ * from invoking function for simplicity.
+ */
+ (rtrue == classutil_class_is_accessible_to(
+ rc->clsidx,
+ clsidx1)))
+ {
+ /* Report matching class index and field index*/
+ rc->clsidx = clsidxCLS;
+ rc->fldidx = fldidxCLS;
+ return(rtrue);
+ }
+ }
+ break;
+
+ case MEMBER_TYPE_METHOD:
+ case MEMBER_TYPE_INTERFACE_METHOD:
+ mthidxCLS =
+ method_find_by_cp_entry(
+ clsidxCLS,
+
+ pcfs2->constant_pool
+ [pcpma_NameAndType->name_index],
+
+ pcfs2->constant_pool
+ [pcpma_NameAndType->descriptor_index]);
+
+ /*
+ * Match found if method has same name and type
+ * as name_and_type_index2
+ */
+ if (jvm_method_index_bad != mthidxCLS)
+ {
+ if ((rfalse == isaccessible) ||
+ (rtrue ==
+ /*
+ * Call classutil_method_is_accessible_to()
+ * from invoking function for simplicity.
+ */
+ classutil_class_is_accessible_to(rc->clsidx,
+ clsidx1)))
+ {
+ /*Report matching class index and method index*/
+ rc->clsidx = clsidxCLS;
+ rc->mthidx = mthidxCLS;
+ return(rtrue);
+ }
+ }
+ break;
+
+ } /* switch (member_type) */
+
+ /* Retrieve next superclass, but java.lang.Object for arrays */
+ clsidxCLS =
+ (CLASS(clsidx1).status & CLASS_STATUS_ARRAY)
+ ? pjvm->class_java_lang_Object
+ : OBJECT_CLASS_LINKAGE(OBJECT(CLASS(clsidxCLS)
+ .class_objhash)
+ .objhash_super_class)
+ ->clsidx;
+ }
+
+ /* Valid member not found */
+ return(rfalse);
+
+} /* END of classutil_class_object_has_a_common_member() */
+
+
+/*!
+ * @brief Locate class index of class of @c @b objhash1 or one of its
+ * parent objects that <em>has a</em> member method @c @b mthref2 .
+ *
+ *
+ * @returns @link #rvoid rvoid@endlink
+ *
+ */
+rvoid classutil_class_has_a_method(
+ class_resolve_member *rc,
+ jvm_object_hash objhash1,
+ ClassFile *pcfs2,
+ CONSTANT_Methodref_info *mthref2,
+ rboolean isaccessible)
+{
+ ARCH_FUNCTION_NAME(classutil_class_has_a_method);
+
+ jvm_class_index clsidx1 = OBJECT_CLASS_LINKAGE(objhash1)->clsidx;
+
+ /* Disallow trivial null method reference cases */
+ if (rnull == mthref2)
+ {
+ sysErrMsg(arch_function_name, "bad method reference pointer");
+ return;
+ }
+
+ u2 name_and_type_index2 = mthref2->name_and_type_index;
+
+ if (rfalse == classutil_class_has_a_common_member(
+ rc,
+ clsidx1,
+ pcfs2,
+ name_and_type_index2,
+ isaccessible,
+ MEMBER_TYPE_METHOD))
+ {
+ return;
+ }
+
+ if (rfalse == classutil_method_is_accessible_to(mthref2,clsidx1))
+ {
+ /* Clear result to "class not found with matching member" */
+ INITIALIZE_CLASS_RESOLVE_MEMBER(rc);
+ }
+
+ return;
+
+} /* END of classutil_class_has_a_method() */
+
+
+/*!
+ * @brief Locate class index of class of @c @b objhash1 or one of its
+ * parent objects that <em>has a</em> member method @c @b mthref2 .
+ *
+ *
+ * @returns @link #rvoid rvoid@endlink
+ *
+ */
+rvoid classutil_class_has_an_interface_method(
+ class_resolve_member *rc,
+ jvm_object_hash objhash1,
+ ClassFile *pcfs2,
+ CONSTANT_InterfaceMethodref_info *mthref2)
+{
+ ARCH_FUNCTION_NAME(classutil_class_has_an_interface_method);
+
+ jvm_class_index clsidx1 = OBJECT_CLASS_LINKAGE(objhash1)->clsidx;
+
+ /* Disallow trivial null method reference cases */
+ if (rnull == mthref2)
+ {
+ sysErrMsg(arch_function_name, "bad method reference pointer");
+ return;
+ }
+
+ u2 name_and_type_index2 = mthref2->name_and_type_index;
+
+ if (rfalse == classutil_class_has_a_common_member(
+ rc,
+ objhash1,
+ pcfs2,
+ name_and_type_index2,
+ rfalse,
+ MEMBER_TYPE_INTERFACE_METHOD))
+ {
+ return;
+ }
+
+ if (rfalse ==
+ classutil_interface_method_is_accessible_to(mthref2, clsidx1))
+ {
+ /* Clear result to "class not found with matching member" */
+ INITIALIZE_CLASS_RESOLVE_MEMBER(rc);
+ }
+
+ return;
+
+} /* END of classutil_class_has_an_interface_method() */
+
+
+/*!
+ * @brief Locate class index of class of @c @b objhash1 or one of its
+ * parent objects that <em>has a</em> member field @c @b fldref2 .
+ *
+ *
+ * @returns @link #rvoid rvoid@endlink
+ *
+ */
+rvoid classutil_class_has_a_field(class_resolve_member *rc,
+ jvm_object_hash objhash1,
+ ClassFile *pcfs2,
+ CONSTANT_Fieldref_info *fldref2)
+{
+ ARCH_FUNCTION_NAME(classutil_class_has_a_field);
+
+ jvm_class_index clsidx1 = OBJECT_CLASS_LINKAGE(objhash1)->clsidx;
+
+ /* Disallow trivial null method reference cases */
+ if (rnull == fldref2)
+ {
+ sysErrMsg(arch_function_name, "bad field reference pointer");
+ return;
+ }
+
+ u2 name_and_type_index2 = fldref2->name_and_type_index;
+
+ if (rfalse == classutil_class_has_a_common_member(
+ rc,
+ objhash1,
+ pcfs2,
+ name_and_type_index2,
+ rfalse,
+ MEMBER_TYPE_FIELD))
+ {
+ return;
+ }
+
+ if (rfalse == classutil_field_is_accessible_to(fldref2, clsidx1))
+ {
+ /* Clear result to "class not found with matching member" */
+ INITIALIZE_CLASS_RESOLVE_MEMBER(rc);
+ }
+
+ return;
+
+} /* END of classutil_class_has_a_field() */
+
/*@} */ /* End of grouped definitions */