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

object.c

Go to the documentation of this file.
00001 /*!
00002  * @file object.c
00003  *
00004  * @brief Create and manage real machine Java object data structures.
00005  *
00006  * An object reference is a simple (@b jobject ), an integer index
00007  * into the object table.
00008  *
00009  *
00010  * @section Control
00011  *
00012  * \$URL: https://svn.apache.org/path/name/object.c $ \$Id: object.c 0 09/28/2005 dlydick $
00013  *
00014  * Copyright 2005 The Apache Software Foundation
00015  * or its licensors, as applicable.
00016  *
00017  * Licensed under the Apache License, Version 2.0 ("the License");
00018  * you may not use this file except in compliance with the License.
00019  * You may obtain a copy of the License at
00020  *
00021  *     http://www.apache.org/licenses/LICENSE-2.0
00022  *
00023  * Unless required by applicable law or agreed to in writing,
00024  * software distributed under the License is distributed on an
00025  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
00026  * either express or implied.
00027  *
00028  * See the License for the specific language governing permissions
00029  * and limitations under the License.
00030  *
00031  * @version \$LastChangedRevision: 0 $
00032  *
00033  * @date \$LastChangedDate: 09/28/2005 $
00034  *
00035  * @author \$LastChangedBy: dlydick $
00036  *         Original code contributed by Daniel Lydick on 09/28/2005.
00037  *
00038  * @section Reference
00039  *
00040  */
00041 
00042 #include "arch.h"
00043 ARCH_COPYRIGHT_APACHE(object, c, "$URL: https://svn.apache.org/path/name/object.c $ $Id: object.c 0 09/28/2005 dlydick $");
00044 
00045 
00046 #include "jvmcfg.h"
00047 #include "cfmacros.h"
00048 #include "classfile.h"
00049 #include "exit.h"
00050 #include "gc.h" 
00051 #include "jvm.h"
00052 #include "jvmclass.h"
00053 #include "linkage.h" 
00054 #include "method.h"
00055 #include "native.h"
00056 #include "opcode.h"
00057 #include "utf.h"
00058 #include "util.h"
00059 
00060 
00061 /*!
00062  * @brief Initialize the object area of the JVM model
00063  *
00064  *
00065  * @b Parameters: @link #rvoid rvoid@endlink
00066  *
00067  *
00068  *       @returns @link #rvoid rvoid@endlink
00069  *
00070  */
00071 rvoid object_init()
00072 {
00073     object_new_setup(jvm_object_hash_null);
00074 
00075     pjvm->object_allocate_last = jvm_object_hash_null;
00076 
00077     /* Declare this module initialized */
00078     jvm_object_initialized = rtrue;
00079 
00080     return;
00081 
00082 } /* END of object_init() */
00083 
00084 
00085 /*!
00086  * @brief Invoke a method on a thread for any class, either
00087  * static or instance method, either native or virtual.
00088  *
00089  * Similar logic may be found in opcode_run() in its uncaught
00090  * exception handler concerning initiating execution of a JVM method.
00091  *
00092  *
00093  * @param  clsidx   Class table index of method to invoke.
00094  *
00095  * @param  mthname  Null-terminated name of method to invoke.
00096  *
00097  * @param  mthdesc  Null-terminated description of method parameters
00098  *                    and return types.
00099  *
00100  * @param  thridx   Thread table index of thread to load and run it on.
00101  *
00102  *
00103  * @returns @link #rvoid rvoid@endlink
00104  *
00105  *
00106  * @throws JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR
00107  *         @link #JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR
00108  *         if the requested method is not found in the class
00109  *         or has no code attribute.@endlink.
00110  *
00111  * @throws JVMCLASS_JAVA_LANG_INTERNALERROR
00112  *         @link #JVMCLASS_JAVA_LANG_INTERNALERROR
00113  *         if null thread index@endlink.
00114  *
00115  */
00116 rvoid object_run_method(jvm_class_index   clsidx,
00117                         rchar            *mthname,
00118                         rchar            *mthdesc,
00119                         jvm_thread_index  thridx)
00120 {
00121     /* Must specify a valid thread */
00122     if (jvm_thread_index_null == thridx)
00123     {
00124         exit_throw_exception(EXIT_JVM_THREAD,
00125                              JVMCLASS_JAVA_LANG_INTERNALERROR);
00126 /*NOTREACHED*/
00127     }
00128 
00129     /* No error will thrown here, it is handled below */
00130     jvm_method_index mthidx =
00131         method_find_by_prchar(clsidx, mthname, mthdesc);
00132 
00133     if (jvm_method_index_bad == mthidx)
00134     {
00135         exit_throw_exception(EXIT_JVM_METHOD,
00136                              JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR);
00137 /*NOTREACHED*/
00138     }
00139 
00140     /*
00141      * Set FP lower boundary so Java @c @b return
00142      * instruction does not keep going after handler,
00143      * chk if @c @b <init> is there, and run it.
00144      */
00145     jvm_sp fp_save_end_program = THREAD(thridx).fp_end_program;
00146 
00147     /* Make JVM execution stop once method has finished running */
00148     THREAD(thridx).fp_end_program = THREAD(thridx).fp;
00149 
00150     /* Load up entry point for method */
00151     ClassFile *pcfs = CLASS_OBJECT_LINKAGE(clsidx)->pcfs;
00152 
00153     jvm_attribute_index codeatridx =
00154         pcfs->methods[mthidx]->LOCAL_method_binding.codeatridxJVM;
00155 
00156     /*
00157      * In reality, should have both or neither mthidx/codeatridx
00158      * in a valid and properly linked class file.
00159      */
00160     if (jvm_attribute_index_bad == codeatridx)
00161     {
00162         exit_throw_exception(EXIT_JVM_ATTRIBUTE,
00163                              JVMCLASS_JAVA_LANG_NOSUCHMETHODERROR);
00164 /*NOTREACHED*/
00165     }
00166 
00167     if (jvm_attribute_index_native == codeatridx)
00168     {
00169         /* Pass parameters for both local method and JNI call */
00170         native_run_method(thridx,
00171                           pcfs
00172                             ->methods[mthidx]
00173                               ->LOCAL_method_binding.nmordJVM,
00174                           clsidx,
00175                           pcfs->methods[mthidx]->name_index,
00176                           pcfs->methods[mthidx]->descriptor_index);
00177     }
00178     else
00179     {
00180 
00181         Code_attribute *pca =
00182             (Code_attribute *)
00183             &pcfs->methods[mthidx]->attributes[codeatridx];
00184 
00185         PUSH_FRAME(thridx, pca->max_locals);
00186         PUT_PC_IMMEDIATE(thridx,
00187                          clsidx,
00188                          mthidx,
00189                          pcfs->methods[mthidx]
00190                                  ->LOCAL_method_binding.codeatridxJVM,
00191                          pcfs->methods[mthidx]
00192                                  ->LOCAL_method_binding.excpatridxJVM,
00193                          CODE_CONSTRAINT_START_PC);
00194 
00195         /*
00196          * WARNING:  RECURSIVE CALL!!! But should @e only go one
00197          *           level deep per throwable condition, which
00198          *           may or may not have iterative behavior, but
00199          *           will not likely recurse infinitely.
00200          */
00201         if (rfalse == opcode_run(thridx, rfalse))
00202         {
00203             /* Problem running error class, so quit */
00204             sysErrMsg("opcode_load_run_throwable",
00205                       "Cannot run method %s%s",
00206                       mthname,
00207                       mthdesc);
00208 
00209             jvmutil_print_stack(thridx, (rchar *) rnull);
00210 
00211             exit_jvm(EXIT_JVM_THREAD);
00212 /*NOTREACHED*/
00213         }
00214 
00215         /*
00216          * Permit java.lang.Exception * and java.lang.Throwable
00217          * to continue by restoring lower FP boundary.
00218          */
00219         THREAD(thridx).fp_end_program = fp_save_end_program;
00220     }
00221 
00222     return;
00223 
00224 } /* END of object_run_method() */
00225 
00226 
00227 /*!
00228  * @brief Set up an empty object in a given object table slot.
00229  *
00230  * The @b objhash of JVMCFG_NULL_OBJECT has special
00231  * properties in that it can ALWAYS be allocated and
00232  * is NEVER garbage collected!  Part of the purpose
00233  * for this is the JVMCFG_NULL_OBJECT is of value zero,
00234  * which is widely used throughout the code as a special
00235  * value.  This this slot is not available for @e anything
00236  * else.
00237  * 
00238  *
00239  * @param  objhash   Object table hash of slot to set up.
00240  *
00241  *
00242  * @returns @link #rvoid rvoid@endlink
00243  *
00244  */
00245 rvoid object_new_setup(jvm_object_hash objhash)
00246 {
00247     /*
00248      * Declare slot in use, but not initialized.
00249      * (Redundant for most situations where
00250      * object_allocate_slot() was called, but needed
00251      * for initializing classes like JVMCFG_NULL_OBJECT
00252      * with an absolute slot number that was not
00253      * searched for by the allocator.)
00254      */
00255     OBJECT(objhash).status = OBJECT_STATUS_INUSE | OBJECT_STATUS_NULL;
00256 
00257     /*
00258      * Start out with no array allocation and no array dimensions
00259      */
00260     OBJECT(objhash).arraybasetype = LOCAL_BASETYPE_ERROR;
00261     OBJECT(objhash).arraydims     = LOCAL_CONSTANT_NO_ARRAY_DIMS;
00262     OBJECT(objhash).arraylength   = (jint *) rnull;
00263     OBJECT(objhash).arraydata     = (rvoid *) rnull;
00264 
00265     /* No object monitor is locked */
00266     OBJECT(objhash).mlock_count   = 0;
00267     OBJECT(objhash).mlock_thridx  = jvm_thread_index_null;
00268 
00269     /* No superclass */
00270     OBJECT(objhash).objhash_superclass = jvm_object_hash_null;
00271 
00272     /* No access flag context */
00273     OBJECT(objhash).access_flags = LOCAL_ACC_EMPTY;
00274 
00275     /* No class or class file or thread linkage */
00276     OBJECT_OBJECT_LINKAGE(objhash)->pcfs   = (ClassFile *) rnull;
00277     OBJECT_OBJECT_LINKAGE(objhash)->clsidx = jvm_class_index_null;
00278     OBJECT_OBJECT_LINKAGE(objhash)->thridx = jvm_thread_index_null;
00279 
00280     /* No object instance fields */
00281     OBJECT(objhash).object_instance_field_data = (jvalue *) rnull;
00282 
00283     /*
00284      * Garbage collection @e initialization is performed by
00285      * @link #GC_OBJECT_NEW GC_OBJECT_NEW()@endlink.
00286      *
00287      * Garbage collection @e finalization is performed by
00288      * @link #GC_OBJECT_DELETE GC_OBJECT_DELETE()@endlink.
00289      */
00290     OBJECT(objhash).pgarbage = (rvoid *) rnull;
00291 
00292     /*
00293      * Do not set up GC_OBJECT_NEW() unless there is
00294      * a real object with the possibility of real fields.
00295      */
00296 
00297     return;
00298 
00299 } /* END of object_new_setup() */
00300 
00301 
00302 /*!
00303  * @brief Locate and reserve  an unused object table slot for
00304  * a new object instance.
00305  *
00306  *
00307  * @param  tryagain   If @link #rtrue rtrue@endlink, run garbage
00308  *                    collection @e once if no empty slots are
00309  *                    available so as to try and free up something.
00310  *                    Typically, invoke as @link #rtrue rtrue@endlink,
00311  *                    and let recursion call it with
00312  *                    @link #rfalse rfalse@endlink.
00313  *
00314  *
00315  * @returns Object hash of an empty slot.  Throw error if no slots.
00316  *
00317  *
00318  * @throws JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00319  *         @link #JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00320  *         if no object slots are available.@endlink.
00321  *
00322  */
00323 static jvm_object_hash object_allocate_slot(rboolean tryagain)
00324 {
00325     /* Search for a free object table slot */
00326     jvm_object_hash objhash =
00327         (JVMCFG_MAX_OBJECTS == pjvm->object_allocate_last)
00328         ? JVMCFG_FIRST_OBJECT
00329         : 1 + pjvm->object_allocate_last;
00330 
00331     /* Count allocated slots in all slots are full */
00332     jvm_object_hash count = 0;
00333 
00334     while(rtrue)
00335     {
00336         if (OBJECT(objhash).status & OBJECT_STATUS_INUSE)
00337         {
00338             /* Point to next slot, wrap around at end */
00339             objhash++;
00340 
00341             if (objhash == JVMCFG_MAX_OBJECTS - 1)
00342             {
00343                 objhash = JVMCFG_FIRST_OBJECT;
00344             }
00345 
00346             /* Limit high value to end of table */
00347             if (pjvm->object_allocate_last == JVMCFG_MAX_OBJECTS - 1)
00348             {
00349                 pjvm->object_allocate_last = JVMCFG_FIRST_OBJECT - 1;
00350             }
00351 
00352 
00353             /* Count this attempt and keep looking */
00354             count++;
00355 
00356             if (count ==  (JVMCFG_MAX_OBJECTS - JVMCFG_FIRST_OBJECT))
00357             {
00358                 /* Try again (with rfalse) if requested */
00359                 if (rtrue == tryagain)
00360                 {
00361                     GC_RUN(rtrue);  /* Try to free up some space */
00362 
00363                     /* Now try to locate a free slot */
00364 
00365                     /* WARNING!!! Recursive call-- but only 1 deep */
00366                     return(object_allocate_slot(rfalse));
00367                 }
00368 
00369                 /* No more slots, cannot continue */
00370                 exit_throw_exception(EXIT_JVM_OBJECT,
00371                                    JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR);
00372 /*NOTREACHED*/
00373             }
00374         }
00375 
00376 
00377         /* Declare slot in use, but not initialized. */
00378         OBJECT(objhash).status =
00379                                OBJECT_STATUS_INUSE | OBJECT_STATUS_NULL;
00380 
00381         /* Report where this allocation was performed */
00382         pjvm->object_allocate_last = objhash;
00383 
00384         return(objhash);
00385     }
00386 /*NOTREACHED*/
00387     return(jvm_object_hash_null); /* Satisfy compiler */
00388 
00389 } /* END of object_allocate_slot() */
00390 
00391 
00392 /*!
00393  * @brief Create a Java @c @b new object instance of a class and
00394  * optionally run its @c @b <init> method with default
00395  * parameters (none).
00396  *
00397  * The following four mutually exclusive variations are available using
00398  * @b special_obj modifier:
00399  *
00400  * <ul>
00401  * <li><b>OBJECT_STATUS_EMPTY</b>: Normal object, no special treatment.
00402  * </li>
00403  *
00404  * <li><b>OBJECT_STATUS_THREAD</b>: Treat the object instance creation
00405  *                                  as a normal object, but mark it as a
00406  *                                  @c @b java.lang.Thread .
00407  * </li>
00408  *
00409  * <li><b>OBJECT_STATUS_CLASS</b>:  Treat the object instance creation
00410  *                                  as loading a class instead of
00411  *                                  instantiating an object and use
00412  *                                  @b clsidx as the class table slot
00413  *                                  value that defines the class.
00414  * </li>
00415  *
00416  * <li><b>OBJECT_STATUS_ARRAY</b>:  Treat the object instance creation
00417  *                                  as a dimension of an array class
00418  *                                  instead of instantiating an object
00419  *                                  of the requested class.
00420  * </li>
00421  *
00422  * Plus a fifth for internal use in this function only:
00423  *
00424  * <li><b>OBJECT_STATUS_SUBARRAY</b>: used internally to flag that this
00425  *                                    object is a subset of a larger
00426  *                                    array.  <em>DO NOT USE this
00427  *                                    modifier!</em>
00428  * </li>
00429  * </ul>
00430  *
00431  * No verification of @b special_obj is performed, only these values
00432  * are assumed.
00433  *
00434  * All fields (or array components) are set to zeroes per JVM spec.
00435  *
00436  * Notice that standard practice is to do
00437  * <b><code>new ArrayType[][][]</code></b> and initialize one
00438  * dimension at a time.  This function can certainly operate
00439  * in this way, simply set @link robject#arraydims arraydims@endlink
00440  * to 1.  But it @e can initialize a multi-dimensional array all at
00441  * once.
00442  *
00443  * Use a simple circular slot allocation mechanism to report where
00444  * most recent object was allocated.  The search for the next slot
00445  * will begin from here and go all the way around the array to this
00446  * same slot.  If not successful, return a
00447  * @link #jvm_object_hash_null jvm_object_hash_null@endlink, else
00448  * the object hash value of the slot.
00449  *
00450  * Even though this function makes types of two recursive calls to
00451  * itself, there is very little local storage allocated on the stack,
00452  * and that is mainly fragmented into the if() blocks where such
00453  * storage is used.  Therefore, even though this function may recurse
00454  * for either (a) number of array dimensions, or (b) number of
00455  * superclasses, in depth, there should never be any real machine
00456  * stack overflow problems unless the stack is either, (a) unnaturally
00457  * restricted to a very small size or, (b) a class file is not checked
00458  * for CONSTANT_MAX_ARRAY_DIMS or, (c) test for superclass circularity
00459  * is not working properly or, (d) a class has zillions of legitimate
00460  * superclasses, such as could be created by an automated JVM
00461  * regression tester.
00462  *
00463  *
00464  * @param   special_obj Bit-mapped request for various special
00465  *                      considerations for object construction. If not
00466  *                      needed, use @link #OBJECT_STATUS_EMPTY
00467                         OBJECT_STATUS_EMPTY@endlink.
00468  *                      If used, the values are:
00469  *
00470  * <ul>
00471  * <li>         @link #OBJECT_STATUS_THREAD OBJECT_STATUS_THREAD@endlink
00472  *                                              This is a normal object,
00473  *                                              and it is an instance of
00474  *                                              @c @b java.lang.Thread .
00475  * </li>
00476  *
00477  * <li>         @link #OBJECT_STATUS_CLASS OBJECT_STATUS_CLASS@endlink
00478  *                                             create new class object
00479  *                                             instead of class instance
00480  * </li>
00481  *
00482  * <li>         @link #OBJECT_STATUS_ARRAY OBJECT_STATUS_ARRAY@endlink
00483  *                                              create new array object
00484  *                                              reference.
00485  * </li>
00486  *
00487  * <li>     @link #OBJECT_STATUS_SUBARRAY OBJECT_STATUS_SUBARRAY@endlink
00488  *                                              this array is a subset
00489  *                                              of a larger array
00490  *                                          (<em>internal use only</em>)
00491  * </li>
00492  * </ul>
00493  *
00494  * @param    pcfs       Pointer to ClassFile area.
00495  *
00496  * @param    clsidx     Class table index for class object linkage.
00497  *
00498  * @param    arraydims  If this is an instance of an array object,
00499  *                      specifies the number of array dimensions.
00500  *                      @e Always use LOCAL_CONSTANT_NO_ARRAY_DIMS for
00501  *                      non-arrays, that is, when OBJECT_STATUS_ARRAY
00502  *                      is not set.
00503  *
00504  * @param   arraylength Array of number of elements in @e each array
00505  *                      dimension. Only meaningful when
00506  *                      OBJECT_STATUS_ARRAY is set.  Okay to be zero
00507  *                      in the first dimension, meaning no data in the
00508  *                    object's @link robject#arraydata arraydata@endlink
00509  *                       member (@link #rnull rnull@endlink instead).
00510  *
00511  * @param   run_init_   When @link #rtrue rtrue@endlink, run the
00512  *                      object's @c @b <init> method with default
00513  *                      parameters, otherwise
00514  *                      @link #rfalse rfalse@endlink.
00515  *
00516  * @param   thridx      Thread table index associated with this
00517  *                      @c @b java.lang.Thread object.
00518  *                      Meaningful only when OBJECT_STATUS_THREAD is
00519  *                      set or when @b run_init_ is
00520  *                      @link #rtrue rtrue@endlink.
00521  *
00522  *
00523  * @returns  Object hash value of allocation.  Throw error if no slots.
00524  *
00525  *
00526  * @throws JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00527  *         @link #JVMCLASS_JAVA_LANG_OUTOFMEMORYERROR
00528  *         if no object slots are available@endlink.
00529  *
00530  * @throws JVMCLASS_JAVA_LANG_UNSUPPORTEDCLASSVERSIONERROR
00531  *         @link #JVMCLASS_JAVA_LANG_UNSUPPORTEDCLASSVERSIONERROR
00532  *         if there is an unrecognized array base type@endlink.
00533  *
00534  */
00535 
00536 jvm_object_hash object_instance_new(rushort          special_obj,
00537                                     ClassFile       *pcfs,
00538                                     jvm_class_index  clsidx,
00539                                     jvm_array_dim    arraydims,
00540                                     jint            *arraylength,
00541                                     rboolean         run_init_,
00542                                     jvm_thread_index thridx)
00543 {
00544     /* Locate an empty slot */
00545     jvm_object_hash objhash = object_allocate_slot(rtrue);
00546 
00547     /* Initialize object structures */
00548     object_new_setup(objhash);
00549 
00550     /*
00551      * Store table linkages early for immediate use
00552      * (esp loading field data)
00553      */
00554     OBJECT(objhash).table_linkage.pcfs   = pcfs;
00555     OBJECT(objhash).table_linkage.clsidx = clsidx;
00556     OBJECT(objhash).table_linkage.thridx = jvm_thread_index_null;
00557 
00558     /*
00559      * Read values from *pcfs where possible
00560      * (need for loading field data soon)
00561      */
00562     OBJECT(objhash).access_flags = pcfs->access_flags;
00563 
00564     /* Check if class load instead of object instantiate */
00565     if (OBJECT_STATUS_CLASS & special_obj)
00566     {
00567         /*
00568          * Mark slot as being a class, not an object.
00569          * (See comments on recursion below as to
00570          * disposition of superclass definition.)
00571          */
00572         OBJECT(objhash).status |= OBJECT_STATUS_CLASS;
00573     }
00574     else
00575     if (OBJECT_STATUS_ARRAY & special_obj)
00576     {
00577         /*
00578          * Since pcfs points to non-array version of class, use it
00579          * to extract the formatted class string, including the
00580          * base type.  Everything will be BASETYPE_CHAR_L except
00581          * for the java.lang.Class primative pseudo-classes, which
00582          * will contain other types.  The base type of the array
00583          * ultimately governs the structure of the last array
00584          * dimension, where the actual data is stored.
00585          */
00586         CONSTANT_Utf8_info *pclsname = PTR_CP1_CLASS_NAME(pcfs,
00587                                                       pcfs->this_class);
00588 
00589         OBJECT(objhash).arraydims = arraydims;
00590 
00591         if (CLASS(clsidx).status & CLASS_STATUS_PRIMATIVE)
00592         {
00593             OBJECT(objhash).arraybasetype = (jvm_basetype)
00594                        pclsname->bytes[utf_get_utf_arraydims(pclsname)];
00595         }
00596         else
00597         {
00598             OBJECT(objhash).arraybasetype = BASETYPE_CHAR_L;
00599         }
00600 
00601         OBJECT(objhash).arraylength   = arraylength;
00602 
00603         /* Set ARRAY status if applicable, also SUBARRAY */
00604         OBJECT(objhash).status |=
00605            special_obj & (OBJECT_STATUS_ARRAY | OBJECT_STATUS_SUBARRAY);
00606 
00607 
00608         /* Recursively build array object with 1 less array dimension */
00609 
00610         /* Allocate this current array dimension--arraylength[0] */
00611         if (1 < arraydims)
00612         {
00613             /*
00614              * @c @b arraylength[0] may be zero,
00615              * meaning no data
00616              */
00617 
00618             OBJECT(objhash).arraydata =
00619                 (0 > arraylength[0])
00620 
00621                 ? HEAP_GET_DATA(
00622                       arraylength[0] * sizeof(jvm_object_hash),
00623                       rtrue)
00624 
00625                 /*! @todo  case needs testing: 0 == arraylength[0] */
00626                 : (rvoid *) rnull;
00627         }
00628         else
00629         {
00630             /*
00631              * Notice OBJECT(objhash).status does NOT have
00632              * OBJECT_STATUS_ARRAY set once the final array component
00633              * is to be constructed.  It is @e only for the data
00634              * superstructures of these components.
00635              *
00636              * Now look up base type, less BASETYPE_CHAR_ARRAY,
00637              * which is already accounted for.
00638              */
00639             int unit;
00640             switch(OBJECT(objhash).arraybasetype)
00641             {
00642                 case BASETYPE_CHAR_B:  unit = sizeof(jbyte);    break;
00643                 case BASETYPE_CHAR_C:  unit = sizeof(jchar);    break;
00644                 case BASETYPE_CHAR_D:  unit = sizeof(jdouble);  break;
00645                 case BASETYPE_CHAR_F:  unit = sizeof(jfloat);   break;
00646                 case BASETYPE_CHAR_I:  unit = sizeof(jint);     break;
00647                 case BASETYPE_CHAR_J:  unit = sizeof(jlong);    break;
00648                 case BASETYPE_CHAR_L:  unit = sizeof(jvm_object_hash);
00649                                                                 break;
00650                 case BASETYPE_CHAR_S:  unit = sizeof(jshort); break;
00651                 case BASETYPE_CHAR_Z:  unit = sizeof(jboolean); break;
00652 
00653                 default:
00654                     exit_throw_exception(EXIT_JVM_OBJECT,
00655                        JVMCLASS_JAVA_LANG_UNSUPPORTEDCLASSVERSIONERROR);
00656             }
00657 
00658             /* Allocate and zero out each component of 1-dim array */
00659             if (0 < arraylength[0])
00660             {
00661                 OBJECT(objhash).arraydata =
00662                     HEAP_GET_DATA(unit * arraylength[0], rtrue);
00663             }
00664             else
00665             {
00666                 OBJECT(objhash).arraydata = (rvoid *) rnull;
00667             }
00668         }
00669 
00670         if (1 < arraydims)
00671         {
00672             jint dimlength;
00673 
00674             /* Notice if 0 == arraylength[0], this loop is skipped */
00675             for (dimlength = 0; dimlength < arraylength[0]; dimlength++)
00676             {
00677                 /*
00678                  * Go allocate each element of this dimension of array,
00679                  * namely, the sub-array of arraylength[1]...
00680                  * ONLY set SUBARRAY status from this recursive call.
00681                  * Its purpose is for deallocation and cleanup.
00682                  */
00683 
00684                 /* WARNING!  Recursive call, @b arraydims levels deep */
00685                 jvm_object_hash objhasharray =
00686                     object_instance_new(
00687                         OBJECT_STATUS_ARRAY | OBJECT_STATUS_SUBARRAY,
00688                         pcfs,
00689                         clsidx,
00690                         arraydims - 1,
00691                         &arraylength[1],
00692                         run_init_,
00693                         thridx);
00694 
00695                 /*
00696                  * Add this object to this dimension's array and
00697                  * mark it as having one reference to it.
00698                  */
00699                 ((jvm_object_hash *)
00700                  OBJECT(objhasharray)
00701                    .arraydata)[dimlength] = objhasharray;
00702 
00703                 (rvoid) GC_OBJECT_MKREF_FROM_CLASS(clsidx,
00704                                                    objhasharray);
00705             }
00706         }
00707         else
00708         {
00709             /*
00710              * Nothing further needs to be done for 1-dim array
00711              * since all components were cleared upon allocation.
00712              */
00713         }
00714 
00715     } /* if OBJECT_STATUS_ARRAY */
00716     else
00717     {
00718         if (OBJECT_STATUS_THREAD & special_obj)
00719         {
00720             /*
00721              * Mark slot as being a @c @b java.lang.Thread,
00722              * which is simply a status bit set on a normal object.
00723              */
00724             OBJECT(objhash).status |= OBJECT_STATUS_THREAD;
00725             OBJECT(objhash).table_linkage.thridx = thridx;
00726         }
00727 
00728         /* Initialize object instance fields, read initialized fields */
00729         OBJECT(objhash).object_instance_field_data =
00730             class_get_object_instance_field_data(clsidx,
00731                                                  objhash,
00732                                                  pcfs);
00733     }
00734 
00735     /*
00736      * After allocating slot, instantiate superclass first,
00737      * then load up remainder of this object.
00738      */
00739     if (CONSTANT_CP_DEFAULT_INDEX != pcfs->super_class)
00740     {
00741         /*
00742          * WARNING!  RECURSIVE CALL!  This will recurse until
00743          * the superclass of this object is
00744          * @c @b java/Lang/Object.
00745          * The recursion for class definitions is performed
00746          * by the calling method, so class loading does not
00747          * need recursion.
00748          */
00749         rchar *supername =
00750             utf_utf2prchar_classname(PTR_CP1_CLASS_NAME(pcfs,
00751                                                     pcfs->super_class));
00752 
00753         jvm_class_index clsidxsuper = class_find_by_prchar(supername);
00754 
00755         HEAP_FREE_DATA(supername);
00756 
00757         if (jvm_object_hash_null == clsidxsuper)
00758         {
00759             return(jvm_object_hash_null);
00760         }
00761 
00762         jvm_table_linkage *ptl = CLASS_OBJECT_LINKAGE(clsidxsuper);
00763 
00764         /*
00765          * @warning  Recursive call, <b># of superclasses</b>
00766          *           levels deep.
00767          */
00768         OBJECT(objhash).objhash_superclass =
00769             object_instance_new(
00770                 (0 == utf_prchar_classname_strcmp(
00771                           JVMCLASS_JAVA_LANG_THREAD,
00772                           ptl->pcfs,
00773                           ptl->pcfs->this_class))
00774                     ? OBJECT_STATUS_THREAD
00775                     : OBJECT_STATUS_EMPTY,
00776                 ptl->pcfs,
00777                 clsidxsuper,
00778                 LOCAL_CONSTANT_NO_ARRAY_DIMS,
00779                 (jint *) rnull,
00780                 run_init_,
00781                 thridx);
00782 
00783         (rvoid) GC_OBJECT_MKREF_FROM_OBJECT(
00784                     objhash,
00785                     OBJECT(objhash).objhash_superclass);
00786     }
00787 
00788     (rvoid) GC_CLASS_MKREF_FROM_OBJECT(
00789                 objhash,
00790                 OBJECT(objhash).table_linkage.clsidx);
00791 
00792     /* Start GC tracking for object */
00793     (rvoid) GC_OBJECT_NEW(objhash);
00794 
00795     /* Declare that object is initialized */
00796     OBJECT(objhash).status &= ~OBJECT_STATUS_NULL;
00797 
00798     /* Done if not running @c @b <init> method */
00799     if (rfalse == run_init_)
00800     {
00801         return(objhash);
00802     }
00803 
00804     object_run_method(clsidx,
00805                       CONSTANT_UTF8_INSTANCE_CONSTRUCTOR,
00806                   CONSTANT_UTF8_INSTANCE_CONSTRUCTOR_DESCRIPTOR_DEFAULT,
00807                       thridx);
00808 
00809     /*
00810      * Declare this object instance as being referenced,
00811      * but not here.  The calling function must perform
00812      * this task.
00813      */
00814     /* (rvoid) GC_OBJECT_MKREF(objhash); */
00815 
00816 
00817     /* Done running @c @b <init> method, so quit */
00818     return(objhash);
00819 
00820 } /* END of object_instance_new() */
00821 
00822 
00823 /*!
00824  * @brief Finalize an object instance before deletion.
00825  *
00826  * This invokes an object's finalize() method, if declared,
00827  * on the specified thread, or on the system thread if
00828  * @link #jvm_thread_index_null jvm_thread_index_null@endlink
00829  * thread given.
00830  *
00831  *
00832  * @param  objhash   Object hash of object to finalize.
00833  *
00834  * @param  thridx    Thread table index of thread to run finalize() on.
00835  *
00836  *
00837  * @returns @link #rvoid rvoid@endlink
00838  *
00839  */
00840 rvoid object_instance_finalize(jvm_object_hash objhash,
00841                                jvm_thread_index thridx)
00842 {
00843     jvm_class_index clsidx = OBJECT_OBJECT_LINKAGE(objhash)->clsidx;
00844 
00845     jvm_method_index mthidx =
00846         method_find_by_prchar(clsidx,
00847                               JVMCFG_FINALIZE_OBJECT_METHOD,
00848                               JVMCFG_FINALIZE_OBJECT_PARMS);
00849 
00850     /* Done if no finalize() method to invoke */
00851     if (jvm_method_index_bad == mthidx)
00852     {
00853         return;
00854     }
00855 
00856     /*If null thread index,run on GC thread-- This is @e very unlikely*/
00857     if (jvm_thread_index_null == thridx)
00858     {
00859         thridx = JVMCFG_GC_THREAD;
00860     }
00861 
00862     object_run_method(clsidx,
00863                       JVMCFG_FINALIZE_OBJECT_METHOD,
00864                       JVMCFG_FINALIZE_OBJECT_PARMS,
00865                       thridx);
00866 
00867 } /* END of object_instance_finalize() */
00868 
00869 
00870 /*!
00871  * @brief Check whether or not a class file data area is used
00872  * by at least one other object besides this one.
00873  *
00874  * If a @link #jvm_table_linkage.pcfs jvm_table_linkage.pcfs@endlink
00875  *  pointer is @link #rnull rnull@endlink, that means that that object
00876  * has probably already run this function from object_instance_delete(),
00877  * having found that at least one other object was using this class
00878  * data.  After all other objects have cleared out that pointer,
00879  * there will only be one reference, and that is the one from this
00880  * object.  Upon return to object_instance_delete(), call
00881  * classfile_unload_classdata() and clear the pointer to
00882  * @link #rnull rnull@endlink, thus completing the unload process
00883  * for the class file data area and all its object slot pointers.
00884  *
00885  *
00886  * @param  objhash   Object hash of object to unload its class data
00887  *
00888  *
00889  * @returns  @link #rtrue rtrue@endlink if another object is using
00890  *           this class file, otherwise @link #rfalse rfalse@endlink.
00891  *
00892  */ 
00893 rboolean object_locate_pcfs(jvm_object_hash objhash)
00894 {
00895     jvm_object_hash objhashSCAN;
00896 
00897     ClassFile *pcfs = OBJECT_OBJECT_LINKAGE(objhash)->pcfs;
00898 
00899     /*
00900      * With @link #rnull rnull@endlink class file pointer, not only
00901      * is this class not using a class file (such as the
00902      * @link #jvm_class_index_null jvm_class_index_null@endlink class),
00903      * but it is not known if another class actually @e is using one
00904      * because there is nothing to compare against.  Therefore, cannot
00905      * unload a non-existent class and cannot free an
00906      * @link #rnull rnull@endlink pointer.
00907      */
00908     if (rnull == pcfs)
00909     {
00910         return(rtrue);
00911     }
00912 
00913     /* Scan object table for other classes using this class file */
00914     for (objhashSCAN = jvm_object_hash_null;
00915          objhashSCAN < JVMCFG_MAX_OBJECTS;
00916          objhashSCAN++)
00917     {
00918         /* Already know this one is in use due to calling sequence */
00919         if (objhash == objhashSCAN)
00920         {
00921             continue;
00922         }
00923 
00924         /* Skip empty slots */
00925         if (!(OBJECT(objhash).status & OBJECT_STATUS_INUSE))
00926         {
00927             continue;
00928         }
00929 
00930         /* Check if this object has already cleared it or not */
00931         ClassFile *pcfsSCAN = OBJECT_OBJECT_LINKAGE(objhashSCAN)->pcfs;
00932 
00933         if (rnull == pcfsSCAN)
00934         {
00935             continue;
00936         }
00937 
00938         /*
00939          * If not already cleared, check if this object uses the
00940          * same class file data area as requested object.
00941          */
00942         if (pcfs == pcfsSCAN)
00943         {
00944             return(rtrue);
00945         }
00946     }
00947 
00948     return(rfalse);
00949 
00950 } /* END of object_locate_pcfs() */
00951 
00952 /*!
00953  * @brief Un-reserve a slot from the object area.
00954  *
00955  * This is the reverse of the process of object_instance_new() above.
00956  * Only tear down the heap allocations and mark the slot as empty.
00957  * Leave the rest of the data in place for post-mortem.  When the slot
00958  * gets allocated again, any zeroing out of values will just get
00959  * overwritten again, so don't bother.
00960  *
00961  * The object_instance_finalize() function MUST be run before
00962  * calling this function!
00963  *
00964  *
00965  * @param    objhash  Object hash value of allocation.
00966  *
00967  * @param    rmref    @link #rtrue rtrue@endlink if @e object
00968  *                    references should be removed,
00969  *                    which is NOT SO during JVM shutdown.
00970  *                    Regardless of this value, @e class references
00971  *                    are always removed.
00972  *
00973  *
00974  * @returns  Same as input if slot was freed, else
00975  *           @link #jvm_object_hash_null jvm_object_hash_null@endlink.
00976  *
00977  */
00978 
00979 jvm_object_hash object_instance_delete(jvm_object_hash objhash,
00980                                        rboolean        rmref)
00981 {
00982 #if 0
00983     /*!
00984      * @todo  Should the @link #jvm_object_hash_null
00985               jvm_object_hash_null@endlink object be undeleteable?
00986      */
00987     if (jvm_object_hash_null == objhash)
00988     { 
00989         return(jvm_object_hash_null);
00990     }
00991 #endif
00992 
00993     if (OBJECT(objhash).status & OBJECT_STATUS_INUSE)
00994     {
00995         /*!
00996          * @todo  Is the java.lang.Object.finalize() method (or
00997          *        its subclass) invoked by the actual Java code
00998          *        when an object reference is removed?  Is this a
00999          *        GC function?  Where should this method be called
01000          *        when tearing down this object?
01001          */
01002 
01003         /* Deallocate slot, report to caller */
01004         if ((OBJECT_STATUS_ARRAY    & OBJECT(objhash).status) ||
01005             (OBJECT_STATUS_SUBARRAY & OBJECT(objhash).status))
01006         {
01007             if (1 == OBJECT(objhash).arraydims)
01008             {
01009                 /*
01010                  * 1-dimensional arrays store data directly
01011                  * in *arraydata, so just HEAP_FREE_DATA() for it.
01012                  */
01013             }
01014             else
01015             {
01016                 if (rtrue == rmref)
01017                 {
01018                     rint i;
01019                     for (i = 0; i < OBJECT(objhash).arraylength[0]; i++)
01020                     {
01021                         (rvoid) GC_OBJECT_RMREF_FROM_OBJECT(
01022                                     objhash,
01023                                     ((jvm_object_hash *)
01024                                      OBJECT(objhash).arraydata)[i]);
01025                     }
01026                 }
01027             }
01028         }
01029 
01030         /*
01031          * Only free the top-level arraylength[] specification; the
01032          * OBJECT_STATUS_SUBARRAY versions are pointers @e within this
01033          * complete version.
01034          */
01035         if ((OBJECT_STATUS_ARRAY    & OBJECT(objhash).status) ||
01036             (!(OBJECT_STATUS_SUBARRAY & OBJECT(objhash).status)))
01037         {
01038             if (rnull != OBJECT(objhash).arraylength)
01039             {
01040                 HEAP_FREE_DATA(OBJECT(objhash).arraylength);
01041                 /* OBJECT(objhash).arraylength   = (jint *) rnull; */
01042             }
01043         }
01044 
01045         if (rnull != OBJECT(objhash).arraydata)
01046         {
01047             HEAP_FREE_DATA(OBJECT(objhash).arraydata);
01048         }
01049         /* OBJECT(objhash).arraydata     =  (rvoid *) rnull; */
01050 
01051         /* OBJECT(objhash).mlock_count   = 0; */
01052         /* OBJECT(objhash).mlock_thridx  = jvm_thread_index_null; */
01053         if (jvm_object_hash_null != OBJECT(objhash).objhash_superclass)
01054         {
01055             if (rtrue == rmref)
01056             {
01057                 (rvoid) GC_OBJECT_RMREF_FROM_OBJECT(
01058                             objhash,
01059                             OBJECT(objhash).objhash_superclass);
01060             }
01061         }
01062         /* OBJECT(objhash).objhash_superclass = jvm_object_hash_null; */
01063         /* OBJECT(objhash).access_flags  = LOCAL_ACC_EMPTY; */
01064 
01065         (rvoid) GC_CLASS_RMREF_FROM_OBJECT(
01066                     objhash,
01067                     OBJECT(objhash).table_linkage.clsidx);
01068 
01069         /* Unload class file if no other references to it */
01070         if (rfalse == object_locate_pcfs(objhash))
01071         {
01072             classfile_unloadclassdata(OBJECT(objhash)
01073                                         .table_linkage.pcfs);
01074         }
01075 
01076         /* Disables @link jvm/src/linkage.h linkage.h@endlink
01077          * macros, specifically:
01078          *
01079          * CLASS_OBJECT_LINKAGE(),
01080          * OBJECT_CLASS_LINKAGE(),
01081          * THREAD_OBJECT_LINKAGE()
01082          * OBJECT_THREAD_LINKAGE()
01083          * OBJECT_OBJECT_LINKAGE()
01084          */
01085         /* OBJECT(objhash).table_linkage.pcfs   = (ClassFile *) rnull;*/
01086         /* OBJECT(objhash).table_linkage.clsidx =jvm_class_index_null;*/
01087         /* OBJECT(objhash).table_linkage.thridx=jvm_thread_index_null;*/
01088 
01089         if (rnull != OBJECT(objhash).object_instance_field_data)
01090         {
01091             /* Remove object instance field reference markings */
01092             u2 noifl = CLASS(OBJECT_OBJECT_LINKAGE(objhash)->clsidx)
01093                          .num_object_instance_field_lookups;
01094             jvm_field_lookup_index oiflidx;
01095             for (oiflidx = 0; oiflidx < noifl; oiflidx++)
01096             {
01097                 (rvoid) GC_OBJECT_FIELD_RMREF(objhash, oiflidx);
01098             }
01099 
01100             HEAP_FREE_DATA(OBJECT(objhash).object_instance_field_data);
01101         }
01102         /* OBJECT(objhash).object_instance_field_data =
01103                                                     (jvalue *) rnull; */
01104 
01105         /* Finalize garbage collection status of this object instance */
01106         (rvoid) GC_OBJECT_DELETE(objhash);
01107 
01108         /* OBJECT(objhash).status = OBJECT_STATUS_EMPTY; */
01109         OBJECT(objhash).status &= ~OBJECT_STATUS_INUSE;
01110 
01111         return(objhash);
01112     }
01113     else
01114     {
01115         /* Error-- slot was already free */
01116         return(jvm_object_hash_null);
01117     }
01118 
01119 } /* END of object_instance_delete() */
01120 
01121 
01122 /*!
01123  * @brief Shut down the object area of the JVM model after JVM execution
01124  *
01125  * See also comments on why there are two stages of class shutdown,
01126  * class_shutdown_1() and class_shutdown_2().
01127  *
01128  *
01129  * @b Parameters: @link #rvoid rvoid@endlink
01130  *
01131  *
01132  *       @returns @link #rvoid rvoid@endlink
01133  *
01134  */
01135 rvoid object_shutdown()
01136 {
01137     jvm_object_hash objhash;
01138 
01139     for (objhash = jvm_object_hash_null;
01140          objhash < JVMCFG_MAX_OBJECTS;
01141          objhash++)
01142     {
01143         if (OBJECT(objhash).status & OBJECT_STATUS_INUSE)
01144         {
01145             (rvoid) GC_CLASS_RMREF_FROM_OBJECT(
01146                         OBJECT_OBJECT_LINKAGE(objhash)->clsidx,
01147                         objhash);
01148 
01149             (rvoid) GC_OBJECT_RMREF_FROM_OBJECT(
01150                         objhash,
01151                         OBJECT(objhash).objhash_superclass);
01152 
01153             (rvoid) GC_OBJECT_RMREF_FROM_OBJECT(jvm_object_hash_null,
01154                                                 objhash);
01155         }
01156     }
01157 
01158     /* This may result in a @e large garbage collection */
01159     GC_RUN(rfalse);
01160 
01161     /* Go clear out any remaining objects */
01162     for (objhash = jvm_object_hash_null;
01163          objhash < JVMCFG_MAX_OBJECTS;
01164          objhash++)
01165     {
01166         if (OBJECT(objhash).status & OBJECT_STATUS_INUSE)
01167         {
01168             if (!(OBJECT(objhash).status & OBJECT_STATUS_NULL))
01169             {
01170                 object_instance_finalize(objhash, JVMCFG_SYSTEM_THREAD);
01171             }
01172             (rvoid) object_instance_delete(objhash, rfalse);
01173         }
01174     }
01175 
01176     /* Declare this module uninitialized */
01177     jvm_object_initialized = rfalse;
01178 
01179     return;
01180 
01181 } /* END of object_shutdown() */
01182 
01183 
01184 /* EOF */
01185 

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