From b49d65a276f2c37776db354927130a574cc5e2de Mon Sep 17 00:00:00 2001 From: Stephen Dolan Date: Tue, 18 Jun 2013 01:36:18 +0100 Subject: [PATCH 1/2] Fold opcode.{c,h} into bytecode.{c,h} --- Makefile.am | 8 ++++---- builtin.h | 11 +---------- bytecode.c | 32 +++++++++++++++++++++++++++++++- bytecode.h | 46 ++++++++++++++++++++++++++++++++++++++++++++-- compile.c | 1 - compile.h | 6 +----- execute.c | 1 - jq_parser.h | 2 ++ opcode.c | 31 ------------------------------- opcode.h | 41 ----------------------------------------- 10 files changed, 83 insertions(+), 96 deletions(-) delete mode 100644 opcode.c delete mode 100644 opcode.h diff --git a/Makefile.am b/Makefile.am index c4f79e04..ceeadb1a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,11 +2,11 @@ JQ_INCS = jq_parser.h builtin.h bytecode.h compile.h execute.h \ forkable_stack.h frame_layout.h jv.h jv_alloc.h jv_aux.h jv_dtoa.h \ - jv_file.h jv_parse.h jv_unicode.h locfile.h opcode.h opcode_list.h \ - parser.y jv_utf8_tables.h lexer.l + jv_file.h jv_parse.h jv_unicode.h locfile.h opcode_list.h parser.y \ + jv_utf8_tables.h lexer.l -JQ_SRC = locfile.c opcode.c bytecode.c compile.c execute.c builtin.c \ - jv.c jv_parse.c jv_print.c jv_dtoa.c jv_unicode.c jv_aux.c jv_file.c \ +JQ_SRC = locfile.c bytecode.c compile.c execute.c builtin.c jv.c \ + jv_parse.c jv_print.c jv_dtoa.c jv_unicode.c jv_aux.c jv_file.c \ jv_alloc.c jq_test.c ${JQ_INCS} diff --git a/builtin.h b/builtin.h index fdbce92a..63562635 100644 --- a/builtin.h +++ b/builtin.h @@ -1,20 +1,11 @@ #ifndef BUILTIN_H #define BUILTIN_H +#include "bytecode.h" #include "compile.h" int builtins_bind(block*); - -typedef void (*cfunction_ptr)(void); - -struct cfunction { - cfunction_ptr fptr; - const char* name; - int nargs; -}; - - jv cfunction_invoke(struct cfunction* function, jv input[]); diff --git a/bytecode.c b/bytecode.c index 184cf983..1277fdc1 100644 --- a/bytecode.c +++ b/bytecode.c @@ -3,9 +3,39 @@ #include #include "bytecode.h" -#include "opcode.h" #include "jv_alloc.h" +// flags, length +#define NONE 0, 1 +#define CONSTANT OP_HAS_CONSTANT, 2 +#define VARIABLE (OP_HAS_VARIABLE | OP_HAS_BINDING), 3 +#define BRANCH OP_HAS_BRANCH, 2 +#define CFUNC (OP_HAS_CFUNC | OP_HAS_BINDING), 3 +#define UFUNC (OP_HAS_UFUNC | OP_HAS_BINDING | OP_IS_CALL_PSEUDO), 4 +#define DEFINITION (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 0 +#define CLOSURE_REF_IMM (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 2 + +#define OP(name, imm, in, out) \ + {name, #name, imm, in, out}, + +static const struct opcode_description opcode_descriptions[] = { +#include "opcode_list.h" +}; + +static const struct opcode_description invalid_opcode_description = { + -1, "#INVALID", 0, 0, 0, 0 +}; + + +const struct opcode_description* opcode_describe(opcode op) { + if ((int)op >= 0 && (int)op < NUM_OPCODES) { + return &opcode_descriptions[op]; + } else { + return &invalid_opcode_description; + } +} + + static int bytecode_operation_length(uint16_t* codeptr) { int length = opcode_describe(*codeptr)->length; if (*codeptr == CALL_JQ) { diff --git a/bytecode.h b/bytecode.h index 70929c91..ba5fec3a 100644 --- a/bytecode.h +++ b/bytecode.h @@ -3,10 +3,52 @@ #include #include "jv.h" -#include "opcode.h" -#include "builtin.h" + +typedef enum { +#define OP(name, imm, in, out) name, +#include "opcode_list.h" +#undef OP +} opcode; + +enum { + NUM_OPCODES = +#define OP(name, imm, in, out) +1 +#include "opcode_list.h" +#undef OP +}; + +enum { + OP_HAS_CONSTANT = 2, + OP_HAS_VARIABLE = 4, + OP_HAS_BRANCH = 8, + OP_HAS_CFUNC = 32, + OP_HAS_UFUNC = 64, + OP_IS_CALL_PSEUDO = 128, + OP_HAS_BINDING = 1024, +}; +struct opcode_description { + opcode op; + const char* name; + + int flags; + + // length in 16-bit units + int length; + + int stack_in, stack_out; +}; + +const struct opcode_description* opcode_describe(opcode op); + #define MAX_CFUNCTION_ARGS 10 +typedef void (*cfunction_ptr)(void); +struct cfunction { + cfunction_ptr fptr; + const char* name; + int nargs; +}; + struct symbol_table { struct cfunction* cfunctions; int ncfunctions; diff --git a/compile.c b/compile.c index 4dda1011..248d363e 100644 --- a/compile.c +++ b/compile.c @@ -2,7 +2,6 @@ #include #include #include -#include "opcode.h" #include "compile.h" #include "bytecode.h" #include "locfile.h" diff --git a/compile.h b/compile.h index 4ac7168b..531e853e 100644 --- a/compile.h +++ b/compile.h @@ -2,13 +2,9 @@ #define COMPILE_H #include #include "jv.h" -#include "opcode.h" +#include "bytecode.h" #include "locfile.h" -struct bytecode; -struct symbol_table; -struct cfunction; - struct inst; typedef struct inst inst; diff --git a/execute.c b/execute.c index 3a5512aa..b43ad26a 100644 --- a/execute.c +++ b/execute.c @@ -6,7 +6,6 @@ #include "execute.h" #include "exec_stack.h" -#include "opcode.h" #include "bytecode.h" #include "jv_alloc.h" diff --git a/jq_parser.h b/jq_parser.h index 8dc37163..809ace06 100644 --- a/jq_parser.h +++ b/jq_parser.h @@ -1,5 +1,7 @@ #ifndef JQ_PARSER_H #define JQ_PARSER_H +#include "locfile.h" +#include "compile.h" int jq_parse(struct locfile* source, block* answer); int jq_parse_library(struct locfile* locations, block* answer); diff --git a/opcode.c b/opcode.c deleted file mode 100644 index 4e785b8f..00000000 --- a/opcode.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "opcode.h" - -// flags, length -#define NONE 0, 1 -#define CONSTANT OP_HAS_CONSTANT, 2 -#define VARIABLE (OP_HAS_VARIABLE | OP_HAS_BINDING), 3 -#define BRANCH OP_HAS_BRANCH, 2 -#define CFUNC (OP_HAS_CFUNC | OP_HAS_BINDING), 3 -#define UFUNC (OP_HAS_UFUNC | OP_HAS_BINDING | OP_IS_CALL_PSEUDO), 4 -#define DEFINITION (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 0 -#define CLOSURE_REF_IMM (OP_IS_CALL_PSEUDO | OP_HAS_BINDING), 2 - -#define OP(name, imm, in, out) \ - {name, #name, imm, in, out}, - -static const struct opcode_description opcode_descriptions[] = { -#include "opcode_list.h" -}; - -static const struct opcode_description invalid_opcode_description = { - -1, "#INVALID", 0, 0, 0, 0 -}; - - -const struct opcode_description* opcode_describe(opcode op) { - if ((int)op >= 0 && (int)op < NUM_OPCODES) { - return &opcode_descriptions[op]; - } else { - return &invalid_opcode_description; - } -} diff --git a/opcode.h b/opcode.h deleted file mode 100644 index ee956e27..00000000 --- a/opcode.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef OPCODE_H -#define OPCODE_H -#include - -typedef enum { -#define OP(name, imm, in, out) name, -#include "opcode_list.h" -#undef OP -} opcode; - -enum { - NUM_OPCODES = -#define OP(name, imm, in, out) +1 -#include "opcode_list.h" -#undef OP -}; - -enum { - OP_HAS_CONSTANT = 2, - OP_HAS_VARIABLE = 4, - OP_HAS_BRANCH = 8, - OP_HAS_CFUNC = 32, - OP_HAS_UFUNC = 64, - OP_IS_CALL_PSEUDO = 128, - OP_HAS_BINDING = 1024, -}; -struct opcode_description { - opcode op; - const char* name; - - int flags; - - // length in 16-bit units - int length; - - int stack_in, stack_out; -}; - -const struct opcode_description* opcode_describe(opcode op); - -#endif From 7af88962eea41fd25b483f1e4ef750bfd8a999e8 Mon Sep 17 00:00:00 2001 From: Stephen Dolan Date: Fri, 21 Jun 2013 12:06:28 +0100 Subject: [PATCH 2/2] Move cfunction invocation code to the interpreter loop. --- builtin.c | 18 +----------------- builtin.h | 3 --- bytecode.h | 2 +- execute.c | 24 ++++++++++++++++++++---- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/builtin.c b/builtin.c index a2adb1ac..bfad155d 100644 --- a/builtin.c +++ b/builtin.c @@ -3,29 +3,13 @@ #include "builtin.h" #include "compile.h" #include "jq_parser.h" +#include "bytecode.h" #include "locfile.h" #include "jv_aux.h" #include "jv_file.h" #include "jv_unicode.h" - -typedef jv (*func_1)(jv); -typedef jv (*func_2)(jv,jv); -typedef jv (*func_3)(jv,jv,jv); -typedef jv (*func_4)(jv,jv,jv,jv); -typedef jv (*func_5)(jv,jv,jv,jv,jv); -jv cfunction_invoke(struct cfunction* function, jv input[]) { - switch (function->nargs) { - case 1: return ((func_1)function->fptr)(input[0]); - case 2: return ((func_2)function->fptr)(input[0], input[1]); - case 3: return ((func_3)function->fptr)(input[0], input[1], input[2]); - case 4: return ((func_4)function->fptr)(input[0], input[1], input[2], input[3]); - case 5: return ((func_5)function->fptr)(input[0], input[1], input[2], input[3], input[4]); - default: return jv_invalid_with_msg(jv_string("Function takes too many arguments")); - } -} - static jv type_error(jv bad, const char* msg) { jv err = jv_invalid_with_msg(jv_string_fmt("%s %s", jv_kind_name(jv_get_kind(bad)), diff --git a/builtin.h b/builtin.h index 63562635..1aab133f 100644 --- a/builtin.h +++ b/builtin.h @@ -6,7 +6,4 @@ int builtins_bind(block*); -jv cfunction_invoke(struct cfunction* function, jv input[]); - - #endif diff --git a/bytecode.h b/bytecode.h index ba5fec3a..b81e1478 100644 --- a/bytecode.h +++ b/bytecode.h @@ -42,7 +42,7 @@ const struct opcode_description* opcode_describe(opcode op); #define MAX_CFUNCTION_ARGS 10 -typedef void (*cfunction_ptr)(void); +typedef void (*cfunction_ptr)(); struct cfunction { cfunction_ptr fptr; const char* name; diff --git a/execute.c b/execute.c index b43ad26a..ad7419b2 100644 --- a/execute.c +++ b/execute.c @@ -241,6 +241,8 @@ static void jq_reset(jq_state *jq) { } + + void print_error(jv value) { assert(!jv_is_valid(value)); jv msg = jv_invalid_get_msg(value); @@ -601,12 +603,26 @@ jv jq_next(jq_state *jq) { case CALL_BUILTIN: { int nargs = *pc++; jv top = stack_pop(jq); - cfunc_input[0] = top; + jv* in = cfunc_input; + in[0] = top; for (int i = 1; i < nargs; i++) { - cfunc_input[i] = stack_pop(jq); + in[i] = stack_pop(jq); } - struct cfunction* func = &frame_current(jq)->bc->globals->cfunctions[*pc++]; - top = cfunction_invoke(func, cfunc_input); + struct cfunction* function = &frame_current(jq)->bc->globals->cfunctions[*pc++]; + typedef jv (*func_1)(jv); + typedef jv (*func_2)(jv,jv); + typedef jv (*func_3)(jv,jv,jv); + typedef jv (*func_4)(jv,jv,jv,jv); + typedef jv (*func_5)(jv,jv,jv,jv,jv); + switch (function->nargs) { + case 1: top = ((func_1)function->fptr)(in[0]); break; + case 2: top = ((func_2)function->fptr)(in[0], in[1]); break; + case 3: top = ((func_3)function->fptr)(in[0], in[1], in[2]); break; + case 4: top = ((func_4)function->fptr)(in[0], in[1], in[2], in[3]); break; + case 5: top = ((func_5)function->fptr)(in[0], in[1], in[2], in[3], in[4]); break; + default: return jv_invalid_with_msg(jv_string("Function takes too many arguments")); + } + if (jv_is_valid(top)) { stack_push(jq, top); } else {