1#include <stdio.h>
2#include <stdlib.h>
3#include <sys/mman.h>
4#include <sys/types.h>
5#include <time.h>
6#include "wrapper.h"
7
8void jit_exec(long *);
9
10
11/* global variables */
12
13#ifdef DEBUG
14long gc_count = 0;
15long *exp_stack;
16long *heap1;
17long *heap2;
18char *symtable;
19char *code_heap;
20long original_stack_size;
21long original_code_heap_size;
22time_t prev_print;
23#endif
24
25/* functions which can be called from within the verified code */
26
27void print_str (char* str, long i, long e, long wsp) {
28  printf("%s",str);
29#ifdef DEBUG
30  if ((int)str[0] == 10) {
31    if (i == e) {
32      printf(";  heap: 1.00000  ");
33    } else {
34      printf(";  heap: 0.%05ld  ", i * 100000 / e);
35    }
36    time(&prev_print);
37    printf("stack: %ld  GCs: %ld  consts: %ld  code: %ldkB  time: %s",
38           original_stack_size - wsp, gc_count, exp_stack[18+8],
39           (original_code_heap_size - exp_stack[18+3]) / 1024, ctime(&prev_print));
40  }
41#endif
42}
43
44long read_line_counter = 0;
45char read_line_buffer[1024*1024];
46char* read_line() {
47  read_line_counter++;
48  printf("> ");
49  if (fgets (read_line_buffer, 1024*1024, stdin) == NULL) {
50    printf("\n");
51    return "";
52  }
53  return read_line_buffer;
54}
55
56/* long gc_started = 0; */
57void print_stats (long state, long i, long e) {
58#ifdef DEBUG
59  if (state == 1) { gc_count++; } else {}
60#endif
61  /*
62  time_t now; time(&now);
63  if (state == 1) {
64    gc_started = now; printf("GC: ");
65  } else {
66    printf("lasted %ld seconds, heap usage %02f %s  --- %s", now - gc_started, ((float)i)/((float)e) * 100.0, "%", ctime(&now));
67  }
68  */
69}
70
71void report_error(long bp, long sp, long error) {
72  printf("ERROR: ");
73  switch (error) {
74    case  0: printf("Not enough heap space.\n\n"); break;
75    case  1: printf("Not enough stack space.\n\n"); break;
76    case  2: printf("Arithmetic overflow.\n\n"); break;
77    case  3: printf("Not enough space in code heap.\n\n"); break;
78    case  4: printf("Runtime error caused by 'error' function.\n\n"); break;
79    case  5: printf("Syntax error.\n\n"); break;
80    case  6: printf("Encountered a symbol longer than 255 characters.\n\n"); break;
81    case  7: printf("Not enough space in symbol table.\n\n"); break;
82    case  8: printf("Illformed abbreviation.\n\n"); break;
83    case  9: printf("Encountered a number larger than 1,073,741,823.\n\n"); break;
84    case 10: printf("Unexpected end of input stream.\n\n"); break;
85    case 11: printf("An undefined function was called.\n\n"); break;
86    case 12: printf("Not enough space for new constant.\n\n"); break;
87  default: printf("Unknown error (%d).\n\n",(int)error); break;
88  }
89  exit(EXIT_SUCCESS);
90}
91
92
93/* a function which allocates memory with EXEC enabled */
94
95char * alloc_executable(size_t len) { /* len = number of bytes */
96  /* Local variables */
97  size_t page_size = getpagesize();
98  /* Round up so that len is a multiple of getpagesize() */
99  if (len % page_size) {
100    len &= ~(page_size-1);
101    len += page_size;
102  }
103  /* Open a file for use as scratch memory */
104  int fd = 0, ret = 0;
105  void *pa = MAP_FAILED;
106  char template[] = "/tmp/alloc_executable_XXXXXX";
107  fd = mkstemp(template);
108  if (fd < 0) return pa;
109  unlink(template);
110  ret = ftruncate(fd, len);
111  if (ret < 0) return pa;
112  /* Do the allocation */
113  return mmap(NULL, len, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0);
114}
115
116
117/* main function */
118
119int main(int argc, char** argv) {
120
121  printf("Jitawa -- test version (built %s)\n", NOW);
122
123  setvbuf(stdout, NULL, _IONBF, 0); // this line makes sure stdout is not buffered
124
125#ifndef DEBUG
126  long gc_count = 0;
127  long *exp_stack;
128  long *heap1;
129  long *heap2;
130  char *symtable;
131  char *code_heap;
132  long original_stack_size;
133  long original_code_heap_size;
134  time_t prev_print;
135#endif
136
137  char* settings = "default";
138  long heap_size = 1;             // million cons-cells that fit into the heap
139  long stack_size = 1;            // million expressions that fit into the stack
140  long const_table_size = 1;      // thousand expressions that fit into the const table
141  long symtable_size = 64;        // kilo roughly speaking the number of characters
142  long abbrev_array_length = 10;  // number of cells in abbrev-speed-up array
143  long code_heap_size = 1;        // megabytes
144  long generation_size = 0;       // million cons-cells that fit into the first generation heap
145
146  if (1 < argc) {
147    if (strcmp(argv[1],"large") == 0) {
148      heap_size = 1500;
149      generation_size = 700;
150      stack_size = 600;
151      const_table_size = 1024;
152      symtable_size = 1024;
153      abbrev_array_length = 550000000;
154      code_heap_size = 500;
155      settings = argv[1];
156    }
157  }
158  printf("Using %s settings: heap[%ldMcons], stack[%ldMcons], symtable[%ldkB], code[%ldMB]\n",settings,heap_size,stack_size,symtable_size,code_heap_size);
159
160  heap_size        *= 1024 * 1024;
161  generation_size  *= 1024 * 1024;
162  stack_size       *= 1024 * 1024;
163  const_table_size *= 1024;
164  symtable_size    *= 1024;
165  code_heap_size   *= 1024 * 1024;
166
167  if (generation_size == 0) {
168    generation_size = heap_size / 4;
169  }
170
171  exp_stack = malloc(4 * stack_size + 256 + 4 * const_table_size + 32);
172  heap1 = malloc(8 * heap_size);
173  heap2 = malloc(8 * heap_size);
174  symtable = malloc(symtable_size);
175  code_heap = alloc_executable(code_heap_size);
176  if (exp_stack == NULL) { printf("Unable to allocate stack of size %ld.\n", stack_size); exit(EXIT_FAILURE); }
177  if (heap1 == NULL) { printf("Unable to allocate heap(1) of size %ld.\n", heap_size); exit(EXIT_FAILURE); }
178  if (heap2 == NULL) { printf("Unable to allocate heap(2) of size %ld.\n", heap_size); exit(EXIT_FAILURE); }
179  if (symtable == NULL) { printf("Unable to allocate symbol table of size %ld.\n", symtable_size); exit(EXIT_FAILURE); }
180  if (code_heap == NULL) { printf("Unable to allocate code heap of size %ld.\n", code_heap_size); exit(EXIT_FAILURE); }
181
182  /* initialising the state based on lisp_init_def and zLISP_INTI_def */
183  read_line_buffer[0] = 0;
184  // main init state
185  exp_stack[0]  = (long)heap1;
186  exp_stack[1]  = (long)heap2;
187  exp_stack[2]  = (long)heap_size;
188  exp_stack[3]  = (long)stack_size;
189  exp_stack[4]  = (long)symtable;
190  exp_stack[5]  = (long)symtable_size;
191  exp_stack[6]  = (long)0;
192  exp_stack[7]  = (long)(*report_error);
193  // cs starts at exp_stack[8]
194  exp_stack[8]  = (long)print_str;
195  exp_stack[9]  = (long)read_line;
196  exp_stack[10] = (long)print_stats;
197  exp_stack[11] = (long)abbrev_array_length;
198  exp_stack[12] = (long)code_heap;
199  exp_stack[13] = (long)code_heap_size;
200  exp_stack[14] = (long)0;
201  exp_stack[15] = (long)0;
202  exp_stack[16] = (long)0;
203  exp_stack[17] = (long)0;
204  // ds starts at exp_stack[8]
205  exp_stack[18] = (long)read_line_buffer;
206  exp_stack[18+5] = (long)generation_size;
207  exp_stack[18+7] = (long)const_table_size;
208  original_stack_size = (long)stack_size;
209  original_code_heap_size = (long)code_heap_size;
210
211  jit_exec(exp_stack);
212
213  printf("\n");
214  exit(EXIT_SUCCESS);
215}
216
217
218