From a1d2ea31c81086eb585c4b6cb49a66bfabe5aae2 Mon Sep 17 00:00:00 2001 From: Rick L Bird Date: Sat, 14 May 2011 12:57:23 -0400 Subject: [PATCH] PennMUSH 1.8.3p12 Author: allthecoolkidshaveone Date: Sat Jan 2 04:12:32 2010 +0000 Issue 175: llocks() returning a list of lock names Author: allthecoolkidshaveone Date: Sat Jan 2 02:45:01 2010 +0000 The lock optimizer now handles a few trivial things like svn status -qfoo Fixes #203 Fixes #177 --- src/boolexp.c | 122 +++++++++++++++++++++++++++++++++++++++---------- src/function.c | 2 +- src/fundb.c | 22 ++++++++- 3 files changed, 120 insertions(+), 26 deletions(-) diff --git a/src/boolexp.c b/src/boolexp.c index f47b0ac..8e10b4b 100644 --- a/src/boolexp.c +++ b/src/boolexp.c @@ -325,9 +325,8 @@ static size_t offset_to_string(struct bvm_asm *a, int c); static struct bvm_asmnode * insn_after_label(struct bvm_asm *a, int label); -static void -opt_thread_jumps(struct bvm_asm *a); -static void +static void optimize_bvm_ast(struct boolexp_node *); + static void optimize_bvm_asm(struct bvm_asm *a); static boolexp emit_bytecode(struct bvm_asm *a, int derefs); @@ -1672,18 +1671,106 @@ insn_after_label(struct bvm_asm *a, int label) return NULL; } -/** Avoid jumps that lead straight to another jump. If the second jump - * is on the same condition as the first one, jump instead to its - * destination. If it's the opposite condition, jump instead to the - * first instruction after the second jump to avoid the useless - * conditional check. - * \param a the assembler list to thread. */ +/** Do some trivial optimizations at the syntax tree level. Some of + * these catch things that no normal person would do with a lock, but + * might be created artificially at some point in the future -- for + * example, if we ever go through and replace reference to a deleted + * object with #false in locks. + * + * Current optimizations: + * + * Turn =#123|+#123 into the equivalent #123 (Won't work with + * =#123|+#123|foo); doing so is probably overkill.) + * Turn !!foo into foo + * Turn !#TRUE into #FALSE and vis versa + * + * Possible future additions: + * Change foo&#FALSE&bar into #FALSE + * Change foo|#TRUE|bar into #TRUE + * + * \param ast the syntax tree to transform + */ +static void +optimize_bvm_ast(struct boolexp_node *ast) +{ + struct boolexp_node *temp; + + if (!ast) + return; + switch (ast->type) { + case BOOLEXP_OR: + if (((ast->data.sub.a->type == BOOLEXP_IS && ast->data.sub.b->type == BOOLEXP_CARRY) + || (ast->data.sub.a->type == BOOLEXP_CARRY && ast->data.sub.b->type == BOOLEXP_IS)) + && (ast->data.sub.a->thing == ast->data.sub.b->thing)) { + /* Turn =#123|+#123 into #123 */ + + dbref thing = ast->data.sub.a->thing; + + free_bool(ast->data.sub.a); + free_bool(ast->data.sub.b); + ast->type = BOOLEXP_CONST; + ast->thing = thing; + ast->data.sub.a = ast->data.sub.b = NULL; + } else { + optimize_bvm_ast(ast->data.sub.a); + optimize_bvm_ast(ast->data.sub.b); + } + break; + case BOOLEXP_AND: + optimize_bvm_ast(ast->data.sub.a); + optimize_bvm_ast(ast->data.sub.b); + break; + case BOOLEXP_NOT: + temp = ast->data.n; + if (temp->type == BOOLEXP_NOT) { + /* Turn !!foo into foo */ + struct boolexp_node *n = temp->data.n; + free_bool(temp); + ast->type = n->type; + ast->thing = n->thing; + ast->data = n->data; + free_bool(n); + optimize_bvm_ast(ast); + } else if (temp->type == BOOLEXP_BOOL) { + /* Turn !#true into #false */ + ast->type = BOOLEXP_BOOL; + ast->thing = !temp->thing; + ast->data.n = NULL; + free_bool(temp); + } else + optimize_bvm_ast(ast->data.n); + break; + default: + (void)0; /* Nothing to do. */ + } +} + +/** Do some trivial optimizations of boolexp vm assembly. + * + * + * Current optimizations: Thread jumping + * + * Possible future additions: + * Just-in-time compiling of locks to machine code? Raevnos did this once as a proof of concept. + * + * \param a the assembler list to transform. + */ static void -opt_thread_jumps(struct bvm_asm *a) +optimize_bvm_asm(struct bvm_asm *a) { struct bvm_asmnode *n, *target; + + if (!a) + return; for (n = a->head; n;) { + + /* Avoid jumps that lead straight to another jump. If the second + * jump is on the same condition as the first one, jump instead to its + * destination. If it's the opposite condition, jump instead to the + * first instruction after the second jump to avoid the useless + * conditional check. + */ if (n->op == OP_JMPT || n->op == OP_JMPF) { target = insn_after_label(a, n->arg); if (target && (target->op == OP_JMPT || target->op == OP_JMPF)) { @@ -1698,8 +1785,7 @@ opt_thread_jumps(struct bvm_asm *a) struct bvm_asmnode *newlbl; newlbl = slab_malloc(bvm_asmnode_slab, NULL); if (!newlbl) - mush_panic(T - ("Unable to allocate memory for boolexp asm node!")); + mush_panic(T("Unable to allocate memory for boolexp asm node!")); newlbl->op = OP_LABEL; n->arg = newlbl->arg = gen_label_id(a); if (target->next) @@ -1717,17 +1803,6 @@ opt_thread_jumps(struct bvm_asm *a) } } -/** Do some trivial optimizations. - * \param a the assembler list to transform. - */ -static void -optimize_bvm_asm(struct bvm_asm *a) -{ - if (!a) - return; - opt_thread_jumps(a); -} - /** Turn assembly into bytecode. * \param a the assembly list to emit. * \param the compiled bytecode. @@ -1834,6 +1909,7 @@ parse_boolexp_d(dbref player, const char *buf, lock_type ltype, int derefs) ast = parse_boolexp_E(); if (!ast) return TRUE_BOOLEXP; + optimize_bvm_ast(ast); bvasm = generate_bvm_asm(ast); if (!bvasm) { free_boolexp_node(ast); diff --git a/src/function.c b/src/function.c index 0b7ee59..dd368ba 100644 --- a/src/function.c +++ b/src/function.c @@ -500,7 +500,7 @@ FUNTAB flist[] = { {"LIT", fun_lit, 1, -1, FN_LITERAL}, {"LJUST", fun_ljust, 2, 3, FN_REG}, {"LLOCKFLAGS", fun_lockflags, 0, 1, FN_REG}, - {"LLOCKS", fun_locks, 1, 1, FN_REG}, + {"LLOCKS", fun_locks, 0, 1, FN_REG}, {"LMATH", fun_lmath, 2, 3, FN_REG}, {"LNUM", fun_lnum, 1, 4, FN_REG}, {"LOC", fun_loc, 1, 1, FN_REG}, diff --git a/src/fundb.c b/src/fundb.c index b3e4604..0477824 100644 --- a/src/fundb.c +++ b/src/fundb.c @@ -1127,13 +1127,30 @@ get_locktype(str) return upcasestr(str); } +extern lock_list lock_types[]; /* ARGSUSED */ FUNCTION(fun_locks) { - dbref thing = match_thing(executor, args[0]); + dbref thing; lock_list *ll; const lock_list *p; - int first = 1; + bool first = 1; + + if (nargs == 0) { + /* List all builtin lock names */ + int n; + + for (n = 0; lock_types[n].type; n++) { + if (!first) + safe_chr(' ', buff, bp); + else + first = 0; + safe_str(lock_types[n].type, buff, bp); + } + return; + } + + thing = match_thing(executor, args[0]); if (!GoodObject(thing)) { safe_str(T(e_notvis), buff, bp); @@ -1152,6 +1169,7 @@ FUNCTION(fun_locks) } } + /* ARGSUSED */ FUNCTION(fun_lockflags) { -- 2.30.2