All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.luaj.vm2.luajc.ProtoInfo Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
package org.luaj.vm2.luajc;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Hashtable;

import org.luaj.vm2.Lua;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.Print;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.Upvaldesc;

/**
 * Prototype information for static single-assignment analysis
 */
public class ProtoInfo {

	public final String name;
	public final Prototype prototype;     // the prototype that this info is about
	public final ProtoInfo[] subprotos;   // one per enclosed prototype, or null
	public final BasicBlock[] blocks;     // basic block analysis of code branching
	public final BasicBlock[] blocklist;  // blocks in breadth-first order
	public final VarInfo[] params;        // Parameters and initial values of stack variables
	public final VarInfo[][] vars;        // Each variable
	public final UpvalInfo[] upvals;      // from outer scope
	public final UpvalInfo[][] openups;   // per slot, upvalues allocated by this prototype
	
	// A main chunk proto info.
	public ProtoInfo(Prototype p, String name) {
		// For the outer chunk, we have one upvalue which is the environment.
		this(p,name,null);
	}
	
	private ProtoInfo(Prototype p, String name, UpvalInfo[] u) {
		this.name = name;
		this.prototype = p;
		this.upvals = u != null? u: new UpvalInfo[] { new UpvalInfo(this) };
		this.subprotos = p.p!=null&&p.p.length>0? new ProtoInfo[p.p.length]: null;
		
		// find basic blocks
		this.blocks = BasicBlock.findBasicBlocks(p);
		this.blocklist = BasicBlock.findLiveBlocks(blocks);
		
		// params are inputs to first block
		this.params = new VarInfo[p.maxstacksize];
		for ( int slot=0; slot b0.pc0 )
					propogateVars( v, pc-1, pc );
				
				int a,b,c;
				int ins = prototype.code[pc];
				int op = Lua.GET_OPCODE(ins);
	
				// account for assignments, references and invalidations
				switch ( op ) {
				case Lua.OP_LOADK:/*	A Bx	R(A) := Kst(Bx)					*/
				case Lua.OP_LOADBOOL:/*	A B C	R(A) := (Bool)B; if (C) pc++			*/
				case Lua.OP_GETUPVAL: /*	A B	R(A) := UpValue[B]				*/
				case Lua.OP_NEWTABLE: /*	A B C	R(A) := {} (size = B,C)				*/
					a = Lua.GETARG_A( ins );
					v[a][pc] = new VarInfo(a,pc);
					break;
				
				case Lua.OP_MOVE:/*	A B	R(A) := R(B)					*/				
				case Lua.OP_UNM: /*	A B	R(A) := -R(B)					*/
				case Lua.OP_NOT: /*	A B	R(A) := not R(B)				*/
				case Lua.OP_LEN: /*	A B	R(A) := length of R(B)				*/
				case Lua.OP_TESTSET: /*	A B C	if (R(B) <=> C) then R(A) := R(B) else pc++	*/ 
					a = Lua.GETARG_A( ins );
					b = Lua.GETARG_B( ins );
					v[b][pc].isreferenced = true;
					v[a][pc] = new VarInfo(a,pc);
					break;
					
				case Lua.OP_ADD: /*	A B C	R(A) := RK(B) + RK(C)				*/
				case Lua.OP_SUB: /*	A B C	R(A) := RK(B) - RK(C)				*/
				case Lua.OP_MUL: /*	A B C	R(A) := RK(B) * RK(C)				*/
				case Lua.OP_DIV: /*	A B C	R(A) := RK(B) / RK(C)				*/
				case Lua.OP_MOD: /*	A B C	R(A) := RK(B) % RK(C)				*/
				case Lua.OP_POW: /*	A B C	R(A) := RK(B) ^ RK(C)				*/
					a = Lua.GETARG_A( ins );
					b = Lua.GETARG_B( ins );
					c = Lua.GETARG_C( ins );
					if (!Lua.ISK(b)) v[b][pc].isreferenced = true;
					if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
					v[a][pc] = new VarInfo(a,pc);
					break;
					
				case Lua.OP_SETTABLE: /*	A B C	R(A)[RK(B)]:= RK(C)				*/
					a = Lua.GETARG_A( ins );
					b = Lua.GETARG_B( ins );
					c = Lua.GETARG_C( ins );
					v[a][pc].isreferenced = true;
					if (!Lua.ISK(b)) v[b][pc].isreferenced = true;
					if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
					break;

				case Lua.OP_SETTABUP: /*	A B C	UpValue[A][RK(B)] := RK(C)			*/
					b = Lua.GETARG_B( ins );
					c = Lua.GETARG_C( ins );
					if (!Lua.ISK(b)) v[b][pc].isreferenced = true;
					if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
					break;
					
				case Lua.OP_CONCAT: /*	A B C	R(A) := R(B).. ... ..R(C)			*/
					a = Lua.GETARG_A( ins );
					b = Lua.GETARG_B( ins );
					c = Lua.GETARG_C( ins );
					for ( ; b<=c; b++ )
						v[b][pc].isreferenced = true;
					v[a][pc] = new VarInfo(a,pc);
					break;
					
				case Lua.OP_FORPREP: /*	A sBx	R(A)-=R(A+2); pc+=sBx				*/
					a = Lua.GETARG_A( ins );
					v[a+2][pc].isreferenced = true;
					v[a][pc] = new VarInfo(a,pc);
					break;
					
				case Lua.OP_GETTABLE: /*	A B C	R(A) := R(B)[RK(C)]				*/
					a = Lua.GETARG_A( ins );
					b = Lua.GETARG_B( ins );
					c = Lua.GETARG_C( ins );
					v[b][pc].isreferenced = true;
					if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
					v[a][pc] = new VarInfo(a,pc);
					break;
					
				case Lua.OP_GETTABUP: /*	A B C	R(A) := UpValue[B][RK(C)]			*/
					a = Lua.GETARG_A( ins );
					c = Lua.GETARG_C( ins );
					if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
					v[a][pc] = new VarInfo(a,pc);
					break;

				case Lua.OP_SELF: /*	A B C	R(A+1) := R(B); R(A) := R(B)[RK(C)]		*/
					a = Lua.GETARG_A( ins );
					b = Lua.GETARG_B( ins );
					c = Lua.GETARG_C( ins );
					v[b][pc].isreferenced = true;
					if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
					v[a][pc] = new VarInfo(a,pc);
					v[a+1][pc] = new VarInfo(a+1,pc);
					break;
					
				case Lua.OP_FORLOOP: /*	A sBx	R(A)+=R(A+2);
					if R(A) =0; a++ )
						v[a][pc] = new VarInfo(a,pc);
					break;
					
				case Lua.OP_VARARG: /*	A B	R(A), R(A+1), ..., R(A+B-1) = vararg		*/			
					a = Lua.GETARG_A( ins );
					b = Lua.GETARG_B( ins );
					for ( int j=1; j C) then pc++			*/ 
					a = Lua.GETARG_A( ins );
					v[a][pc].isreferenced = true;
					break;

				case Lua.OP_EQ: /*	A B C	if ((RK(B) == RK(C)) ~= A) then pc++		*/
				case Lua.OP_LT: /*	A B C	if ((RK(B) <  RK(C)) ~= A) then pc++  		*/
				case Lua.OP_LE: /*	A B C	if ((RK(B) <= RK(C)) ~= A) then pc++  		*/
					b = Lua.GETARG_B( ins );
					c = Lua.GETARG_C( ins );
					if (!Lua.ISK(b)) v[b][pc].isreferenced = true;
					if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
					break;

				case Lua.OP_JMP: /*	sBx	pc+=sBx					*/
					a = Lua.GETARG_A( ins );
					if (a > 0)
						for ( --a; a 0 && vars[slot][pc] != null && vars[slot][pc].pc == pc && vars[slot][pc-1] != null  )
			pc -= 1;
		VarInfo v = pc<0? params[slot]: vars[slot][pc];
		return v != null && v.upvalue != null && v.upvalue.rw;
	}

	public boolean isInitialValueUsed(int slot) {
		VarInfo v = params[slot];
		return v.isreferenced;
	}

	public boolean isReadWriteUpvalue(UpvalInfo u) {
		return u.rw;
	}
	
	private String[] findInnerprotoNames() {
		if (prototype.p.length <= 0)
			return null;
		// find all the prototype names
		String[] names = new String[prototype.p.length];
		Hashtable used = new Hashtable(); 
		int[] code = prototype.code;
		int n = code.length;
		for ( int pc=0; pc




© 2015 - 2024 Weber Informatics LLC | Privacy Policy