LCOV - code coverage report
Current view: top level - vm/jit - executionstate.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 63 97 64.9 %
Date: 2015-06-10 18:10:59 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /* src/vm/jit/executionstate.cpp - execution-state handling
       2             : 
       3             :    Copyright (C) 1996-2013
       4             :    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
       5             : 
       6             :    This file is part of CACAO.
       7             : 
       8             :    This program is free software; you can redistribute it and/or
       9             :    modify it under the terms of the GNU General Public License as
      10             :    published by the Free Software Foundation; either version 2, or (at
      11             :    your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful, but
      14             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :    General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program; if not, write to the Free Software
      20             :    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
      21             :    02110-1301, USA.
      22             : 
      23             : */
      24             : 
      25             : #include "vm/jit/executionstate.hpp"
      26             : #include <stdint.h>                     // for uintptr_t, int32_t, uint8_t, etc
      27             : #include <string.h>                     // for memcmp
      28             : #include <cstdio>                       // for printf
      29             : #include "config.h"                     // for SIZEOF_VOID_P
      30             : #include "arch.hpp"
      31             : #include "md-abi.hpp"                   // for FLT_REG_CNT, INT_REG_CNT
      32             : #include "md.hpp"                       // for md_codegen_get_pv_from_pc, etc
      33             : #include "vm/descriptor.hpp"            // for methoddesc
      34             : #include "vm/exceptions.hpp"            // for exceptions_handle_exception
      35             : #include "vm/jit/abi.hpp"               // for nregdescfloat, nregdescint
      36             : #include "vm/jit/code.hpp"              // for codeinfo, etc
      37             : #include "vm/method.hpp"                // for method_print, methodinfo
      38             : #include "vm/os.hpp"                    // for os
      39             : #include "vm/types.hpp"                 // for s4, ptrint, u1, u8
      40             : 
      41             : /**
      42             :  * Restore callee-saved registers (including the RA register),
      43             :  * set the stack pointer to the next stackframe,
      44             :  * set the PC to the return address of the popped frame.
      45             :  *
      46             :  * *** This function imitates the effects of the method epilog ***
      47             :  * *** and returning from the method call.                     ***
      48             :  *
      49             :  * @param es Execution state to be modified.
      50             :  *        NOTE: es->code and es->pv are NOT updated.
      51             :  */
      52          29 : void executionstate_pop_stackframe(executionstate_t *es)
      53             : {
      54             :         int32_t reg;
      55             :         int32_t i;
      56             : 
      57             :         // Sanity checks.
      58          29 :         assert(es->code != NULL);
      59             : 
      60             :         // Calculate the size of the stackframe.
      61          29 :         int32_t framesize = md_stacktrace_get_framesize(es->code);
      62             : 
      63             :         // Read the return address.
      64             :         uint8_t* ra;
      65             : #if STACKFRAME_LEAFMETHODS_RA_REGISTER
      66             :         if (code_is_leafmethod(es->code))
      67             :                 ra = es->ra;
      68             :         else
      69             : #endif
      70          29 :                 ra = (u1*) md_stacktrace_get_returnaddress(es->sp, framesize);
      71             : 
      72             :         // Calculate the base of the stack frame.
      73          29 :         uintptr_t sp     = (uintptr_t) es->sp;
      74          29 :         uintptr_t basesp = sp + es->code->stackframesize * SIZE_OF_STACKSLOT;
      75             : 
      76             :         // Restore return address, if part of frame.
      77             : #if STACKFRAME_RA_TOP_OF_FRAME
      78             : # if STACKFRAME_LEAFMETHODS_RA_REGISTER
      79             :         if (!code_is_leafmethod(es->code)) {
      80             : # endif
      81             :                 basesp -= 1 * SIZE_OF_STACKSLOT;
      82             :                 es->ra = *((uint8_t**) basesp);
      83             : # if STACKFRAME_LEAFMETHODS_RA_REGISTER
      84             :         }
      85             : # endif
      86             : #endif /* STACKFRAME_RA_TOP_OF_FRAME */
      87             : 
      88             :         // Restore return address, if inside linkage area.
      89             : #if STACKFRAME_RA_LINKAGE_AREA
      90             : # if STACKFRAME_LEAFMETHODS_RA_REGISTER
      91             :         if (!code_is_leafmethod(es->code))
      92             : # endif
      93             :                 es->ra = *((uint8_t**) (basesp + LA_LR_OFFSET));
      94             : #endif /* STACKFRAME_RA_LINKAGE_AREA */
      95             : 
      96             :         // Restore saved int registers.
      97          29 :         reg = INT_REG_CNT;
      98          74 :         for (i=0; i<es->code->savedintcount; ++i) {
      99          57 :                 while (nregdescint[--reg] != REG_SAV)
     100             :                         ;
     101          45 :                 basesp -= 1 * SIZE_OF_STACKSLOT;
     102          45 :                 es->intregs[reg] = *((uintptr_t*) basesp);
     103             :         }
     104             : 
     105             :         // Restore saved flt registers.
     106             :         // XXX align?
     107          29 :         reg = FLT_REG_CNT;
     108          29 :         for (i=0; i<es->code->savedfltcount; ++i) {
     109           0 :                 while (nregdescfloat[--reg] != REG_SAV)
     110             :                         ;
     111           0 :                 basesp -= STACK_SLOTS_PER_FLOAT * SIZE_OF_STACKSLOT;
     112           0 :                 es->fltregs[reg] = *((double*) basesp);
     113             :         }
     114             : 
     115             :         // Adjust the stackpointer.
     116          29 :         es->sp += framesize;
     117             : #if STACKFRMAE_RA_BETWEEN_FRAMES
     118          29 :         es->sp += SIZEOF_VOID_P; /* skip return address */
     119             : #endif
     120             : 
     121             :         // Set the program counter to the return address.
     122          29 :         es->pc = ra;
     123             : 
     124             :         // In debugging mode clobber non-saved registers.
     125             : #if !defined(NDEBUG)
     126         493 :         for (i=0; i<INT_REG_CNT; ++i)
     127         464 :                 if (nregdescint[i] != REG_SAV)
     128         319 :                         es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
     129         493 :         for (i=0; i<FLT_REG_CNT; ++i)
     130         464 :                 if (nregdescfloat[i] != REG_SAV)
     131         464 :                         *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
     132             : #endif /* !defined(NDEBUG) */
     133          29 : }
     134             : 
     135             : /**
     136             :  * Performs stack unwinding in case of an exception. This is done by
     137             :  * popping frames off the given execution state until a frame is reached
     138             :  * for which there is a handler. Execution will continue at the handler
     139             :  * site once the execution state is written back to the machine.
     140             :  *
     141             :  * @param es Execution state to be modified.
     142             :  * @param e The thrown exception object.
     143             :  *
     144             :  * This is specified in:
     145             :  *    The Java(TM) Virtual Machine Specification, Second Edition
     146             :  *    Section 3.6.5: Abrupt Method Invocation Completion
     147             :  */
     148          91 : void executionstate_unwind_exception(executionstate_t* es, java_handle_t* e)
     149             : {
     150          91 :         void* handler = NULL;
     151             : 
     152             :         // Iterate until we find an exception handler.
     153         211 :         while (handler == NULL) {
     154             : 
     155             :                 // Search an exception handler in the current frame.
     156         120 :                 handler = exceptions_handle_exception(e, es->pc, es->pv, es->sp);
     157             : 
     158             :                 // Jump directly into the handler in case we found one.
     159         120 :                 if (handler != NULL)
     160          91 :                         break;
     161             : 
     162             :                 // Find the codeinfo structure for the current frame.
     163          29 :                 es->code = code_get_codeinfo_for_pv(es->pv);
     164             : 
     165             :                 // Pop one frame off the stack.
     166          29 :                 executionstate_pop_stackframe(es);
     167             : 
     168             :                 // Get the PV for the parent Java method.
     169          29 :                 es->pv = (uint8_t*) md_codegen_get_pv_from_pc(es->pc);
     170             : 
     171             :                 // After popping the frame the PC points to the instruction just after
     172             :                 // the invocation. To get the XPC we need to correct the PC to point
     173             :                 // just before the invocation. But we do not know how big the
     174             :                 // invocation site actually is, so we subtract one, which should be
     175             :                 // sufficient for our purposes.
     176          29 :                 es->pc -= 1;
     177             :         }
     178             : 
     179             :         // Update the execution state to continue at the handler site.
     180          91 :         es->pc = (uint8_t*) handler;
     181          91 : }
     182             : 
     183             : 
     184             : /* executionstate_sanity_check *************************************************
     185             : 
     186             :    Perform some sanity checks for the md_executionstate_read and
     187             :    md_executionstate_write functions.
     188             : 
     189             : *******************************************************************************/
     190             : 
     191             : #if !defined(NDEBUG)
     192      197445 : void executionstate_sanity_check(void *context)
     193             : {
     194             :     /* estimate a minimum for the context size */
     195             : 
     196             : #define MINIMUM_CONTEXT_SIZE  (SIZEOF_VOID_P    * INT_REG_CNT \
     197             :                                        + sizeof(double) * FLT_REG_CNT)
     198             : 
     199             :         executionstate_t es1;
     200             :         executionstate_t es2;
     201             :         executionstate_t es3;
     202             :         unsigned int i;
     203             :         unsigned char reference[MINIMUM_CONTEXT_SIZE];
     204             : 
     205             :         /* keep a copy of (a prefix of) the context for reference */
     206             : 
     207      197445 :         os::memcpy(&reference, context, MINIMUM_CONTEXT_SIZE);
     208             : 
     209             :         /* different poisons */
     210             : 
     211      197445 :         os::memset(&es1, 0xc9, sizeof(executionstate_t));
     212      197445 :         os::memset(&es2, 0xb5, sizeof(executionstate_t));
     213      197445 :         os::memset(&es3, 0x6f, sizeof(executionstate_t));
     214             : 
     215      197445 :         md_executionstate_read(&es1, context);
     216             : 
     217             :         /* verify that item-by-item copying preserves the state */
     218             : 
     219      197445 :         es2.pc = es1.pc;
     220      197445 :         es2.sp = es1.sp;
     221      197445 :         es2.pv = es1.pv;
     222      197445 :         es2.ra = es1.ra;
     223      197445 :         es2.code = es1.code;
     224     3356565 :         for (i = 0; i < INT_REG_CNT; ++i)
     225     3159120 :                 es2.intregs[i] = es1.intregs[i];
     226     3356565 :         for (i = 0; i < FLT_REG_CNT; ++i)
     227     3159120 :                 es2.fltregs[i] = es1.fltregs[i];
     228             : 
     229             :         /* write it back - this should not change the context */
     230             :         /* We cannot check that completely, unfortunately, as we don't know */
     231             :         /* the size of the (OS-dependent) context. */
     232             : 
     233      197445 :         md_executionstate_write(&es2, context);
     234             : 
     235             :         /* Read it again, Sam! */
     236             : 
     237      197445 :         md_executionstate_read(&es3, context);
     238             : 
     239             :         /* Compare. Note: Because of the NAN madness, we cannot compare
     240             :          * doubles using '=='. */
     241             : 
     242      197452 :         assert(es3.pc == es1.pc);
     243      197452 :         assert(es3.sp == es1.sp);
     244      197452 :         assert(es3.pv == es1.pv);
     245     3356572 :         for (i = 0; i < INT_REG_CNT; ++i)
     246     3159120 :                 assert(es3.intregs[i] == es1.intregs[i]);
     247     3356562 :         for (i = 0; i < FLT_REG_CNT; ++i)
     248     3159117 :                 assert(memcmp(es3.fltregs+i, es1.fltregs+i, sizeof(double)) == 0);
     249             : 
     250             :         /* i386 and x86_64 do not have an RA register */
     251             : 
     252             : #if defined(__I386__) || defined(__X86_64__)
     253      197445 :         assert(es3.ra != es1.ra);
     254             : #else
     255             :         assert(es3.ra == es1.ra);
     256             : #endif
     257             : 
     258             :         /* "code" is not set by the md_* functions */
     259             : 
     260      197445 :         assert(es3.code != es1.code);
     261             : 
     262             :         /* assert that we have not messed up the context */
     263             : 
     264      197445 :         assert(memcmp(&reference, context, MINIMUM_CONTEXT_SIZE) == 0);
     265      197445 : }
     266             : #endif
     267             : 
     268             : 
     269             : /* executionstate_println ******************************************************
     270             : 
     271             :    Print execution state
     272             : 
     273             :    IN:
     274             :        es...............the execution state to print
     275             : 
     276             : *******************************************************************************/
     277             : 
     278             : #if !defined(NDEBUG)
     279           0 : void executionstate_println(executionstate_t *es)
     280             : {
     281             :         uint64_t *sp;
     282             :         int       slots;
     283             :         int       extraslots;
     284             :         int       i;
     285             : 
     286           0 :         if (!es) {
     287           0 :                 printf("(executionstate_t *)NULL\n");
     288           0 :                 return;
     289             :         }
     290             : 
     291           0 :         printf("executionstate_t:\n");
     292           0 :         printf("\tpc = %p", es->pc);
     293           0 :         printf("  sp = %p", es->sp);
     294           0 :         printf("  pv = %p", es->pv);
     295           0 :         printf("  ra = %p\n", es->ra);
     296             : 
     297             : #if defined(ENABLE_DISASSEMBLER)
     298             :         for (i=0; i<INT_REG_CNT; ++i) {
     299             :                 if (i%4 == 0)
     300             :                         printf("\t");
     301             :                 else
     302             :                         printf(" ");
     303             : # if SIZEOF_VOID_P == 8
     304             :                 printf("%-3s = %016lx", abi_registers_integer_name[i], es->intregs[i]);
     305             : # else
     306             :                 printf("%-3s = %08x", abi_registers_integer_name[i], (unsigned) es->intregs[i]);
     307             : # endif
     308             :                 if (i%4 == 3)
     309             :                         printf("\n");
     310             :         }
     311             : 
     312             :         for (i=0; i<FLT_REG_CNT; ++i) {
     313             :                 if (i%4 == 0)
     314             :                         printf("\t");
     315             :                 else
     316             :                         printf(" ");
     317             :                 printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
     318             :                 if (i%4 == 3)
     319             :                         printf("\n");
     320             :         }
     321             : #endif
     322             : 
     323           0 :         sp = (uint64_t *) es->sp;
     324             : 
     325           0 :         extraslots = 2;
     326             : 
     327           0 :         if (es->code) {
     328           0 :                 methoddesc *md = es->code->m->parseddesc;
     329           0 :                 slots = es->code->stackframesize;
     330           0 :                 extraslots = 1 + md->memuse;
     331             :         }
     332             :         else
     333           0 :                 slots = 0;
     334             : 
     335             : 
     336           0 :         if (slots) {
     337           0 :                 printf("\tstack slots(+%d) at sp:", extraslots);
     338           0 :                 for (i=0; i<slots+extraslots; ++i) {
     339           0 :                         if (i%4 == 0)
     340           0 :                                 printf("\n\t\t");
     341           0 :                         printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
     342           0 :                         printf("%016llx",(unsigned long long)*sp++);
     343           0 :                         printf("%c", (i >= slots) ? ')' : ' ');
     344             :                 }
     345           0 :                 printf("\n");
     346             :         }
     347             : 
     348           0 :         printf("\tcode: %p", (void*)es->code);
     349           0 :         if (es->code != NULL) {
     350           0 :                 printf(" stackframesize=%d ", es->code->stackframesize);
     351           0 :                 method_print(es->code->m);
     352             :         }
     353           0 :         printf("\n");
     354             : 
     355           0 :         printf("\n");
     356             : }
     357             : #endif
     358             : 
     359             : 
     360             : /*
     361             :  * These are local overrides for various environment variables in Emacs.
     362             :  * Please do not remove this and leave it at the end of the file, where
     363             :  * Emacs will automagically detect them.
     364             :  * ---------------------------------------------------------------------
     365             :  * Local variables:
     366             :  * mode: c++
     367             :  * indent-tabs-mode: t
     368             :  * c-basic-offset: 4
     369             :  * tab-width: 4
     370             :  * End:
     371             :  * vim:noexpandtab:sw=4:ts=4:
     372             :  */

Generated by: LCOV version 1.11