org.xmlvm.refcount.InstructionUseInfo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dragome-bytecode-js-compiler Show documentation
Show all versions of dragome-bytecode-js-compiler Show documentation
Dragome SDK module: bytecode to javascript compiler
/* Copyright (c) 2002-2011 by XMLVM.org
*
* Project Info: http://www.xmlvm.org
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package org.xmlvm.refcount;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import org.jdom.DataConversionException;
import org.jdom.Element;
import org.jdom.Attribute;
/**
* This class contains information about how an instruction uses registers.
*/
public class InstructionUseInfo
{
/**
* The instruction that we collect information about
*/
Element Instruction;
/**
* On construction, we check for the normal vx vy vz register usage patterns
* present in DEX, adding them to our info store if they exist.
*/
public InstructionUseInfo(Element element) throws DataConversionException
{
this.Instruction= element;
checkUsage(element.getAttribute("vx"), element.getAttribute("vx-type"));
checkUsage(element.getAttribute("vy"), element.getAttribute("vy-type"));
checkUsage(element.getAttribute("vz"), element.getAttribute("vz-type"));
checkUsage(element.getAttribute("register"), element.getAttribute("type"));
checkUsage(element.getAttribute("register"), element.getAttribute("class-type"));
possibleWrites.add("vx");
}
/**
* Meaning that we are doing something like aput, which means we will need
* to potentially insert a release before we overwrite the pointer in the
* array.
*/
public Element putRelease= null;
/**
* Given a register attribute and a type attribute, this method adds both to
* this classes list of register usage. It also determines whether the usage
* is object or not object depending on the type. In order for all of the
* ref counting code to work, all register usage everywhere must be
* registered with this function.
*/
public void checkUsage(Attribute vy, Attribute vyType) throws DataConversionException
{
InstructionUseInfo use= this;
if (vy != null)
{
if (vyType != null)
{
if (InstructionProcessor.nonObjTypes.matcher(vyType.getValue()).matches())
{
use.typeIsObj.put(vy, Boolean.FALSE);
}
else
{
use.typeIsObj.put(vy, Boolean.TRUE);
}
}
}
}
/**
* If this instruction is a write instruction, the name of the register that
* is being written into.
*/
public List possibleWrites= new ArrayList();
/**
* Returns the registers which this instruction writes objects into
*/
public RegisterSet writesObj() throws DataConversionException
{
if (isWrite)
{
for (Attribute key : typeIsObj.keySet())
{
for (String s : possibleWrites)
{
if (key.getName().equals(s))
{
if (typeIsObj.get(key))
{
return RegisterSet.from(key.getIntValue());
}
}
}
}
}
return RegisterSet.none();
}
/**
* The list of registers this instruction writes with non objects
*/
public RegisterSet writesNonObj() throws DataConversionException
{
if (isWrite)
{
for (Attribute key : typeIsObj.keySet())
{
for (String s : possibleWrites)
{
if (key.getName().equals(s))
{
if (!typeIsObj.get(key))
{
return RegisterSet.from(key.getIntValue());
}
}
}
}
}
return RegisterSet.none();
}
/**
* The list of registers this instruction uses as objects
*/
public RegisterSet usesAsObj() throws DataConversionException
{
RegisterSet toRet= RegisterSet.none();
if (isWrite)
{
for (Entry a : typeIsObj.entrySet())
{
if (!possibleWrites.contains(a.getKey().getName()) && a.getValue())
{
// is object
toRet.add(a.getKey().getIntValue());
}
}
}
else
{
for (Entry a : typeIsObj.entrySet())
{
if (a.getValue())
{
// is object
toRet.add(a.getKey().getIntValue());
}
}
}
return toRet;
}
/**
* The list of registers this instruction uses as non objects
*/
public RegisterSet usesAsNonObj() throws DataConversionException
{
RegisterSet toRet= RegisterSet.none();
if (isWrite)
{
for (Entry a : typeIsObj.entrySet())
{
if (!possibleWrites.contains(a.getKey().getName()) && !a.getValue())
{
// is object
toRet.add(a.getKey().getIntValue());
}
}
}
else
{
for (Entry a : typeIsObj.entrySet())
{
if (!a.getValue())
{
// is object
toRet.add(a.getKey().getIntValue());
}
}
}
return toRet;
}
/**
* What registers should be freed after this instruction
*/
public RegisterSet willFree= RegisterSet.none();
/**
* What registers should be nulled after any free
*/
public RegisterSet willNull= RegisterSet.none();
/**
* The list of registers that require a retain after this instruction
* executes.
*/
public RegisterSet requiresRetain= RegisterSet.none();
/**
* Whether or not we need to free the temp register after this instruction
*/
public boolean freeTmpAfter;
/**
* Whether or not this instruction writes any registers.
*/
public boolean isWrite;
/**
* Given a register name, is it referring to an object or a non object?
*/
public HashMap typeIsObj= new HashMap();
/**
* The all registers (non object or object) used by this instruction
*/
public RegisterSet usedReg() throws DataConversionException
{
return usesAsNonObj().or(usesAsObj());
}
/*
* All registers written (non object or object) by this instruction
*/
public RegisterSet allWrites() throws DataConversionException
{
return writesObj().or(writesNonObj());
}
/**
* Complete dump of all registers used by this instruction
*/
public String toString()
{
StringBuilder toRet= new StringBuilder();
try
{
toRet.append(Instruction.getName());
if (isWrite)
{
if (!writesNonObj().isEmpty())
{
toRet.append(" Wi:" + writesNonObj());
}
else
{
toRet.append(" Wo:" + writesObj());
}
}
if (!usesAsNonObj().isEmpty())
{
toRet.append(" Ri:" + usesAsNonObj());
}
if (!usesAsObj().isEmpty())
{
toRet.append(" Ro:" + usesAsObj());
}
}
catch (DataConversionException ex)
{
toRet.append(ex.getMessage());
}
return toRet.toString();
}
}