00001 #ifndef _jvmreg_h_included_ 00002 #define _jvmreg_h_included_ 00003 00004 /*! 00005 * @file jvmreg.h 00006 * 00007 * @brief Registers of the Java Virtual Machine, including 00008 * the program counter, stack pointer, frame pointer, etc. 00009 * 00010 * Definition of the JVM registers for this real machine 00011 * implementation, namely, the stack area and program counter. 00012 * There are a significant number of macros available for 00013 * navigating push-up stack area, the stack pointer, and 00014 * stack frame. 00015 * 00016 * 00017 * @section Control 00018 * 00019 * \$URL: https://svn.apache.org/path/name/jvmreg.h $ \$Id: jvmreg.h 0 09/28/2005 dlydick $ 00020 * 00021 * Copyright 2005 The Apache Software Foundation 00022 * or its licensors, as applicable. 00023 * 00024 * Licensed under the Apache License, Version 2.0 ("the License"); 00025 * you may not use this file except in compliance with the License. 00026 * You may obtain a copy of the License at 00027 * 00028 * http://www.apache.org/licenses/LICENSE-2.0 00029 * 00030 * Unless required by applicable law or agreed to in writing, 00031 * software distributed under the License is distributed on an 00032 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 00033 * either express or implied. 00034 * 00035 * See the License for the specific language governing permissions 00036 * and limitations under the License. 00037 * 00038 * @version \$LastChangedRevision: 0 $ 00039 * 00040 * @date \$LastChangedDate: 09/28/2005 $ 00041 * 00042 * @author \$LastChangedBy: dlydick $ 00043 * Original code contributed by Daniel Lydick on 09/28/2005. 00044 * 00045 * @section Reference 00046 * 00047 */ 00048 00049 ARCH_COPYRIGHT_APACHE(jvmreg, h, "$URL: https://svn.apache.org/path/name/jvmreg.h $ $Id: jvmreg.h 0 09/28/2005 dlydick $"); 00050 00051 /*! 00052 * @brief Program counter. 00053 * 00054 * The program counter is the location in the code array of a 00055 * JVM method of current JVM instruction. Definition includes 00056 * class, method, attribute of code area, and offset in the 00057 * code array. 00058 * 00059 * @todo Does an @p @b arraydims item need to be added for processing 00060 * of array classes, or is the scalar concept sufficient in code? 00061 */ 00062 typedef struct 00063 { 00064 jvm_class_index clsidx; /**< class[clsidx] of code location*/ 00065 jvm_method_index mthidx; /**< method[mthidx] of code location*/ 00066 jvm_attribute_index codeatridx;/**< attributes[atridx] of code */ 00067 jvm_attribute_index excpatridx;/**< attributes[atridx] of 00068 exceptions */ 00069 jvm_pc_offset offset; /**< instruction within code area */ 00070 } jvm_pc; 00071 00072 00073 /*! 00074 * The JVM's virtual operation codes are defined as single bytes. 00075 * This type definition is used to address them. 00076 */ 00077 typedef u1 jvm_virtual_opcode; 00078 00079 00080 /*! 00081 * @name Two types of exception tables. 00082 * 00083 * The JVM exception index table (defined by @b Exceptions attribute) 00084 * and JVM exception table (defined inside @b Code attribute) are both 00085 * simple offsets into their respective tables. Both are bound up 00086 * directly with the program counter, so are defined here. 00087 */ 00088 /*@{ */ 00089 00090 typedef u2 jvm_exception_table_index; 00091 typedef u2 jvm_exception_index_table_index; 00092 00093 /*@} */ 00094 00095 00096 00097 /*! 00098 * @brief Access structures of stack at certain index 00099 */ 00100 #define STACK(thridx, stkidx) THREAD(thridx).stack[stkidx] 00101 00102 00103 /*! 00104 * @name Stack frame geometry. 00105 * 00106 * Frame height = PC + GC + FP + max_locals (from code atr) + SA (aka 00107 * max_stack, SA being scratch area, the operand stack). 00108 * Minimum will be a zero-sized max_locals plus current SA. 00109 */ 00110 00111 /*@{ */ /* Begin grouped definitions */ 00112 00113 /*! Each of 5 items takes 1 stack word*/ 00114 #define JVMREG_STACK_PC_HEIGHT 5 00115 00116 00117 /*! Frame pointer takes one word */ 00118 #define JVMREG_STACK_FP_HEIGHT 1 00119 00120 #ifdef CONFIG_WORDSIZE64 00121 /*! GC real machine 64-bit ptr 00122 takes 2 words */ 00123 #define JVMREG_STACK_GC_HEIGHT 2 00124 #else 00125 /*! GC real machine 32-bit ptr 00126 takes 1 word */ 00127 #define JVMREG_STACK_GC_HEIGHT 1 00128 #endif 00129 00130 /*! Num local storage words 00131 takes 1 word */ 00132 #define JVMREG_STACK_LS_HEIGHT 1 00133 00134 /*! 00135 * @warning WATCH OUT! When invoking POP_GC() you are working with a 00136 * partially torn down frame, so can't use this macro: 00137 */ 00138 #define JVMREG_STACK_MIN_FRAME_HEIGHT (JVMREG_STACK_GC_HEIGHT + \ 00139 JVMREG_STACK_FP_HEIGHT + \ 00140 JVMREG_STACK_LS_HEIGHT) 00141 00142 /*! Offsets from current FP of local storage size word */ 00143 #define JVMREG_STACK_LS_OFFSET JVMREG_STACK_LS_HEIGHT 00144 00145 /*! Offsets from current FP of garbage collection pointer */ 00146 #define JVMREG_STACK_GC_OFFSET JVMREG_STACK_LS_OFFSET \ 00147 + JVMREG_STACK_GC_HEIGHT 00148 00149 /*! Offsets from current FP of old frame pointer */ 00150 #define JVMREG_STACK_FP_OFFSET JVMREG_STACK_GC_OFFSET \ 00151 + JVMREG_STACK_FP_HEIGHT 00152 00153 /*! Offsets from current FP of stack pointer */ 00154 #define JVMREG_STACK_PC_OFFSET JVMREG_STACK_FP_OFFSET \ 00155 + JVMREG_STACK_PC_HEIGHT 00156 00157 /*@} */ /* End of grouped definitions */ 00158 00159 00160 /*! 00161 * @name Reading and writing to the stack pointer. 00162 * 00163 * @brief Load/store values from/to the stack pointer itself, 00164 * not stack memory it points to. 00165 * 00166 * 00167 * @param thridx Thread index of thread whose stack pointer 00168 * is to be referenced. 00169 * 00170 * @param value (jvm_sp) value to store into stack pointer. 00171 * 00172 * 00173 * @returns The @b GET_SP() macros return a (jvm_sp) value of 00174 * a stack pointer, the others return 00175 * @link #rvoid rvoid@endlink. 00176 * 00177 */ 00178 00179 /*@{ */ /* Begin grouped definitions */ 00180 00181 #define GET_SP(thridx) (THREAD(thridx).sp) 00182 00183 00184 #define PUT_SP_IMMEDIATE(thridx, value) THREAD(thridx).sp = value 00185 00186 /*@} */ /* End of grouped definitions */ 00187 00188 00189 /*! 00190 * @name Reading and writing into the stack area. 00191 * 00192 * 00193 * @param thridx Thread index of thread whose stack it to 00194 * be manipulated. 00195 * 00196 * @param value (jint) value to store into stack location. 00197 * 00198 * 00199 * @returns The @b GET_SP() macros return a (jint) value from 00200 * the stack, the others 00201 * return @link #rvoid rvoid@endlink. 00202 * 00203 */ 00204 00205 /*@{ */ /* Begin grouped definitions */ 00206 00207 /*! 00208 * @brief Read a word at given depth in stack. 00209 */ 00210 #define GET_SP_WORD(thridx, idx, cast) \ 00211 ((cast) (STACK(thridx, GET_SP(thridx) - idx))) 00212 00213 /*! 00214 * @brief Write a word at given depth in stack. 00215 */ 00216 #define PUT_SP_WORD(thridx, idx, value) \ 00217 STACK(thridx, GET_SP(thridx) - idx) = (jint) (value) 00218 00219 /*@} */ /* End of grouped definitions */ 00220 00221 00222 /*! 00223 * @name Reading and writing to the stack pointer. 00224 * 00225 * @brief Load/store values from/to the frame pointer. 00226 * 00227 * 00228 * @param thridx Thread index of thread whose frame pointer 00229 * is to be referenced. 00230 * 00231 * @param value (jvm_sp) value to store into frame pointer. 00232 * 00233 * 00234 * @returns The @b GET_FP() macros return a (jvm_sp) value of 00235 * a stack pointer, the others 00236 * return @link #rvoid rvoid@endlink. 00237 * 00238 */ 00239 00240 /*@{ */ /* Begin grouped definitions */ 00241 00242 #define GET_FP(thridx) (THREAD(thridx).fp) 00243 00244 #define PUT_FP_IMMEDIATE(thridx, value) THREAD(thridx).fp = (value) 00245 00246 /*@} */ /* End of grouped definitions */ 00247 00248 00249 /*! 00250 * @brief Retrieve the stack frame garbage collection pointer. 00251 * 00252 * 00253 * @param thridx Thread index of thread whose garbage collection 00254 * pointer is to be referenced. 00255 * 00256 * 00257 * @returns (@link #rvoid rvoid@endlink *) is a real machine untyped 00258 * pointer that is stored in a JVM stack location. 00259 * Adjustments for 32-bit and 64-bit real machine pointers 00260 * are already considered by @link #JVMREG_STACK_GC_HEIGHT 00261 JVMREG_STACK_GC_HEIGHT@endlink. 00262 * 00263 */ 00264 #define GET_GC(thridx) \ 00265 ((rvoid *) &STACK(thridx, GET_FP(thridx) + JVMREG_STACK_GC_OFFSET)) 00266 00267 /*! 00268 * @name Move the stack pointer up and down. 00269 * 00270 * @brief Increment/decrement SP (N/A to frame pointer). 00271 * 00272 * It is safe to reference @b SP in the @p @b value parameter. 00273 * 00274 * 00275 * @param thridx Thread index of thread whose stack pointer 00276 * is to be referenced. 00277 * 00278 * @param value (jint) value to change stack pointer by. 00279 * 00280 * 00281 * @returns @link #rvoid rvoid@endlink 00282 * 00283 */ 00284 00285 /*@{ */ /* Begin grouped definitions */ 00286 00287 #define INC_SP(thridx, value) THREAD(thridx).sp += (value) 00288 #define DEC_SP(thridx, value) THREAD(thridx).sp -= (value) 00289 00290 /*@} */ /* End of grouped definitions */ 00291 00292 00293 /*! 00294 * @name Stack push and pop for any 32-bit data type. 00295 * 00296 * @brief Push/pop item to/from stack (MUST be integer size!). 00297 * 00298 * @warning <b>DO NOT</b> push/pop any 64-bit item, namely 00299 * any @link #jlong jlong@endlink or 00300 * @link #jdouble jdouble@endlink value. 00301 * The stack pointer is only adjusted by 00302 * a single 32-bit word. Use two operations 00303 * to push/pop each half of such types. There 00304 * are a number of examples in code, both in 00305 * @link jvm/src/opcode.c opcode.c@endlink and 00306 * @link jvm/src/native.c native.c@endlink. 00307 * 00308 * @warning It is @e not safe to reference @b SP in the @p @b item 00309 * parameter of @b POP(). 00310 * 00311 * 00312 * @param thridx Thread index of thread whose stack pointer 00313 * is to be referenced. 00314 * 00315 * @param item (@b cast) variable to push/pop to/from the stack. 00316 * 00317 * @param cast Type cast of variable being poped from the stack. 00318 * 00319 * 00320 * @returns @link #PUSH() PUSH()@endlink returns 00321 * @link #rvoid rvoid@endlink, @link #POP() POP()@endlink 00322 * returns the requested (jint) value. 00323 * 00324 */ 00325 00326 /*@{ */ /* Begin grouped definitions */ 00327 00328 #define PUSH(thridx, item) INC_SP(thridx, 1); \ 00329 PUT_SP_WORD(thridx, 0, (item)) 00330 00331 #define POP(thridx, item, cast) item = GET_SP_WORD(thridx, 0, cast); \ 00332 DEC_SP(thridx, 1) 00333 00334 /*@} */ /* End of grouped definitions */ 00335 00336 /*! 00337 * @name Stack push and pop of frame pointer. 00338 * 00339 * @brief Push/pop FP to/from stack. 00340 * 00341 * 00342 * @param thridx Thread index of thread whose stack pointer 00343 * is to be referenced. 00344 * 00345 * 00346 * @returns @link #PUSH_FP() PUSH_FP()@endlink returns 00347 * @link #rvoid rvoid@endlink, @link #POP_FP() POP_FP()@endlink 00348 * returns the requested (jvm_sp) value. 00349 * 00350 */ 00351 00352 /*@{ */ /* Begin grouped definitions */ 00353 00354 #define PUSH_FP(thridx) PUSH(thridx, THREAD(thridx).fp) 00355 00356 #define POP_FP(thridx) POP(thridx, THREAD(thridx).fp, jvm_sp) 00357 00358 /*@} */ /* End of grouped definitions */ 00359 00360 00361 /*! 00362 * @name Stack push and pop of garbage collection pointer. 00363 * 00364 * @brief Push/pop GC pointer to/from stack. 00365 * 00366 * Due to the potential for multiple GC implementations in this JVM, 00367 * the GC pointer here is @e not related to any one of them. Instead, 00368 * it is cast here as a simple @link #rvoid rvoid@endlink pointer so as 00369 * to support all of them. 00370 * 00371 * @todo Verify that the 64-bit real pointer 00372 * calculations work properly for @b PUSH_GC() and @b POP_GC() 00373 * (namely, where use fo JVMREG_STACK_GC_HEIGHT is involved) 00374 * 00375 * @warning WATCH OUT! When invoking @b POP_GC() you are working with a 00376 * partially torn down frame, so can't use standard macros 00377 * to calculate stack offsets! 00378 * 00379 * 00380 * @param thridx Thread index of thread whose stack pointer 00381 * is to be referenced. 00382 * 00383 * 00384 * @returns @link #rvoid rvoid@endlink 00385 * 00386 */ 00387 00388 /*@{ */ /* Begin grouped definitions */ 00389 00390 #define PUSH_GC(thridx, num_locals) \ 00391 INC_SP(thridx, JVMREG_STACK_GC_HEIGHT); \ 00392 ((rvoid *) \ 00393 *(&STACK(thridx, THREAD(thridx).sp - JVMREG_STACK_GC_HEIGHT+1))) =\ 00394 GC_STACK_NEW(thridx, num_locals) 00395 00396 #define POP_GC(thridx) \ 00397 GC_STACK_DELETE(thridx, \ 00398 ((rvoid **) \ 00399 &STACK(thridx, THREAD(thridx).sp - \ 00400 JVMREG_STACK_GC_HEIGHT + 1)), \ 00401 (&STACK(thridx, THREAD(thridx).sp - \ 00402 JVMREG_STACK_GC_HEIGHT + 1 - \ 00403 JVMREG_STACK_LS_HEIGHT - 1))); \ 00404 DEC_SP(thridx, JVMREG_STACK_GC_HEIGHT) 00405 00406 /*@} */ /* End of grouped definitions */ 00407 00408 00409 /*! 00410 * @name Push and pop of local variables. 00411 * 00412 * @brief Add/remove empty space for local storage to/from stack. 00413 * 00414 * 00415 * @param thridx Thread index of thread whose stack pointer 00416 * is to be referenced. 00417 * 00418 * @param value (jint) value to change stack pointer by. 00419 * 00420 * 00421 * @returns @link #rvoid rvoid@endlink 00422 * 00423 */ 00424 00425 /*@{ */ /* Begin grouped definitions */ 00426 00427 #define PUSH_LOCAL(thridx, items) INC_SP(thridx, items) /*! alias */ 00428 #define POP_LOCAL(thridx, items) DEC_SP(thridx, items) /*! alias */ 00429 00430 /*@} */ /* End of grouped definitions */ 00431 00432 00433 /*! 00434 * @name Locate position in stack frame of its components. 00435 * 00436 * @brief Locate the local storage size, garbage collection pointer, 00437 * old frame pointer, and start of local storage area. 00438 * 00439 * The current frame pointer always points to the first word of 00440 * the local storage area of the stack frame. 00441 * 00442 * 00443 * @param thridx Thread index of thread whose stack pointer 00444 * is to be referenced. 00445 * 00446 * 00447 * @returns (jvm_sp) stack offset value of requested item. 00448 * 00449 */ 00450 00451 /*@{ */ /* Begin grouped definitions */ 00452 00453 #define JVMREG_FRAME_CURRENT_LOCAL_STORAGE_SIZE(thridx) \ 00454 (GET_FP(thridx) + JVMREG_STACK_LS_OFFSET) 00455 00456 #define JVMREG_FRAME_GC(thridx) \ 00457 (GET_FP(thridx) + JVMREG_STACK_GC_OFFSET) 00458 00459 #define JVMREG_FRAME_PREVIOUS_FP(thridx) \ 00460 (GET_FP(thridx) + JVMREG_STACK_FP_OFFSET) 00461 00462 #define JVMREG_FRAME_CURRENT_SCRATCH_AREA(thridx) GET_FP(thridx) 00463 00464 /*@} */ /* End of grouped definitions */ 00465 00466 00467 /*! 00468 * @name Macros for manipulating program counter. 00469 * 00470 * @brief load the program counter and store its contents from/to 00471 * an arbitrary location, from/to the stack, and load with an 00472 * immediate value. 00473 * 00474 * 00475 * @param _thridx Thread index of thread whose stack pointer 00476 * is to be referenced. 00477 * 00478 * @param _source (jvm_pc) value to be loaded 00479 * into program counter. 00480 * 00481 * @param _clsidx (jvm_class_index) value to be loaded 00482 * into program counter class index 00483 * 00484 * @param _mthidx (jvm_method_index) value to be loaded 00485 * into program counter class index 00486 * 00487 * @param _codeatridx (jvm_attribute_index) value to be loaded 00488 * into program counter class index 00489 * 00490 * @param _excpatridx (jvm_attribute_index) value to be loaded 00491 * into program counter class index 00492 * 00493 * @param _excpatridx (jvm_attribute_index) value to be loaded 00494 * into program counter class index 00495 * 00496 * @param _offset (jvm_pc_offset) value to be loaded 00497 * into program counter class index 00498 * 00499 * @param _field Field from program counter to extract. 00500 * 00501 * 00502 * @returns (jvm_sp) stack offset value of requested item. 00503 * 00504 */ 00505 /*@{ */ /* Begin grouped definitions */ 00506 00507 #define PUT_PC(_thridx, _source) \ 00508 THREAD(_thridx).pc.clsidx = (_source).clsidx; \ 00509 THREAD(_thridx).pc.mthidx = (_source).mthidx; \ 00510 THREAD(_thridx).pc.codeatridx = (_source).atridx; \ 00511 THREAD(_thridx).pc.excpatridx = (_source).atridx; \ 00512 THREAD(_thridx).pc.offset = (_source).offset 00513 00514 #define PUT_PC_IMMEDIATE(_thridx, \ 00515 _clsidx, \ 00516 _mthidx, \ 00517 _codeatridx, \ 00518 _excpatridx, \ 00519 _offset) \ 00520 THREAD(_thridx).pc.clsidx = (_clsidx); \ 00521 THREAD(_thridx).pc.mthidx = (_mthidx); \ 00522 THREAD(_thridx).pc.codeatridx = (_codeatridx); \ 00523 THREAD(_thridx).pc.excpatridx = (_excpatridx); \ 00524 THREAD(_thridx).pc.offset = (_offset) 00525 00526 #define GET_PC(_thridx, _target) \ 00527 _target.clsidx = THREAD(_thridx).pc.clsidx \ 00528 _target.mthidx = THREAD(_thridx).pc.mthidx \ 00529 _target.codeatridx = THREAD(_thridx).pc.codeatridx \ 00530 _target.excpatridx = THREAD(_thridx).pc.excpatridx \ 00531 _target.offset = THREAD(_thridx).pc.offset 00532 00533 #define GET_PC_FIELD_IMMEDIATE(_thridx, _field) \ 00534 THREAD(_thridx).pc._field 00535 00536 #define GET_PC_FIELD(_thridx, _target, _field) \ 00537 _target = GET_PC_FIELD_IMMEDIATE(_thridx, _field) 00538 00539 #define PUSH_PC(_thridx) \ 00540 PUSH(_thridx, THREAD(_thridx).pc.offset); \ 00541 PUSH(_thridx, THREAD(_thridx).pc.excpatridx); \ 00542 PUSH(_thridx, THREAD(_thridx).pc.codeatridx); \ 00543 PUSH(_thridx, THREAD(_thridx).pc.mthidx); \ 00544 PUSH(_thridx, THREAD(_thridx).pc.clsidx); /* Extra ; */ 00545 00546 #define POP_PC(_thridx) \ 00547 POP(_thridx, THREAD(_thridx).pc.clsidx, jvm_class_index); \ 00548 POP(_thridx, THREAD(_thridx).pc.mthidx, u2); \ 00549 POP(_thridx, THREAD(_thridx).pc.codeatridx, u2); \ 00550 POP(_thridx, THREAD(_thridx).pc.excpatridx, u2); \ 00551 POP(_thridx, THREAD(_thridx).pc.offset, jvm_pc_offset); /*Extra ; */ 00552 00553 /*@} */ /* End of grouped definitions */ 00554 00555 00556 /*! 00557 * @name Location of the old program counter in the current stack frame. 00558 * 00559 * @warning Notice NEGATIVE INDEX used to address the stack frame. 00560 */ 00561 00562 /*@{ */ /* Begin grouped definitions */ 00563 00564 #define JVMREG_STACK_PC_CLSIDX_OFFSET JVMREG_STACK_PC_OFFSET - 0 00565 #define JVMREG_STACK_PC_MTHIDX_OFFSET JVMREG_STACK_PC_OFFSET - 1 00566 #define JVMREG_STACK_PC_CODEATRIDX_OFFSET JVMREG_STACK_PC_OFFSET - 2 00567 #define JVMREG_STACK_PC_EXCPATRIDX_OFFSET JVMREG_STACK_PC_OFFSET - 3 00568 #define JVMREG_STACK_PC_OFFSET_OFFSET JVMREG_STACK_PC_OFFSET - 4 00569 00570 /*@} */ /* End of grouped definitions */ 00571 00572 00573 /*! 00574 * @name Navigate the code area of of the current method. 00575 * 00576 * @brief Calculate pointers to several important real machine 00577 * addresses in the class file of the current method of a 00578 * specific thread: 00579 * 00580 * <ul> 00581 * <li> 00582 * <b>(1)</b> current program counter in THIS_PC() macro. 00583 * </li> 00584 * <li> 00585 * <b>(2)</b> current class file in THIS_PCFS() macro. 00586 * </li> 00587 * <li> 00588 * <b>(3)</b> PC exception index table base (list of legal exceptions) 00589 * in DEREFERENCE_PC_EXCEPTIONS_ATTRIBUTE() macro. 00590 * </li> 00591 * <li> 00592 * <b>(4)</b> PC exception base (list of actual exceptions thrown) 00593 * in DEREFERENCE_PC_EXCEPTION_TABLE() macro. 00594 * </li> 00595 * <li> 00596 * <b>(5)</b> PC base (start of method) in DEREFERENCE_PC_CODE_BASE() 00597 * macro. 00598 * </li> 00599 * <li> 00600 * <b>(6)</b> current opcode in DEREFERENCE_PC_CODE_CURRENT_OPCODE() 00601 * macro. 00602 * </li> 00603 * </ul> 00604 * 00605 */ 00606 00607 /*@{ */ /* Begin grouped definitions */ 00608 00609 /*! 00610 * @def THIS_PC() 00611 * 00612 * @brief Locate program counter for a given thread. 00613 * 00614 * 00615 * @param thridx Thread table index of program counter to locate. 00616 * 00617 * 00618 * @returns address of program counter in this thread table. 00619 * 00620 */ 00621 #define THIS_PC(thridx) (&THREAD(thridx).pc) 00622 00623 00624 /*! 00625 * @def THIS_PCFS() 00626 * 00627 * @brief Locate ClassFile for current program counter 00628 * on a given thread. 00629 * 00630 * 00631 * @param thridx Thread table index of class to locate for 00632 * current program counter. 00633 * 00634 * 00635 * @returns address of ClassFile structure containing code at 00636 * current program counter on this thread. 00637 * 00638 */ 00639 #define THIS_PCFS(thridx) \ 00640 (CLASS_OBJECT_LINKAGE(THIS_PC(thridx)->clsidx)->pcfs) 00641 00642 00643 /*! 00644 * @def DEREFERENCE_PC_GENERIC_ATTRIBUTE() 00645 * 00646 * @brief Untyped attribute in method table for current program 00647 * counter on a given thread. 00648 * 00649 * 00650 * @param thridx Thread table index of attribute to locate for 00651 * current program counter. 00652 * 00653 * @param pc_member jvm_pc member index in current program counter to 00654 * pick out and examine. 00655 * 00656 * 00657 * @returns Plain attribute address (no special attribute type) 00658 * of an attribute in method area of the current program counter 00659 * on this thread, or @link #rnull rnull@endlink if a @b BAD attribute . 00660 * 00661 * @todo Watch out for when @p @b codeatridx is a BAD index, namely 00662 * @link #jvm_attribute_index_bad jvm_attribute_index_bad@endlink 00663 * 00664 */ 00665 #define DEREFERENCE_PC_GENERIC_ATTRIBUTE(thridx, pc_member) \ 00666 ((jvm_attribute_index_bad != THIS_PC(thridx)->pc_member) \ 00667 ? (&THIS_PCFS(thridx)->methods[THIS_PC(thridx)->mthidx] \ 00668 ->attributes[THIS_PC(thridx)->pc_member] \ 00669 ->ai) \ 00670 : rnull) 00671 00672 00673 /*! 00674 * @def DEREFERENCE_PC_EXCEPTIONS_ATTRIBUTE() 00675 * 00676 * @brief Exceptions_attribute in method table for current program 00677 * counter on a given thread. 00678 * 00679 * 00680 * @param thridx Thread table index of @b Exceptions attribute to 00681 * locate for current program counter. 00682 * 00683 * 00684 * @returns Address of @b Exceptions attribute in method area of 00685 * the current program counter on this thread. 00686 * 00687 */ 00688 #define DEREFERENCE_PC_EXCEPTIONS_ATTRIBUTE(thridx) \ 00689 ((Exceptions_attribute *) \ 00690 DEREFERENCE_PC_GENERIC_ATTRIBUTE(thridx, excpatridx)) 00691 00692 00693 /*! 00694 * @def DEREFERENCE_PC_CODE_ATTRIBUTE() 00695 * 00696 * @brief Code_attribute in method table for current program counter 00697 * on a given thread. 00698 * 00699 * 00700 * @param thridx Thread table index of @b Code attribute to locate for 00701 * current program counter. 00702 * 00703 * 00704 * @returns Address of @b Code attribute in method area of 00705 * the current program counter on this thread, or 00706 * @link #rnull rnull@endlink if not present in class file. 00707 * 00708 */ 00709 #define DEREFERENCE_PC_CODE_ATTRIBUTE(thridx) \ 00710 ((Code_attribute *) \ 00711 DEREFERENCE_PC_GENERIC_ATTRIBUTE(thridx, codeatridx)) 00712 00713 00714 /*! 00715 * @def DEREFERENCE_PC_EXCEPTION_TABLE() 00716 * 00717 * @brief Real address of exception table of this method in 00718 * current program counter on a given thread. 00719 * 00720 * 00721 * @param thridx Thread table index of program counter to locate. 00722 * 00723 * 00724 * @returns address of program counter in this thread table, or 00725 * @link #rnull rnull@endlink if not present in class file. 00726 * 00727 */ 00728 #define DEREFERENCE_PC_EXCEPTION_TABLE(thridx) \ 00729 (DEREFERENCE_PC_CODE_ATTRIBUTE(thridx)->exception_table) 00730 00731 00732 /*! 00733 * @def DEREFERENCE_PC_CODE_BASE 00734 * 00735 * @brief Real address of first opcode of this method in current 00736 * program counter on a given thread. 00737 * 00738 * 00739 * @param thridx Thread table index of opcode to locate for 00740 * current program counter. 00741 * 00742 * 00743 * @returns Real machine address of @e first opcode in current 00744 * program counter on this thread. 00745 * 00746 */ 00747 #define DEREFERENCE_PC_CODE_BASE(thridx) \ 00748 (DEREFERENCE_PC_CODE_ATTRIBUTE(thridx)->code) 00749 00750 00751 /*! 00752 * @def DEREFERENCE_PC_CODE_CURRENT_OPCODE() 00753 * 00754 * @brief Real address of first opcode of this method in current 00755 * program counter on a given thread. 00756 * 00757 * 00758 * @param thridx Thread table index of opcode to locate for 00759 * current program counter. 00760 * 00761 * 00762 * @returns Real machine address of @e current opcode in current 00763 * program counter on this thread. 00764 * 00765 */ 00766 #define DEREFERENCE_PC_CODE_CURRENT_OPCODE(thridx) \ 00767 (&DEREFERENCE_PC_CODE_BASE(thridx)[THIS_PC(thridx)->offset]) 00768 00769 /*@} */ /* End of grouped definitions */ 00770 00771 00772 /*! 00773 * @name Geometry of a complete stack frame. 00774 * 00775 * @brief A complete stack frame is pushed every time a JVM virtual 00776 * method is called, where old program counter and old stack state 00777 * must be saved and a new one created on top of it. The macro 00778 * @b PUSH_FRAME() is designed for this use. For example, 00779 * here is an existing stack frame: 00780 * 00781 * @verbatim 00782 SP --> [scratch] (operand stack, >= 0 words) ... higher address 00783 ... ... 00784 [scratch] ... 00785 [top of previous frame] ... 00786 FP -> [locals of previous frame] ... lower address 00787 00788 @endverbatim 00789 * 00790 * During @b PUSH_FRAME(n), there are a@b n words of local storage 00791 * allocated for JVM method scratch area, where @b n >= 0, up to 00792 * the maximum stack size less the top few words: 00793 * 00794 * @verbatim 00795 00796 new SP --> [PC of next JVM instruction] ... high address 00797 [old FP] ... 00798 [GC pointer for this NEW frame] ... 00799 [value 'n', size of LS (local storage) area beneath] 00800 new FP --> [local 0] ... 00801 [local 1] ... 00802 [local 2] ... 00803 ... ... 00804 [local n-1] ... 00805 00806 --- end of NEW frame --- 00807 00808 old SP -> [scratch] (same data shown above) ... 00809 ... ... 00810 [scratch] ... 00811 [top of previous frame] ... 00812 old FP -> [locals of previous frame] ... low address 00813 00814 --- end of OLD frame --- 00815 00816 @endverbatim 00817 * 00818 * 00819 * POP_FRAME() does the reverse or @b PUSH_FRAME and removes 00820 * the top stack frame. The final @b POP_FRAME() will have a 00821 * stored (old) frame pointer containing 00822 * @link #JVMCFG_NULL_SP JVMCFG_NULL_SP@endlink, so when this 00823 * frame is popped, @link #opcode_run() opcode_run()@endlink 00824 * will detect that this thread has finished running. 00825 * 00826 * 00827 * @param thridx Thread index of thread whose stack pointer 00828 * is to be referenced. 00829 * 00830 * @param locals Number of local variables to be reserved 00831 * in the new stack frame. 00832 * 00833 * 00834 * @returns @link #rvoid rvoid@endlink. 00835 * 00836 */ 00837 00838 /*@{ */ /* Begin grouped definitions */ 00839 00840 #define PUSH_FRAME(thridx, locals) \ 00841 PUSH_LOCAL(thridx, (locals)); \ 00842 PUSH(thridx, (locals)); \ 00843 PUSH_GC(thridx, (locals)); \ 00844 PUSH_FP(thridx); \ 00845 PUT_FP_IMMEDIATE(thridx, \ 00846 GET_SP(thridx) - JVMREG_STACK_MIN_FRAME_HEIGHT); \ 00847 PUSH_PC(thridx); /* Extra ; */ 00848 00849 #define POP_FRAME(thridx) \ 00850 POP_PC(thridx); \ 00851 POP_FP(thridx); \ 00852 POP_GC(thridx); \ 00853 POP_LOCAL(thridx, (1 + GET_SP_WORD(thridx, 0, jint))); /* Extra ; */ 00854 00855 /*@} */ /* End of grouped definitions */ 00856 00857 /*! 00858 * @name Access the stack frame. 00859 * 00860 * @brief Read and write (jint) values from and to the current 00861 * stack frame. 00862 * 00863 * Accesses are @e always as (jint), casting is performed 00864 * outside of these macros. 00865 * 00866 * @todo This implementation is being changed to point local variable 00867 * zero to the _last_ word of the local variable area instead of the 00868 * _first_ word. This will create a run-time tradeoff between reversing 00869 * the stack frame for method calls and a slightly longer expression 00870 * needed to access local variables. The former (current way) makes 00871 * for a somewhat more complex method invocation procedure, while the 00872 * latter (to be done) provides an easy method invocation with a bit 00873 * more work to access locals. The following warning notice will go 00874 * away when this is done: 00875 * 00876 * NOTICE THE INDEX IS ***NEGATIVE*** in this implementation! 00877 * This allows FP to use constant values to each and every element of 00878 * the frame, including a constant value to point to the @e first of 00879 * the local variables. By inverting the frame to have the locals on 00880 * top, this same thing could be done and the FP could point either 00881 * to its corresponding inverse location or to the first word of the 00882 * frame above the old stack contents. 00883 * 00884 * 00885 * @param thridx Thread index of thread whose stack pointer 00886 * is to be referenced. 00887 * 00888 * @param frmidx Stack frame index (local variable index) of stack 00889 * frame to be referenced. 00890 * 00891 * @param cast Arbitrary data type that is of size (jint) or 00892 * smaller. This includes (jbyte), (jboolean), 00893 * (jchar), (jshort), (jshort), and (jobject). 00894 * 00895 */ 00896 /*@{ */ /* Begin grouped definitions */ 00897 00898 /*! 00899 * @brief Read a local variable from the stack frame 00900 * 00901 * @note For (jlong) and (jdouble) local variables, there are 00902 * @e two accesses required per JVM spec to retrieve the two 00903 * (jint) words of such a data type. Use bytegames_combine_long() 00904 * and bytegames_combine_double(), respectively, to combine the 00905 * two words into a single variable. The parameters may be 00906 * read directly from the stack frame with this macro. 00907 * 00908 * 00909 * @returns (jint) value of a local variable in the stack frame. 00910 * 00911 */ 00912 #define GET_LOCAL_VAR(thridx, frmidx) \ 00913 ((jint) (STACK(thridx, GET_FP(thridx) - frmidx))) 00914 00915 /*! 00916 * @brief Cast a @link #GET_LOCAL_VAR() GET_LOCAL_VAR()@endlink 00917 * as any arbitrary data type. 00918 * 00919 * @note This macro is not appropriate for (jlong) and (jdouble) 00920 * data types since they require two (jint) local variable 00921 * stack frame accesses. 00922 * 00923 * @returns @b (cast) value of (jint) local variable. 00924 * 00925 */ 00926 #define GET_TYPED_LOCAL_VAR(thridx, frmidx, cast) \ 00927 ((cast) GET_LOCAL_VAR(thridx, frmidx))) 00928 00929 00930 /*! 00931 * @brief Real machine address of a local variable in the stack frame 00932 * 00933 * 00934 * @returns Real machine (jint *) address of a (jint) local variable 00935 * in the stack frame. 00936 * 00937 */ 00938 #define JINT_ADDRESS_LOCAL_VAR(thridx, frmidx) \ 00939 ((jint *) &STACK(thridx, GET_FP(thridx) - frmidx)) 00940 00941 00942 /*! 00943 * @brief Write a local variable from the stack frame 00944 * 00945 * @note For (jlong) and (jdouble) local variables, there are 00946 * @e two accesses required per JVM spec to store the two 00947 * (jint) words of such a data type. Use bytegames_split_long() 00948 * and bytegames_split_double(), respectively, to split 00949 * a single variable into its two words. The parameters may be 00950 * written directly into the stack frame with this macro. 00951 * 00952 * 00953 * @returns (jint) value of a local variable in the stack frame. 00954 * 00955 */ 00956 #define PUT_LOCAL_VAR(thridx, frmidx, value) \ 00957 *JINT_ADDRESS_LOCAL_VAR(thridx, frmidx) = (jint) (value) 00958 00959 00960 /*@} */ /* End of grouped definitions */ 00961 00962 /*! 00963 * @name Navigate stack frame in depth. 00964 * 00965 * @brief Use these macros to iteratively point up and down the 00966 * stack from from current fram to bottom of the stack. 00967 * 00968 * 00969 * @param thridx Thread index of thread whose stack pointer 00970 * is to be referenced. 00971 * 00972 * @param some_fp Stack pointer index of stack frame to be referenced. 00973 * 00974 */ 00975 00976 /*@{ */ /* Begin grouped definitions */ 00977 00978 /*! 00979 * @returns Requested frame pointer 00980 * 00981 */ 00982 #define NEXT_STACK_FRAME_GENERIC(thridx, some_fp) \ 00983 STACK(thridx, some_fp + JVMREG_STACK_FP_OFFSET) 00984 00985 /*! 00986 * @returns @link #rtrue rtrue@endlink if @p some_fp now points 00987 * to the bottom of the stack frame. 00988 * 00989 */ 00990 #define CHECK_FINAL_STACK_FRAME_GENERIC(thridx, some_fp) \ 00991 ((JVMCFG_NULL_SP == NEXT_STACK_FRAME_GENERIC(thridx, some_fp)) \ 00992 ? rtrue \ 00993 : rfalse) 00994 00995 #define FIRST_STACK_FRAME(thridx) GET_FP(thridx) 00996 00997 #define NEXT_STACK_FRAME(thridx) \ 00998 NEXT_STACK_FRAME_GENERIC(thridx, GET_FP(thridx)) 00999 01000 #define CHECK_FINAL_STACK_FRAME(thridx) \ 01001 CHECK_FINAL_STACK_FRAME_GENERIC(thridx, GET_FP(thridx)) 01002 01003 #define CHECK_FINAL_STACK_FRAME_ULTIMATE(thridx) \ 01004 (JVMCFG_NULL_SP == GET_FP(thridx)) 01005 01006 /*@} */ /* End of grouped definitions */ 01007 01008 01009 #endif /* _jvmreg_h_included_ */ 01010 01011 01012 /* EOF */ 01013