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: 2017-07-14 10:03:36 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       20521 : void executionstate_pop_stackframe(executionstate_t *es)
      53             : {
      54             :         int32_t reg;
      55             :         int32_t i;
      56             : 
      57             :         // Sanity checks.
      58       20521 :         assert(es->code != NULL);
      59             : 
      60             :         // Calculate the size of the stackframe.
      61       20521 :         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       20521 :                 ra = (u1*) md_stacktrace_get_returnaddress(es->sp, framesize);
      71             : 
      72             :         // Calculate the base of the stack frame.
      73       20521 :         uintptr_t sp     = (uintptr_t) es->sp;
      74       20521 :         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             : # if STACKFRAME_PACKED_SAVED_REGISTERS
      82             :                 basesp -= 1 * SIZEOF_VOID_P;
      83             : # else
      84             :                 basesp -= 1 * SIZE_OF_STACKSLOT;
      85             : # endif
      86             :                 es->ra = *((uint8_t**) basesp);
      87             : # if STACKFRAME_LEAFMETHODS_RA_REGISTER
      88             :         }
      89             : # endif
      90             : #endif /* STACKFRAME_RA_TOP_OF_FRAME */
      91             : 
      92             :         // Restore return address, if inside linkage area.
      93             : #if STACKFRAME_RA_LINKAGE_AREA
      94             : # if STACKFRAME_LEAFMETHODS_RA_REGISTER
      95             :         if (!code_is_leafmethod(es->code))
      96             : # endif
      97             :                 es->ra = *((uint8_t**) (basesp + LA_LR_OFFSET));
      98             : #endif /* STACKFRAME_RA_LINKAGE_AREA */
      99             : 
     100             :         // Restore saved int registers.
     101       20521 :         reg = INT_REG_CNT;
     102       42175 :         for (i=0; i<es->code->savedintcount; ++i) {
     103       22698 :                 while (nregdescint[--reg] != REG_SAV)
     104             :                         ;
     105             : #if STACKFRAME_PACKED_SAVED_REGISTERS
     106             :                 basesp -= 1 * SIZEOF_VOID_P;
     107             : #else
     108       21654 :                 basesp -= 1 * SIZE_OF_STACKSLOT;
     109             : #endif
     110       21654 :                 es->intregs[reg] = *((uintptr_t*) basesp);
     111             :         }
     112             : 
     113             :         // Restore saved flt registers.
     114             :         // XXX align?
     115       20521 :         reg = FLT_REG_CNT;
     116       20521 :         for (i=0; i<es->code->savedfltcount; ++i) {
     117           0 :                 while (nregdescfloat[--reg] != REG_SAV)
     118             :                         ;
     119           0 :                 basesp -= STACK_SLOTS_PER_FLOAT * SIZE_OF_STACKSLOT;
     120           0 :                 es->fltregs[reg] = *((double*) basesp);
     121             :         }
     122             : 
     123             :         // Adjust the stackpointer.
     124       20521 :         es->sp += framesize;
     125             : #if STACKFRAME_RA_BETWEEN_FRAMES
     126       20521 :         es->sp += SIZEOF_VOID_P; /* skip return address */
     127             : #endif
     128             : 
     129             :         // Set the program counter to the return address.
     130       20521 :         es->pc = ra;
     131             : 
     132             :         // In debugging mode clobber non-saved registers.
     133             : #if !defined(NDEBUG)
     134      348857 :         for (i=0; i<INT_REG_CNT; ++i)
     135      328336 :                 if (nregdescint[i] != REG_SAV && nregdescint[i] != REG_RES)
     136      164168 :                         es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
     137      348857 :         for (i=0; i<FLT_REG_CNT; ++i)
     138      328336 :                 if (nregdescfloat[i] != REG_SAV && nregdescfloat[i] != REG_RES)
     139      266773 :                         *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
     140             : #endif /* !defined(NDEBUG) */
     141       20521 : }
     142             : 
     143             : /**
     144             :  * Performs stack unwinding in case of an exception. This is done by
     145             :  * popping frames off the given execution state until a frame is reached
     146             :  * for which there is a handler. Execution will continue at the handler
     147             :  * site once the execution state is written back to the machine.
     148             :  *
     149             :  * @param es Execution state to be modified.
     150             :  * @param e The thrown exception object.
     151             :  *
     152             :  * This is specified in:
     153             :  *    The Java(TM) Virtual Machine Specification, Second Edition
     154             :  *    Section 3.6.5: Abrupt Method Invocation Completion
     155             :  */
     156       21025 : void executionstate_unwind_exception(executionstate_t* es, java_handle_t* e)
     157             : {
     158       21025 :         void* handler = NULL;
     159             : 
     160             :         // Iterate until we find an exception handler.
     161       62571 :         while (handler == NULL) {
     162             : 
     163             :                 // Search an exception handler in the current frame.
     164       41546 :                 handler = exceptions_handle_exception(e, es->pc, es->pv, es->sp);
     165             : 
     166             :                 // Jump directly into the handler in case we found one.
     167       41546 :                 if (handler != NULL)
     168       21025 :                         break;
     169             : 
     170             :                 // Find the codeinfo structure for the current frame.
     171       20521 :                 es->code = code_get_codeinfo_for_pv(es->pv);
     172             : 
     173             :                 // Pop one frame off the stack.
     174       20521 :                 executionstate_pop_stackframe(es);
     175             : 
     176             :                 // Get the PV for the parent Java method.
     177       20521 :                 es->pv = (uint8_t*) md_codegen_get_pv_from_pc(es->pc);
     178             : 
     179             :                 // After popping the frame the PC points to the instruction just after
     180             :                 // the invocation. To get the XPC we need to correct the PC to point
     181             :                 // just before the invocation. But we do not know how big the
     182             :                 // invocation site actually is, so we subtract one, which should be
     183             :                 // sufficient for our purposes.
     184       20521 :                 es->pc -= 1;
     185             :         }
     186             : 
     187             :         // Update the execution state to continue at the handler site.
     188       21025 :         es->pc = (uint8_t*) handler;
     189       21025 : }
     190             : 
     191             : 
     192             : /* executionstate_sanity_check *************************************************
     193             : 
     194             :    Perform some sanity checks for the md_executionstate_read and
     195             :    md_executionstate_write functions.
     196             : 
     197             : *******************************************************************************/
     198             : 
     199             : #if !defined(NDEBUG)
     200      218378 : void executionstate_sanity_check(void *context)
     201             : {
     202             :     /* estimate a minimum for the context size */
     203             : 
     204             : #define MINIMUM_CONTEXT_SIZE  (SIZEOF_VOID_P    * INT_REG_CNT \
     205             :                                        + sizeof(double) * FLT_REG_CNT)
     206             : 
     207             :         executionstate_t es1;
     208             :         executionstate_t es2;
     209             :         executionstate_t es3;
     210             :         unsigned int i;
     211             :         unsigned char reference[MINIMUM_CONTEXT_SIZE];
     212             : 
     213             :         /* keep a copy of (a prefix of) the context for reference */
     214             : 
     215      218378 :         os::memcpy(&reference, context, MINIMUM_CONTEXT_SIZE);
     216             : 
     217             :         /* different poisons */
     218             : 
     219      218378 :         os::memset(&es1, 0xc9, sizeof(executionstate_t));
     220      218377 :         os::memset(&es2, 0xb5, sizeof(executionstate_t));
     221      218378 :         os::memset(&es3, 0x6f, sizeof(executionstate_t));
     222             : 
     223      218377 :         md_executionstate_read(&es1, context);
     224             : 
     225             :         /* verify that item-by-item copying preserves the state */
     226             : 
     227      218378 :         es2.pc = es1.pc;
     228      218378 :         es2.sp = es1.sp;
     229      218378 :         es2.pv = es1.pv;
     230      218378 :         es2.ra = es1.ra;
     231      218378 :         es2.code = es1.code;
     232     3712421 :         for (i = 0; i < INT_REG_CNT; ++i)
     233     3494043 :                 es2.intregs[i] = es1.intregs[i];
     234     3712419 :         for (i = 0; i < FLT_REG_CNT; ++i)
     235     3494041 :                 es2.fltregs[i] = es1.fltregs[i];
     236             : 
     237             :         /* write it back - this should not change the context */
     238             :         /* We cannot check that completely, unfortunately, as we don't know */
     239             :         /* the size of the (OS-dependent) context. */
     240             : 
     241      218378 :         md_executionstate_write(&es2, context);
     242             : 
     243             :         /* Read it again, Sam! */
     244             : 
     245      218378 :         md_executionstate_read(&es3, context);
     246             : 
     247             :         /* Compare. Note: Because of the NAN madness, we cannot compare
     248             :          * doubles using '=='. */
     249             : 
     250      218377 :         assert(es3.pc == es1.pc);
     251      218377 :         assert(es3.sp == es1.sp);
     252      218377 :         assert(es3.pv == es1.pv);
     253     3712425 :         for (i = 0; i < INT_REG_CNT; ++i)
     254     3494048 :                 assert(es3.intregs[i] == es1.intregs[i]);
     255     3712425 :         for (i = 0; i < FLT_REG_CNT; ++i)
     256     3494047 :                 assert(memcmp(es3.fltregs+i, es1.fltregs+i, sizeof(double)) == 0);
     257             : 
     258             :         /* i386 and x86_64 do not have an RA register */
     259             : 
     260             : #if defined(__I386__) || defined(__X86_64__)
     261      218378 :         assert(es3.ra != es1.ra);
     262             : #else
     263             :         assert(es3.ra == es1.ra);
     264             : #endif
     265             : 
     266             :         /* "code" is not set by the md_* functions */
     267             : 
     268      218378 :         assert(es3.code != es1.code);
     269             : 
     270             :         /* assert that we have not messed up the context */
     271             : 
     272      218378 :         assert(memcmp(&reference, context, MINIMUM_CONTEXT_SIZE) == 0);
     273      218378 : }
     274             : #endif
     275             : 
     276             : 
     277             : /* executionstate_println ******************************************************
     278             : 
     279             :    Print execution state
     280             : 
     281             :    IN:
     282             :        es...............the execution state to print
     283             : 
     284             : *******************************************************************************/
     285             : 
     286             : #if !defined(NDEBUG)
     287           0 : void executionstate_println(executionstate_t *es)
     288             : {
     289             :         uint64_t *sp;
     290             :         int       slots;
     291             :         int       extraslots;
     292             :         int       i;
     293             : 
     294           0 :         if (!es) {
     295           0 :                 printf("(executionstate_t *)NULL\n");
     296           0 :                 return;
     297             :         }
     298             : 
     299           0 :         printf("executionstate_t:\n");
     300           0 :         printf("\tpc = %p", es->pc);
     301           0 :         printf("  sp = %p", es->sp);
     302           0 :         printf("  pv = %p", es->pv);
     303           0 :         printf("  ra = %p\n", es->ra);
     304             : 
     305             : #if defined(ENABLE_DISASSEMBLER)
     306             :         for (i=0; i<INT_REG_CNT; ++i) {
     307             :                 if (i%4 == 0)
     308             :                         printf("\t");
     309             :                 else
     310             :                         printf(" ");
     311             : # if SIZEOF_VOID_P == 8
     312             :                 printf("%-3s = %016lx", abi_registers_integer_name[i], es->intregs[i]);
     313             : # else
     314             :                 printf("%-3s = %08x", abi_registers_integer_name[i], (unsigned) es->intregs[i]);
     315             : # endif
     316             :                 if (i%4 == 3)
     317             :                         printf("\n");
     318             :         }
     319             : 
     320             :         for (i=0; i<FLT_REG_CNT; ++i) {
     321             :                 if (i%4 == 0)
     322             :                         printf("\t");
     323             :                 else
     324             :                         printf(" ");
     325             :                 printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
     326             :                 if (i%4 == 3)
     327             :                         printf("\n");
     328             :         }
     329             : #endif
     330             : 
     331           0 :         sp = (uint64_t *) es->sp;
     332             : 
     333           0 :         extraslots = 2;
     334             : 
     335           0 :         if (es->code) {
     336           0 :                 methoddesc *md = es->code->m->parseddesc;
     337           0 :                 slots = es->code->stackframesize;
     338           0 :                 extraslots = 1 + md->memuse;
     339             :         }
     340             :         else
     341           0 :                 slots = 0;
     342             : 
     343             : 
     344           0 :         if (slots) {
     345           0 :                 printf("\tstack slots(+%d) at sp:", extraslots);
     346           0 :                 for (i=0; i<slots+extraslots; ++i) {
     347           0 :                         if (i%4 == 0)
     348           0 :                                 printf("\n\t\t");
     349           0 :                         printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
     350           0 :                         printf("%016llx",(unsigned long long)*sp++);
     351           0 :                         printf("%c", (i >= slots) ? ')' : ' ');
     352             :                 }
     353           0 :                 printf("\n");
     354             :         }
     355             : 
     356           0 :         printf("\tcode: %p", (void*)es->code);
     357           0 :         if (es->code != NULL) {
     358           0 :                 printf(" stackframesize=%d ", es->code->stackframesize);
     359           0 :                 method_print(es->code->m);
     360             :         }
     361           0 :         printf("\n");
     362             : 
     363           0 :         printf("\n");
     364             : }
     365             : #endif
     366             : 
     367             : 
     368             : /*
     369             :  * These are local overrides for various environment variables in Emacs.
     370             :  * Please do not remove this and leave it at the end of the file, where
     371             :  * Emacs will automagically detect them.
     372             :  * ---------------------------------------------------------------------
     373             :  * Local variables:
     374             :  * mode: c++
     375             :  * indent-tabs-mode: t
     376             :  * c-basic-offset: 4
     377             :  * tab-width: 4
     378             :  * End:
     379             :  * vim:noexpandtab:sw=4:ts=4:
     380             :  */

Generated by: LCOV version 1.11