123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- // Copyright (c) 1997, 2004 Per M.A. Bothner.
- // This is free software; for terms and warranty disclaimer see ./COPYING.
- package gnu.bytecode;
- import java.util.HashMap;
- public class Scope
- {
- /** The enclosing scope. */
- Scope parent;
- Scope nextSibling;
- Scope firstChild, lastChild;
- /** If true, don't call freeLocal on our variables (yet). */
- boolean preserved;
- boolean autoPop;
- Label start;
- Label end;
- private Variable vars;
- Variable last_var;
- public Scope()
- {
- }
- public Scope (Label start, Label end)
- {
- this.start = start;
- this.end = end;
- }
- // Variable lookup (String name);
- public final Variable firstVar () { return vars; }
- public VarEnumerator allVars () { return new VarEnumerator (this); }
- public Label getStartLabel() { return start; }
- public Label getEndLabel() { return end; }
- /** Link this scope as the next child of its parent scope. */
- public void linkChild (Scope parent)
- {
- this.parent = parent;
- if (parent == null)
- return;
- if (parent.lastChild == null)
- parent.firstChild = this;
- else
- parent.lastChild.nextSibling = this;
- parent.lastChild = this;
- }
- public Variable addVariable (CodeAttr code, Type type, String name)
- {
- Variable var = new Variable(name, type);
- addVariable (code, var);
- return var;
- }
- public void addVariable (Variable var)
- {
- if (last_var == null)
- vars = var;
- else
- last_var.next = var;
- last_var = var;
- var.setScope(this);
- }
- /* Add a new Variable, linking it in after a given Variable, */
- public void addVariableAfter (Variable prev, Variable var)
- {
- if (prev == null)
- { // Put first
- var.next = vars;
- vars = var;
- }
- else
- {
- var.next = prev.next;
- prev.next = var;
- }
- if (last_var == prev)
- last_var = var;
- if (var.next == var)
- throw new Error("cycle");
- var.setScope(this);
- }
- public void addVariable (CodeAttr code, Variable var)
- {
- addVariable (var);
- if (var.isSimple() && code != null)
- var.allocateLocal(code);
- }
- /**
- * Return a variable the scope, by numerical index.
- * @param index the number of the variable
- */
- public Variable getVariable(int index) {
- Variable var = vars;
- while (--index >= 0)
- var = var.next;
- return var;
- }
- /** Fix duplicate names.
- * This is needed for Android, since otherwise dex complains.
- */
- public void fixParamNames(HashMap<String,Variable> map) {
- for (Variable var = firstVar(); var != null;
- var = var.nextVar()) {
- String name = var.getName();
- if (name != null) {
- String xname = name;
- Variable old;
- for (int i = 0; (old = map.get(xname)) != null; i++)
- xname = name + '$' + i;
- if (name != xname)
- var.setName(xname);
- map.put(xname, var);
- }
- }
- }
- static boolean equals (byte[] name1, byte[] name2) {
- if (name1.length != name2.length)
- return false;
- if (name1 == name2)
- return true;
- for (int i = name1.length; --i >= 0; )
- if (name1[i] != name2[i])
- return false;
- return true;
- }
- public void setStartPC(CodeAttr code)
- {
- if (start == null)
- start = new Label();
- boolean reachable = code.reachableHere();
- start.define(code);
- code.setReachable(reachable);
- }
- /** Should be called at the start of a logical function - inlined or not. */
- public void noteStartFunction(CodeAttr code)
- {
- setStartPC(code);
- }
- /**
- * Search by name for a Variable in this Scope (only).
- * @param name name to search for
- * @return the Variable, or null if not found (in this scope).
- */
- public Variable lookup (String name) {
- for (Variable var = vars; var != null; var = var.next) {
- if (name.equals(var.name))
- return var;
- }
- return null;
- }
- /** Make local variable slots of this scope available for re-use.
- * However, if the 'preserved' flag is set, defer doing so until
- * we exit a non-preserved Scope. */
- void freeLocals (CodeAttr code)
- {
- if (preserved)
- return;
- for (Variable var = vars; var != null; var = var.next)
- {
- if (var.isSimple () && ! var.dead ())
- var.freeLocal(code);
- }
- for (Scope child = firstChild; child != null; child = child.nextSibling)
- {
- if (child.preserved)
- {
- child.preserved = false;
- child.freeLocals(code);
- }
- }
- }
- /* DEBUG
- static int counter; int id=++counter;
- public String toString() { return "Scope#"+id; }
- */
- }
|