Author | Jakob Wakeling <[email protected]> |
Date | 2020-07-01 11:50:21 |
Commit | 6fb8c64b9e1d312272eafaf3ddddbaa9b7969ff5 |
Parent | 177d490ae0f49c270608ece44b871c8efd18bd79 |
Fix linking order having an effect on performance
The array being in global space was having an effect on performance when the object files were linked in a certain order. Moving the array into the execution scope, and onto the stack, solves this issue. In addition to this fix, I have made a number of smaller optimisations and improvements, to both the performance of the interpreter, as well as its error handling.
Diffstat
M | CMakeLists.txt | | | 2 | +- |
M | src/main.c | | | 72 | +++++++++++++++++++++++++++++++++++++++++------------------------------- |
M | src/parse.c | | | 11 | +++++------ |
M | src/parse.h | | | 5 | +---- |
4 files changed, 48 insertions, 42 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d59a99..cac770c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib) SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) -ADD_COMPILE_DEFINITIONS(VERSION="1.0.0") +ADD_COMPILE_DEFINITIONS(VERSION="1.0.1") FILE(GLOB SOURCES ${CMAKE_SOURCE_DIR}/src/*) diff --git a/src/main.c b/src/main.c index 22adaf8..119d803 100644 --- a/src/main.c +++ b/src/main.c @@ -42,12 +42,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. #include <errno.h> #include <stddef.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -static char arr[30000] = { 0 }, *ptr = arr; -static tok_t **dat; static size_t cap, top; +static int execute(tok_t *toks); static void help(void); static void version(void); @@ -68,44 +68,54 @@ int main(int argc, char *argv[]) { if (opt.ind == argc) { error(1, "%s: missing operand", argv[0]); } - char *file = argv[opt.ind]; struct stat fs; stat(file, &fs); + char *file = argv[opt.ind]; struct stat fs; + if (stat(file, &fs)) { error(1, "%s: %s: %s", argv[0], file, serrno); } + char *fb = malloc(sizeof (*fb) * fs.st_size + 1); fb[fs.st_size] = 0; if (!fb) { error(1, "%s: %s", argv[0], serrno); } - FILE *fi = fopen(file, "r"); fread(fb, fs.st_size, 1, fi); fclose(fi); + FILE *fi = fopen(file, "r"); + if (!fi) { free(fb); error(1, "%s: %s: %s", argv[0], file, serrno); } + + fread(fb, 1, fs.st_size, fi); fclose(fi); + if (errno) { free(fb); error(1, "%s: %s: %s", argv[0], file, serrno); } tok_t *toks = parse(fb, fs.st_size); free(fb); + if (!toks) { error(1, "%s: %s", argv[0], serrno); } - cap = 64; top = 0; dat = malloc(sizeof (*dat) * cap); - if (!dat) { error(1, "%s: %s", argv[0], serrno); } + if (execute(toks)) { free(toks); error(1, "%s: %s", argv[0], serrno); } - for (tok_t *t = toks; t->typ != EOF; ++t) { -start: switch (t->typ) { - case RGT: { ptr += t->num; break; } - case LFT: { ptr -= t->num; break; } - case ADD: { *ptr += t->num; break; } - case SUB: { *ptr -= t->num; break; } - case PUT: { fputc(*ptr, stdout); break; } - case GET: { *ptr = fgetc(stdin); break; } - case OPN: { - if (!*ptr) { - register size_t i = 1; for (++t; i != 0; ++t) { - if (t->typ == OPN) { ++i; } else if (t->typ == CLS) { --i; } - } goto start; - } - - if (top == cap) { - register tok_t **old = dat; cap *= 2; dat = realloc(dat, cap); - if (!dat) { free(old); error(1, "%s: %s", argv[0], serrno); } - } dat[top++] = t; break; - } - case CLS: { - if (*ptr) { t = dat[top - 1]; } else { dat[--top] = 0; } break; - } - } + free(toks); return 0; +} + +static int execute(tok_t *toks) { + uint8_t arr[30000] = { 0 }, *ptr = arr; + + size_t cap = 64, top = 0; tok_t **dat; + if (!(dat = malloc(sizeof (*dat) * cap))) { return 1; } + + for (tok_t *t = toks; t->typ != EOF; ++t) switch (t->typ) { + case RGT: { ptr += t->num; break; } + case LFT: { ptr -= t->num; break; } + case ADD: { *ptr += t->num; break; } + case SUB: { *ptr -= t->num; break; } + case PUT: { fputc(*ptr, stdout); break; } + case GET: { *ptr = fgetc(stdin); break; } + case OPN: { + if (!*ptr) { for (size_t i = 1; i != 0; ++t) { + if ((t + 1)->typ == OPN) { ++i; } + else if ((t + 1)->typ == CLS) { --i; } + } break; } + + if (top == cap) { + tok_t **old = dat; cap *= 2; dat = realloc(dat, cap); + if (!dat) { free(old); return 1; } + } dat[top++] = t; break; + } + case CLS: { if (*ptr) { t = dat[top - 1]; } else { --top; } break; } } - free(dat); free(toks); return 0; + free(dat); return 0; } static void help(void) { diff --git a/src/parse.c b/src/parse.c index 3021504..154453a 100644 --- a/src/parse.c +++ b/src/parse.c @@ -42,7 +42,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. #define TOKSET(type) tok.typ = type; tok.ln = line; tok.cl = col -tok_t lex(char *str) { +static inline tok_t lex(char *str) { static char *p; static size_t line, col; tok_t tok; if (str) { p = str; line = 0; col = 0; } tok.num = 1; @@ -69,11 +69,10 @@ tok_t lex(char *str) { tok_t *parse(char *str, size_t len) { tok_t *toks = malloc(sizeof (*toks) * len); - register tok_t *p = toks; + if (!toks) { return NULL; } - tok_t tok = lex(str); if (tok.typ == EOF) { goto end; } - do { *p++ = tok; } while ((tok = lex(NULL)).typ != EOF); + register tok_t *p = toks; + *p = lex(str); while (p->typ != EOF) { *++p = lex(NULL); } -end: - *p = tok; return toks; + return toks; } diff --git a/src/parse.h b/src/parse.h index 25fe480..306636d 100644 --- a/src/parse.h +++ b/src/parse.h @@ -41,7 +41,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. enum { END = EOF, // EOF - ERR = 0, // ERROR RGT = 1, // '>' LFT = 2, // '<' ADD = 3, // '+' @@ -50,12 +49,10 @@ enum { GET = 6, // ',' OPN = 7, // '[' CLS = 8, // ']' - SET = 9, // '[-]', '[+]' }; typedef struct { int typ; size_t num, ln, cl; } tok_t; -tok_t lex(char *str); -tok_t *parse(char *str, size_t len); +extern tok_t *parse(char *str, size_t len); #endif // OMKOV_OBFI_LEX_H_AD07BU3C