1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
#ifndef PURE_MODULE_RUN_H
#define PURE_MODULE_RUN_H
/* How a block runs, shared by the executor (module.c) and the compiled code
* (module-jit.c): their frame, and the steps the compiled code calls. Not a
* public interface. */
#include "module.h"
/* An item's or a key's op->plan: its cell a text; a FIND joined to the ITEM_GET after it. */
enum { PLAN_TEXT = 1, PLAN_JOINED = 2 };
typedef struct { union { double num; int64_t i64; }; PureBytes bytes; } Slot;
/* A walk (EACH): the list, the item it runs for, where it ends (items the
* walk removes move it), and whether that item left. */
typedef struct { uint32_t list; size_t at, end; bool removed; } Walk;
/* A loop that runs in its block's run (LOOP, EACH): its block and where
* the code around it ends, the arena as it began, a walk's walk and the
* event's walk and row around it, a count's values (low + k of count) and
* slot. */
typedef struct {
uint32_t start, end, outer;
size_t mark;
bool walking, integer;
Walk walk, *around;
size_t row;
uint64_t count, k;
PureValue low, *slot;
} Loop;
typedef struct {
PureApp *app;
const PureInputShape *shape; /* message, or NULL */
const char *key; /* a keyed message's key */
int64_t base; /* the revision a message's edit was made against, or -1 */
PureArena *arena;
double dt;
size_t row; /* the row a column is evaluated for (in a fold, the fold's item) */
size_t outer; /* in a fold, the row of the column it runs in */
Walk *walk; /* the walk the code runs in, or NULL */
PureValue *locals; /* the event's locals (a handler's, and what runs in it), or NULL */
bool arguments; /* FIELD reads the arguments given for a view, not the message */
bool modified, exists;
uint32_t (*spans)[2]; /* a message's variable fields: start and size in the payload */
} Event;
/* ---- Running a block (docs/design/021). A frame holds what a block reads
* and changes as it runs: its operand stack and the loops open in it. step
* runs one instruction but a branch or a loop's; run takes those itself, as
* the compiled code does (module-jit.c), so both run the same steps. */
typedef struct {
const PureModule *m;
PureValue *values;
Event *ev;
PureApp *app;
PureArena *arena;
Slot *stack;
size_t sp;
uint32_t end; /* where the innermost loop's block ends, or the block's */
unsigned depth; /* the loops open */
PureFault kind; /* a fault's */
PureResult status; /* what refused or stopped it */
uint32_t fault_pc; /* the instruction that faulted or refused */
Loop *loops; /* PURE_MODULE_NESTING of them, apart: a walk points into its loop */
} Frame;
/* How a step went: on to the next instruction; a fault (kind at fault_pc);
* refused (status: past a limit or nothing found is a fault there, else it
* is returned); stopped (status returned as it is). */
enum { STEP_NEXT, STEP_FAULT, STEP_REFUSED, STEP_RETURN };
/* The instruction after op at pc: past a fold's block, or the ITEM_GET a FIND was joined to. */
static inline uint32_t after(const PureOp *op, uint32_t pc) {
return op->op == PURE_OP_FOLD ? pc + 1 + (op->arg >> 16) : pc + 1 + (op->op == PURE_OP_LIST_FIND && op->plan & PLAN_JOINED);
}
/* The steps compiled code takes from the executor (module.c): an
* instruction but a branch or a loop's (how; the next is after()); a walk or
* a loop opened at pc (STEP_NEXT: its block next, STEP_SKIP: none, past its
* block); BREAK; a loop's block ran once (STEP_NEXT: again, STEP_DONE: the
* loop ended). */
enum { STEP_SKIP = 4, STEP_DONE = 5 };
int pure_run_step(Frame *, uint32_t pc);
int pure_run_each(Frame *, uint32_t pc);
int pure_run_loop(Frame *, uint32_t pc);
void pure_run_break(Frame *);
int pure_run_iterate(Frame *);
/* A module's code compiled (AArch64 Linux; elsewhere, or with PURE_JIT=0 in
* the environment, none): a block's code runs a frame as run does, giving how
* it went (a STEP_). */
typedef int (*PureCompiled)(Frame *);
struct PureJit *pure_jit_make(const PureModule *);
void pure_jit_free(struct PureJit *);
PureCompiled pure_jit_code(const struct PureJit *, PureBlock);
#endif
|