X-Git-Url: https://git.hcoop.net/bpt/guile.git/blobdiff_plain/b07a3cfda145c11039eb92a9d92ee2257479e2b7..731dd0ce191bf4f3ba8fedfe0e08c0e67a966ce4:/libguile/vm-engine.h diff --git a/libguile/vm-engine.h b/libguile/vm-engine.h index 6bb235401..d69328944 100644 --- a/libguile/vm-engine.h +++ b/libguile/vm-engine.h @@ -1,43 +1,20 @@ -/* Copyright (C) 2001 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. +/* Copyright (C) 2001, 2009 Free Software Foundation, Inc. * - * You should have received a copy of the GNU General Public License - * along with this software; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307 USA - * - * As a special exception, the Free Software Foundation gives permission - * for additional uses of the text contained in its release of GUILE. - * - * The exception is that, if you link the GUILE library with other files - * to produce an executable, this does not by itself cause the - * resulting executable to be covered by the GNU General Public License. - * Your use of that executable is in no way restricted on account of - * linking the GUILE library code into it. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. * - * This exception does not however invalidate any other reasons why - * the executable file might be covered by the GNU General Public License. + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * This exception applies only to the code released by the - * Free Software Foundation under the name GUILE. If you copy - * code from other Free Software Foundation releases into a copy of - * GUILE, as the General Public License permits, the exception does - * not apply to the code that you add in this way. To avoid misleading - * anyone as to the status of such modified files, you must delete - * this exception notice from them. - * - * If you write modifications of your own for GUILE, it is your choice - * whether to permit this exception to apply to your modifications. - * If you do not wish that, delete this exception notice. */ + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ /* This file is included in vm_engine.c */ @@ -77,13 +54,9 @@ #endif #endif #ifdef __i386__ -/* gcc on lenny actually crashes if we allocate these variables in registers. - hopefully this is the only one of these. */ -#if !(__GNUC__==4 && __GNUC_MINOR__==1 && __GNUC_PATCHLEVEL__==2) -#define IP_REG asm("%esi") -#define SP_REG asm("%edi") -#define FP_REG -#endif +/* too few registers! because of register allocation errors with various gcs, + just punt on explicit assignments on i386, hoping that the "register" + declaration will be sufficient. */ #endif #if defined(PPC) || defined(_POWER) || defined(_IBMR2) #define IP_REG asm("26") @@ -134,7 +107,6 @@ ip = vp->ip; \ sp = vp->sp; \ fp = vp->fp; \ - stack_base = fp ? SCM_FRAME_UPPER_ADDRESS (fp) - 1 : vp->stack_base; \ } #define SYNC_REGISTER() \ @@ -144,22 +116,36 @@ vp->fp = fp; \ } +/* FIXME */ +#define ASSERT_VARIABLE(x) \ + do { if (!SCM_VARIABLEP (x)) { SYNC_REGISTER (); abort(); } \ + } while (0) +#define ASSERT_BOUND_VARIABLE(x) \ + do { ASSERT_VARIABLE (x); \ + if (SCM_VARIABLE_REF (x) == SCM_UNDEFINED) \ + { SYNC_REGISTER (); abort(); } \ + } while (0) + #ifdef VM_ENABLE_PARANOID_ASSERTIONS #define CHECK_IP() \ do { if (ip < bp->base || ip - bp->base > bp->len) abort (); } while (0) +#define ASSERT_ALIGNED_PROCEDURE() \ + do { if ((scm_t_bits)bp % 8) abort (); } while (0) +#define ASSERT_BOUND(x) \ + do { if ((x) == SCM_UNDEFINED) { SYNC_REGISTER (); abort(); } \ + } while (0) #else #define CHECK_IP() +#define ASSERT_ALIGNED_PROCEDURE() +#define ASSERT_BOUND(x) #endif -/* Get a local copy of the program's "object table" (i.e. the vector of - external bindings that are referenced by the program), initialized by - `load-program'. */ -/* XXX: We could instead use the "simple vector macros", thus not having to - call `scm_vector_writable_elements ()' and the likes. */ +/* Cache the object table and free variables. */ #define CACHE_PROGRAM() \ { \ if (bp != SCM_PROGRAM_DATA (program)) { \ bp = SCM_PROGRAM_DATA (program); \ + ASSERT_ALIGNED_PROCEDURE (); \ if (SCM_I_IS_VECTOR (SCM_PROGRAM_OBJTABLE (program))) { \ objects = SCM_I_VECTOR_WELTS (SCM_PROGRAM_OBJTABLE (program)); \ object_count = SCM_I_VECTOR_LENGTH (SCM_PROGRAM_OBJTABLE (program)); \ @@ -168,6 +154,19 @@ object_count = 0; \ } \ } \ + { \ + SCM c = SCM_PROGRAM_FREE_VARIABLES (program); \ + if (SCM_I_IS_VECTOR (c)) \ + { \ + free_vars = SCM_I_VECTOR_WELTS (c); \ + free_vars_count = SCM_I_VECTOR_LENGTH (c); \ + } \ + else \ + { \ + free_vars = NULL; \ + free_vars_count = 0; \ + } \ + } \ } #define SYNC_BEFORE_GC() \ @@ -185,14 +184,6 @@ * Error check */ -#undef CHECK_EXTERNAL -#if VM_CHECK_EXTERNAL -#define CHECK_EXTERNAL(e) \ - do { if (SCM_UNLIKELY (!SCM_CONSP (e))) goto vm_error_external; } while (0) -#else -#define CHECK_EXTERNAL(e) -#endif - /* Accesses to a program's object table. */ #if VM_CHECK_OBJECT #define CHECK_OBJECT(_num) \ @@ -201,6 +192,13 @@ #define CHECK_OBJECT(_num) #endif +#if VM_CHECK_FREE_VARIABLES +#define CHECK_FREE_VARIABLE(_num) \ + do { if (SCM_UNLIKELY ((_num) >= free_vars_count)) goto vm_error_free_variable; } while (0) +#else +#define CHECK_FREE_VARIABLE(_num) +#endif + /* * Hooks @@ -253,11 +251,11 @@ #endif #define CHECK_OVERFLOW() \ - if (sp > stack_limit) \ + if (sp >= stack_limit) \ goto vm_error_stack_overflow #define CHECK_UNDERFLOW() \ - if (sp < stack_base) \ + if (sp < SCM_FRAME_UPPER_ADDRESS (fp)) \ goto vm_error_stack_underflow; #define PUSH(x) do { sp++; CHECK_OVERFLOW (); *sp = x; } while (0) @@ -361,70 +359,16 @@ do { \ } -/* - * Stack frame - */ - -#define INIT_ARGS() \ -{ \ - if (SCM_UNLIKELY (bp->nrest)) \ - { \ - int n = nargs - (bp->nargs - 1); \ - if (n < 0) \ - goto vm_error_wrong_num_args; \ - /* NB, can cause GC while setting up the \ - stack frame */ \ - POP_LIST (n); \ - } \ - else \ - { \ - if (SCM_UNLIKELY (nargs != bp->nargs)) \ - goto vm_error_wrong_num_args; \ - } \ -} - /* See frames.h for the layout of stack frames */ /* When this is called, bp points to the new program data, and the arguments are already on the stack */ -#define NEW_FRAME() \ -{ \ - int i; \ - SCM *dl, *data; \ - scm_byte_t *ra = ip; \ - \ - /* Save old registers */ \ - ra = ip; \ - dl = fp; \ - \ - /* New registers */ \ - fp = sp - bp->nargs + 1; \ - data = SCM_FRAME_DATA_ADDRESS (fp); \ - sp = data + 3; \ - CHECK_OVERFLOW (); \ - stack_base = sp; \ - ip = bp->base; \ - \ - /* Init local variables */ \ - for (i=bp->nlocs; i; i--) \ - data[-i] = SCM_UNDEFINED; \ - \ - /* Set frame data */ \ - data[3] = (SCM)ra; \ - data[2] = 0x0; \ - data[1] = (SCM)dl; \ - \ - /* Postpone initializing external vars, \ - because if the CONS causes a GC, we \ - want the stack marker to see the data \ - array formatted as expected. */ \ - data[0] = SCM_UNDEFINED; \ - external = SCM_PROGRAM_EXTERNALS (fp[-1]); \ - for (i = 0; i < bp->nexts; i++) \ - CONS (external, SCM_UNDEFINED, external); \ - data[0] = external; \ -} - -#define CACHE_EXTERNAL() external = fp[bp->nargs + bp->nlocs] +#define DROP_FRAME() \ + { \ + sp -= 3; \ + NULLSTACK (3); \ + CHECK_UNDERFLOW (); \ + } + /* Local Variables: