[pure-lang-svn] SF.net SVN: pure-lang: [106] pure/trunk
Status: Beta
Brought to you by:
agraef
From: <ag...@us...> - 2008-05-22 14:42:13
|
Revision: 106 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=106&view=rev Author: agraef Date: 2008-05-22 07:42:19 -0700 (Thu, 22 May 2008) Log Message: ----------- Reenable some optimizations to speed up trivial cases of function calls and returns, which were previously removed (cf. rev. 97) to facilitate implementation of the shadow stack. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/interpreter.cc pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-05-22 07:14:45 UTC (rev 105) +++ pure/trunk/ChangeLog 2008-05-22 14:42:19 UTC (rev 106) @@ -4,8 +4,8 @@ handling. Fixed the shadow stack and memory debugging code. Both function arguments and environment are now visible on the shadow stack, and all remaining memory leaks have been fixed. Note that, - compared to previous revisions, the shadow stack slows down the - interpreter a little bit and it also needs some additional memory. + compared to previous revisions, the shadow stack slows down + compiled code by some 10% and it needs some additional memory. OTOH, it also provides additional data that will be needed in the planned symbolic debugger, and it seems to be the most efficient way to handle dangling expression pointers after an exception Modified: pure/trunk/interpreter.cc =================================================================== --- pure/trunk/interpreter.cc 2008-05-22 07:14:45 UTC (rev 105) +++ pure/trunk/interpreter.cc 2008-05-22 14:42:19 UTC (rev 106) @@ -253,6 +253,13 @@ declare_extern((void*)pure_pop_tail_args, "pure_pop_tail_args", "void", -2, "expr*", "int"); + declare_extern((void*)pure_push_arg, + "pure_push_arg", "void", 1, "expr*"); + declare_extern((void*)pure_pop_arg, + "pure_pop_arg", "void", 1, "expr*"); + declare_extern((void*)pure_pop_tail_arg, + "pure_pop_tail_arg", "void", 1, "expr*"); + declare_extern((void*)pure_debug, "pure_debug", "void", -2, "int", "char*"); } @@ -1678,6 +1685,7 @@ ReturnInst *ret = builder.CreateRet(v); Instruction *pi = ret; Function *free_fun = interp.module->getFunction("pure_pop_args"); + Function *free1_fun = interp.module->getFunction("pure_pop_arg"); if (isa<CallInst>(v)) { CallInst* c = cast<CallInst>(v); // Check whether the call is actually subject to tail call elimination (as @@ -1691,8 +1699,12 @@ if (isa<CallInst>(it)) { CallInst* c1 = cast<CallInst>(it); if (c1->getCalledFunction() == - interp.module->getFunction("pure_push_args")) + interp.module->getFunction("pure_push_args") || + c1->getCalledFunction() == + interp.module->getFunction("pure_push_arg")) { free_fun = interp.module->getFunction("pure_pop_tail_args"); + free1_fun = interp.module->getFunction("pure_pop_tail_arg"); + } } } pi = c; @@ -1700,7 +1712,12 @@ // We must garbage-collect args and environment here, immediately before the // call (if any), or the return instruction otherwise. vector<Value*> myargs; - if (n+m != 0) { + if (pi != ret && n == 1 && m == 0) + new CallInst(free1_fun, args[0], "", pi); + else if (pi != ret && n == 0 && m == 1) { + Value *v = new GetElementPtrInst(envs, Zero, "", pi); + new CallInst(free1_fun, new LoadInst(v, "", pi), "", pi); + } else if (n+m != 0) { if (pi == ret) myargs.push_back(v); else @@ -3075,10 +3092,14 @@ if (n>0) { for (i = 0; i < n; i++) argv[i] = codegen(args[i]); - vector<Value*> argv1; - argv1.push_back(UInt(n)); - argv1.insert(argv1.end(), argv.begin(), argv.end()); - act_env().CreateCall(module->getFunction("pure_push_args"), argv1); + if (n == 1) + act_env().CreateCall(module->getFunction("pure_push_arg"), argv); + else { + vector<Value*> argv1; + argv1.push_back(UInt(n)); + argv1.insert(argv1.end(), argv.begin(), argv.end()); + act_env().CreateCall(module->getFunction("pure_push_args"), argv1); + } } return act_env().CreateCall(info.f, argv); } @@ -3360,10 +3381,14 @@ return fcall(f, x); else { // create a boxed closure - vector<Value*> newargs; - newargs.push_back(UInt(f.m)); - newargs.insert(newargs.end(), x.begin(), x.end()); - act_env().CreateCall(module->getFunction("pure_new_args"), newargs); + if (f.m == 1) + act_env().CreateCall(module->getFunction("pure_new"), x); + else { + vector<Value*> newargs; + newargs.push_back(UInt(f.m)); + newargs.insert(newargs.end(), x.begin(), x.end()); + act_env().CreateCall(module->getFunction("pure_new_args"), newargs); + } return call("pure_clos", f.local, thunked, f.tag, f.h, f.n, x); } } @@ -3578,10 +3603,14 @@ return fcall(f, x); else { // create a boxed closure - vector<Value*> newargs; - newargs.push_back(UInt(f.m)); - newargs.insert(newargs.end(), x.begin(), x.end()); - act_env().CreateCall(module->getFunction("pure_new_args"), newargs); + if (f.m == 1) + act_env().CreateCall(module->getFunction("pure_new"), x); + else { + vector<Value*> newargs; + newargs.push_back(UInt(f.m)); + newargs.insert(newargs.end(), x.begin(), x.end()); + act_env().CreateCall(module->getFunction("pure_new_args"), newargs); + } return call("pure_clos", f.local, thunked, f.tag, f.h, f.n, x); } } @@ -3605,7 +3634,11 @@ x.push_back(e.argv); } // count references to parameters - if (n+m > 0) { + if (n == 1 && m == 0) + e.CreateCall(module->getFunction("pure_push_arg"), args); + else if (n == 0 && m == 1) + e.CreateCall(module->getFunction("pure_push_arg"), env); + else if (n+m > 0) { vector<Value*> args1; args1.push_back(UInt(n+m)); args1.insert(args1.end(), args.begin(), args.end()); @@ -4039,10 +4072,14 @@ x[i] = f.CreateLoadGEP(f.envs, UInt(i)); assert(x[i]->getType() == ExprPtrTy); } - vector<Value*> newargs; - newargs.push_back(UInt(f.m)); - newargs.insert(newargs.end(), x.begin(), x.end()); - act_env().CreateCall(module->getFunction("pure_new_args"), newargs); + if (f.m == 1) + act_env().CreateCall(module->getFunction("pure_new"), x); + else { + vector<Value*> newargs; + newargs.push_back(UInt(f.m)); + newargs.insert(newargs.end(), x.begin(), x.end()); + act_env().CreateCall(module->getFunction("pure_new_args"), newargs); + } Value *defaultv = call("pure_clos", f.local, true, f.tag, f.h, f.n, x); for (size_t i = 0; i < f.n; ++i) { Value *arg = f.args[i]; Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-05-22 07:14:45 UTC (rev 105) +++ pure/trunk/runtime.cc 2008-05-22 14:42:19 UTC (rev 106) @@ -1027,6 +1027,66 @@ } extern "C" +void pure_push_arg(pure_expr *x) +{ + interpreter& interp = *interpreter::g_interp; + size_t sz = interp.sstk_sz; + resize_sstk(interp.sstk, interp.sstk_cap, sz, 2); + pure_expr** sstk = interp.sstk; + sstk[sz++] = 0; sstk[sz++] = x; + if (x->refc > 0) + x->refc++; + else + pure_new_internal(x); +#if SSTK_DEBUG>1 + cerr << "++ stack: (sz = " << sz << ")\n"; + for (size_t i = 0; i < sz; i++) { + pure_expr *x = sstk[i]; + if (i == interp.sstk_sz) cerr << "** pushed:\n"; + if (x) + cerr << i << ": " << (void*)x << ": " << x << endl; + else + cerr << i << ": " << "** frame **\n"; + } +#endif + interp.sstk_sz = sz; +} + +extern "C" +void pure_pop_arg(pure_expr *x) +{ +#if SSTK_DEBUG + pure_pop_args(0, 1, x); +#else + interpreter& interp = *interpreter::g_interp; + interp.sstk_sz -= 2; + if (x->refc > 1) + x->refc--; + else + pure_free_internal(x); +#endif +} + +extern "C" +void pure_pop_tail_arg(pure_expr *x) +{ +#if SSTK_DEBUG + pure_pop_tail_args(0, 1, x); +#else + interpreter& interp = *interpreter::g_interp; + pure_expr **sstk = interp.sstk; + size_t lastsz = interp.sstk_sz, oldsz = lastsz; + while (lastsz > 0 && sstk[--lastsz]) ; + memmove(sstk+lastsz-2, sstk+lastsz, (oldsz-lastsz)*sizeof(pure_expr*)); + interp.sstk_sz -= 2; + if (x->refc > 1) + x->refc--; + else + pure_free_internal(x); +#endif +} + +extern "C" void pure_debug(int32_t tag, const char *format, ...) { cout << "break at "; Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-05-22 07:14:45 UTC (rev 105) +++ pure/trunk/runtime.h 2008-05-22 14:42:19 UTC (rev 106) @@ -183,6 +183,12 @@ void pure_pop_args(pure_expr *x, uint32_t n, ...); void pure_pop_tail_args(pure_expr *x, uint32_t n, ...); +/* Optimize the special case of a single argument to be pushed/popped. */ + +void pure_push_arg(pure_expr *x); +void pure_pop_arg(pure_expr *x); +void pure_pop_tail_arg(pure_expr *x); + /* Debugging support. Preliminary. */ void pure_debug(int32_t tag, const char *format, ...); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |