From 46f726843cdc443b93cba6facecf6909b8ec78cb Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Fri, 24 Jan 2014 01:27:44 +0100 Subject: [PATCH] Leave last evaluated expression on the stack for script code. Pop before evaluating an expression statement, rather than after. Keep track of the stack when looping and exiting a for-in statement (which keeps the iterator on the stack between statements). This involves a few more stack gyrations during for-in statements, so the code is predicated on compiling script code. --- jscompile.c | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/jscompile.c b/jscompile.c index ebf3631..c2e0357 100644 --- a/jscompile.c +++ b/jscompile.c @@ -654,10 +654,17 @@ static void cexit(JF, js_AstType T, js_Ast *node, js_Ast *target) case STM_FOR_IN: case STM_FOR_IN_VAR: /* pop the iterator if leaving the loop */ - if (T == STM_RETURN) - emit(J, F, OP_ROT2POP1); /* save the return value */ - if (T == STM_BREAK) - emit(J, F, OP_POP); + if (F->script) { + if (T == STM_RETURN || T == STM_BREAK || (T == STM_CONTINUE && target != node)) + emit(J, F, OP_ROT2POP1); /* pop the iterator, save the return or exp value */ + if (T == STM_CONTINUE) + emit(J, F, OP_ROT2); /* put the iterator back on top */ + } else { + if (T == STM_RETURN) + emit(J, F, OP_ROT2POP1); /* pop the iterator, save the return value */ + if (T == STM_BREAK || (T == STM_CONTINUE && target != node)) + emit(J, F, OP_POP); /* pop the iterator */ + } break; case STM_TRY: /* came from try block */ @@ -810,6 +817,10 @@ static void cstm(JF, js_Ast *stm) break; case STM_EMPTY: + if (F->script) { + emit(J, F, OP_POP); + emit(J, F, OP_UNDEF); + } break; case STM_VAR: @@ -887,7 +898,13 @@ static void cstm(JF, js_Ast *stm) emit(J, F, OP_NEXTITER); end = jump(J, F, OP_JFALSE); cassignforin(J, F, stm); - cstm(J, F, stm->c); + if (F->script) { + emit(J, F, OP_ROT2); + cstm(J, F, stm->c); + emit(J, F, OP_ROT2); + } else { + cstm(J, F, stm->c); + } jumpto(J, F, OP_JUMP, loop); } label(J, F, end); @@ -977,8 +994,13 @@ static void cstm(JF, js_Ast *stm) break; default: - cexp(J, F, stm); - emit(J, F, OP_POP); + if (F->script) { + emit(J, F, OP_POP); + cexp(J, F, stm); + } else { + cexp(J, F, stm); + emit(J, F, OP_POP); + } break; } } @@ -1047,14 +1069,21 @@ static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body) cparams(J, F, params); + if (F->script) + emit(J, F, OP_UNDEF); + if (body) { cfundecs(J, F, body); cvardecs(J, F, body); cstmlist(J, F, body); } - emit(J, F, OP_UNDEF); - emit(J, F, OP_RETURN); + if (F->script) { + emit(J, F, OP_RETURN); + } else { + emit(J, F, OP_UNDEF); + emit(J, F, OP_RETURN); + } } js_Function *jsC_compile(js_State *J, js_Ast *prog)