From 80d9b09f351c7a9be557116e9c79ae11e9b3f032 Mon Sep 17 00:00:00 2001
From: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Wed, 13 Sep 2017 16:50:08 -0300
Subject: jumps do not close upvalues (to be faster and simpler); explicit
 instruction to close upvalues; command 'break' not handled like a 'goto' (to
 optimize removal of uneeded 'close' instructions)

---
 lcode.c | 51 +++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 41 insertions(+), 10 deletions(-)

(limited to 'lcode.c')

diff --git a/lcode.c b/lcode.c
index 169c439d..1edf08aa 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.120 2017/06/27 11:35:31 roberto Exp roberto $
+** $Id: lcode.c,v 2.121 2017/06/29 15:06:44 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -272,20 +272,51 @@ void luaK_patchlist (FuncState *fs, int list, int target) {
 
 
 /*
-** Path all jumps in 'list' to close upvalues up to given 'level'
-** (The assertion checks that jumps either were closing nothing
-** or were closing higher levels, from inner blocks.)
+** Check whether some jump in given list needs a close instruction.
 */
-void luaK_patchclose (FuncState *fs, int list, int level) {
-  level++;  /* argument is +1 to reserve 0 as non-op */
+int luaK_needclose (FuncState *fs, int list) {
   for (; list != NO_JUMP; list = getjump(fs, list)) {
-    lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP &&
-                (GETARG_A(fs->f->code[list]) == 0 ||
-                 GETARG_A(fs->f->code[list]) >= level));
-    SETARG_A(fs->f->code[list], level);
+    if (GETARG_A(fs->f->code[list]))  /* needs close? */
+      return 1;
+  }
+  return 0;
+}
+
+
+/*
+** Correct a jump list to jump to 'target'. If 'hasclose' is true,
+** 'target' contains an OP_CLOSE instruction (see first assert).
+** Only jumps with the A arg true need that close; other jumps
+** avoid it jumping to the next instruction.
+*/
+void luaK_patchgoto (FuncState *fs, int list, int target, int hasclose) {
+  lua_assert(!hasclose || GET_OPCODE(fs->f->code[target]) == OP_CLOSE);
+  while (list != NO_JUMP) {
+    int next = getjump(fs, list);
+    lua_assert(!GETARG_A(fs->f->code[list]) || hasclose);
+    patchtestreg(fs, list, NO_REG);  /* do not generate values */
+    if (!hasclose || GETARG_A(fs->f->code[list]))
+      fixjump(fs, list, target);
+    else  /* there is a CLOSE instruction but jump does not need it */
+      fixjump(fs, list, target + 1);  /* avoid CLOSE instruction */
+    list = next;
   }
 }
 
+
+/*
+** Mark (using the A arg) all jumps in 'list' to close upvalues. Mark
+** will instruct 'luaK_patchgoto' to make these jumps go to OP_CLOSE
+** instructions.
+*/
+void luaK_patchclose (FuncState *fs, int list) {
+  for (; list != NO_JUMP; list = getjump(fs, list)) {
+    lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP);
+    SETARG_A(fs->f->code[list], 1);
+  }
+}
+
+
 #if !defined(MAXIWTHABS)
 #define MAXIWTHABS	120
 #endif
-- 
cgit v1.2.3-55-g6feb