/** * */ package org.mod.luaj.vm2.luajc; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class VarInfo { public static VarInfo INVALID = new VarInfo(-1, -1); public static VarInfo PARAM(int slot) { return new ParamVarInfo(slot, -1); } public static VarInfo NIL(final int slot) { return new NilVarInfo(slot, -1); } public static VarInfo PHI(final ProtoInfo pi, final int slot, final int pc) { return new PhiVarInfo(pi, slot, pc); } public final int slot; // where assigned public final int pc; // where assigned, or -1 if for block inputs public UpvalInfo upvalue; // not null if this var is an upvalue public boolean allocupvalue; // true if this variable allocates r/w upvalue // storage public boolean isreferenced; // true if this variable is refenced by some // opcode public VarInfo(int slot, int pc) { this.slot = slot; this.pc = pc; } public String toString() { return slot < 0 ? "x.x" : (slot + "." + pc); } /** Return replacement variable if there is exactly one value possible, * otherwise compute entire collection of variables and return null. * Computes the list of aall variable values, and saves it for the future. * * @return new Variable to replace with if there is only one value, or null to leave alone. */ public VarInfo resolvePhiVariableValues() { return null; } protected void collectUniqueValues(Set visitedBlocks, Set vars) { vars.add(this); } public boolean isPhiVar() { return false; } private static final class ParamVarInfo extends VarInfo { private ParamVarInfo(int slot, int pc) { super(slot, pc); } public String toString() { return slot + ".p"; } } private static final class NilVarInfo extends VarInfo { private NilVarInfo(int slot, int pc) { super(slot, pc); } public String toString() { return "nil"; } } private static final class PhiVarInfo extends VarInfo { private final ProtoInfo pi; VarInfo[] values; private PhiVarInfo(ProtoInfo pi, int slot, int pc) { super(slot, pc); this.pi = pi; } public boolean isPhiVar() { return true; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append( super.toString() ); sb.append("={"); for (int i=0, n=(values!=null? values.length : 0); i<n; i++) { if ( i>0 ) sb.append( "," ); sb.append(String.valueOf(values[i])); } sb.append("}"); return sb.toString(); } public VarInfo resolvePhiVariableValues() { Set visitedBlocks = new HashSet(); Set vars = new HashSet(); this.collectUniqueValues(visitedBlocks, vars); if (vars.contains(INVALID)) return INVALID; int n = vars.size(); Iterator it = vars.iterator(); if (n == 1) { VarInfo v = (VarInfo) it.next(); v.isreferenced |= this.isreferenced; return v; } this.values = new VarInfo[n]; for ( int i=0; i<n; i++ ) { this.values[i] = (VarInfo) it.next(); this.values[i].isreferenced |= this.isreferenced; } return null; } protected void collectUniqueValues(Set visitedBlocks, Set vars) { BasicBlock b = pi.blocks[pc]; if ( pc == 0 ) vars.add(pi.params[slot]); for (int i = 0, n = b.prev != null ? b.prev.length : 0; i < n; i++) { BasicBlock bp = b.prev[i]; if (!visitedBlocks.contains(bp)) { visitedBlocks.add(bp); VarInfo v = pi.vars[slot][bp.pc1]; if ( v != null ) v.collectUniqueValues(visitedBlocks, vars); } } } } }