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