diff --git a/src/main/java/org/squiddev/luaj/luajc/compilation/JavaBuilder.java b/src/main/java/org/squiddev/luaj/luajc/compilation/JavaBuilder.java index cbe4c24..8c74c08 100644 --- a/src/main/java/org/squiddev/luaj/luajc/compilation/JavaBuilder.java +++ b/src/main/java/org/squiddev/luaj/luajc/compilation/JavaBuilder.java @@ -113,10 +113,13 @@ public final class JavaBuilder { private final Map constants = new HashMap(); + private final SlotInfo[] slots; + public JavaBuilder(ProtoInfo pi, String prefix, String filename) { this.pi = pi; this.p = pi.prototype; this.prefix = prefix; + this.slots = new SlotInfo[p.maxstacksize]; String className = this.className = prefix + pi.name; @@ -232,7 +235,8 @@ public void initializeSlots() { } else { // fixed arg function between 0 and 3 arguments for (slot = 0; slot < p.numparams; slot++) { - this.plainSlotVars.put(slot, slot + VARARGS_SLOT); + SlotInfo info = slots[slot] = new SlotInfo(slot); + info.valueSlot = slot + VARARGS_SLOT; if (pi.params[slot].isUpvalueCreate(-1)) { main.visitVarInsn(ALOAD, slot + VARARGS_SLOT); storeLocal(-1, slot); @@ -260,12 +264,8 @@ public byte[] completeClass() { main.visitMaxs(0, 0); // Add upvalue & local value slot names - for (Map.Entry slot : plainSlotVars.entrySet()) { - main.visitLocalVariable(PREFIX_LOCAL_SLOT + "_" + slot.getKey(), TYPE_LUAVALUE, null, start, end, slot.getValue()); - } - - for (Map.Entry slot : upvalueSlotVars.entrySet()) { - main.visitLocalVariable(PREFIX_UPVALUE_SLOT + "_" + slot.getKey(), TYPE_UPVALUE, null, start, end, slot.getValue()); + for (SlotInfo slot : slots) { + if (slot != null) slot.injectSlot(main, start, end); } main.visitEnd(); @@ -296,22 +296,19 @@ public void loadBoolean(boolean b) { main.visitFieldInsn(GETSTATIC, "org/luaj/vm2/LuaValue", field, "Lorg/luaj/vm2/LuaBoolean;"); } - private final Map plainSlotVars = new HashMap(); - private final Map upvalueSlotVars = new HashMap(); - - private int findSlot(int luaSlot, Map map) { - if (map.containsKey(luaSlot)) return map.get(luaSlot); - - // This will always be an Upvalue/LuaValue so the slot size is 1 as it is a reference - int javaSlot = ++maxLocals; - map.put(luaSlot, javaSlot); - return javaSlot; - } - private int findSlotIndex(int slot, boolean isUpvalue) { - return isUpvalue ? - findSlot(slot, upvalueSlotVars) : - findSlot(slot, plainSlotVars); + SlotInfo info = slots[slot]; + if (info == null) info = slots[slot] = new SlotInfo(slot); + + if (isUpvalue) { + int javaSlot = info.upvalueSlot; + if (javaSlot < 0) javaSlot = info.upvalueSlot = ++maxLocals; + return javaSlot; + } else { + int javaSlot = info.valueSlot; + if (javaSlot < 0) javaSlot = info.valueSlot = ++maxLocals; + return javaSlot; + } } public void loadLocal(int pc, int slot) { diff --git a/src/main/java/org/squiddev/luaj/luajc/compilation/SlotInfo.java b/src/main/java/org/squiddev/luaj/luajc/compilation/SlotInfo.java new file mode 100644 index 0000000..fde529e --- /dev/null +++ b/src/main/java/org/squiddev/luaj/luajc/compilation/SlotInfo.java @@ -0,0 +1,32 @@ +package org.squiddev.luaj.luajc.compilation; + +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; + +import static org.squiddev.luaj.luajc.Constants.PREFIX_LOCAL_SLOT; +import static org.squiddev.luaj.luajc.Constants.TYPE_LUAVALUE; + +/** + * Tracks information in a slot + */ +public final class SlotInfo { + public final int luaSlot; + + public int valueSlot = -1; + + public int upvalueSlot = -1; + + public SlotInfo(int luaSlot) { + this.luaSlot = luaSlot; + } + + public void injectSlot(MethodVisitor visitor, Label start, Label end) { + if (valueSlot >= 0) { + visitor.visitLocalVariable(PREFIX_LOCAL_SLOT + "_" + luaSlot, TYPE_LUAVALUE, null, start, end, valueSlot); + } + + if (upvalueSlot >= 0) { + visitor.visitLocalVariable(PREFIX_LOCAL_SLOT + "_" + luaSlot, TYPE_LUAVALUE, null, start, end, upvalueSlot); + } + } +}