]> git.unchartedbackwaters.co.uk Git - francis/libjit.git/commitdiff
Use computed goto's in the interpreter if supported by the underlying compiler.
authorRhys Weatherley <rweather@southern-storm.com.au>
Fri, 21 May 2004 05:55:49 +0000 (05:55 +0000)
committerRhys Weatherley <rweather@southern-storm.com.au>
Fri, 21 May 2004 05:55:49 +0000 (05:55 +0000)
ChangeLog
configure.in
jit/.cvsignore
jit/Makefile.am
jit/jit-interp.c
jit/mklabel.sh [new file with mode: 0755]

index 8e1fdd0cbfb181524d7ce2bb0bd42957717a3950..197a5ee44cb70e16107bef6d1da0d35b11dbf14a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
        jit/jit-opcode.c, jitplus/jit-plus-function.cpp:
        add the "jit_insn_alloca" instruction.
 
+       * configure.in, jit/.cvsignore, jit/Makefile.am, jit/jit-interp.c,
+       jit/mklabel.sh: use computed goto's in the interpreter if supported
+       by the underlying compiler.
+
 2004-05-20  Rhys Weatherley  <rweather@southern-storm.com.au>
 
        * include/jit/jit-value.h, jit/jit-insn.c, jit/jit-value.c:
index d91559b0373891695747f9ccd4c87a28f207e613..fd1cc8def8df02debd1fef42aad1df24d034ef40 100644 (file)
@@ -362,6 +362,29 @@ else
        LIB_STDCPP=""
 fi
 
+dnl Check for computed goto support in the compiler.
+AC_MSG_CHECKING(for computed goto support)
+AC_TRY_COMPILE([], [
+       static void *labels[] = {&&label0, &&label1, &&label2};
+       unsigned char *pc = 0;
+       goto *labels[*pc];
+       label0: ;
+       label1: ;
+       label2: ;
+], AC_DEFINE(HAVE_COMPUTED_GOTO, 1, [Define if you have support for computed gotos]) compgoto=yes, compgoto=no)
+AC_MSG_RESULT($compgoto)
+AC_MSG_CHECKING(for pic computed goto support)
+AC_TRY_COMPILE([], [
+       static int labelOffsets[] =
+               {&&label0 - &&label0, &&label1 - &&label0, &&label2 - &&label0};
+       unsigned char *pc = 0;
+       goto *(&&label0 + labelOffsets[*pc]);
+       label0: ;
+       label1: ;
+       label2: ;
+], AC_DEFINE(HAVE_PIC_COMPUTED_GOTO, 1, [Define if you have PIC support for computed gotos]) piccompgoto=yes, piccompgoto=no)
+AC_MSG_RESULT($piccompgoto)
+
 dnl Checks for library functions.
 if test "x$suppress_libm" = "xno" ; then
        AC_CHECK_LIB(m, sin)
index 743b011c90db32a2065398f72553e9ac4cf8cac5..47f9d319073e7b916b332c5d14eb066210766413 100644 (file)
@@ -3,5 +3,6 @@ Makefile.in
 .deps
 .libs
 jit-apply-rules.h
+jit-interp-labels.h
 *.lo
 *.la
index a6234730fa234312ab5bafdd5be6419f443c8f8b..a0295a2b1914c4b3a71bcbae9d7baf268bd1b1b4 100644 (file)
@@ -52,3 +52,13 @@ libjit_la_SOURCES = \
 AM_CFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I. -I$(srcdir)
 
 libjit_la_LDFLAGS = -version-info $(LIBJIT_VERSION)
+
+jit-interp.lo: jit-interp-labels.h
+
+jit-interp-labels.h: $(top_srcdir)/include/jit/jit-opcode.h \
+               $(top_srcdir)/jit/jit-interp.h $(srcdir)/mklabel.sh
+       $(SHELL) $(srcdir)/mklabel.sh "$(AWK)" \
+               $(top_srcdir)/include/jit/jit-opcode.h \
+               $(top_srcdir)/jit/jit-interp.h >jit-interp-labels.h
+
+CLEANFILES = jit-interp-labels.h
index 6579e4b33bedf4de6d0bbf68b3f4f26aab2b5bca..34bd53cf3786cdda3b25b47e685505513c874a9f 100644 (file)
@@ -44,18 +44,19 @@ straight vanilla ANSI C.
 #if defined(JIT_BACKEND_INTERP)
 
 /*
- * Macros that help with the definition of the interpreter switch loop.
+ * Determine what kind of interpreter dispatch to use.
  */
-#define        VMSWITCH(pc)    \
-               for(;;) \
-               { \
-                       switch((int)*((jit_nint *)(pc)))
-#define        VMSWITCHEND             \
-               }
-#define        VMCASE(opcode)  \
-               case opcode
-#define        VMBREAK                 \
-               break
+#ifdef HAVE_COMPUTED_GOTO
+       #if defined(PIC) && defined(HAVE_PIC_COMPUTED_GOTO)
+               #define JIT_INTERP_TOKEN_PIC    1
+       #elif defined(PIC)
+               #define JIT_INTERP_SWITCH               1
+       #else
+               #define JIT_INTERP_TOKEN                1
+       #endif
+#else /* !HAVE_COMPUTED_GOTO */
+       #define JIT_INTERP_SWITCH                       1
+#endif /* !HAVE_COMPUTED_GOTO */
 
 /*
  * Modify the program counter and stack pointer.
@@ -243,6 +244,9 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
        void *handler;
        jit_jmp_buf *jbuf;
 
+       /* Define the label table for computed goto dispatch */
+       #include "jit-interp-labels.h"
+
        /* Set up the stack frame for this function */
        frame = (jit_item *)alloca(func->frame_size);
        stacktop = frame + func->working_area;
@@ -4468,7 +4472,6 @@ void _jit_run_function(jit_function_interp_t func, jit_item *args,
                VMCASE(JIT_OP_PUSH_FLOAT64):
                VMCASE(JIT_OP_PUSH_NFLOAT):
                VMCASE(JIT_OP_FLUSH_SMALL_STRUCT):
-               VMCASE(JIT_OP_END_MARKER):
                VMCASE(JIT_OP_ENTER_CATCH):
                VMCASE(JIT_OP_ENTER_FINALLY):
                VMCASE(JIT_OP_ENTER_FILTER):
diff --git a/jit/mklabel.sh b/jit/mklabel.sh
new file mode 100755 (executable)
index 0000000..fe4b023
--- /dev/null
@@ -0,0 +1,298 @@
+#!/bin/sh
+#
+# mklabel.sh - Make label tables for computed goto's.
+#
+# Copyright (C) 2002, 2004  Southern Storm Software, Pty Ltd.
+#
+# 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 of the License, 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+# Usage: mklabel.sh awk jit-opcode.h jit-interp.h >jit-interp-labels.h
+
+# Validate the parameters.
+if test "x$1" = "x" ; then
+       echo "Usage: $0 awk jit-opcode.h jit-interp.h >jit-interp-labels.h" 1>&2
+       exit 1
+fi
+if test "x$2" = "x" ; then
+       echo "Usage: $0 awk jit-opcode.h jit-interp.h >jit-interp-labels.h" 1>&2
+       exit 1
+fi
+if test "x$3" = "x" ; then
+       echo "Usage: $0 awk jit-opcode.h jit-interp.h >jit-interp-labels.h" 1>&2
+       exit 1
+fi
+
+# Output the "do not edit" header.
+echo '/* This file is automatically generated - do not edit */'
+echo ''
+
+# Define a null assembly statement.  This is a trick to stop gcc doing
+# tail-end combination on the cases within the switch statements.
+echo '#if defined(__GNUC__)'
+echo '#define VMNULLASM()         __asm__("")'
+echo '#else'
+echo '#define VMNULLASM()'
+echo '#endif'
+echo '#define VMFETCH(pc)         ((int)*((jit_nint *)(pc)))'
+echo ''
+
+# Are we compiling an interpreter that uses PIC computed goto's?
+echo '#if defined(JIT_INTERP_TOKEN_PIC)'
+echo ''
+
+# Output a table of PIC labels, based on an incoming stream
+# of #define's for opcodes.  Some awks don't support hex
+# string to number conversion, which is why we have to convert
+# the opcode value the hard way.
+pic_table()
+{
+       "$1" 'BEGIN{
+                     nextval=0
+                 }
+                 {
+                     currval=0;
+                         hexval=$3
+                         ch=substr(hexval,1,1);
+                         if(ch == "(")
+                           hexval=$5
+                         ch=substr(hexval,3,1);
+                         if(ch == "0") currval=currval+0; else
+                         if(ch == "1") currval=currval+1; else
+                         if(ch == "2") currval=currval+2; else
+                         if(ch == "3") currval=currval+3; else
+                         if(ch == "4") currval=currval+4; else
+                         if(ch == "5") currval=currval+5; else
+                         if(ch == "6") currval=currval+6; else
+                         if(ch == "7") currval=currval+7; else
+                         if(ch == "8") currval=currval+8; else
+                         if(ch == "9") currval=currval+9; else
+                         if(ch == "A") currval=currval+10; else
+                         if(ch == "B") currval=currval+11; else
+                         if(ch == "C") currval=currval+12; else
+                         if(ch == "D") currval=currval+13; else
+                         if(ch == "E") currval=currval+14; else
+                         if(ch == "F") currval=currval+15;
+                         currval=currval*16;
+                         ch=substr(hexval,4,1);
+                         if(ch == "0") currval=currval+0; else
+                         if(ch == "1") currval=currval+1; else
+                         if(ch == "2") currval=currval+2; else
+                         if(ch == "3") currval=currval+3; else
+                         if(ch == "4") currval=currval+4; else
+                         if(ch == "5") currval=currval+5; else
+                         if(ch == "6") currval=currval+6; else
+                         if(ch == "7") currval=currval+7; else
+                         if(ch == "8") currval=currval+8; else
+                         if(ch == "9") currval=currval+9; else
+                         if(ch == "A") currval=currval+10; else
+                         if(ch == "B") currval=currval+11; else
+                         if(ch == "C") currval=currval+12; else
+                         if(ch == "D") currval=currval+13; else
+                         if(ch == "E") currval=currval+14; else
+                         if(ch == "F") currval=currval+15;
+                         currval=currval*16;
+                         ch=substr(hexval,5,1);
+                         if(ch == "0") currval=currval+0; else
+                         if(ch == "1") currval=currval+1; else
+                         if(ch == "2") currval=currval+2; else
+                         if(ch == "3") currval=currval+3; else
+                         if(ch == "4") currval=currval+4; else
+                         if(ch == "5") currval=currval+5; else
+                         if(ch == "6") currval=currval+6; else
+                         if(ch == "7") currval=currval+7; else
+                         if(ch == "8") currval=currval+8; else
+                         if(ch == "9") currval=currval+9; else
+                         if(ch == "A") currval=currval+10; else
+                         if(ch == "B") currval=currval+11; else
+                         if(ch == "C") currval=currval+12; else
+                         if(ch == "D") currval=currval+13; else
+                         if(ch == "E") currval=currval+14; else
+                         if(ch == "F") currval=currval+15;
+                         currval=currval*16;
+                         ch=substr(hexval,6,1);
+                         if(ch == "0") currval=currval+0; else
+                         if(ch == "1") currval=currval+1; else
+                         if(ch == "2") currval=currval+2; else
+                         if(ch == "3") currval=currval+3; else
+                         if(ch == "4") currval=currval+4; else
+                         if(ch == "5") currval=currval+5; else
+                         if(ch == "6") currval=currval+6; else
+                         if(ch == "7") currval=currval+7; else
+                         if(ch == "8") currval=currval+8; else
+                         if(ch == "9") currval=currval+9; else
+                         if(ch == "A") currval=currval+10; else
+                         if(ch == "B") currval=currval+11; else
+                         if(ch == "C") currval=currval+12; else
+                         if(ch == "D") currval=currval+13; else
+                         if(ch == "E") currval=currval+14; else
+                         if(ch == "F") currval=currval+15;
+                     while(nextval < currval)
+                         {
+                             print "   &&'"$2"' - &&JIT_OP_NOP_label,"
+                             ++nextval
+                         }
+                     print "   &&" $2 "_label - &&JIT_OP_NOP_label,"
+                     ++nextval
+                 }' -
+       return 0
+}
+
+# Output the label table (PIC version).
+echo 'static int const main_label_table[JIT_OP_END_MARKER] = {'
+grep '^#define[        ]*JIT_OP_' "$2" | grep -v 'JIT_OP_NUM_OPCODES' | \
+       pic_table "$1" JIT_OP_NOP_label
+grep '^#define[        ]*JIT_OP_' "$3" | grep -v 'JIT_OP_NUM_INTERP_OPCODES' | \
+       grep -v 'JIT_OP_END_MARKER' | pic_table "$1" JIT_OP_NOP_label
+echo '};'
+echo ''
+
+# Output the helper macros (PIC).
+echo '#define VMSWITCH(pc)        { goto *(&&JIT_OP_NOP_label + main_label_table[VMFETCH((pc))]);'
+echo '#define VMSWITCHEND         }'
+echo '#define VMCASE(val)         val##_label'
+echo '#define VMBREAK             \
+            goto *(&&JIT_OP_NOP_label + main_label_table[VMFETCH((pc))])'
+echo ''
+
+# Now to handle the non-PIC case of using computed goto's.
+echo '#elif defined(JIT_INTERP_TOKEN)'
+echo ''
+
+# Output a table of non-PIC labels, based on an incoming stream
+# of #define's for opcodes.  Some awks don't support hex
+# string to number conversion, which is why we have to convert
+# the opcode value the hard way.
+non_pic_table()
+{
+       "$1" 'BEGIN{
+                     nextval=0
+                 }
+                 {
+                     currval=0;
+                         hexval=$3
+                         ch=substr(hexval,1,1);
+                         if(ch == "(")
+                           hexval=$5
+                         ch=substr(hexval,3,1);
+                         if(ch == "0") currval=currval+0; else
+                         if(ch == "1") currval=currval+1; else
+                         if(ch == "2") currval=currval+2; else
+                         if(ch == "3") currval=currval+3; else
+                         if(ch == "4") currval=currval+4; else
+                         if(ch == "5") currval=currval+5; else
+                         if(ch == "6") currval=currval+6; else
+                         if(ch == "7") currval=currval+7; else
+                         if(ch == "8") currval=currval+8; else
+                         if(ch == "9") currval=currval+9; else
+                         if(ch == "A") currval=currval+10; else
+                         if(ch == "B") currval=currval+11; else
+                         if(ch == "C") currval=currval+12; else
+                         if(ch == "D") currval=currval+13; else
+                         if(ch == "E") currval=currval+14; else
+                         if(ch == "F") currval=currval+15;
+                         currval=currval*16;
+                         ch=substr(hexval,4,1);
+                         if(ch == "0") currval=currval+0; else
+                         if(ch == "1") currval=currval+1; else
+                         if(ch == "2") currval=currval+2; else
+                         if(ch == "3") currval=currval+3; else
+                         if(ch == "4") currval=currval+4; else
+                         if(ch == "5") currval=currval+5; else
+                         if(ch == "6") currval=currval+6; else
+                         if(ch == "7") currval=currval+7; else
+                         if(ch == "8") currval=currval+8; else
+                         if(ch == "9") currval=currval+9; else
+                         if(ch == "A") currval=currval+10; else
+                         if(ch == "B") currval=currval+11; else
+                         if(ch == "C") currval=currval+12; else
+                         if(ch == "D") currval=currval+13; else
+                         if(ch == "E") currval=currval+14; else
+                         if(ch == "F") currval=currval+15;
+                         currval=currval*16;
+                         ch=substr(hexval,5,1);
+                         if(ch == "0") currval=currval+0; else
+                         if(ch == "1") currval=currval+1; else
+                         if(ch == "2") currval=currval+2; else
+                         if(ch == "3") currval=currval+3; else
+                         if(ch == "4") currval=currval+4; else
+                         if(ch == "5") currval=currval+5; else
+                         if(ch == "6") currval=currval+6; else
+                         if(ch == "7") currval=currval+7; else
+                         if(ch == "8") currval=currval+8; else
+                         if(ch == "9") currval=currval+9; else
+                         if(ch == "A") currval=currval+10; else
+                         if(ch == "B") currval=currval+11; else
+                         if(ch == "C") currval=currval+12; else
+                         if(ch == "D") currval=currval+13; else
+                         if(ch == "E") currval=currval+14; else
+                         if(ch == "F") currval=currval+15;
+                         currval=currval*16;
+                         ch=substr(hexval,6,1);
+                         if(ch == "0") currval=currval+0; else
+                         if(ch == "1") currval=currval+1; else
+                         if(ch == "2") currval=currval+2; else
+                         if(ch == "3") currval=currval+3; else
+                         if(ch == "4") currval=currval+4; else
+                         if(ch == "5") currval=currval+5; else
+                         if(ch == "6") currval=currval+6; else
+                         if(ch == "7") currval=currval+7; else
+                         if(ch == "8") currval=currval+8; else
+                         if(ch == "9") currval=currval+9; else
+                         if(ch == "A") currval=currval+10; else
+                         if(ch == "B") currval=currval+11; else
+                         if(ch == "C") currval=currval+12; else
+                         if(ch == "D") currval=currval+13; else
+                         if(ch == "E") currval=currval+14; else
+                         if(ch == "F") currval=currval+15;
+                     while(nextval < currval)
+                         {
+                             print "   &&'"$2"',"
+                             ++nextval
+                         }
+                     print "   &&" $2 "_label,"
+                     ++nextval
+                 }' -
+       return 0
+}
+
+# Output the label table (non-PIC).
+echo 'static void * main_label_table[JIT_OP_END_MARKER] = {'
+grep '^#define[        ]*JIT_OP_' "$2" | grep -v 'JIT_OP_NUM_OPCODES' | \
+       non_pic_table "$1" JIT_OP_NOP_label
+grep '^#define[        ]*JIT_OP_' "$3" | grep -v 'JIT_OP_NUM_INTERP_OPCODES' | \
+       grep -v 'JIT_OP_END_MARKER' | non_pic_table "$1" JIT_OP_NOP_label
+echo '};'
+echo ''
+
+# Output the helper macros (non-PIC).
+echo '#define VMSWITCH(pc)        { goto *main_label_table[VMFETCH((pc))];'
+echo '#define VMSWITCHEND         }'
+echo '#define VMCASE(val)         val##_label'
+echo '#define VMBREAK             \
+            goto *main_label_table[VMFETCH((pc))]'
+echo ''
+
+# Output the non-goto case of the helper macros.
+echo '#else /* JIT_INTERP_SWITCH */'
+echo ''
+echo '#define VMSWITCH(pc)        for(;;) { switch(VMFETCH((pc)))'
+echo '#define VMSWITCHEND         }'
+echo '#define VMCASE(val)         case (val)'
+echo '#define VMBREAK             VMNULLASM(); break'
+echo ''
+echo '#endif /* JIT_INTERP_SWITCH */'
+
+# Done.
+exit 0