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