Main Page | Namespace List | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

class.c

Go to the documentation of this file.
00001 /*!
00002  * @file class.c
00003  *
00004  * @brief Create and manage real machine Java class data structures.
00005  *
00006  *
00007  * @section Control
00008  *
00009  * \$URL: https://svn.apache.org/path/name/class.c $ \$Id: class.c 0 09/28/2005 dlydick $
00010  *
00011  * Copyright 2005 The Apache Software Foundation
00012  * or its licensors, as applicable.
00013  *
00014  * Licensed under the Apache License, Version 2.0 ("the License");
00015  * you may not use this file except in compliance with the License.
00016  * You may obtain a copy of the License at
00017  *
00018  *     http://www.apache.org/licenses/LICENSE-2.0
00019  *
00020  * Unless required by applicable law or agreed to in writing,
00021  * software distributed under the License is distributed on an
00022  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
00023  * either express or implied.
00024  *
00025  * See the License for the specific language governing permissions
00026  * and limitations under the License.
00027  *
00028  * @version \$LastChangedRevision: 0 $
00029  *
00030  * @date \$LastChangedDate: 09/28/2005 $
00031  *
00032  * @author \$LastChangedBy: dlydick $
00033  *         Original code contributed by Daniel Lydick on 09/28/2005.
00034  *
00035  * @section Reference
00036  *
00037  */
00038 
00039 #include "arch.h"
00040 ARCH_COPYRIGHT_APACHE(class, c, "$URL: https://svn.apache.org/path/name/class.c $ $Id: class.c 0 09/28/2005 dlydick $");
00041 
00042 
00043 #include <string.h>
00044 
00045 #include "jvmcfg.h"
00046 #include "cfmacros.h"
00047 #include "classfile.h"
00048 #include "classfile.h"
00049 #include "classpath.h"
00050 #include "exit.h"
00051 #include "field.h"
00052 #include "gc.h"
00053 #include "jvm.h"
00054 #include "jvmclass.h"
00055 #include "linkage.h"
00056 #include "method.h"
00057 #include "nts.h"
00058 #include "utf.h"
00059 #include "util.h"
00060 
00061 
00062 /*!
00063  * @brief Set up an empty class in a given class table slot.
00064  *
00065  * The @b clsidx of JVMCFG_NULL_CLASS has special
00066  * properties in that it can ALWAYS be allocated and
00067  * is NEVER garbage collected!  Part of the purpose
00068  * for this is the JVMCFG_NULL_CLASS is of value zero,
00069  * which is widely used throughout the code as a special
00070  * value.  This this slot is not available for @e anything
00071  * else.
00072  * 
00073  *
00074  * @param  clsidx   Class table index of slot to set up.
00075  *
00076  *
00077  * @returns @link #rvoid rvoid@endlink
00078  *
00079  */
00080 rvoid class_static_setup(jvm_class_index clsidx)
00081 {
00082     /*
00083      * Declare slot in use, but not initialized.
00084      * (Redundant for most situations where
00085      * class_allocate_slot() was called, but needed
00086      * for initializing classes like JVMCFG_NULL_CLASS
00087      * with an absolute slot number that was not
00088      * searched for by the allocator.)
00089      */
00090     CLASS(clsidx).status = CLASS_STATUS_INUSE | CLASS_STATUS_NULL;
00091 
00092     /*
00093      * Start out with no array allocation and no array dimensions
00094      */
00095     CLASS(clsidx).arraydims = LOCAL_CONSTANT_NO_ARRAY_DIMS;
00096     CLASS(clsidx).arraylength = (jint *) rnull;
00097     CLASS(clsidx).lower_dim_array = jvm_class_index_null;
00098 
00099     /* Start out with no object hash */
00100     CLASS(clsidx).class_objhash = jvm_object_hash_null;
00101 
00102     /* Start out with no class static field lookups */
00103     CLASS(clsidx).num_class_static_field_lookups = 0;
00104     CLASS(clsidx).class_static_field_lookup = (jvm_class_index *) rnull;
00105     CLASS(clsidx).class_static_field_data = (jvalue *) rnull;
00106 
00107     /* Start out with no object instance field lookups */
00108     CLASS(clsidx).num_object_instance_field_lookups = 0;
00109     CLASS(clsidx).object_instance_field_lookup =
00110                                               (jvm_field_index *) rnull;
00111 
00112     /*
00113      * Report which @c @b java.lang.ClassLoader initiated
00114      * and defined this class.  The bootstrap ClassLoader always
00115      * reports @link #jvm_class_index_null jvm_class_index_null@endlink
00116      * for both of these items.
00117      */
00118     CLASS(clsidx).initiating_ClassLoader = jvm_class_index_null;
00119     CLASS(clsidx).defining_ClassLoader   = jvm_class_index_null;
00120 
00121     /*
00122      * Garbage collection @e initialization is performed by
00123      * @link #GC_CLASS_NEW GC_CLASS_NEW()@endlink.
00124      *
00125      * Garbage collection @e finalization is performed by
00126      * @link #GC_CLASS_DELETE GC_CLASS_DELETE()@endlink.
00127      */
00128     CLASS(clsidx).pgarbage = (rvoid *) rnull;
00129 
00130     /*
00131      * Do not set up GC_CLASS_NEW() unless there is
00132      * a real class with the possibility of real fields.
00133      */
00134 
00135     return;
00136 
00137 } /* END of class_static_setup() */
00138 
00139 
00140 /*!
00141  * @brief Initialize the class area of the JVM model
00142  *
00143  *
00144  * @b Parameters: @link #rvoid rvoid@endlink
00145  *
00146  *
00147  *       @returns @link #rvoid rvoid@endlink
00148  *
00149  */
00150 rvoid class_init()
00151 {
00152     class_static_setup(jvm_class_index_null);
00153 
00154     pjvm->class_allocate_last = jvm_class_index_null;
00155 
00156     /* Declare this module initialized */
00157     jvm_class_initialized = rtrue;
00158 
00159     return;
00160 
00161 } /* END of class_init() */
00162 
00163 
00164 /*!
00165  * @brief Locate and reserve an unused class table slot for a new class.
00166  *
00167  *
00168  * @param  tryagain   If @link #rtrue rtrue@endlink, run garbage
00169  *                    collection @e once if no empty slots are
00170  *                    available so as to try and free up something.
00171  *                    Typically, invoke as
00172  *                    @link #rtrue rtrue@endlink, and
00173  *                    let recursion call it with
00174  *                    @link #rfalse rfalse@endlink.
00175  *
00176  *
00177  * @returns Class table index of an empty slot.  Throw error if no
00178  *          slots.
00179  *
00180  * @throws JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00181  *         @link #JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00182  *         if no slots are available.@endlink.
00183  *
00184  */
00185 static jvm_class_index class_allocate_slot(rboolean tryagain)
00186 {
00187     /* Search for a free class table slot */
00188     jvm_class_index clsidx =
00189         (JVMCFG_MAX_CLASSES == (1 + pjvm->class_allocate_last))
00190         ? JVMCFG_FIRST_CLASS
00191         : 1 + pjvm->class_allocate_last;
00192 
00193     /* Count allocated slots in all slots are full */
00194     jvm_class_index count = 0;
00195 
00196     while(rtrue)
00197     {
00198         if (CLASS(clsidx).status & CLASS_STATUS_INUSE)
00199         {
00200             /* Point to next slot, wrap around at end */
00201             clsidx++;
00202 
00203             if (clsidx == JVMCFG_MAX_CLASSES - 1)
00204             {
00205                 clsidx = JVMCFG_FIRST_CLASS;
00206             }
00207 
00208             /* Limit high value to end of table */
00209             if (pjvm->class_allocate_last == JVMCFG_MAX_CLASSES - 1)
00210             {
00211                 pjvm->class_allocate_last = JVMCFG_FIRST_CLASS - 1;
00212             }
00213 
00214             /* Count this attempt and keep looking */
00215             count++;
00216 
00217             if (count == (JVMCFG_MAX_CLASSES - JVMCFG_FIRST_CLASS))
00218             {
00219                 /* Try again (with rfalse) if requested */
00220                 if (rtrue == tryagain)
00221                 {
00222                     GC_RUN(rtrue);  /* Try to free up some space */
00223 
00224                     /* Now try to locate a free slot */
00225 
00226                     /* WARNING!!! Recursive call-- but only 1 deep */
00227                     return(class_allocate_slot(rfalse));
00228                 }
00229 
00230                 /* No more slots, cannot continue */
00231                 exit_throw_exception(EXIT_JVM_CLASS,
00232                                    JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR);
00233 /*NOTREACHED*/
00234             }
00235         }
00236 
00237         /* Declare slot in use, but not initialized */
00238         CLASS(clsidx).status = CLASS_STATUS_INUSE | CLASS_STATUS_NULL;
00239 
00240         /* Report where this allocation was performed */
00241         pjvm->class_allocate_last = clsidx;
00242 
00243         return(clsidx);
00244     }
00245 /*NOTREACHED*/
00246     return(jvm_class_index_null); /* Satisfy compiler */
00247 
00248 } /* END of class_allocate_slot() */
00249 
00250 
00251 /*!
00252  * @brief Load a class into ad class table slot and load up its
00253  * associated class definition object.
00254  *
00255  * Create a Java class itself (and NOT a @c @b new instance
00256  * of a class!).  The following three mutially exclusive variations
00257  * are available using the @b special_cls modifier:
00258  *
00259  * <ul>
00260  * <li>(1) @b CLASS_STATUS_EMPTY:     Normal class, no special
00261  *                                    treatment.
00262  * </li>
00263  *
00264  * <li>(2) @b CLASS_STATUS_ARRAY:     Treat class instance creation
00265  *                                    as a dimension of an array
00266  *                                    instead of as a normal class
00267  *                                    load.  The recursion will
00268  *                                    eventually load its base
00269  *                                    class and superclasses.
00270  *                                    When allocating an array
00271  *                                    class, DO NOT EVER INVOKE
00272  *                                    THIS FUNCTION FOR A PRIMATIVE
00273  *                                    ARRAY!
00274  * </li>
00275  *
00276  * <li>(3) @b CLASS_STATUS_PRIMATIVE: Treat class instance creation
00277  *                                    as loading a primative
00278  *                                    pseudo-class for use by
00279  *                                    @c @b java.lang.Class.
00280  *                                    A related Classfile structure
00281  *                                    will be generated for this
00282  *                                    pseudo-class.
00283  * </li></ul>
00284  *
00285  * No verification of @b special_cls is performed, only these values
00286  * are assumed.
00287  *
00288  * Use a simple circular slot allocation mechanism to report where
00289  * most recent class was allocated.  The search for the next slot
00290  * will begin from here and go all the way around the array to this
00291  * same slot.  If not successful, throw error, but do @e not return.
00292  *
00293  *
00294  * @param   special_cls Bit-mapped request for various special
00295  *                      considerations for class construction.  If not
00296  *                      needed, use @b CLASS_STATUS_EMPTY.  If used, the
00297  *                      values are:
00298  *
00299  * <ul><li>
00300  *                      @b CLASS_STATUS_ARRAY create new array class
00301  *                                            instead of class instance
00302  * </li>
00303  *
00304  * <li>
00305  *                      @b CLASS_STATUS_PRIMATIVE create special class
00306  *                                                instance of a Java
00307  *                                                primative for use by
00308  *                                                @c @b java.lang.Class
00309  * </li>
00310  * </ul>
00311  *
00312  * @param    pcfs       Pointer to ClassFile area which contains this
00313  *                      class, @link #rnull rnull@endlink for
00314  *                      @b CLASS_STATUS_PRIMATIVE requests.
00315  *
00316  * @param    arraydims  Number of array dimensions for this class,
00317  *                        or zero if not an array class.
00318  *
00319  * @param  arraylength  Array of length @b arraydims containing the
00320  *                        length of array in each of those dimensions.
00321  *                        E.g., @b arraydims is 4 for new X[7][3][9][2]
00322  *                        so this parameter will be a 4-element array
00323  *                        containing the numbers {7, 3, 9, 2}
00324  *
00325  * @param lower_dim_array Class index of this array class' next
00326  *                        lower dimension, e.g. if this is a 3-dim
00327  *                        array @c @b [[[L then need index
00328  *                        it as @c @b [[L .
00329  *
00330  *
00331  * @returns   Class index value of allocation.  Throw error if no slots.
00332  *
00333  *
00334  * @throws JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00335  *         @link #JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00336  *         if no slots are available.@endlink.
00337  *
00338  */
00339 
00340 jvm_class_index class_static_new(rushort          special_cls,
00341                                  ClassFile       *pcfs,
00342                                  jvm_array_dim    arraydims,
00343                                  jint            *arraylength,
00344                                  jvm_class_index  lower_dim_array)
00345 {
00346     jvm_class_index clsidx;
00347 
00348     /* Locate an empty slot */
00349     clsidx = class_allocate_slot(rtrue);
00350 
00351     /* Abort if no more class table slots */
00352     if(jvm_class_index_null == clsidx)
00353     {
00354         return(jvm_class_index_null);
00355     }
00356 
00357     /* Initialize class structures */
00358     class_static_setup(clsidx);
00359 
00360 
00361 
00362     /*
00363      * Set up empty class static field lookup table
00364      * and object instance lookup table now
00365      * instead of later so that GC_CLASS_NEW()
00366      * and GC_OBJECT_NEW() know how many fields
00367      * to anticipate for primative and array classes,
00368      * namely zero.
00369      */
00370     CLASS(clsidx).num_class_static_field_lookups = 0;
00371     CLASS(clsidx).num_object_instance_field_lookups = 0;
00372 
00373 
00374     /*
00375      * Start GC references on new and valid class.
00376      * Unlike for objects, this must be done @e immediately
00377      * so that object_instance_new() can add references to
00378      * it from @link table_linkage#clsidx table_linkage.clsidx@endlink
00379      * and write to an initialized structure.
00380      *
00381      *     GC_CLASS_NEW(clsidx);
00382      *
00383      * ... but not until after num_XXX_field_lookups() is known.
00384      *
00385      */
00386 
00387 
00388     /* Check for special class instances, then normal ones */
00389     jvm_object_hash objhash;
00390     if (CLASS_STATUS_PRIMATIVE & special_cls)
00391     {
00392         /* Start GC tracking for class */
00393         (rvoid) GC_CLASS_NEW(clsidx);
00394 
00395         /*
00396          * Allocate a primative class
00397          */
00398 
00399         objhash = object_instance_new(OBJECT_STATUS_EMPTY,
00400                                       pcfs,
00401                                       clsidx,
00402                                       arraydims,
00403                                       arraylength,
00404                                       rfalse,
00405                                       jvm_thread_index_null);
00406 
00407         /*
00408          * Mark as a primative class, @c @b <clinit> done
00409          * (not applicable)
00410          */
00411         CLASS(clsidx).status |= CLASS_STATUS_PRIMATIVE |
00412                                 CLASS_STATUS_CLINIT;
00413     }
00414     else
00415     if (special_cls & CLASS_STATUS_ARRAY)
00416     {
00417         /* Start GC tracking for class */
00418         (rvoid) GC_CLASS_NEW(clsidx);
00419 
00420         /*
00421          * Allocate an array class-- but treat object as a class object
00422          * lest it try to initialize the array dimensions, which is
00423          * @e only something that an array @e instance object can do.
00424          */
00425 
00426         objhash = object_instance_new(OBJECT_STATUS_CLASS,
00427                                       pcfs,
00428                                       clsidx,
00429                                       arraydims,
00430                                       arraylength,
00431                                       rfalse,
00432                                       jvm_thread_index_null);
00433 
00434         CLASS(clsidx).status |= CLASS_STATUS_ARRAY;
00435 
00436         CLASS(clsidx).arraydims         = arraydims;
00437         CLASS(clsidx).arraylength       = arraylength;
00438         CLASS(clsidx).lower_dim_array   = lower_dim_array;
00439 
00440         /*! @todo   Where is this mkref's GC_CLASS_RMREF() ??? */
00441         (rvoid) GC_CLASS_MKREF_FROM_CLASS(clsidx,
00442                                          CLASS(clsidx).lower_dim_array);
00443     }
00444     else
00445     {
00446         /*
00447          * Allocate a normal class
00448          */
00449         CLASS(clsidx).num_class_static_field_lookups =
00450             class_get_num_static_fields(pcfs);
00451         CLASS(clsidx).class_static_field_lookup =
00452             class_get_static_field_lookups(pcfs);
00453 
00454         CLASS(clsidx).num_object_instance_field_lookups =
00455             class_get_num_object_instance_fields(pcfs);
00456         CLASS(clsidx).object_instance_field_lookup =
00457             class_get_object_instance_field_lookups(pcfs);
00458 
00459         /*
00460          * Start GC tracking for class, now that actual
00461          * number and type of fields is known
00462          */
00463         (rvoid) GC_CLASS_NEW(clsidx);
00464 
00465 
00466         objhash = object_instance_new(OBJECT_STATUS_EMPTY,
00467                                       pcfs,
00468                                       clsidx,
00469                                       arraydims,
00470                                       arraylength,
00471                                       rfalse,
00472                                       jvm_thread_index_null);
00473 
00474         /* Delay loading field data until after @b objhash is known */
00475         CLASS(clsidx).class_static_field_data =
00476             class_get_static_field_data(clsidx, pcfs);
00477     }
00478 
00479     /*
00480      * Declare this class instance as being
00481      * referenced by a class object
00482      */
00483     CLASS(clsidx).class_objhash = objhash;
00484     (rvoid) GC_OBJECT_MKREF_FROM_CLASS(clsidx, objhash);
00485 
00486     /* normal class definition */
00487     CLASS(clsidx).status &= ~CLASS_STATUS_NULL;
00488 
00489     /*
00490      * Declare this class as being referenced, but not here.
00491      * The calling function must perform this task.
00492      */
00493     /* GC_CLASS_MKREF(clsidx); */
00494 
00495     return(clsidx);
00496 
00497 } /* END of class_static_new() */
00498 
00499 
00500 /*!
00501  * @brief Reload a class in the class table after
00502  * @c @b java.lang.String has become available.
00503  *
00504  * This process does @e not re-read the class file, only redoes
00505  * class initialization.  The @b class_objhash does not get deleted.
00506  *
00507  *
00508  * @param    clsidxOLD  Class table index of slot to tear down.
00509  *
00510  * @returns   New class index of rebuilt class slot.  Throw error if
00511  *             no slots.
00512  *
00513  * @throws JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00514  *         @link #JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00515  *         if no slots are available.@endlink.
00516  *
00517  *
00518  * @todo  This function needs more testing.  Also, is it @e really
00519  *        needed in the implementation?
00520  */
00521 
00522 jvm_class_index class_reload(jvm_class_index clsidxOLD)
00523 {
00524 
00525     if (CLASS(clsidxOLD).status & CLASS_STATUS_INUSE)
00526     {
00527         /* Locate an empty slot */
00528         jvm_class_index clsidxNEW = class_allocate_slot(rtrue);
00529 
00530         /*
00531          * Save image of class slot to be copied into new slot
00532          */
00533         rclass *dupslot = HEAP_GET_METHOD(sizeof(rclass), rfalse);
00534 
00535         memcpy(dupslot, &CLASS(clsidxOLD), sizeof(rclass));
00536 
00537 
00538         /* Mark old slot as partially initialized */
00539         CLASS(clsidxOLD).status |= CLASS_STATUS_NULL;
00540 
00541         /* Should @e always be true */
00542         if (jvm_object_hash_null != CLASS(clsidxOLD).class_objhash)
00543         {
00544             /* Replace old class slot ref with new class slot ref.  */
00545             OBJECT(dupslot->class_objhash).table_linkage.clsidx =
00546                                                               clsidxNEW;
00547 
00548             /* Make SURE there is at least 1 class object reference */
00549             (rvoid) GC_OBJECT_MKREF_FROM_CLASS(
00550                         clsidxOLD,
00551                         dupslot->class_objhash);
00552             (rvoid) GC_CLASS_MKREF_FROM_CLASS(
00553                         clsidxOLD,
00554                         dupslot->lower_dim_array);
00555             (rvoid) GC_CLASS_MKREF_FROM_OBJECT(
00556                         dupslot->class_objhash,
00557                         OBJECT(dupslot->class_objhash)
00558                           .table_linkage
00559                           .clsidx);
00560 
00561             /* Unwind real class object reference */
00562             (rvoid) GC_OBJECT_RMREF_FROM_CLASS(
00563                         clsidxOLD,
00564                         CLASS(clsidxOLD).class_objhash);
00565             (rvoid) GC_CLASS_RMREF_FROM_CLASS(
00566                         clsidxOLD,
00567                         CLASS(clsidxOLD).lower_dim_array);
00568             (rvoid) GC_CLASS_RMREF_FROM_OBJECT(
00569                         CLASS(clsidxOLD).class_objhash,
00570                         OBJECT(CLASS(clsidxOLD).class_objhash)
00571                           .table_linkage
00572                           .clsidx);
00573 
00574             /* DO NOT DO THIS-- use same object, incl. class file
00575              * object_instance_delete(CLASS(clsidxOLD)
00576              *                                      .class_objhash);
00577              */
00578 
00579             CLASS(clsidxOLD).class_objhash = jvm_object_hash_null;
00580         }
00581 
00582         /* Unhook class object's class ref, then all unhook class refs*/
00583         (rvoid) GC_CLASS_RMREF_FROM_CLASS(
00584                     clsidxOLD,
00585                     CLASS(clsidxOLD).lower_dim_array);
00586         (rvoid) GC_CLASS_RMREF_FROM_CLASS(jvm_class_index_null,
00587                                           clsidxOLD);
00588         (rvoid) linkage_unresolve_class(clsidxOLD);
00589 
00590         /*
00591          * Finalize garbage collection status of this class instance,
00592          * but DO NOT do class_static_delete()!
00593          */
00594         (rvoid) GC_CLASS_DELETE(clsidxOLD, rfalse);
00595 
00596         /*
00597          * Wipe out old structures, see similar in class_static_delete()
00598          */
00599         CLASS(clsidxOLD).class_static_field_lookup =
00600                                               (jvm_class_index *) rnull;
00601         CLASS(clsidxOLD).num_class_static_field_lookups = 0;
00602 
00603         CLASS(clsidxOLD).object_instance_field_lookup =
00604                                               (jvm_class_index *) rnull;
00605         CLASS(clsidxOLD).num_object_instance_field_lookups = 0;
00606 
00607 
00608         CLASS(clsidxOLD).status = CLASS_STATUS_EMPTY;
00609 
00610         /*
00611          * Copy slot image into new slot
00612          */
00613         dupslot->status |= CLASS_STATUS_NULL; /* Partial init */
00614 
00615         memcpy(&CLASS(clsidxNEW), dupslot, sizeof(rclass));
00616 
00617         /* Reverse of first pair of mkref/rmref */
00618         (rvoid) GC_OBJECT_MKREF_FROM_CLASS(
00619                     clsidxNEW,
00620                     CLASS(clsidxNEW).class_objhash);
00621         (rvoid) GC_CLASS_MKREF_FROM_CLASS(
00622                     clsidxNEW,
00623                     CLASS(clsidxNEW).lower_dim_array);
00624         (rvoid) GC_CLASS_MKREF_FROM_OBJECT(
00625                     CLASS(clsidxNEW).class_objhash,
00626                     OBJECT(CLASS(clsidxNEW).class_objhash)
00627                       .table_linkage
00628                       .clsidx);
00629 
00630         (rvoid) GC_OBJECT_RMREF_FROM_CLASS(
00631                     clsidxOLD,
00632                     dupslot->class_objhash);
00633         (rvoid) GC_CLASS_RMREF_FROM_CLASS(
00634                     clsidxOLD,
00635                     dupslot->lower_dim_array);
00636         (rvoid) GC_CLASS_RMREF_FROM_OBJECT(
00637                     dupslot->class_objhash,
00638                     OBJECT(dupslot->class_objhash)
00639                       .table_linkage
00640                       .clsidx);
00641 
00642             /* Unwind real class object reference */
00643         HEAP_FREE_METHOD(&dupslot);
00644 
00645         return(clsidxNEW);
00646     }
00647     else
00648     {
00649         /* Error-- slot was already free */
00650         return(jvm_class_index_null);
00651     }
00652 
00653 } /* END of class_reload() */
00654 
00655 
00656 /*!
00657  * @brief Un-reserve a slot from the class table.
00658  *
00659  * This is the reverse of the process of class_static_new() above.
00660  *  Only tear down the heap allocations and mark the slot as empty.
00661  * Leave the rest of the data in place for post-mortem.  When the
00662  * slot gets allocated again, any zeroing out of values will just
00663  * get overwritten again, so don't bother.
00664  *
00665  * @todo  Make @e sure all objects of this class type have been
00666  *        destroyed @e before destroying this class itself!
00667  *
00668  * @todo  This function may be used to declutter the class table when
00669  *        a class has not been used for some period of time (including
00670  *        any static methods and fields, watch out for static final
00671  *        constants), so as to free up its slot for other purposes.
00672  *
00673  *
00674  * @param    clsidx   Class index value of allocation.
00675  *
00676  * @param    rmref    @link #rtrue rtrue@endlink if @e class references
00677  *                    should be removed, which is NOT SO during JVM
00678  *                    shutdown.  Regardless of this value, @e object
00679  *                    references are always removed.
00680  *
00681  *
00682  * @returns   Same class index as input if slot was freed, else
00683  *             @link #jvm_class_index_null jvm_class_index_null@endlink
00684  *             if slot was already free.
00685  *
00686  */
00687 
00688 jvm_class_index class_static_delete(jvm_class_index clsidx,
00689                                     rboolean        rmref)
00690 {
00691     if (CLASS(clsidx).status & CLASS_STATUS_INUSE)
00692     {
00693         /*!
00694          * @todo Determine what to do, if anything, when rfalse is
00695          *       returned from linkage_unresolve_class().  Is the
00696          *       class slot unusable?  Should class_static_delete()
00697          *       proceed?
00698          */
00699         (rvoid) linkage_unresolve_class(clsidx);
00700 
00701         /*!
00702          * @todo  Is there anything equivalent to calling
00703          *        @c @b java.lang.Object.finalize() for an object
00704          *        that must be invoked before unloading a class?
00705          */
00706 
00707         if (jvm_object_hash_null != CLASS(clsidx).class_objhash)
00708         {
00709             (rvoid) GC_OBJECT_RMREF_FROM_CLASS(
00710                         clsidx,
00711                         CLASS(clsidx).class_objhash);
00712 
00713             object_instance_finalize(CLASS(clsidx).class_objhash,
00714                                      JVMCFG_GC_THREAD);
00715 
00716             (rvoid) object_instance_delete(
00717                         CLASS(clsidx).class_objhash,
00718                         rtrue);
00719 
00720             /* CLASS(clsidx).class_objhash = jvm_object_hash_null;*/
00721         }
00722 
00723         /* Finalize garbage collection status of this class instance */
00724         if (rtrue == rmref)
00725         {
00726             (rvoid) GC_CLASS_RMREF_FROM_CLASS(clsidx,
00727                                          CLASS(clsidx).lower_dim_array);
00728         }
00729         (rvoid) GC_CLASS_DELETE(clsidx, rfalse);
00730 
00731         if (rnull != CLASS(clsidx).class_static_field_data)
00732         {
00733             /* Remove class static field reference markings */
00734             u2 ncsfl = CLASS(clsidx).num_class_static_field_lookups;
00735             jvm_field_lookup_index csflidx;
00736             for (csflidx = 0; csflidx < ncsfl; csflidx++)
00737             {
00738                 (rvoid) GC_CLASS_FIELD_RMREF(clsidx, csflidx);
00739             }
00740 
00741             HEAP_FREE_DATA(CLASS(clsidx).class_static_field_data);
00742         }
00743 
00744         if (rnull != CLASS(clsidx).class_static_field_lookup)
00745         {
00746             HEAP_FREE_DATA(CLASS(clsidx).class_static_field_lookup);
00747         }
00748         /* CLASS(clsidx).class_static_field_lookup =
00749                                            (jvm_class_index *) rnull; */
00750         /* CLASS(clsidx).num_class_static_field_lookups = 0; */
00751 
00752         if (rnull != CLASS(clsidx).object_instance_field_lookup)
00753         {
00754             HEAP_FREE_DATA(CLASS(clsidx).object_instance_field_lookup);
00755         }
00756         /* CLASS(clsidx).object_instance_field_lookup =
00757                                            (jvm_class_index *) rnull; */
00758         /* CLASS(clsidx).num_object_instance_field_lookups = 0; */
00759 
00760 
00761         /* CLASS(clsidx).status                 = CLASS_STATUS_EMPTY; */
00762 
00763         CLASS(clsidx).status &= ~CLASS_STATUS_INUSE;
00764 
00765         return(clsidx);
00766     }
00767     else
00768     {
00769         /* Error-- slot was already free */
00770         return(jvm_class_index_null);
00771     }
00772 
00773 } /* END of class_static_delete() */
00774 
00775 
00776 /*!
00777  * @brief Scan class table using CP table entry for presence of a class
00778  * of specific name and number of dimensions.
00779  *
00780  *
00781  * @param  clsname    UTF8 string pointer to a class
00782  *                    name, possibly with array dimensions:
00783  *                    @c @b [[Lsome/class/path/SomeClassname;
00784  *                    has two array dimensions.  Can also
00785  *                    accept classes that are null-terminated
00786  *                    strings @e without class formatting.
00787  *                    Such strings @e may start with @c @b L
00788  *                    but will @e not end with @c @b ; .
00789  *
00790  *
00791  * @returns its index in pjvm->class if present, else
00792  *         @link #jvm_class_index_null jvm_class_index_null@endlink.
00793  *
00794  */
00795 jvm_class_index class_find_by_cp_entry(cp_info_dup *clsname)
00796 {
00797     jvm_class_index clsidx;
00798 
00799     jvm_array_dim arraydims =
00800         utf_get_utf_arraydims(PTR_THIS_CP_Utf8(clsname));
00801 
00802     for (clsidx = JVMCFG_FIRST_CLASS;
00803          clsidx < JVMCFG_MAX_CLASSES;
00804          clsidx++)
00805     {
00806         if ( (CLASS_STATUS_INUSE  & CLASS(clsidx).status) &&
00807             !(CLASS_STATUS_NULL   & CLASS(clsidx).status))
00808         {
00809             ClassFile *pcfs = CLASS_OBJECT_LINKAGE(clsidx)->pcfs;
00810             u2 cpidx = pcfs->this_class;
00811 
00812             /*
00813              * Check if this slot's class name matches input request.
00814              * Must match BOTH @b arraydims and string name.
00815              */
00816             if (arraydims != CLASS(clsidx).arraydims)
00817             {
00818                 continue;
00819             }
00820 
00821             if (0 == utf_classname_strcmp(
00822                          PTR_THIS_CP_Utf8(clsname),
00823                          pcfs,
00824                          cpidx))
00825             {
00826                 return(clsidx);
00827             }
00828         }
00829     }
00830 
00831     /* Return NULL if entry not found */
00832     return(jvm_class_index_null);
00833 
00834 } /* END of class_find_by_cp_entry() */
00835 
00836 
00837 /*!
00838  * @brief Retrieve by (rchar *) name a class index to a class.
00839  *
00840  *
00841  * @param  clsname           Null-terminated string of name of class.
00842  *
00843  *
00844  * @returns class index of located class, otherwise
00845  *          @link #jvm_class_index_null jvm_class_index_null@endlink.
00846  *
00847  */
00848 jvm_class_index class_find_by_prchar(rchar *clsname)
00849 {
00850     cp_info_dup *pcip_clsname = nts_prchar2utf(clsname);
00851 
00852     jvm_method_index rc =
00853         class_find_by_cp_entry(pcip_clsname);
00854 
00855     HEAP_FREE_DATA(pcip_clsname);
00856 
00857     return(rc);
00858 
00859 } /* END of class_find_by_prchar() */
00860 
00861 
00862 /*!
00863  * @brief Load primative classes for @c @b java.lang.Class
00864  *
00865  * Load primative classes as opposed to a real class
00866  * @c @b LSome/Package/Name/SomeClassName; .
00867  * These will be known by their primative types: @c @b I
00868  * for "integer", @c @b S for "short", etc.
00869  *
00870  * Classes loaded with this method will typically @e never have any
00871  * references to them except from their class object created
00872  * within class_static_new(), yet are completely valid and are used
00873  * intensively by class type processing.  Because they never have
00874  * references @e removed, they will never be marked for garbage
00875  * collection, either. In this way, they are permanently available
00876  * to the JVM for class type processing.
00877  *
00878  * @param  basetype   One of the primative base types BASETYPE_CHAR_x
00879  *
00880  *
00881  * @returns class table index to loaded primative [pseudo-]class,
00882  *         ready for use.  Throw error if could not load.
00883  *
00884  *
00885  * @throws JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00886  *         @link #JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00887  *         if no slots are available.@endlink.
00888  *
00889  */
00890 jvm_class_index class_load_primative(u1 basetype)
00891 {
00892     ClassFile *pcfs = classfile_allocate_primative(basetype);
00893 
00894     return(class_static_new(CLASS_STATUS_PRIMATIVE,
00895                             pcfs,
00896                             LOCAL_CONSTANT_NO_ARRAY_DIMS,
00897                             (jint *) rnull,
00898                             jvm_class_index_null));
00899 
00900 } /* END of class_load_primative() */
00901 
00902 
00903 /*!
00904  * @name DEFAULT SYSTEM CLASS LOADER:
00905  *
00906  * @brief perform the duties of @c @b java.lang.ClassLoader
00907 
00908  * Using either null-terminated strings or UTF strings from
00909  * @link #CONSTANT_Utf8_info CONSTANT_Utf8_info@endlink or
00910  * @link #CONSTANT_Class_info CONSTANT_Class_info@endlink
00911  * constant_pool entries, the following three functions function
00912  * as the system default class loader that can be invoked three
00913  * different ways.  It searches @b CLASSPATH, reads in a class
00914  * file, parses its contents, and loads it into the class table
00915  * and object table, and performs static initialization.
00916  *
00917  * Notice that the array formatting @e must already be included in
00918  * @b clsname (if this is an array class), and that the @b arraylength
00919  * array must contain the same number of integers as described
00920  * in @b clsname.  No checking is done for this in this function.
00921  *
00922  * @attention This function performs the task of the method
00923  *
00924  * @verbatim
00925      ClassLoader.defineClass(String name, byte[] b, int off, int len)
00926    @endverbatim
00927  *
00928  * but combines the operands effectively into,
00929  *
00930  * @verbatim
00931        ClassLoader.defineClass(String name)
00932    @endverbatim
00933  *
00934  *   where @b name is a null-terminated string passed as the only parm,
00935  *   and @b b is the byte array read in by classfile_readclassfile()
00936  *   or classfile_readjarfile(), and @b off is zero, and @b len being
00937  *   discovered by classfile_read_XXXfile().
00938  *
00939  * @todo  Spec section 5.3.4 <b>Loading Constraints</b> has not been
00940  *        considered in this implementation.  It needs to be looked at.
00941  *
00942  * @todo  Convert this function from recursive (easy to write) into
00943  *        iterative (easier to run and maintain).
00944  *
00945  *
00946  * @param  clsname   This parameter may be one of three styles:
00947  *
00948  * <ul>
00949  * <li> for class_load_from_cp_entry_utf() only: a
00950  *                   CONSTANT_Utf8_info constant_pool entry string
00951  *                   containing unqualified class name:
00952  *
00953  *                   @c @b Lsome/class/path/SomeClassname;
00954  *
00955  *                   with possible array specification:
00956  *
00957  *                   @c @b [[[Lsome/class/path/SomeClassname;
00958  *
00959  *                   This example has three array dimensions.
00960  * </li>
00961  *
00962  * <li> for class_load_from_prchar() only: a null-terminated string
00963  *                   containing unqualified class name.
00964  *                   See above for further comments.
00965  * </li>
00966  *
00967  * <li> for class_load_from_cp_entry_class() only: a
00968  *                   CONSTANT_Class_info constant_pool entry containing
00969  *                   constant_pool entry to unqualified class name.
00970  *                   See above for further comments.
00971  * </li>
00972  * </ul>
00973  *
00974  * @param find_registerNatives When @link #rtrue rtrue@endlink,
00975  *                   will return the ordinal for
00976  *                   @link #JVMCFG_JLOBJECT_NMO_REGISTER 
00977                             JVMCFG_JLOBJECT_NMO_REGISTER@endlink and
00978  *                   @link #JVMCFG_JLOBJECT_NMO_UNREGISTER 
00979                             JVMCFG_JLOBJECT_NMO_UNREGISTER@endlink
00980  *                   as well as the other ordinals.  Once JVM
00981  *                   initialization is complete, this should always
00982  *                   be @link #rfalse rfalse@endlink because all future
00983  *                   classes should @e never have local ordinals.
00984  *
00985  * @param arraylength Array of number of elements in @e each array
00986  *                    dimension.  If not needed, set to
00987  *                    @link #rnull rnull@endlink.
00988  *                    Notice that @b clsname will determine how many
00989  *                    array dimensions are needed.  In the above
00990  *                    example of 3 dimensions, an array of 3 numbers
00991  *                    must be passed here.  If the declaration was,
00992  *                    <b><code>new SomeClassname[4][7][8]</code></b>,
00993  *                    then the array {4, 7, 8} must be passed here.
00994  *
00995  *
00996  * @returns class table index to loaded class, ready for use, or
00997  *          @link #jvm_class_index_null jvm_class_index_null@endlink
00998  *          if could not load.
00999  *
01000  *
01001  * @throws JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
01002  *         @link #JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
01003  *         if no slots are available.@endlink.
01004  *
01005  * @throws JVMCLASS_JAVA_LANG_INTERNALERROR
01006  *         @link #JVMCLASS_JAVA_LANG_INTERNALERROR
01007  *         with bad clsname constant_pool entry type@endlink.
01008  *         Meaninful only for
01009  *         @link #class_load_from_cp_entry_utf()
01010                   class_load_from_cp_entry_utf()@endlink
01011  *
01012  */
01013 /*         and @link #@class_load_from_cp_entry_class()
01014                    class_load_from_cp_entry_class()@endlink only. */
01015 
01016 /*@{ */ /* Begin grouped definitions */
01017 
01018 jvm_class_index
01019     class_load_from_cp_entry_utf(cp_info_dup *clsname,
01020                                  rboolean     find_registerNatives,
01021                                  jint        *arraylength)
01022 {
01023     /* Disallow all but UTF8 constant_pool entries */
01024     if (CONSTANT_Utf8 != PTR_THIS_CP_Utf8(clsname)->tag)
01025     {
01026         /* Somebody goofed */
01027         exit_throw_exception(EXIT_JVM_INTERNAL,
01028                              JVMCLASS_JAVA_LANG_INTERNALERROR);
01029 /*NOTREACHED*/
01030     }
01031 
01032     /* 
01033      * Be @e VERY conservative about local var allocation
01034      * due to upcoming deep recursion.
01035      */
01036     jvm_class_index rc;
01037 
01038     /*
01039      * Ignore this request if class already loaded, but distinguish
01040      * between array and non-array classes
01041      */
01042     rc = class_find_by_cp_entry(clsname);
01043 
01044     /* If class already loaded, then do nothing */
01045     if (jvm_class_index_null != rc)
01046     {
01047         return(rc);
01048     }
01049 
01050     /* Inquire if this is an array class */
01051     jvm_array_dim arraydims =
01052         utf_get_utf_arraydims(PTR_THIS_CP_Utf8(clsname));
01053 
01054     /*
01055      * If an array class, load array class of 1 lower dimension,
01056      * or non-array version if this is array dimension 1.
01057      */
01058     if (LOCAL_CONSTANT_NO_ARRAY_DIMS < arraydims)
01059     {
01060         rchar *pnextdim = utf_utf2prchar(PTR_THIS_CP_Utf8(clsname));
01061 
01062         /*
01063          * WARNING! RECURSIVE CALL! This call goes 1 level per
01064          *          array dimension.
01065          */
01066         rc = class_load_from_prchar(&pnextdim[1 * sizeof(u1)],
01067                                     find_registerNatives,
01068                                     (rnull == arraylength)
01069                                         ? (jint *) rnull
01070                                         : &arraylength[1]);
01071 
01072         HEAP_FREE_DATA(pnextdim);
01073     }
01074 
01075     /*
01076      * Be conservative about number of local variables above
01077      * due to possibility of deep recursion (avert stack overflow).
01078      * Now that recursion is over, can allocate locals more freely.
01079      */
01080     {
01081         /* Use name more descriptive of new role.  Known non-zero. */
01082         jvm_class_index lower_dim_clsidx = rc;
01083 
01084         /*
01085          * For an array, locate class file structure of non-array
01086          * version and mark class as being an array class (through
01087          * agency of class_static_new(,,arraydims,)).  If not an
01088          * array class, load the class file.  This will be
01089          * known to array classes as the "non-array version" of
01090          * the class.  All array class file pointers will point
01091          * to this class file structure.
01092          */
01093         u1              *pcfd;
01094         ClassFile       *pcfs;
01095         rchar           *pcname;
01096         jvm_class_index  clsidx;
01097 
01098         if (LOCAL_CONSTANT_NO_ARRAY_DIMS < arraydims)
01099         {
01100             /* Locate non-array version of class in class table */
01101             jvm_class_index next_clsidx = lower_dim_clsidx;
01102 
01103             while(jvm_class_index_null !=
01104                   CLASS(next_clsidx).lower_dim_array)
01105             {
01106                 next_clsidx =
01107                     CLASS(CLASS_OBJECT_LINKAGE(next_clsidx)->clsidx)
01108                         .lower_dim_array;
01109             }
01110 
01111             /* Having traversed the indices, found non-array version */
01112             ClassFile *pcfs = CLASS_OBJECT_LINKAGE(next_clsidx)->pcfs;
01113 
01114             /* Load into class and object tables */
01115             clsidx =
01116                 class_static_new(((LOCAL_CONSTANT_NO_ARRAY_DIMS ==
01117                                    arraydims)
01118                                       ? CLASS_STATUS_EMPTY
01119                                       : CLASS_STATUS_ARRAY),
01120                                   pcfs,
01121                                   arraydims,
01122                                   arraylength,
01123                                   lower_dim_clsidx);
01124 
01125         } /* if arraydims */
01126         else
01127         {
01128             cp_info_dup *pnofmt =
01129                              utf_utf2utf_unformatted_classname(clsname);
01130 
01131             pcname = classpath_get_from_cp_entry_utf(pnofmt);
01132 
01133             HEAP_FREE_DATA(pnofmt);
01134 
01135             GENERIC_FAILURE1_THROWERROR((rnull == pcname),
01136                                         DMLNORM,
01137                                         "class_load_from_prchar",
01138                                         "Cannot locate class %s",
01139                                         clsname,
01140                                         EXIT_JVM_CLASS,
01141                                JVMCLASS_JAVA_LANG_NOCLASSDEFFOUNDERROR,
01142                                         pcname,
01143                                         rnull);
01144 
01145             /*
01146              * Check if JAR file or class file and read in the class
01147              * file data stream as a simple binary image.
01148              */
01149             if (rtrue == classpath_isjar(pcname))
01150             {
01151                 pcfd = classfile_readjarfile(pcname);
01152             }
01153             else
01154             {
01155                 pcfd = classfile_readclassfile(pcname);
01156             }
01157 
01158             GENERIC_FAILURE1_THROWERROR((rnull == pcfd),
01159                                         DMLNORM,
01160                                         "class_load_from_prchar",
01161                                         "Cannot read file %s",
01162                                         pcname,
01163                                         EXIT_JVM_CLASS,
01164                                    JVMCLASS_JAVA_LANG_CLASSFORMATERROR,
01165                                         pcfd,
01166                                         pcname);
01167 
01168             /*! @todo  Throw @b UnsupportedClassVersionError */
01169 
01170             /* Parse out the class file input stream */
01171             pcfs = classfile_loadclassdata(pcfd);
01172 
01173             /* Load into class and object tables */
01174             clsidx = class_static_new(CLASS_STATUS_EMPTY,
01175                                       pcfs,
01176                                       LOCAL_CONSTANT_NO_ARRAY_DIMS,
01177                                       (jint *) rnull,
01178                                       jvm_class_index_null);
01179 
01180             /* Don't need file image any more */
01181             HEAP_FREE_DATA(pcfd);
01182 
01183             GENERIC_FAILURE1_THROWERROR((rnull == pcfs),
01184                                         DMLNORM,
01185                                         "class_load_from_prchar",
01186                                         "Invalid class file %s",
01187                                         pcname,
01188                                         EXIT_JVM_CLASS,
01189                                    JVMCLASS_JAVA_LANG_CLASSFORMATERROR,
01190                                         pcname,
01191                                         rnull);
01192 
01193             /* Don't need absolute path name any more, either */
01194             HEAP_FREE_DATA(pcname);
01195 
01196             /*!
01197              * @internal Load superclass
01198              *
01199              * @todo  (The @c @b <clinit> procedure is run when the
01200              *        JVM virtual machine execution engine moves
01201              *        a new class from the START state into the
01202              *        RUNNABLE state.)
01203              */
01204             if (jvm_class_index_null != pcfs->super_class)
01205             {
01206                 CONSTANT_Utf8_info *name = PTR_CP1_CLASS_NAME(pcfs,
01207                                                      pcfs->super_class);
01208 
01209                 rchar *super_name = utf_utf2prchar_classname(name);
01210 
01211                 /*!
01212                  * @internal WATCH OUT!  RECURSIVE CALL!  This will
01213                  * recurse until super_class is a
01214                  * @c @b java.lang.Object, where
01215                  * @link ClassFile.super_class
01216                    ClassFile.super_class@endlink is 0 (per JVM spec.
01217                  * Throw error if could not load superclass.
01218                  * Don't care about its class index, as
01219                  * that is also available in other places.
01220                  *
01221                  * @todo Make @e sure that this superclass and all of
01222                  *       its superclasses are not only loaded, but also
01223                  *       linked and have @c @b <clinit> run also.
01224                  *
01225                  */
01226                 (rvoid) class_load_from_prchar(super_name,
01227                                                find_registerNatives,
01228                                                (jint *) rnull);
01229 
01230                 /*
01231                  * If error above, neither HEAP_FREE_DATA(super_name)
01232                  * nor classfile_unloadclassdata(pcfs) will be called.
01233                  */
01234             }
01235 
01236             /* Mark as needing @c @b <clinit> in JVM class startup */
01237             CLASS(clsidx).status |= CLASS_STATUS_DOCLINIT;
01238 
01239         } /* if arraydims else */
01240 
01241         /* Make a pass at resolving constant_pool linkages */
01242         (rvoid) linkage_resolve_class(clsidx, find_registerNatives);
01243 
01244         /*
01245          * Class is ready for JVM execution.
01246          */
01247         return(clsidx);
01248 
01249     } /* local block */
01250 
01251 } /* END of class_load_from_cp_entry_utf() */
01252 
01253 
01254 jvm_class_index class_load_from_prchar(rchar    *clsname,
01255                                        rboolean  find_registerNatives,
01256                                        jint     *arraylength)
01257 {
01258     cp_info_dup *cp_clsname = nts_prchar2utf(clsname);
01259 
01260     jvm_class_index clsidx =
01261         class_load_from_cp_entry_utf(cp_clsname,
01262                                      find_registerNatives,
01263                                      arraylength);
01264 
01265     HEAP_FREE_DATA(cp_clsname);
01266 
01267     return(clsidx);
01268 
01269 } /* END of class_load_from_prchar() */
01270 
01271 
01272 #if 0
01273 /* Can use if want to add @b pcfs to parm list or some such */
01274 jvm_class_index
01275     class_load_from_cp_entry_class(cp_info_dup *clsname,
01276                                    rboolean     find_registerNatives,
01277                                    jint        *arraylength)
01278 {
01279     /* Disallow all but CLASS constant_pool entries */
01280     if (CONSTANT_Class != PTR_THIS_CP_Class(clsname)->tag)
01281     {
01282         /* Somebody goofed */
01283         exit_throw_exception(EXIT_JVM_INTERNAL,
01284                              JVMCLASS_JAVA_LANG_INTERNALERROR);
01285 /*NOTREACHED*/
01286     }
01287 
01288     rchar *prchar_clsname =
01289         utf_utf2prchar(
01290             PTR_THIS_CP_Utf8(
01291                 &pcfs->constant_pool
01292                  [PTR_THIS_CP_Class(clsname)->name_index]));
01293 
01294     jvm_class_index clsidx = class_load_from_prchar(prchar_clsname,
01295                                                    find_registerNatives,
01296                                                     arraylength);
01297 
01298     HEAP_FREE_DATA(prchar_clsname);
01299 
01300     return(clsidx);
01301 
01302 } /* END of class_load_from_cp_entry_class() */
01303 #endif
01304 
01305 /*@} */ /* End of grouped definitions */
01306 
01307 
01308 /*!
01309  * @brief All-purpose class loading, load, resolve, @c @b <clinit> ,
01310  * each step only run if needed.
01311  *
01312  * Load a class into the JVM, resolve its linkages, and run its
01313  * @c @b <clinit> method, if any, typically on the system thread.
01314  * All three steps are optional and will be invoked @e only if needed.
01315  * Therefore it is possible that @e none of the steps will be run.
01316  * However, if @e any step needs to performed, that step will be run.
01317  *
01318  *
01319  * @param  clsname           Null-terminated string of unformatted
01320  *                           class name.(Formatting is okay, but don't
01321  *                           pass an array class)
01322  *
01323  * @param  thridx            If a non-null thread index is passed in,
01324  *                           use the current state of that thread to
01325  *                           load the class and run its
01326  *                           @c @b <clinit> .
01327  *                           If null thread index is passed in, use
01328  *                           the @b usesystemthread parameter to
01329  *                           further clarify which thread to load up
01330  *                           with class @c @b <clinit> .
01331  *
01332  * @param  usesystemthread   Load onto system thread when
01333  *                           @link #rtrue rtrue@endlink, use
01334  *                           an available thread otherwise.
01335  *
01336  * @param find_registerNatives When @link #rtrue rtrue@endlink,
01337  *                      will return the ordinal for
01338  *                      @link #JVMCFG_JLOBJECT_NMO_REGISTER 
01339                                JVMCFG_JLOBJECT_NMO_REGISTER@endlink and
01340  *                      @link #JVMCFG_JLOBJECT_NMO_UNREGISTER 
01341                                JVMCFG_JLOBJECT_NMO_UNREGISTER@endlink
01342  *                      as well as the other ordinals.  Once JVM
01343  *                      initialization is complete, this should always
01344  *                      be @link #rfalse rfalse@endlink because all
01345  *                      future classes should @e never have local
01346  *                      ordinals.
01347  *
01348  *
01349  * @returns class index of loaded class, whether or not a
01350  *          @c @b <clinit> method was available.  Throw
01351  *          error if not slots available.
01352  *
01353  *
01354  * @throws JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
01355  *         @link #JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
01356  *         if no slots are available.@endlink.
01357  *
01358  * @throws JVMCLASS_JAVA_LANG_INTERNALERROR
01359  *         @link #JVMCLASS_JAVA_LANG_INTERNALERROR
01360            if invalid clsidx@endlink
01361  *
01362  * @throws JVMCLASS_JAVA_LANG_NOSUCHFIELDERROR
01363  *         @link #JVMCLASS_JAVA_LANG_NOSUCHFIELDERROR
01364            if invalid field linked by class@endlink
01365  *
01366  * @throws JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR
01367  *         @link #JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR
01368            if invalid method linked by class@endlink
01369  *
01370  * @todo  Any JAR file passed in here that has a @c @b [ in its
01371  *        first one or more characters may be interpreted as an array
01372  *        class.  I have not tested this, and it is an oddball,
01373  *        but somebody needs to make sure that either, (a) such
01374  *        a name is @e never passed in, which is preferred due to
01375  *        standard industry file naming practices, and/or (b) that
01376  *        no array processing happens in the lower levels.
01377  *
01378  */
01379 
01380 
01381 jvm_class_index class_load_resolve_clinit(rchar        *clsname,
01382                                       jvm_thread_index  thridx,
01383                                           rboolean      usesystemthread,
01384                                           rboolean find_registerNatives)
01385 {
01386     jvm_class_index clsidx = class_load_from_prchar(clsname,
01387                                                    find_registerNatives,
01388                                                     (jint *) rnull);
01389 
01390     /*
01391      * Make another pass at class linkage (if completely linked,
01392      * request is ignored).
01393      */
01394     (rvoid) linkage_resolve_class(clsidx, find_registerNatives);
01395 
01396     /*
01397      * If @c @b <clinit> has been run due to previous class load,
01398      * done
01399      */
01400     if (CLASS_STATUS_CLINIT & CLASS(clsidx).status)
01401     {
01402         return(clsidx);
01403     }
01404 
01405     /*
01406      * Need to explicitly run @c @b <clinit> since not
01407      * in main JVM loop
01408      */
01409     jvm_method_index mthidx =
01410         method_find_by_prchar(clsidx,
01411                               LOCAL_CONSTANT_UTF8_CLASS_CONSTRUCTOR,
01412                            LOCAL_CONSTANT_UTF8_CLASS_CONSTRUCTOR_PARMS);
01413     if (jvm_method_index_bad == mthidx)
01414     {
01415         /*
01416          * Return valid class index even if no @c @b <clinit>
01417          * was available
01418          */
01419         return(clsidx);
01420     }
01421     else
01422     {
01423         jvm_thread_index thridxLOAD;
01424 
01425         if (jvm_thread_index_null != thridx)
01426         {
01427             thridxLOAD = thridx;
01428 
01429             /*!
01430              * @internal see similar logic for loading a new stack
01431              * frame and PC in thread_new_common()
01432              *
01433              */
01434 
01435             ClassFile *pcfs = CLASS_OBJECT_LINKAGE(clsidx)->pcfs;
01436 
01437             jvm_attribute_index codeatridx =
01438                 pcfs
01439                   ->methods[mthidx]
01440                     ->LOCAL_method_binding
01441                       .codeatridxJVM;
01442 
01443             if (jvm_attribute_index_bad == codeatridx)
01444             {
01445                 /*!
01446                  * @todo Currently, return valid class index even
01447                  * if no @c @b <clinit> was available.  Is this
01448                  * correct? Or should it throw a @b VerifyError since
01449                  * a method was declared, yet had no code area?  Take
01450                  * the easy way out for now, evaluate and maybe fix
01451                  * later.
01452                  */
01453                 return(clsidx);
01454             }
01455 
01456             jvm_attribute_index excpatridx =
01457                 pcfs
01458                   ->methods[mthidx]
01459                     ->LOCAL_method_binding
01460                       .excpatridxJVM;
01461 
01462             Code_attribute *pca =
01463                 (Code_attribute *)
01464                 &pcfs->methods[mthidx]->attributes[codeatridx]->ai;
01465 
01466             /* Check for stack overflow if this frame is loaded */
01467             if (JVMCFG_MAX_SP <= GET_SP(thridx) +
01468                                  JVMREG_STACK_MIN_FRAME_HEIGHT +
01469                                  JVMREG_STACK_PC_HEIGHT +
01470                                  pca->max_stack +
01471                                  pca->max_locals)
01472             {
01473                 exit_throw_exception(EXIT_JVM_CLASS,
01474                                    JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR);
01475 /*NOTLOADED*/
01476             }
01477 
01478             /*
01479              * Save old stack frame for @b RETURN from @c b <clinit>
01480              */
01481             PUSH_FRAME(thridx, pca->max_locals);
01482 
01483             /* Load PC of @c @b <clinit> method */
01484             PUT_PC_IMMEDIATE(thridx,
01485                              clsidx,
01486                              mthidx,
01487                              codeatridx,
01488                              excpatridx,
01489                              CODE_CONSTRAINT_START_PC);
01490         }
01491         else
01492         {
01493             /*
01494              * Class is now known to be available,
01495              * so start it on the system thread.
01496              *
01497              * There is no old stack frame to save for @b RETURN
01498              * from @c @b <clinit> because this a new thread.  The
01499              * starting stack frame is set up by thread_class_load()
01500              * and returning to it will @b COMPLETE the thread.
01501              */
01502             thridxLOAD =
01503                 thread_class_load(clsname,
01504                                   LOCAL_CONSTANT_UTF8_CLASS_CONSTRUCTOR,
01505                             LOCAL_CONSTANT_UTF8_CLASS_CONSTRUCTOR_PARMS,
01506                                   THREAD_PRIORITY_MAX,
01507                                   rfalse,
01508                                   usesystemthread,
01509                                   find_registerNatives);
01510         }
01511 
01512         jvm_manual_thread_run(thridxLOAD,
01513                               ((rtrue == usesystemthread) ||
01514                                (jvm_thread_index_null == thridx))
01515                                 ? rtrue /* Die if not prev @b RUN */
01516                                 : rfalse,
01517                               clsname,
01518                               LOCAL_CONSTANT_UTF8_CLASS_CONSTRUCTOR,
01519                            LOCAL_CONSTANT_UTF8_CLASS_CONSTRUCTOR_PARMS);
01520 
01521         /* Class @c @b <clinit> has been completed (manually) */
01522         CLASS(clsidx).status &= ~CLASS_STATUS_DOCLINIT;
01523         CLASS(clsidx).status |= CLASS_STATUS_CLINIT;
01524 
01525 
01526         /*Return class index of class loaded,resolved,and ready to use*/
01527         return(clsidx);
01528     }
01529 
01530 } /* END of class_load_resolve_clinit() */
01531 
01532 
01533 /*!
01534  * @brief Retrieve data from a @link #CONSTANT_Class_info
01535    CONSTANT_xxx_info@endlink structure and insert it
01536  * into a slot in the field data table.  Also implements table 4.6.
01537  *
01538  *
01539  * @param   clsidx        Class table index of slot having class loaded
01540  *
01541  * @param   pcfs          Pointer to ClassFile area
01542  *
01543  * @param   fldidx        Class file field info table index
01544  *
01545  * @param   field_data    Field data tbl in class tbl entry(on the heap)
01546  *
01547  * @param   fluidx        Field lookup index into field_data table
01548  *
01549  * @param  staticmark     If @link #rtrue rtrue@endlink, this
01550  *                        invocation is for a class static field lookup
01551  *                        table, so call
01552  *                        GC_CLASS_FIELD_MKREF(clsidx, fluidx) for
01553  *                        reference types (namely CONSTANT_String
01554  *                        types).  When @link #rfalse rfalse@endlink,
01555  *                        call instead
01556  *                        GC_OBJECT_FIELD_MKREF(objhash, fluidx) for
01557  *                        reference types.  It is for this @e specific
01558  *                        purpose that @b objhash is supplied below:
01559  *
01560  * @param  objhash        If @b staticmark is
01561  *                        @link #rfalse rfalse@endlink,
01562  *                        this is the object
01563  *                        hash of the field lookup table whose reference
01564  *                        types should be GC marked, otherwise ignored.
01565  *                        See @b staticmark above for details.
01566  *
01567  *
01568  * @returns @link #rvoid rvoid@endlink
01569  *
01570  */
01571 static
01572    rvoid class_get_constant_field_attribute(jvm_class_index  clsidx,
01573                                             ClassFile       *pcfs,
01574                                             jvm_field_index  fldidx,
01575                                             jvalue          *field_data,
01576                                       jvm_field_lookup_index fluidx,
01577                                             rboolean         staticmark,
01578                                             jvm_object_hash  objhash)
01579 {
01580     /* Check for an initial value for each field */
01581      jvm_attribute_index atridx;
01582      for (atridx = 0;
01583           atridx < pcfs->fields[fldidx]->attributes_count;
01584           atridx++)
01585      {
01586          rulong *prl8;
01587          rdouble *prd8;
01588 
01589          u4 *pu4, *pu4h, *pu4l;
01590          jint vali;
01591          jlong vall;
01592          jfloat valf;
01593          jdouble vald;
01594 
01595          jvalue  val;
01596 
01597          jvm_constant_pool_index constantvalue_index;
01598 
01599          switch (cfattrib_atr2enum(pcfs,
01600                                    pcfs->fields[fldidx]
01601                                          ->attributes[atridx]
01602                                            ->ai.attribute_name_index))
01603          {
01604              case LOCAL_SIGNATURE_ATTRIBUTE:
01605                  /*! @todo  Need to recognize signatures */
01606                  break;
01607 
01608              case LOCAL_CONSTANTVALUE_ATTRIBUTE:
01609                  constantvalue_index = 
01610                      ((ConstantValue_attribute *)
01611                       &pcfs->fields[fldidx]->attributes[atridx]->ai)
01612                      ->constantvalue_index;
01613 
01614                  /* Spec table 4.6 implementation */
01615                  switch(CP_TAG(pcfs, constantvalue_index))
01616                  {
01617                      case CONSTANT_Long:
01618                          pu4h = &PTR_CP_ENTRY_TYPE(
01619                                      CONSTANT_Long_info,
01620                                      pcfs,
01621                                      constantvalue_index)->high_bytes;
01622 
01623                          pu4l = &PTR_CP_ENTRY_TYPE(
01624                                      CONSTANT_Long_info,
01625                                      pcfs,
01626                                      constantvalue_index)->low_bytes;
01627 
01628                          /*
01629                           * if WORDSIZE/32/64 mismatches -m32/-m64,
01630                           * the <code>JBITS * sizeof(u4)<code>
01631                           * calculation @e will cause a runtime-visible
01632                           * compiler warning!
01633                           */
01634 /*
01635  *                       vall = (jlong)
01636  *                          ((((julong) *pu4h) << (JBITS * sizeof(u4)))|
01637  *                           ((julong) *pu4l));
01638  */
01639 
01640 /*! @todo  Above logic works, 64-bit logic below needs testing: */
01641                          /* LS word always follows MS word */
01642                          prl8 = (rulong *) pu4h;
01643                          vall = (jlong) GETRL8(prl8);
01644 
01645                          val._jlong = vall;
01646                          break;
01647 
01648                      case CONSTANT_Float:
01649                          pu4 = &PTR_CP_ENTRY_TYPE(
01650                                     CONSTANT_Float_info,
01651                                     pcfs,
01652                                     constantvalue_index)
01653                                 ->bytes;
01654 
01655                          valf = (jfloat) (jint) *pu4;
01656 
01657                          val._jfloat = valf;
01658                          break;
01659 
01660                      case CONSTANT_Double:
01661                          pu4h = &PTR_CP_ENTRY_TYPE(
01662                                      CONSTANT_Long_info,
01663                                      pcfs,
01664                                      constantvalue_index)->high_bytes;
01665                          pu4l = &PTR_CP_ENTRY_TYPE(
01666                                      CONSTANT_Long_info,
01667                                      pcfs,
01668                                      constantvalue_index)->low_bytes;
01669 
01670                          /*
01671                           * if WORDSIZE/32/64 mismatches -m32/-m64,
01672                           * the <code>JBITS * sizeof(u4)<code>
01673                           * calculation @e will cause a runtime-visible
01674                           * compiler warning!
01675                           */
01676 /*
01677  *                       vald = (jdouble)
01678  *                          ((((julong) *pu4h) << (JBITS * sizeof(u4)))|
01679  *                           ((julong) *pu4l));
01680  */
01681 
01682 /*! @todo  Above logic works, 64-bit logic below needs testing: */
01683                          /* LS word always follows MS word */
01684                          prd8 = (rdouble *) pu4h;
01685                          vald = (jdouble) GETRL8((rulong *) prd8);
01686 
01687 
01688                          val._jdouble = vald;
01689                          break;
01690 
01691                      case CONSTANT_Integer:
01692                          pu4 = &PTR_CP_ENTRY_TYPE(
01693                                     CONSTANT_Integer_info,
01694                                     pcfs,
01695                                     constantvalue_index)
01696                                 ->bytes;
01697 
01698                          vali = (jint) *pu4;
01699 
01700                          /*
01701                           * Casting to shorter types, namely
01702                           * (jshort), (jchar), (jbyte), and
01703                           * (jboolean), is done during field
01704                           * access, not here.
01705                           */
01706                          val._jint = vali;
01707 
01708                          break;
01709     
01710 
01711                      case CONSTANT_String:
01712                          /*!
01713                           * @todo Load up this string into a
01714                           * @c @b java.lang.String using the
01715                           * source from
01716                           *
01717                           * <b><code> pcfs->constant_pool
01718                                          [PTR_CP_ENTRY_TYPE(
01719                                               CONSTANT_String_info,
01720                                               pcfs,
01721                                               constantvalue_index)
01722                                           ->string_index]</code></b>
01723                           *
01724                           * But do not store directly into,
01725                           *
01726                           * <b><code>val._jstring = ... </code></b>
01727                           *
01728                           * Instead, store the resulting object
01729                           * hash from the algorithm shown in
01730                           * @link #jvm_init() jvm_init()@endlink
01731                           * where the @link #main() main()@endlink
01732                           * parameter @c @b argv[] array is loaded
01733                           * into the Java edition of the same.
01734                           * The pseudocode for this operation is
01735                           * shown there.
01736                           *
01737                           * <em>DO NOT</em> do this until the class
01738                           * initialization is complete for
01739                           * @c @b java.lang.String or the results
01740                           * may be arbitrary or even fatal.  A
01741                           * well-formed class library will not
01742                           * attempt such an operation.
01743                           *
01744                           */
01745 
01746 
01747                          /*
01748                           * DO NOT do GC_OBJECT_MKREF(val._jstring)
01749                           * since it is part of this class
01750                           * definition, that is, self-referential.
01751                           */
01752 
01753 
01754 
01755                          /*
01756                           * Since strings are constant, this is the
01757                           * only opportunity to mark this field.
01758                           */
01759                          if (rtrue == staticmark)
01760                          {
01761                              GC_CLASS_FIELD_MKREF(clsidx, fluidx);
01762                          }
01763                          else
01764                          {
01765                              /*
01766                               * Rearranged higher level logic to
01767                               * make sure that @b objhash was valid
01768                               * by the time this call occurs here:
01769                               */
01770                              GC_OBJECT_FIELD_MKREF(objhash, fluidx);
01771                          }
01772                          break;
01773 
01774                  } /* switch constantvalue_index */
01775 
01776 
01777                  /* Copy constant value into result array */
01778                  memcpy(&field_data[fluidx++], &val, sizeof(jvalue));
01779                  break;
01780 
01781              /* Satisfy compiler that all cases are handled */
01782              case LOCAL_UNKNOWN_ATTRIBUTE:
01783              case LOCAL_CODE_ATTRIBUTE:
01784              case LOCAL_EXCEPTIONS_ATTRIBUTE:
01785              case LOCAL_INNERCLASSES_ATTRIBUTE:
01786              case LOCAL_ENCLOSINGMETHOD_ATTRIBUTE:
01787              case LOCAL_SYNTHETIC_ATTRIBUTE:
01788              case LOCAL_SOURCEFILE_ATTRIBUTE:
01789              case LOCAL_LINENUMBERTABLE_ATTRIBUTE:
01790              case LOCAL_LOCALVARIABLETABLE_ATTRIBUTE:
01791              case LOCAL_LOCALVARIABLETYPETABLE_ATTRIBUTE:
01792              case LOCAL_DEPRECATED_ATTRIBUTE:
01793              case LOCAL_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE:
01794              case LOCAL_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE:
01795              case LOCAL_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE:
01796              case LOCAL_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE:
01797              case LOCAL_ANNOTATIONDEFAULT_ATTRIBUTE:
01798                  break;
01799          } /* switch cfattrib_atr2enum() */
01800 
01801      } /* for atridx */
01802 
01803      return;
01804 
01805 } /* END of class_get_constant_field_attribute() */
01806 
01807 
01808 /*!
01809  * @brief Report number of class static fields are in a class file.
01810  *
01811  *
01812  * @param    pcfs  Pointer to ClassFile area
01813  *
01814  *
01815  * @returns  number of fields marked ACC_STATIC.
01816  *
01817  */
01818 u2 class_get_num_static_fields(ClassFile *pcfs)
01819 {
01820     jvm_field_index fldidx;
01821     u2 rc = 0;
01822 
01823     for (fldidx = 0; fldidx < pcfs->fields_count; fldidx++)
01824     {
01825         if (ACC_STATIC & pcfs->fields[fldidx]->access_flags)
01826         {
01827             rc++;
01828         }
01829     }
01830 
01831     return(rc);
01832 
01833 } /* END of class_get_num_static_fields() */
01834 
01835 
01836 /*!
01837  * @brief Load the field lookup table for class static fields in
01838  * this class.
01839  *
01840  *
01841  * @param    pcfs         Pointer to ClassFile area
01842  * 
01843  *
01844  * @returns   array of field indices in ClassFile @b fields table
01845  *           for all static fields in this class or
01846  *           @link #rnull rnull@endlink if no values
01847  *           to initialize or heap allocation error.  The
01848  *           size of the array is determined by the result
01849  *           of class_get_num_static_fields().
01850  *
01851  */
01852 jvm_field_index *class_get_static_field_lookups(ClassFile *pcfs)
01853 {
01854     u2 num_static_fields = class_get_num_static_fields(pcfs);
01855 
01856     /* Done if no static fields to initialize */
01857     if (0 == num_static_fields)
01858     {
01859         return((u2 *) rnull);
01860     }
01861 
01862     u2 fldidx;
01863     u2 fluidx = 0;
01864     jvm_field_index *rc =
01865         HEAP_GET_DATA(sizeof(jvm_field_index) * num_static_fields,
01866                       rfalse);
01867 
01868     for (fldidx = 0; fldidx < pcfs->fields_count; fldidx++)
01869     {
01870         if (ACC_STATIC & pcfs->fields[fldidx]->access_flags)
01871         {
01872             rc[fluidx++] = fldidx;
01873         }
01874     }
01875 
01876     return(rc);
01877 
01878 } /* END of class_get_static_field_lookups() */
01879 
01880 
01881 /*!
01882  * @brief Load the field data table for class static fields in
01883  * this class
01884  *
01885  *
01886  * @param   clsidx        Class table index of slot having class loaded
01887  *
01888  * @param  pcfs           Pointer to ClassFile area
01889  * 
01890  *
01891  * @returns  array of data values corresponding to each field index
01892  *           as returned from class_get_static_field_lookups() or
01893  *           @link #rnull rnull@endlink if no values to initialize
01894  *           or heap allocation error.
01895  *           The size of the array is determined by the result of
01896  *           class_get_num_static_fields().
01897  *
01898  */
01899 jvalue *class_get_static_field_data(jvm_class_index  clsidx,
01900                                     ClassFile       *pcfs)
01901 {
01902     u2 num_static_fields = class_get_num_static_fields(pcfs);
01903 
01904     /* Done if no static fields to initialize */
01905     if (0 == num_static_fields)
01906     {
01907         return((jvalue *) rnull);
01908     }
01909 
01910     u2 fldidx;
01911     u2 fluidx = 0;
01912 
01913     /*
01914      * Allocate heap are for data table, SET ALL VALUES TO ZERO.
01915      * This will accomplish the intention of clearing all primative
01916      * data types.
01917      */
01918     jvalue *rc =HEAP_GET_DATA(sizeof(jvalue) * num_static_fields,rtrue);
01919 
01920     for (fldidx = 0; fldidx < pcfs->fields_count; fldidx++)
01921     {
01922         if (ACC_STATIC & pcfs->fields[fldidx]->access_flags)
01923         {
01924             class_get_constant_field_attribute(clsidx,
01925                                                pcfs,
01926                                                fldidx,
01927                                                rc,
01928                                                fluidx,
01929                                                rtrue,
01930                                                jvm_object_hash_null);
01931 
01932             fluidx++;
01933         }
01934     }
01935 
01936     return(rc);
01937 
01938 } /* END of class_get_static_field_data() */
01939 
01940 
01941 /*!
01942  * @brief Report number of object instance fields are in a class file.
01943  *
01944  *
01945  * @param    pcfs       Pointer to ClassFile area
01946  *
01947  *
01948  * @returns  number of fields @e not marked ACC_STATIC.
01949  *
01950  */
01951 u2 class_get_num_object_instance_fields(ClassFile *pcfs)
01952 {
01953     jvm_field_index fldidx;
01954     u2 rc = 0;
01955 
01956     for (fldidx = 0; fldidx < pcfs->fields_count; fldidx++)
01957     {
01958         if (!(ACC_STATIC & pcfs->fields[fldidx]->access_flags))
01959         {
01960             rc++;
01961         }
01962     }
01963 
01964     return(rc);
01965 
01966 } /* END of class_get_num_object_instance_fields() */
01967 
01968 
01969 /*!
01970  * @brief Load the field lookup table for object instance fields in
01971  * this class
01972  *
01973  *
01974  * @param  pcfs           Pointer to ClassFile area
01975  * 
01976  *
01977  * @returns  array of field indices in ClassFile @b fields table
01978  *           for all object instance fields in this class or
01979  *           @link #rnull rnull@endlink if no values to initialize
01980  *           or heap allocation error.  The size of the array is
01981  *           determined by the result of
01982  *           class_get_num_object_instance_fields().
01983  *
01984  */
01985 jvm_field_index
01986     *class_get_object_instance_field_lookups(ClassFile *pcfs)
01987 {
01988     u2 num_instance_fields = class_get_num_object_instance_fields(pcfs);
01989 
01990     /* Done if no object instance fields to initialize */
01991     if (0 == num_instance_fields)
01992     {
01993         return((u2 *) rnull);
01994     }
01995 
01996     u2 fldidx;
01997     u2 fluidx = 0;
01998     jvm_field_index *rc =
01999         HEAP_GET_DATA(sizeof(jvm_field_index) * num_instance_fields,
02000                       rfalse);
02001 
02002     for (fldidx = 0; fldidx < pcfs->fields_count; fldidx++)
02003     {
02004         if (!(ACC_STATIC & pcfs->fields[fldidx]->access_flags))
02005         {
02006             rc[fluidx++] = fldidx;
02007         }
02008     }
02009 
02010     return(rc);
02011 
02012 } /* END of class_get_object_instance_field_lookups() */
02013 
02014 
02015 /*!
02016  * @brief Load the field data table for object instance fields in
02017  * this class.
02018  *
02019  * This initialization is the same for all objects of this class,
02020  * so this function is still naturally a part of class processing
02021  * instead of object processing.
02022  *
02023  *
02024  * @param   clsidx        Class table index of slot having class loaded
02025  *
02026  * @param   objhash       Object hash of object slot being loaded.
02027  *                        This is supplied @e expressly to mark
02028  *                        reference types (that is, CONSTANT_String)
02029  *                        during field loading from the class file,
02030  *                        otherwise not needed.
02031  *
02032  * @param   pcfs          Pointer to ClassFile area
02033  * 
02034  *
02035  * @returns   array of data values corresponding to each field index
02036  *           as returned from class_get_static_field_lookups() or
02037  *           @link #rnull rnull@endlink if no values to initialize
02038  *           or heap allocation error.  The size of the array is
02039  *           determined by the result of
02040  *           class_get_num_object_instance_fields().
02041  */
02042 jvalue *class_get_object_instance_field_data(jvm_class_index  clsidx,
02043                                              jvm_object_hash  objhash,
02044                                              ClassFile       *pcfs)
02045 {
02046     u2 num_object_instance_fields =
02047         class_get_num_object_instance_fields(pcfs);
02048 
02049     /* Done if no object instance fields to initialize */
02050     if (0 == num_object_instance_fields)
02051     {
02052         return((jvalue *) rnull);
02053     }
02054 
02055     u2 fldidx;
02056     u2 fluidx = 0;
02057 
02058     /*
02059      * Allocate heap are for data table, SET ALL VALUES TO ZERO.
02060      * This will accomplish the intention of clearing all primative
02061      * data types.
02062      */
02063     jvalue *rc =
02064        HEAP_GET_DATA(sizeof(jvalue) * num_object_instance_fields,rtrue);
02065 
02066     for (fldidx = 0; fldidx < pcfs->fields_count; fldidx++)
02067     {
02068         if (!(ACC_STATIC & pcfs->fields[fldidx]->access_flags))
02069         {
02070             class_get_constant_field_attribute(clsidx,
02071                                                pcfs,
02072                                                fldidx,
02073                                                rc,
02074                                                fluidx,
02075                                                rfalse,
02076                                                objhash);
02077             fluidx++;
02078         }
02079     }
02080 
02081     return(rc);
02082 
02083 } /* END of class_get_object_instance_field_data() */
02084 
02085 
02086 /*!
02087  * @brief Shut down the class area of the JVM model after JVM execution
02088  * in two stages.
02089  *
02090  *  In between these two stages will be object_shutdown()
02091  * which performs related reference cleanup from the object side:
02092  *
02093  *   Stage 1-- remove class object references and class array
02094  *             references.
02095  *
02096  *   object_shutdown()-- remove @e class references from @e objects
02097  *                       here.
02098  *
02099  *   Stage 2-- all remaining cleanup.  Notice that references are
02100  *             removed here @e also except during this shutdown process.
02101  *
02102  *
02103  * @b Parameters: @link #rvoid rvoid@endlink
02104  *
02105  *
02106  *       @returns @link #rvoid rvoid@endlink
02107  *
02108  */
02109 rvoid class_shutdown_1()
02110 {
02111     jvm_class_index clsidx;
02112 
02113     for (clsidx = jvm_class_index_null;
02114          clsidx < JVMCFG_MAX_CLASSES;
02115          clsidx++)
02116     {
02117         if (CLASS(clsidx).status & CLASS_STATUS_INUSE)
02118         {
02119             if (!(CLASS(clsidx).status & CLASS_STATUS_NULL))
02120             {
02121                 (rvoid) GC_CLASS_RMREF_FROM_CLASS(
02122                             clsidx,
02123                             CLASS(clsidx).lower_dim_array);
02124 
02125                 (rvoid) GC_OBJECT_RMREF_FROM_CLASS(
02126                             clsidx,
02127                             CLASS(clsidx).class_objhash);
02128 
02129                 (rvoid) GC_CLASS_RMREF_FROM_CLASS(
02130                             clsidx,
02131                             CLASS(clsidx).initiating_ClassLoader);
02132 
02133                 (rvoid) GC_CLASS_RMREF_FROM_CLASS(
02134                             clsidx,
02135                             CLASS(clsidx).defining_ClassLoader);
02136             }
02137 
02138             (rvoid) GC_CLASS_RMREF_FROM_CLASS(jvm_class_index_null,
02139                                               clsidx);
02140         }
02141     }
02142 
02143     /* This may result in a @e large garbage collection */
02144     GC_RUN(rfalse);
02145 
02146     return;
02147 
02148 } /* END of class_shutdown_1() */
02149 
02150 
02151 rvoid class_shutdown_2()
02152 {
02153     jvm_class_index clsidx;
02154 
02155     for (clsidx = jvm_class_index_null;
02156          clsidx < JVMCFG_MAX_CLASSES;
02157          clsidx++)
02158     {
02159         if (CLASS(clsidx).status & CLASS_STATUS_INUSE)
02160         {
02161             (rvoid) class_static_delete(clsidx, rfalse);
02162         }
02163     }
02164 
02165     /* Declare this module uninitialized */
02166     jvm_class_initialized = rfalse;
02167 
02168     /* This may result in a @e large garbage collection */
02169     GC_RUN(rfalse);
02170 
02171     return;
02172 
02173 } /* END of class_shutdown_2() */
02174 
02175 
02176 /* EOF */
02177 

Generated on Fri Sep 30 18:48:59 2005 by  doxygen 1.4.4