]> granicus.if.org Git - jq/commitdiff
frame layout refactor
authorStephen Dolan <mu@netsoc.tcd.ie>
Tue, 21 Aug 2012 11:35:36 +0000 (12:35 +0100)
committerStephen Dolan <mu@netsoc.tcd.ie>
Tue, 21 Aug 2012 11:35:44 +0000 (12:35 +0100)
c/bytecode.h
c/compile.c
c/execute.c
c/forkable_stack.h
c/frame_layout.h [new file with mode: 0644]
c/opcode.c
c/opcode.h
c/opcode_list.h

index ddf1105a1b5373596b42b9ba76c01a820a40bb3c..a7141e4bb99b3c1c59d32d8d32d01347f4fce778 100644 (file)
@@ -23,11 +23,18 @@ struct symbol_table {
 struct bytecode {
   uint16_t* code;
   int codelen;
-  int framesize;
+
+  int nlocals;
+  int nclosures;
+
   json_t* constants;
   struct symbol_table* globals;
+
+  struct bytecode* subfunctions;
+  int nsubfunctions;
 };
 
 void dump_disassembly(struct bytecode* code);
 void dump_operation(struct bytecode* bc, uint16_t* op);
+
 #endif
index cc3445754ef82eb1ce7035d2bd9f7dff14d6f955..b102eeeb1b13bc35e757764cc5cf535ad15df097 100644 (file)
@@ -274,7 +274,8 @@ struct bytecode* block_compile(struct symbol_table* syms, block b) {
   }
   free(stack_height);
   bc->constants = constant_pool;
-  bc->framesize = maxvar + 2; // FIXME: frames of size zero?
+  bc->nlocals = maxvar + 2; // FIXME: frames of size zero?
+  bc->nclosures = 0;
   bc->globals = syms;
   return bc;
 }
index 44aaab3a31b24dbcb4c42c78bcb2b560f4bc9892..a97d80f21023934bc3d65a4421c9d16975e9c5fa 100644 (file)
@@ -10,6 +10,7 @@
 #include "compile.h"
 
 #include "forkable_stack.h"
+#include "frame_layout.h"
 
 
 typedef struct {
@@ -52,34 +53,19 @@ typedef struct {
   stackval sv;
 } data_stk_elem;
 
-data_stk_elem* stk_push_frame(int n) {
-  return forkable_stack_push(&data_stk, sizeof(data_stk_elem) * n);
-}
-
-void stk_pop_frame(int n) {
-  forkable_stack_pop(&data_stk, sizeof(data_stk_elem) * n);
-}
-
 void stk_push(stackval val) {
-  data_stk_elem* s = stk_push_frame(1);
+  data_stk_elem* s = forkable_stack_push(&data_stk, sizeof(data_stk_elem));
   s->sv = val;
 }
 
 stackval stk_pop() {
-  data_stk_elem* s = forkable_stack_peek(&data_stk, sizeof(data_stk_elem));
+  data_stk_elem* s = forkable_stack_peek(&data_stk);
   stackval sv = s->sv;
-  forkable_stack_pop(&data_stk, sizeof(data_stk_elem));
+  forkable_stack_pop(&data_stk);
   return sv;
 }
 
-
-typedef struct {
-  FORKABLE_STACK_HEADER;
-  struct bytecode* bc;
-  data_stk_elem* fp;
-  uint16_t* pc;
-} call_stk_elem;
-struct forkable_stack call_stk;
+struct forkable_stack frame_stk;
 
 
 struct forkpoint {
@@ -93,20 +79,20 @@ struct forkable_stack fork_stk;
 void stack_save(){
   struct forkpoint* fork = forkable_stack_push(&fork_stk, sizeof(struct forkpoint));
   forkable_stack_save(&data_stk, &fork->saved_data_stack);
-  forkable_stack_save(&call_stk, &fork->saved_call_stack);
+  forkable_stack_save(&frame_stk, &fork->saved_call_stack);
 }
 
 void stack_switch() {
-  struct forkpoint* fork = forkable_stack_peek(&fork_stk, sizeof(struct forkpoint));
+  struct forkpoint* fork = forkable_stack_peek(&fork_stk);
   forkable_stack_switch(&data_stk, &fork->saved_data_stack);
-  forkable_stack_switch(&call_stk, &fork->saved_call_stack);
+  forkable_stack_switch(&frame_stk, &fork->saved_call_stack);
 }
 
 void stack_restore(){
-  struct forkpoint* fork = forkable_stack_peek(&fork_stk, sizeof(struct forkpoint));
+  struct forkpoint* fork = forkable_stack_peek(&fork_stk);
   forkable_stack_restore(&data_stk, &fork->saved_data_stack);
-  forkable_stack_restore(&call_stk, &fork->saved_call_stack);
-  forkable_stack_pop(&fork_stk, sizeof(struct forkpoint));
+  forkable_stack_restore(&frame_stk, &fork->saved_call_stack);
+  forkable_stack_pop(&fork_stk);
 }
 
 #define stack_push stk_push
@@ -115,29 +101,31 @@ void stack_restore(){
 #define ON_BACKTRACK(op) ((op)+NUM_OPCODES)
 
 json_t* jq_next() {
-  assert(!forkable_stack_empty(&call_stk));
-  call_stk_elem* ctx = forkable_stack_peek(&call_stk, sizeof(call_stk_elem));
-  struct bytecode* bc = ctx->bc;
-  uint16_t* pc = ctx->pc;
-  data_stk_elem* fp = ctx->fp;
-  json_t* cpool = bc->constants;
-
   json_t* cfunc_input[MAX_CFUNCTION_ARGS] = {0};
   json_t* cfunc_output[MAX_CFUNCTION_ARGS] = {0};
+
+
+  assert(!forkable_stack_empty(&frame_stk));
+  uint16_t* pc = *frame_current_pc(&frame_stk);
+
   int backtracking = 0;
   while (1) {
-
-    dump_operation(bc, pc);
+    *frame_current_pc(&frame_stk) = pc;
+    dump_operation(frame_current_bytecode(&frame_stk), pc);
 
     uint16_t opcode = *pc++;
 
     printf("\t");
     const struct opcode_description* opdesc = opcode_describe(opcode);
-    data_stk_elem* param = forkable_stack_peek(&data_stk, sizeof(data_stk_elem));
+    data_stk_elem* param;
     for (int i=0; i<opdesc->stack_in; i++) {
+      if (i == 0) {
+        param = forkable_stack_peek(&data_stk);
+      } else {
+        param = forkable_stack_peek_next(&data_stk, param);
+      }
       json_dumpf(param->sv.value, stdout, JSON_ENCODE_ANY);
       if (i < opdesc->stack_in-1) printf(" | ");
-      param = forkable_stack_peek_next(&data_stk, param, sizeof(data_stk_elem));
     }
 
     if (backtracking) {
@@ -152,7 +140,7 @@ json_t* jq_next() {
     default: assert(0 && "invalid instruction");
 
     case LOADK: {
-      json_t* v = json_array_get(cpool, *pc++);
+      json_t* v = json_array_get(frame_current_bytecode(&frame_stk)->constants, *pc++);
       assert(v);
       stack_push(stackval_replace(stack_pop(), v));
       break;
@@ -205,17 +193,19 @@ json_t* jq_next() {
 
     case LOADV: {
       uint16_t v = *pc++;
-      stack_push(stackval_replace(stack_pop(), fp[v].sv.value));
+      json_t** var = frame_local_var(frame_current(&frame_stk), v);
+      stack_push(stackval_replace(stack_pop(), *var));
       break;
     }
 
     case STOREV: {
       uint16_t v = *pc++;
+      json_t** var = frame_local_var(frame_current(&frame_stk), v);
       stackval val = stack_pop();
       printf("V%d = ", v);
       json_dumpf(val.value, stdout, JSON_ENCODE_ANY);
       printf("\n");
-      fp[v].sv.value = val.value;
+      *var = val.value;
       break;
     }
 
@@ -277,10 +267,7 @@ json_t* jq_next() {
         stack_save();
         stack_push(array);
         stack_push(stackval_root(json_integer(idx+1)));
-        call_stk_elem* ctx = forkable_stack_push(&call_stk, sizeof(call_stk_elem));
-        ctx->bc = bc;
-        ctx->fp = fp;
-        ctx->pc = pc - 1;
+        frame_push_backtrack(&frame_stk, frame_current_bytecode(&frame_stk), pc - 1);
         stack_switch();
         
         stackval sv = {json_array_get(array.value, idx), 
@@ -296,22 +283,15 @@ json_t* jq_next() {
         return 0;
       }
       stack_restore();
-      call_stk_elem* ctx = forkable_stack_peek(&call_stk, sizeof(call_stk_elem));
-      bc = ctx->bc;
-      pc = ctx->pc;
-      fp = ctx->fp;
-      cpool = bc->constants;
-      forkable_stack_pop(&call_stk, sizeof(call_stk_elem));
+      pc = *frame_current_pc(&frame_stk);
+      frame_pop(&frame_stk);
       backtracking = 1;
       break;
     }
 
     case FORK: {
       stack_save();
-      call_stk_elem* ctx = forkable_stack_push(&call_stk, sizeof(call_stk_elem));
-      ctx->bc = bc;
-      ctx->fp = fp;
-      ctx->pc = pc - 1;
+      frame_push_backtrack(&frame_stk, frame_current_bytecode(&frame_stk), pc - 1);
       stack_switch();
       pc++; // skip offset this time
       break;
@@ -324,17 +304,14 @@ json_t* jq_next() {
 
     case YIELD: {
       json_t* value = stack_pop().value;
-      call_stk_elem* ctx = forkable_stack_push(&call_stk, sizeof(call_stk_elem));
-      ctx->bc = bc;
-      ctx->fp = fp;
-      ctx->pc = pc;
+      *frame_current_pc(&frame_stk) = pc;
       return value;
     }
       
     case CALL_BUILTIN_1_1: {
       stackval top = stack_pop();
       cfunc_input[0] = top.value;
-      struct cfunction* func = &bc->globals->cfunctions[*pc++];
+      struct cfunction* func = &frame_current_bytecode(&frame_stk)->globals->cfunctions[*pc++];
       printf(" call %s\n", func->name);
       func->fptr(cfunc_input, cfunc_output);
       stack_push(stackval_replace(top, cfunc_output[0]));
@@ -348,13 +325,19 @@ json_t* jq_next() {
       cfunc_input[0] = top.value;
       cfunc_input[1] = a;
       cfunc_input[2] = b;
-      struct cfunction* func = &bc->globals->cfunctions[*pc++];
+      struct cfunction* func = &frame_current_bytecode(&frame_stk)->globals->cfunctions[*pc++];
       printf(" call %s\n", func->name);
       func->fptr(cfunc_input, cfunc_output);
       stack_push(stackval_replace(top, cfunc_output[0]));
       break;
     }
+
+      /*
+    case CALL_1_1: {
+      uint16_t nargs = *pc++;
       
+    }
+      */
       
     }
   }
@@ -363,16 +346,11 @@ json_t* jq_next() {
 
 void jq_init(struct bytecode* bc, json_t* input) {
   forkable_stack_init(&data_stk, sizeof(stackval) * 100); // FIXME: lower this number, see if it breaks
-  forkable_stack_init(&call_stk, 1024); // FIXME: lower this number, see if it breaks
+  forkable_stack_init(&frame_stk, 1024); // FIXME: lower this number, see if it breaks
   forkable_stack_init(&fork_stk, 1024); // FIXME: lower this number, see if it breaks
   
-  data_stk_elem* frame = stk_push_frame(bc->framesize);
-  
   stack_push(stackval_root(input));
-  call_stk_elem* ctx = forkable_stack_push(&call_stk, sizeof(call_stk_elem));
-  ctx->pc = bc->code;
-  ctx->bc = bc;
-  ctx->fp = frame;
+  frame_push(&frame_stk, bc);
 }
 
 void run_program(struct bytecode* bc) {
index 5b8ec8ad0e6baf4041672b80bdf667939daadaf1..88a280f289d76243e26bd6f78976205a3df2b701 100644 (file)
@@ -1,3 +1,5 @@
+#ifndef FORKABLE_STACK_H
+#define FORKABLE_STACK_H
 #include <stdlib.h>
 #include <stddef.h>
 #include <assert.h>
@@ -65,21 +67,21 @@ static void* forkable_stack_push(struct forkable_stack* s, size_t size) {
   return ret;
 }
 
-static void* forkable_stack_peek(struct forkable_stack* s, size_t size) {
+static void* forkable_stack_peek(struct forkable_stack* s) {
   assert(!forkable_stack_empty(s));
   forkable_stack_check(s);
   return (void*)(s->stk + s->pos);
 }
 
-static void* forkable_stack_peek_next(struct forkable_stack* s, void* top, size_t size) {
+static void* forkable_stack_peek_next(struct forkable_stack* s, void* top) {
   forkable_stack_check(s);
   struct forkable_stack_header* elem = top;
   return (void*)(s->stk + elem->next);
 }
 
-static void forkable_stack_pop(struct forkable_stack* s, size_t size) {
+static void forkable_stack_pop(struct forkable_stack* s) {
   forkable_stack_check(s);
-  struct forkable_stack_header* elem = forkable_stack_peek(s, size);
+  struct forkable_stack_header* elem = forkable_stack_peek(s);
   s->pos = elem->next;
 }
 
@@ -114,3 +116,4 @@ static void forkable_stack_restore(struct forkable_stack* s, struct forkable_sta
   s->savedlimit = state->prevlimit;
   forkable_stack_check(s);
 }
+#endif
diff --git a/c/frame_layout.h b/c/frame_layout.h
new file mode 100644 (file)
index 0000000..55919f8
--- /dev/null
@@ -0,0 +1,81 @@
+#ifndef FRAME_LAYOUT_H
+#include "forkable_stack.h"
+#include "bytecode.h"
+#include <jansson.h>
+
+struct closure {
+  struct bytecode* bc;
+  uint16_t* pc;
+};
+
+typedef union frame_elem {
+  FORKABLE_STACK_HEADER;
+  struct closure closure;
+  json_t* jsonval;
+} *frame_ptr;
+
+/*
+ * Frame layout
+ * fr[0] - FORKABLE_STACK_HEADER (next pointer)
+ * fr[1] - self (used to store return addresses, etc)
+ * fr[2...nclosures+2] - closure params
+ * fr[nclosures+2..nclosures+nlocals+2] - local variables
+ */
+
+static int frame_size(struct bytecode* bc) {
+  return sizeof(union frame_elem) * (bc->nclosures + bc->nlocals + 2);
+}
+
+static struct closure* frame_self(frame_ptr fr) {
+  return &fr[1].closure;
+}
+
+static struct closure* frame_closure_arg(frame_ptr fr, int closure) {
+  assert(closure >= 0);
+  assert(closure < frame_self(fr)->bc->nclosures);
+  return &fr[2+closure].closure;
+}
+
+static json_t** frame_local_var(frame_ptr fr, int var) {
+  assert(var >= 0);
+  assert(var < frame_self(fr)->bc->nlocals);
+  return &fr[2 + frame_self(fr)->bc->nclosures + var].jsonval;
+}
+
+
+static frame_ptr frame_current(struct forkable_stack* stk) {
+  frame_ptr fp = forkable_stack_peek(stk);
+  struct bytecode* bc = frame_self(fp)->bc;
+  assert(frame_self(fp)->pc >= bc->code && frame_self(fp)->pc < bc->code + bc->codelen);
+  return fp;
+}
+
+static struct bytecode* frame_current_bytecode(struct forkable_stack* stk) {
+  return frame_self(frame_current(stk))->bc;
+}
+static uint16_t** frame_current_pc(struct forkable_stack* stk) {
+  return &frame_self(frame_current(stk))->pc;
+}
+
+
+
+
+static void frame_push(struct forkable_stack* stk, struct bytecode* bc) {
+  frame_ptr fp = forkable_stack_push(stk, frame_size(bc));
+  frame_self(fp)->bc = bc;
+  frame_self(fp)->pc = bc->code;
+}
+
+static void frame_push_backtrack(struct forkable_stack* stk, 
+                                      struct bytecode* bc, uint16_t* pc) {
+  frame_ptr fp = forkable_stack_push(stk, sizeof(union frame_elem) * 2);
+  frame_self(fp)->bc = bc;
+  frame_self(fp)->pc = pc;
+}
+
+
+static void frame_pop(struct forkable_stack* stk) {
+  forkable_stack_pop(stk);
+}
+
+#endif
index b14e0db622cfbf2e37321d5431d24344611b2304..92bbcd29f45f6d1fddbe87dbf3fa99c7fc99bafe 100644 (file)
@@ -5,6 +5,7 @@
 #define VARIABLE (OP_HAS_IMMEDIATE | OP_HAS_VARIABLE)
 #define BRANCH (OP_HAS_IMMEDIATE | OP_HAS_BRANCH)
 #define CFUNC (OP_HAS_IMMEDIATE | OP_HAS_SYMBOL | OP_HAS_CFUNC)
+#define UFUNC (OP_HAS_IMMEDIATE | OP_HAS_UFUNC)
 
 #define OP(name, imm, in, out) \
   {name, #name, imm, in, out},
index 797e6a96cd69854f0885c6f1628bcb53a64e7b7a..36d41920ea23105bd27d8c35deec4ee01a6e38ef 100644 (file)
@@ -19,7 +19,8 @@ enum {
   OP_HAS_VARIABLE = 4,
   OP_HAS_BRANCH = 8,
   OP_HAS_SYMBOL = 16,
-  OP_HAS_CFUNC = 32
+  OP_HAS_CFUNC = 32,
+  OP_HAS_UFUNC = 64,
 };
 struct opcode_description {
   opcode op;
index 2fe3f8a80f02a6dc9d2c79ef2174c5fd99e2fe73..d3bfb98346d3f1ff234db962035230302522ae88 100644 (file)
@@ -16,3 +16,5 @@ OP(INSERT, NONE,    4, 2)
 
 OP(CALL_BUILTIN_1_1, CFUNC, 1, 1)
 OP(CALL_BUILTIN_3_1, CFUNC, 3, 1)
+
+OP(CALL_1_1, UFUNC, 1, 1)