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

jvmreg.h

Go to the documentation of this file.
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 

Generated on Fri Sep 30 18:49:04 2005 by  doxygen 1.4.4