package factor;
-import factor.compiler.*;
import java.lang.reflect.*;
-import java.io.FileOutputStream;
import java.util.*;
-import org.objectweb.asm.*;
/**
* : name ... ;
*/
public class FactorCompoundDefinition extends FactorWordDefinition
{
- private static int compileCount;
-
public Cons definition;
private Cons endOfDocs;
/**
* A new definition.
*/
- public FactorCompoundDefinition(FactorWord word, Cons definition,
- FactorInterpreter interp)
+ public FactorCompoundDefinition(FactorWord word, Cons definition)
{
super(word);
- fromList(definition,interp);
+ fromList(definition);
} //}}}
//{{{ eval() method
interp.call(endOfDocs);
} //}}}
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- RecursiveForm rec = recursiveCheck.get(word);
- if(rec.active)
- {
- if(rec.baseCase == null)
- throw new FactorCompilerException("Indeterminate recursive call");
-
- compiler.apply(StackEffect.decompose(rec.effect,rec.baseCase));
- }
- else
- {
- compiler.compile(endOfDocs,null,recursiveCheck);
- }
- } //}}}
-
- //{{{ getClassName() method
- private static String getClassName(String name)
- {
- return FactorJava.getSanitizedName(name)
- + "_" + (compileCount++);
- } //}}}
-
- //{{{ compile() method
- /**
- * Compile the given word, returning a new word definition.
- */
- FactorWordDefinition compile(FactorInterpreter interp,
- RecursiveState recursiveCheck) throws Exception
- {
- // Each word has its own class loader
- FactorClassLoader loader = new FactorClassLoader(
- getClass().getClassLoader());
-
- StackEffect effect = getStackEffect(interp);
-
- if(effect.inR != 0 || effect.outR != 0)
- throw new FactorCompilerException("Compiled code cannot manipulate call stack frames");
-
- String className = getClassName(word.name);
-
- ClassWriter cw = new ClassWriter(true);
- cw.visit(ACC_PUBLIC, className,
- "factor/compiler/CompiledDefinition",
- null, null);
-
- compileConstructor(cw,className);
-
- FactorCompiler compiler = compileEval(interp,cw,loader,
- className,effect,recursiveCheck);
-
- // Generate auxiliary methods
- compiler.generateAuxiliary(cw);
-
- // Generate fields for storing literals and
- // word references
- compiler.generateFields(cw);
-
- compileToList(interp,compiler,cw);
-
- compileGetStackEffect(cw,effect);
-
- // gets the bytecode of the class, and loads it
- // dynamically
- byte[] code = cw.toByteArray();
-
- if(interp.dump)
- {
- FileOutputStream fos = new FileOutputStream(
- className + ".class");
- try
- {
- fos.write(code);
- }
- finally
- {
- fos.close();
- }
- }
-
- String javaClassName = className.replace('/','.');
- word.setCompiledInfo(compiler.loader,javaClassName);
-
- Class compiledWordClass = loader.addClass(
- javaClassName,code,0,code.length);
-
- return CompiledDefinition.create(interp,word,compiledWordClass);
- } //}}}
-
- //{{{ compileConstructor() method
- private void compileConstructor(ClassVisitor cw, String className)
- {
- // creates a MethodWriter for the constructor
- CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
- "<init>",
- "(Lfactor/FactorWord;)V",
- null, null);
- // pushes the 'this' variable
- mw.visitVarInsn(ALOAD, 0);
- // pushes the word parameter
- mw.visitVarInsn(ALOAD, 1);
- // invokes the super class constructor
- mw.visitMethodInsn(INVOKESPECIAL,
- "factor/compiler/CompiledDefinition", "<init>",
- "(Lfactor/FactorWord;)V");
- mw.visitInsn(RETURN);
- mw.visitMaxs(0,0);
- } //}}}
-
- //{{{ compileToList() method
- private void compileToList(FactorInterpreter interp,
- FactorCompiler compiler, ClassVisitor cw)
- {
- // creates a MethodWriter for the toList() method
- CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
- "toList",
- "(Lfactor/FactorInterpreter;)Lfactor/Cons;",
- null, null);
- // push unparsed string representation of this word and parse it
- compiler.generateParse(mw,toList(interp),1);
- mw.visitTypeInsn(CHECKCAST,"factor/Cons");
- mw.visitInsn(ARETURN);
- mw.visitMaxs(0,0);
- } //}}}
-
- //{{{ compileGetStackEffect() method
- private void compileGetStackEffect(ClassVisitor cw, StackEffect effect)
- {
- // creates a MethodWriter for the getStackEffect() method
- CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
- "getStackEffect",
- "(Lfactor/compiler/RecursiveState;"
- + "Lfactor/compiler/FactorCompiler;)V",
- null, null);
-
- mw.visitVarInsn(ALOAD,2);
- mw.visitTypeInsn(NEW,"factor/compiler/StackEffect");
- mw.visitInsn(DUP);
- mw.visitLdcInsn(new Integer(effect.inD));
- mw.visitLdcInsn(new Integer(effect.outD));
- mw.visitLdcInsn(new Integer(effect.inR));
- mw.visitLdcInsn(new Integer(effect.outR));
- mw.visitMethodInsn(INVOKESPECIAL,"factor/compiler/StackEffect",
- "<init>","(IIII)V");
- mw.visitMethodInsn(INVOKEVIRTUAL,"factor/compiler/FactorCompiler",
- "apply","(Lfactor/compiler/StackEffect;)V");
- mw.visitInsn(RETURN);
- mw.visitMaxs(0,0);
- } //}}}
-
- //{{{ compileEval() method
- /**
- * Write the definition of the eval() method in the compiled word.
- * Local 0 -- this
- * Local 1 -- interpreter
- */
- protected FactorCompiler compileEval(FactorInterpreter interp,
- ClassWriter cw, FactorClassLoader loader,
- String className, StackEffect effect,
- RecursiveState recursiveCheck)
- throws Exception
- {
- cw.visitField(ACC_PRIVATE | ACC_STATIC, "initialized", "Z",
- null, null);
-
- // creates a MethodWriter for the 'eval' method
- CodeVisitor mw = cw.visitMethod(ACC_PUBLIC,
- "eval", "(Lfactor/FactorInterpreter;)V",
- null, null);
-
- // eval() method calls core
- mw.visitVarInsn(ALOAD,1);
-
- compileDataStackToJVMStack(effect,mw);
-
- mw.visitMethodInsn(INVOKESTATIC,className,"core",
- effect.getCorePrototype());
-
- compileJVMStackToDataStack(effect,mw);
-
- mw.visitInsn(RETURN);
- mw.visitMaxs(0,0);
-
- // generate core
- FactorCompiler compiler = new FactorCompiler(interp,word,
- className,loader);
- compiler.init(1,effect.inD,effect.inR,"core");
- compiler.compileCore(endOfDocs,cw,effect,recursiveCheck);
-
- return compiler;
- } //}}}
-
- //{{{ compileDataStackToJVMStack() method
- private void compileDataStackToJVMStack(StackEffect effect,
- CodeVisitor mw)
- {
- if(effect.inD != 0)
- {
- mw.visitVarInsn(ALOAD,1);
- mw.visitFieldInsn(GETFIELD,
- "factor/FactorInterpreter", "datastack",
- "Lfactor/FactorArray;");
-
- // ensure the stack has enough elements
- mw.visitInsn(DUP);
- mw.visitIntInsn(BIPUSH,effect.inD);
- mw.visitMethodInsn(INVOKEVIRTUAL,
- "factor/FactorArray", "ensurePop",
- "(I)V");
-
- // datastack.stack -> 2
- mw.visitInsn(DUP);
- mw.visitFieldInsn(GETFIELD,
- "factor/FactorArray", "stack",
- "[Ljava/lang/Object;");
- mw.visitVarInsn(ASTORE,2);
- // datastack.top-args.length -> 3
- mw.visitInsn(DUP);
- mw.visitFieldInsn(GETFIELD,
- "factor/FactorArray", "top",
- "I");
- mw.visitIntInsn(BIPUSH,effect.inD);
- mw.visitInsn(ISUB);
-
- // datastack.top -= args.length
- mw.visitInsn(DUP_X1);
- mw.visitFieldInsn(PUTFIELD,
- "factor/FactorArray", "top",
- "I");
-
- mw.visitVarInsn(ISTORE,3);
-
- for(int i = 0; i < effect.inD; i++)
- {
- mw.visitVarInsn(ALOAD,2);
- mw.visitVarInsn(ILOAD,3);
- mw.visitInsn(AALOAD);
- if(i != effect.inD - 1)
- mw.visitIincInsn(3,1);
- }
- }
- } //}}}
-
- //{{{ compileJVMStackToDataStack() method
- private void compileJVMStackToDataStack(StackEffect effect,
- CodeVisitor mw)
- {
- if(effect.outD == 1)
- {
- // ( datastack )
- mw.visitVarInsn(ALOAD,1);
- mw.visitFieldInsn(GETFIELD,
- "factor/FactorInterpreter", "datastack",
- "Lfactor/FactorArray;");
-
- mw.visitInsn(SWAP);
- mw.visitMethodInsn(INVOKEVIRTUAL,
- "factor/FactorArray", "push",
- "(Ljava/lang/Object;)V");
- }
- } //}}}
-
//{{{ fromList() method
- public void fromList(Cons definition, FactorInterpreter interp)
+ public void fromList(Cons definition)
{
this.definition = definition;
if(definition == null)
} //}}}
//{{{ toList() method
- public Cons toList(FactorInterpreter interp)
+ public Cons toList()
{
return definition;
} //}}}
package factor;
-import factor.compiler.FactorCompiler;
import factor.math.*;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.*;
package factor;
-import factor.compiler.*;
import java.util.Set;
/**
} //}}}
//{{{ fromList() method
- public void fromList(Cons cons, FactorInterpreter interp)
+ public void fromList(Cons cons)
{
} //}}}
}
package factor;
-import factor.compiler.*;
import java.util.*;
-import org.objectweb.asm.*;
/**
* ~<< name ... -- >>~
private int shuffleRlength;
//{{{ FactorShuffleDefinition constructor
- public FactorShuffleDefinition(FactorWord word, Cons definition,
- FactorInterpreter interp) throws FactorException
+ public FactorShuffleDefinition(FactorWord word, Cons definition)
+ throws FactorException
{
super(word);
- fromList(definition,interp);
+ fromList(definition);
} //}}}
//{{{ FactorShuffleDefinition constructor
}
} //}}}
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws FactorStackException
- {
- compileCallTo(null,compiler,recursiveCheck);
- } //}}}
-
- //{{{ compile() method
- /**
- * Compile the given word, returning a new word definition.
- */
- FactorWordDefinition compile(FactorInterpreter interp,
- RecursiveState recursiveCheck) throws Exception
- {
- return this;
- } //}}}
-
- //{{{ compileCallTo() method
- public void compileCallTo(CodeVisitor mw, FactorCompiler compiler,
- RecursiveState recursiveCheck) throws FactorStackException
- {
- compiler.ensure(compiler.datastack,consumeD);
- compiler.ensure(compiler.callstack,consumeR);
- eval(compiler.interp,compiler.datastack,compiler.callstack);
- } //}}}
-
//{{{ eval() method
public void eval(FactorInterpreter interp)
throws FactorStackException
} //}}}
//{{{ fromList() method
- public void fromList(Cons definition, FactorInterpreter interp)
+ public void fromList(Cons definition)
throws FactorRuntimeException
{
String f = "--";
} //}}}
//{{{ toList() method
- public Cons toList(FactorInterpreter interp)
+ public Cons toList()
{
Cons list = null;
package factor;
-import factor.compiler.*;
-import org.objectweb.asm.*;
-
/**
* SYMBOL: name
*
interp.datastack.push(symbol);
} //}}}
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- compiler.pushLiteral(symbol,recursiveCheck);
- } //}}}
-
- //{{{ compile() method
- /**
- * Compile the given word, returning a new word definition.
- */
- FactorWordDefinition compile(FactorInterpreter interp,
- RecursiveState recursiveCheck) throws Exception
- {
- return this;
- } //}}}
-
- //{{{ compileCallTo() method
- public void compileCallTo(CodeVisitor mw, FactorCompiler compiler,
- RecursiveState recursiveCheck) throws FactorStackException
- {
- compiler.pushLiteral(symbol,recursiveCheck);
- } //}}}
-
//{{{ fromList() method
- public void fromList(Cons definition, FactorInterpreter interp)
+ public void fromList(Cons definition)
{
this.symbol = definition.car;
} //}}}
//{{{ toList() method
- public Cons toList(FactorInterpreter interp)
+ public Cons toList()
{
return new Cons(symbol,null);
} //}}}
package factor;
-import factor.compiler.*;
import java.util.*;
/**
*/
public FactorParsingDefinition parsing;
- /**
- * Is this word referenced from a compiled word?
- */
- public boolean compileRef;
-
/**
* Should this word be inlined when compiling?
*/
*/
public boolean interpretOnly;
- /**
- * Only compiled words have this.
- */
- public FactorClassLoader loader;
- public String className;
-
/**
* For text editor integration.
*/
} //}}}
//{{{ define() method
- public synchronized void define(FactorWordDefinition def)
+ public void define(FactorWordDefinition def)
{
- if(compileRef)
- {
- System.err.println("WARNING: " + this
- + " is used in one or more compiled words; old definition will remain until full recompile");
- }
- else if(this.def != null)
- System.err.println("WARNING: redefining " + this);
-
this.def = def;
-
- loader = null;
- className = null;
- } //}}}
-
- //{{{ setCompiledInfo() method
- synchronized void setCompiledInfo(FactorClassLoader loader,
- String className)
- {
- this.loader = loader;
- this.className = className;
- } //}}}
-
- //{{{ compile() method
- public synchronized void compile(FactorInterpreter interp)
- {
- RecursiveState recursiveCheck = new RecursiveState();
- recursiveCheck.add(this,new StackEffect(),null,null,null);
- compile(interp,recursiveCheck);
- recursiveCheck.remove(this);
- } //}}}
-
- //{{{ compile() method
- public synchronized void compile(FactorInterpreter interp,
- RecursiveState recursiveCheck)
- {
- if(def == null)
- return;
-
- if(interpretOnly)
- {
- if(interp.verboseCompile)
- System.err.println(this + " is interpret-only");
- return;
- }
-
- //if(def.compileFailed)
- // return;
-
- if(interp.verboseCompile)
- System.err.println("Compiling " + this);
-
- try
- {
- def = def.compile(interp,recursiveCheck);
- }
- catch(Throwable t)
- {
- def.compileFailed = true;
- if(interp.verboseCompile)
- {
- System.err.println("WARNING: cannot compile " + this);
- t.printStackTrace();
- }
- }
} //}}}
//{{{ toString() method
package factor;
-import factor.compiler.*;
import java.io.*;
import java.util.*;
-import org.objectweb.asm.*;
/**
* A word definition.
*/
-public abstract class FactorWordDefinition implements Constants
+public abstract class FactorWordDefinition
{
public FactorWord word;
- public boolean compileFailed;
//{{{ FactorWordDefinition constructor
/**
throws Exception;
//{{{ fromList() method
- public void fromList(Cons cons, FactorInterpreter interp)
+ public void fromList(Cons cons)
throws FactorRuntimeException
{
throw new FactorRuntimeException("Cannot unpickle " + this);
} //}}}
//{{{ toList() method
- public Cons toList(FactorInterpreter interp)
+ public Cons toList()
{
return new Cons(new FactorWord(null,getClass().getName()),null);
} //}}}
- //{{{ getStackEffect() method
- public final StackEffect getStackEffect(FactorInterpreter interp)
- throws Exception
- {
- return getStackEffect(new RecursiveState(),interp);
- } //}}}
-
- //{{{ getStackEffect() method
- public final StackEffect getStackEffect(RecursiveState recursiveCheck,
- FactorInterpreter interp) throws Exception
- {
- FactorCompiler compiler = new FactorCompiler(interp);
- recursiveCheck.add(word,new StackEffect(),null,null,null);
- getStackEffect(recursiveCheck,compiler);
- recursiveCheck.remove(word);
- return compiler.getStackEffect();
- } //}}}
-
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- throw new FactorCompilerException("Cannot deduce stack effect of " + word);
- } //}}}
-
- //{{{ compile() method
- FactorWordDefinition compile(FactorInterpreter interp,
- RecursiveState recursiveCheck) throws Exception
- {
- return this;
- } //}}}
-
- //{{{ compileCallTo() method
- /**
- * Compile a call to this word. Returns maximum JVM stack use.
- */
- public void compileCallTo(CodeVisitor mw, FactorCompiler compiler,
- RecursiveState recursiveCheck) throws Exception
- {
- // normal word
- String defclass;
- String defmethod;
- StackEffect effect;
-
- FactorClassLoader loader;
-
- RecursiveForm rec = recursiveCheck.get(word);
- if(rec != null && rec.active)
- {
- if(compiler.interp.verboseCompile)
- System.err.println("Recursive call to " + rec);
- effect = StackEffect.decompose(rec.effect,rec.baseCase);
-
- // are we recursing back on a form inside the current
- // method?
- RecursiveForm last = recursiveCheck.last();
- if(recursiveCheck.allTails(rec)
- && last.className.equals(rec.className)
- && last.method.equals(rec.method))
- {
- if(compiler.interp.verboseCompile)
- System.err.println(word + " is tail recursive");
- // GOTO instad of INVOKEVIRTUAL; ie a loop!
- compiler.normalizeStacks(mw);
- mw.visitJumpInsn(GOTO,rec.label);
- compiler.apply(effect);
- return;
- }
-
- /* recursive method call! */
- defclass = rec.className;
- defmethod = rec.method;
- loader = rec.loader;
-
- if(!defclass.equals(compiler.className))
- compiler.loader.addDependency(defclass,loader);
- }
- // not a recursive call but we're still not compiled
- // its a bug in the compiler.
- else if(this instanceof FactorCompoundDefinition)
- {
- throw new FactorCompilerException("You are an idiot!");
- }
- // inlining?
- else if(word.inline)
- {
- compileImmediate(mw,compiler,recursiveCheck);
- return;
- }
- /* ordinary method call! */
- else
- {
- defclass = getClass().getName().replace('.','/');
- defmethod = "core";
- effect = getStackEffect(compiler.interp);
- ClassLoader l = getClass().getClassLoader();
- if(l instanceof FactorClassLoader)
- {
- loader = (FactorClassLoader)l;
- compiler.loader.addDependency(getClass().getName(),loader);
- }
- else
- loader = null;
- }
-
- mw.visitVarInsn(ALOAD,0);
-
- compiler.generateArgs(mw,effect.inD,effect.inR,null);
-
- String signature = effect.getCorePrototype();
-
- mw.visitMethodInsn(INVOKESTATIC,defclass,defmethod,signature);
-
- compiler.generateReturn(mw,effect.outD,effect.outR);
- } //}}}
-
- //{{{ compileNonRecursiveImmediate() method
- /**
- * Non-recursive immediate words are inlined.
- */
- protected void compileNonRecursiveImmediate(CodeVisitor mw,
- FactorCompiler compiler,
- RecursiveState recursiveCheck,
- StackEffect immediateEffect) throws Exception
- {
- Cons definition = toList(compiler.getInterpreter());
-
- Cons endOfDocs = definition;
- while(endOfDocs != null
- && endOfDocs.car instanceof FactorDocComment)
- endOfDocs = endOfDocs.next();
-
- compiler.compile(endOfDocs,mw,recursiveCheck);
- } //}}}
-
- //{{{ compileRecursiveImmediate() method
- /**
- * Recursive immediate words are compiled to an auxiliary method
- * inside the compiled class definition.
- *
- * This must be done so that recursion has something to jump to.
- */
- protected void compileRecursiveImmediate(CodeVisitor mw,
- FactorCompiler compiler,
- RecursiveState recursiveCheck,
- StackEffect immediateEffect) throws Exception
- {
- Cons definition = toList(compiler.getInterpreter());
-
- Cons endOfDocs = definition;
- while(endOfDocs != null
- && endOfDocs.car instanceof FactorDocComment)
- endOfDocs = endOfDocs.next();
-
- String method = compiler.auxiliary(word,
- endOfDocs,immediateEffect,recursiveCheck);
-
- mw.visitVarInsn(ALOAD,0);
-
- compiler.generateArgs(mw,immediateEffect.inD,
- immediateEffect.inR,null);
-
- String signature = immediateEffect.getCorePrototype();
-
- mw.visitMethodInsn(INVOKESTATIC,compiler.className,
- method,signature);
-
- compiler.generateReturn(mw,
- immediateEffect.outD,
- immediateEffect.outR);
- } //}}}
-
- //{{{ compileImmediate() method
- /**
- * Compile a call to this word. Returns maximum JVM stack use.
- */
- public void compileImmediate(CodeVisitor mw, FactorCompiler compiler,
- RecursiveState recursiveCheck) throws Exception
- {
- Cons definition = toList(compiler.getInterpreter());
-
- if(definition == null)
- return;
-
- Cons endOfDocs = definition;
- while(endOfDocs != null
- && endOfDocs.car instanceof FactorDocComment)
- endOfDocs = endOfDocs.next();
-
- // determine stack effect of this instantiation, and if its
- // recursive.
-
- FactorArray savedDatastack = (FactorArray)
- compiler.datastack.clone();
- FactorArray savedCallstack = (FactorArray)
- compiler.callstack.clone();
- StackEffect savedEffect = compiler.getStackEffect();
-
- RecursiveState _recursiveCheck = (RecursiveState)
- recursiveCheck.clone();
- _recursiveCheck.last().effect = compiler.getStackEffect();
- getStackEffect(_recursiveCheck,compiler);
-
- boolean recursive = (_recursiveCheck.last().baseCase != null);
-
- StackEffect effect = compiler.getStackEffect();
-
- StackEffect immediateEffect = StackEffect.decompose(
- savedEffect,compiler.getStackEffect());
-
- // restore previous state.
-
- FactorArray afterDatastack = (FactorArray)
- compiler.datastack.clone();
- FactorArray afterCallstack = (FactorArray)
- compiler.callstack.clone();
-
- compiler.datastack = (FactorArray)savedDatastack.clone();
- compiler.callstack = (FactorArray)savedCallstack.clone();
- compiler.effect = savedEffect;
-
- if(!recursive)
- {
- // not recursive; inline.
- compileNonRecursiveImmediate(mw,compiler,recursiveCheck,
- immediateEffect);
- }
- else
- {
- // recursive; must generate auxiliary method.
- compileRecursiveImmediate(mw,compiler,recursiveCheck,
- immediateEffect);
-
- mergeStacks(savedDatastack,afterDatastack,compiler.datastack);
- mergeStacks(savedCallstack,afterCallstack,compiler.callstack);
- }
- } //}}}
-
- //{{{ mergeStacks() method
- private void mergeStacks(FactorArray s1, FactorArray s2,
- FactorArray into)
- {
- for(int i = 0; i < s2.top; i++)
- {
- if(s1.top <= i)
- break;
-
- if(FactorLib.objectsEqual(s1.stack[i],
- s2.stack[i]))
- {
- into.stack[i] = s1.stack[i];
- }
- }
- } //}}}
-
//{{{ toString() method
public String toString()
{
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-import org.objectweb.asm.*;
-
-class AuxiliaryQuotation
-{
- private String method;
- private FactorArray datastack;
- private FactorArray callstack;
- private Cons code;
- private StackEffect effect;
- private FactorWord word;
- private RecursiveState recursiveCheck;
-
- //{{{ AuxiliaryQuotation constructor
- AuxiliaryQuotation(String method,
- FactorArray datastack,
- FactorArray callstack,
- Cons code,
- StackEffect effect,
- FactorWord word,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- throws Exception
- {
- this.method = method;
- this.datastack = datastack;
- this.callstack = callstack;
- this.code = code;
- this.effect = effect;
- this.word = word;
- this.recursiveCheck = new RecursiveState(recursiveCheck);
-
- System.arraycopy(datastack.stack,datastack.top - effect.inD,
- datastack.stack,0,effect.inD);
- for(int i = 0; i < effect.inD; i++)
- {
- int index = datastack.top - effect.inD + i;
- FlowObject flow = (FlowObject)datastack.stack[index];
- datastack.stack[index] = flow.munge(
- 1,index,compiler,recursiveCheck);
- }
-
- System.arraycopy(callstack.stack,callstack.top - effect.inR,
- callstack.stack,0,effect.inD);
- for(int i = 0; i < effect.inR; i++)
- {
- int index = callstack.top - effect.inR + i;
- FlowObject flow = (FlowObject)callstack.stack[index];
- callstack.stack[index] = flow.munge(
- 1 + effect.inD,index,compiler,recursiveCheck);
- }
- } //}}}
-
- //{{{ compile() method
- void compile(FactorCompiler compiler, ClassWriter cw)
- throws Exception
- {
- // generate core
- compiler.init(1,effect.inD,effect.inR,method);
- compiler.datastack = datastack;
- compiler.callstack = callstack;
- //compiler.produce(compiler.datastack,effect.inD);
- // important: this.recursiveCheck due to
- // lexically-scoped recursion issues
- compiler.compileMethod(code,cw,method,effect,word,
- new RecursiveState(this.recursiveCheck),false);
- } //}}}
-
- //{{{ toString() method
- public String toString()
- {
- return method + effect;
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
-* $Id$
-*
-* Copyright (C) 2003, 2004 Slava Pestov.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are met:
-*
-* 1. Redistributions of source code must retain the above copyright notice,
-* this list of conditions and the following disclaimer.
-*
-* 2. Redistributions in binary form must reproduce the above copyright notice,
-* this list of conditions and the following disclaimer in the documentation
-* and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-package factor.compiler;
-
-import factor.*;
-import java.lang.reflect.*;
-import java.util.Map;
-import org.objectweb.asm.*;
-
-/**
- * Compiled colon definition.
- */
-public abstract class CompiledDefinition
- extends FactorWordDefinition
-{
- //{{{ CompiledDefinition constructor
- public CompiledDefinition(FactorWord word)
- {
- super(word);
- } //}}}
-
- //{{{ create() method
- public static CompiledDefinition create(FactorInterpreter interp,
- FactorWord word, Class compiledWordClass)
- throws Exception
- {
- Constructor constructor = compiledWordClass
- .getConstructor(
- new Class[] {
- FactorWord.class
- });
-
- return (CompiledDefinition)constructor.newInstance(
- new Object[] { word });
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-import java.lang.reflect.*;
-import java.util.*;
-import org.objectweb.asm.*;
-
-public class CompiledList extends FlowObject
-{
- protected Cons quotation;
- protected RecursiveState recursiveCheck;
-
- //{{{ CompiledList constructor
- CompiledList(Cons quotation, FactorCompiler compiler,
- RecursiveState recursiveCheck)
- {
- super(compiler,recursiveCheck.lastCallable());
- this.quotation = quotation;
- // clone it
- this.recursiveCheck = new RecursiveState(
- recursiveCheck);
- expectedType = Cons.class;
- } //}}}
-
- //{{{ pop() method
- public void pop(CodeVisitor mw)
- {
- mw.visitFieldInsn(GETSTATIC,compiler.className,
- compiler.literal(quotation),
- "Ljava/lang/Object;");
- } //}}}
-
- //{{{ munge() method
- /**
- * Munging transforms the flow object such that it is now stored in
- * a local variable and hence can be mutated by compiled code, however
- * its original compileCallTo() semantics remain (for example, if it is
- * a quotation).
- */
- FlowObject munge(int base, int index,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- throws Exception
- {
- return new CompiledListResult(index + base,
- quotation,compiler,
- this.recursiveCheck);
- } //}}}
-
- //{{{ getLiteral() method
- Object getLiteral()
- {
- return quotation;
- } //}}}
-
- //{{{ compileCallTo()
- /**
- * Write code for evaluating this. Returns maximum JVM stack
- * usage.
- */
- public void compileCallTo(CodeVisitor mw,
- RecursiveState recursiveCheck)
- throws Exception
- {
- RecursiveForm last = this.recursiveCheck.last();
- FactorWord word = FactorWord.gensym();
- try
- {
- recursiveCheck.add(word,new StackEffect(),
- last.className,last.loader,last.method,last);
- recursiveCheck.last().callable = false;
- compiler.compile(quotation,mw,recursiveCheck);
- }
- finally
- {
- recursiveCheck.remove(word);
- }
- } //}}}
-
- //{{{ equals() method
- public boolean equals(Object o)
- {
- if(o instanceof CompiledList)
- {
- CompiledList c = (CompiledList)o;
- return FactorLib.objectsEqual(c.quotation,quotation);
- }
- else if(o instanceof Null)
- return quotation == null;
- else
- return false;
- } //}}}
-
- //{{{ clone() method
- public Object clone()
- {
- return new CompiledList(quotation,compiler,recursiveCheck);
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-import java.lang.reflect.*;
-import java.util.*;
-import org.objectweb.asm.*;
-
-public class CompiledListResult extends CompiledList implements Constants
-{
- private int local;
-
- //{{{ CompiledListResult constructor
- CompiledListResult(int local, Cons quotation,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- {
- super(quotation,compiler,recursiveCheck);
- this.local = local;
- } //}}}
-
- //{{{ push() method
- public void push(CodeVisitor mw)
- throws Exception
- {
- mw.visitVarInsn(ASTORE,local);
- } //}}}
-
- //{{{ pop() method
- public void pop(CodeVisitor mw)
- {
- mw.visitVarInsn(ALOAD,local);
- } //}}}
-
- //{{{ getLocal() method
- public int getLocal()
- {
- return local;
- } //}}}
-
- //{{{ usingLocal() method
- boolean usingLocal(int local)
- {
- return (this.local == local);
- } //}}}
-
- //{{{ clone() method
- public Object clone()
- {
- return new CompiledListResult(local,quotation,compiler,
- recursiveCheck);
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-
-public class CompilerState
-{
- public FactorArray datastack;
- public FactorArray callstack;
- public StackEffect effect;
- public Cons inDtypes;
- public Cons inRtypes;
-
- //{{{ CompilerState constructor
- public CompilerState(FactorCompiler compiler)
- {
- datastack = (FactorArray)compiler.datastack.clone();
- callstack = (FactorArray)compiler.callstack.clone();
- effect = (StackEffect)compiler.getStackEffect();
- inDtypes = cloneTypespec(compiler,compiler.inDtypes);
- inRtypes = cloneTypespec(compiler,compiler.inRtypes);
- } //}}}
-
- //{{{ restore() method
- public void restore(FactorCompiler compiler)
- {
- compiler.datastack = (FactorArray)datastack.clone();
- compiler.callstack = (FactorArray)callstack.clone();
- compiler.effect = (StackEffect)effect.clone();
- compiler.inDtypes = cloneTypespec(compiler,inDtypes);
- compiler.inRtypes = cloneTypespec(compiler,inRtypes);
- } //}}}
-
- //{{{ findResult() method
- private static Result findResult(Result result,
- FactorArray stack)
- {
- for(int i = 0; i < stack.top; i++)
- {
- if(stack.stack[i] instanceof Result)
- {
- Result r = (Result)stack.stack[i];
- if(r.getLocal() == result.getLocal())
- return r;
- }
- }
-
- return null;
- } //}}}
-
- //{{{ cloneResult() method
- private static Result cloneResult(Result result,
- FactorArray datastack,
- FactorArray callstack)
- {
- Result r = findResult(result,datastack);
- if(r != null)
- return r;
- r = findResult(result,callstack);
- if(r != null)
- return r;
- return (Result)result.clone();
- } //}}}
-
- //{{{ cloneTypespec() method
- private static Cons cloneTypespec(FactorCompiler compiler, Cons spec)
- {
- Cons newSpec = null;
- while(spec != null)
- {
- newSpec = new Cons(cloneResult((Result)spec.car,
- compiler.datastack,compiler.callstack),
- newSpec);
- spec = spec.next();
- }
- return Cons.reverse(newSpec);
- } //}}}
-
- //{{{ commonAncestor() method
- private static Class commonAncestor(Class ca, Class cb)
- {
- if(ca.isAssignableFrom(cb))
- return ca;
- else if(cb.isAssignableFrom(ca))
- return cb;
- else if(ca.isInterface() || cb.isInterface())
- return Object.class;
- else
- return commonAncestor(ca.getSuperclass(),cb);
- } //}}}
-
- //{{{ unifyTypes() method
- private static Cons unifyTypes(FactorCompiler compiler,
- RecursiveState recursiveCheck,
- Cons a, Cons b)
- {
- Cons cons = null;
-
- for(;;)
- {
- if(a == null && b == null)
- return Cons.reverse(cons);
-
- int la, lb;
- Class ca, cb;
-
- if(a == null)
- {
- la = -1;
- ca = Object.class;
- }
- else
- {
- FlowObject fa = (FlowObject)a.car;
- la = fa.getLocal();
- ca = fa.getType();
-
- a = a.next();
- }
-
- if(b == null)
- {
- lb = -1;
- cb = Object.class;
- }
- else
- {
- FlowObject fb = (FlowObject)b.car;
- lb = fb.getLocal();
- //if(la != -1 && la != lb)
- // System.err.println("? " + a + "," + b);
- cb = fb.getType();
-
- b = b.next();
- }
-
- //System.err.println("Common ancestor of " + ca + " and " + cb + " is " + commonAncestor(ca,cb));
- cons = new Cons(
- new Result(la,compiler,recursiveCheck.last(),
- commonAncestor(ca,cb)),cons);
- }
- } //}}}
-
- //{{{ mergeStacks() method
- private static void mergeStacks(FactorCompiler compiler,
- RecursiveState recursiveCheck,
- FactorArray s1, FactorArray s2,
- FactorArray into)
- {
- for(int i = Math.min(s1.top,s2.top) - 1; i >= 0; i--)
- {
- FlowObject fa = (FlowObject)s1.stack[s1.top - i - 1];
- FlowObject fb = (FlowObject)s2.stack[s2.top - i - 1];
- into.stack[into.top - i - 1]
- = new Result(i,compiler,recursiveCheck.last(),
- commonAncestor(fa.getType(),fb.getType()));
- }
- } //}}}
-
- //{{{ unifyStates() method
- public static void unifyStates(
- FactorCompiler compiler,
- RecursiveState recursiveCheck,
- FlowObject t, FlowObject f,
- CompilerState a, CompilerState b)
- throws Exception
- {
- StackEffect te = a.effect;
- StackEffect fe = b.effect;
-
- // we can only balance out a conditional if
- // both sides leave the same amount of elements
- // on the stack.
- // eg, 1/1 -vs- 2/2 is ok, 3/1 -vs- 4/2 is ok,
- // but 1/2 -vs- 2/1 is not.
- if(te.outD - te.inD != fe.outD - fe.inD
- || te.outR - te.inR != fe.outR - fe.inR)
- {
- throw new FactorCompilerException(
- "Stack effect of " + t + " " + a.effect + " is inconsistent with " + f + " " + b.effect
- + "\nRecursive state:\n"
- + recursiveCheck);
- }
-
- compiler.ensure(compiler.datastack,Math.max(te.outD,fe.outD));
- compiler.ensure(compiler.callstack,Math.max(te.outR,fe.outR));
-
- // replace results from the f branch with
- // dummy values so that subsequent code
- // doesn't assume these values always
- // result from this
-
- mergeStacks(compiler,recursiveCheck,a.datastack,
- b.datastack,compiler.datastack);
- mergeStacks(compiler,recursiveCheck,a.callstack,
- b.callstack,compiler.callstack);
-
- compiler.inDtypes = unifyTypes(compiler,recursiveCheck,
- a.inDtypes,b.inDtypes);
- compiler.inRtypes = unifyTypes(compiler,recursiveCheck,
- a.inRtypes,b.inRtypes);
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-import java.lang.reflect.*;
-import java.util.*;
-import org.objectweb.asm.*;
-
-public class ConstantPoolString extends FlowObject
-{
- private String str;
-
- //{{{ ConstantPoolString constructor
- ConstantPoolString(String str, FactorCompiler compiler,
- RecursiveForm word)
- {
- super(compiler,word);
- this.str = str;
- expectedType = String.class;
- } //}}}
-
- //{{{ pop() method
- public void pop(CodeVisitor mw)
- {
- mw.visitLdcInsn(str);
- } //}}}
-
- //{{{ getLiteral() method
- Object getLiteral()
- {
- return str;
- } //}}}
-
- //{{{ clone() method
- public Object clone()
- {
- return new Null(compiler,word);
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
-* $Id$
-*
-* Copyright (C) 2003, 2004 Slava Pestov.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are met:
-*
-* 1. Redistributions of source code must retain the above copyright notice,
-* this list of conditions and the following disclaimer.
-*
-* 2. Redistributions in binary form must reproduce the above copyright notice,
-* this list of conditions and the following disclaimer in the documentation
-* and/or other materials provided with the distribution.
-*
-* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-* DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-package factor.compiler;
-
-import factor.*;
-import java.util.*;
-
-/**
- * Each word class has a class loader.
- *
- * When compiling a word; add each dependent word to new class loader's
- * delegates map.
- */
-public class FactorClassLoader extends ClassLoader
-{
- private long id;
- private FactorNamespace table = new FactorNamespace();
- private ClassLoader delegate;
-
- //{{{ FactorClassLoader constructor
- public FactorClassLoader(ClassLoader delegate)
- {
- this.delegate = delegate;
- } //}}}
-
- //{{{ addDependency() method
- public void addDependency(String name, FactorClassLoader loader)
- {
- try
- {
- table.setVariable(name,loader);
- }
- catch(Exception e)
- {
- throw new RuntimeException(e);
- }
- } //}}}
-
- //{{{ addClass() method
- public Class addClass(String name, byte[] code, int off, int len)
- {
- return defineClass(name,code,off,len);
- } //}}}
-
- //{{{ loadClass() method
- public synchronized Class loadClass(String name, boolean resolve)
- throws ClassNotFoundException
- {
- Class c = findLoadedClass(name);
- if(c != null)
- {
- if(resolve)
- resolveClass(c);
- return c;
- }
-
- // See if another known class loader has this
- try
- {
- Object obj = table.getVariable(name);
- if(obj instanceof FactorClassLoader)
- {
- return ((FactorClassLoader)obj)
- .loadClass(name,resolve);
- }
- else if(obj != null)
- {
- System.err.println("WARNING: unknown object in class loader table for " + this + ": " + obj);
- }
-
- if(delegate == null)
- return super.loadClass(name,resolve);
- else
- {
- c = delegate.loadClass(name);
- if(resolve)
- resolveClass(c);
- return c;
- }
- }
- catch(ClassNotFoundException e)
- {
- throw e;
- }
- catch(Exception e)
- {
- throw new RuntimeException(e);
- }
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-import java.lang.reflect.*;
-import java.util.*;
-import org.objectweb.asm.*;
-
-public class FactorCompiler implements Constants
-{
- public final FactorInterpreter interp;
-
- public final FactorWord word;
- public final String className;
- public final FactorClassLoader loader;
- public String method;
-
- private int base;
- private int allotD;
- private int allotR;
-
- public FactorArray datastack;
- public FactorArray callstack;
-
- private int literalCount;
-
- private Map literals;
-
- public StackEffect effect;
-
- /**
- * getStackEffect() turns these into arrays and places them in the
- * returned object.
- */
- public Cons inDtypes, inRtypes;
-
- private Cons aux;
- private int auxCount;
-
- //{{{ FactorCompiler constructor
- /**
- * For balancing.
- */
- public FactorCompiler(FactorInterpreter interp)
- {
- this(interp,null,null,null);
- init(0,0,0,null);
- } //}}}
-
- //{{{ FactorCompiler constructor
- /**
- * For compiling.
- */
- public FactorCompiler(FactorInterpreter interp,
- FactorWord word, String className,
- FactorClassLoader loader)
- {
- this.interp = interp;
- this.word = word;
- this.className = className;
- this.loader = loader;
-
- literals = new HashMap();
-
- datastack = new FactorArray();
- callstack = new FactorArray();
- } //}}}
-
- //{{{ getInterpreter() method
- public FactorInterpreter getInterpreter()
- {
- return interp;
- } //}}}
-
- //{{{ init() method
- public void init(int base, int allotD, int allotR, String method)
- {
- effect = new StackEffect();
-
- this.base = base;
-
- datastack.top = 0;
- callstack.top = 0;
-
- for(int i = 0; i < allotD; i++)
- {
- Result r = new Result(base + i,this,null,
- Object.class,true);
- datastack.push(r);
- inDtypes = new Cons(r,inDtypes);
- }
-
- for(int i = 0; i < allotR; i++)
- {
- Result r = new Result(base + allotD + i,this,null,
- Object.class,true);
- callstack.push(r);
- inRtypes = new Cons(r,inRtypes);
- }
-
- this.allotD = allotD;
- this.allotR = allotR;
- effect.inD = allotD;
- effect.inR = allotR;
-
- this.method = method;
- } //}}}
-
- //{{{ getAllotedEffect() method
- public StackEffect getAllotedEffect()
- {
- return new StackEffect(allotD,allotR,0,0);
- } //}}}
-
- //{{{ ensure() method
- public void ensure(FactorArray stack, Class type)
- {
- if(stack.top == 0)
- {
- Result r = new Result(allocate(),this,null,type);
- if(stack == datastack)
- {
- inDtypes = new Cons(r,inDtypes);
- effect.inD++;
- }
- else if(stack == callstack)
- {
- inRtypes = new Cons(r,inRtypes);
- effect.inR++;
- }
- stack.push(r);
- }
- } //}}}
-
- //{{{ ensure() method
- /**
- * Ensure stack has at least 'count' elements.
- * Eg, if count is 4 and stack is A B,
- * stack will become RESULT RESULT A B.
- * Used when deducing stack effects.
- */
- public void ensure(FactorArray stack, Class[] types)
- {
- int top = stack.top;
- if(top < types.length)
- {
- Cons typespec = null;
-
- if(stack == datastack)
- effect.inD += (types.length - top);
- else if(stack == callstack)
- effect.inR += (types.length - top);
-
- stack.ensurePush(types.length - top);
- System.arraycopy(stack.stack,0,stack.stack,
- types.length - top,top);
- for(int i = 0; i < types.length - top; i++)
- {
- int local = allocate();
- Result r = new Result(
- local,this,null,types[i]);
- stack.stack[i] = r;
- typespec = new Cons(r,typespec);
- }
- stack.top = types.length;
-
- if(stack == datastack)
- inDtypes = Cons.nappend(inDtypes,typespec);
- else if(stack == callstack)
- inRtypes = Cons.nappend(inRtypes,typespec);
- }
- } //}}}
-
- //{{{ ensure() method
- /**
- * Ensure stack has at least 'count' elements.
- * Eg, if count is 4 and stack is A B,
- * stack will become RESULT RESULT A B.
- * Used when deducing stack effects.
- */
- public void ensure(FactorArray stack, int count)
- {
- Class[] types = new Class[count];
- for(int i = 0; i < types.length; i++)
- types[i] = Object.class;
- ensure(stack,types);
- } //}}}
-
- //{{{ consume() method
- public void consume(FactorArray stack, int count)
- {
- ensure(stack,count);
- stack.top -= count;
- } //}}}
-
- //{{{ produce() method
- public void produce(FactorArray stack, int count)
- {
- for(int i = 0; i < count; i++)
- {
- int local = allocate();
- stack.push(new Result(local,this,null,Object.class));
- }
- } //}}}
-
- //{{{ apply() method
- public void apply(StackEffect se)
- {
- consume(datastack,se.inD);
- produce(datastack,se.outD);
- consume(callstack,se.inR);
- produce(callstack,se.outR);
- } //}}}
-
- //{{{ getTypeSpec() method
- private Class[] getTypeSpec(Cons list)
- {
- if(list == null)
- return new Class[0];
-
- int length = list.length();
- Class[] typespec = new Class[length];
- int i = 0;
- while(list != null)
- {
- typespec[length - i - 1]
- = ((FlowObject)list.car).getType();
- i++;
- list = list.next();
- }
-
- return typespec;
- } //}}}
-
- //{{{ getStackEffect() method
- public StackEffect getStackEffect()
- {
- effect.inDtypes = getTypeSpec(inDtypes);
-
- effect.outD = datastack.top;
-
- effect.outDtypes = new Class[datastack.top];
- for(int i = 0; i < datastack.top; i++)
- {
- effect.outDtypes[i] = ((FlowObject)datastack.stack[i])
- .getType();
- }
-
- effect.inRtypes = getTypeSpec(inRtypes);
-
- effect.outR = callstack.top;
-
- effect.outRtypes = new Class[callstack.top];
- for(int i = 0; i < callstack.top; i++)
- {
- effect.outRtypes[i] = ((FlowObject)callstack.stack[i])
- .getType();
- }
-
- return (StackEffect)effect.clone();
- } //}}}
-
- //{{{ compileCore() method
- public void compileCore(Cons definition, ClassWriter cw,
- StackEffect effect, RecursiveState recursiveCheck)
- throws Exception
- {
- RecursiveForm last = recursiveCheck.last();
- last.method = "core";
- last.className = className;
- last.loader = loader;
-
- compileMethod(definition,cw,"core",effect,word,recursiveCheck,true);
- } //}}}
-
- //{{{ compileFieldInit() method
- private void compileFieldInit(CodeVisitor mw, Label start)
- {
- mw.visitFieldInsn(GETSTATIC,className,"initialized","Z");
- mw.visitJumpInsn(IFNE,start);
- mw.visitInsn(ICONST_1);
- mw.visitFieldInsn(PUTSTATIC,className,"initialized","Z");
- mw.visitVarInsn(ALOAD,0);
- mw.visitMethodInsn(INVOKESTATIC,className,"setFields",
- "(Lfactor/FactorInterpreter;)V");
- } //}}}
-
- //{{{ compileReturn() method
- /**
- * Once the word finishes executing, any return values need to be
- * passed up.
- */
- private void compileReturn(CodeVisitor mw, Label end,
- StackEffect effect) throws Exception
- {
- // special case where return value is passed on
- // JVM operand stack
-
- // note: in each branch, must visit end label before RETURN!
- if(effect.outD == 0 && effect.outR == 0)
- {
- mw.visitLabel(end);
- mw.visitInsn(RETURN);
- }
- else if(effect.outD == 1 && effect.outR == 0)
- {
- pop(datastack,mw,Object.class);
- mw.visitLabel(end);
- mw.visitInsn(ARETURN);
- }
- else
- {
- // store datastack in a local
- mw.visitVarInsn(ALOAD,0);
- mw.visitFieldInsn(GETFIELD,
- "factor/FactorInterpreter",
- "datastack",
- "Lfactor/FactorArray;");
- int datastackLocal = allocate();
- mw.visitVarInsn(ASTORE,datastackLocal);
-
- for(int i = 0; i < datastack.top; i++)
- {
- mw.visitVarInsn(ALOAD,datastackLocal);
- ((FlowObject)datastack.stack[i])
- .pop(mw,Object.class);
- mw.visitMethodInsn(INVOKEVIRTUAL,
- "factor/FactorArray",
- "push",
- "(Ljava/lang/Object;)V");
- }
-
- datastack.top = 0;
-
- // store callstack in a local
- mw.visitVarInsn(ALOAD,0);
- mw.visitFieldInsn(GETFIELD,
- "factor/FactorInterpreter",
- "callstack",
- "Lfactor/FactorArray;");
- int callstackLocal = allocate();
- mw.visitVarInsn(ASTORE,callstackLocal);
-
- for(int i = 0; i < callstack.top; i++)
- {
- mw.visitVarInsn(ALOAD,callstackLocal);
- ((FlowObject)callstack.stack[i])
- .pop(mw,Object.class);
- mw.visitMethodInsn(INVOKEVIRTUAL,
- "factor/FactorArray",
- "push",
- "(Ljava/lang/Object;)V");
- }
-
- callstack.top = 0;
-
- mw.visitLabel(end);
- mw.visitInsn(RETURN);
- }
- } //}}}
-
- //{{{ compileMethod() method
- /**
- * Compiles a method.
- */
- public void compileMethod(Cons definition, ClassWriter cw,
- String methodName, StackEffect effect, FactorWord word,
- RecursiveState recursiveCheck, boolean fieldInit)
- throws Exception
- {
- String signature = effect.getCorePrototype();
-
- CodeVisitor mw = cw.visitMethod(ACC_PUBLIC | ACC_STATIC,
- methodName,signature,null,null);
-
- Label start = recursiveCheck.get(word).label;
-
- if(fieldInit)
- compileFieldInit(mw,start);
-
- mw.visitLabel(start);
-
- compile(definition,mw,recursiveCheck);
-
- Label end = new Label();
-
- compileReturn(mw,end,effect);
-
- compileExceptionHandler(mw,start,end,word);
-
- mw.visitMaxs(0,0);
- } //}}}
-
- //{{{ compileExceptionHandler() method
- private void compileExceptionHandler(CodeVisitor mw,
- Label start, Label end, FactorWord word)
- {
- // otherwise no code can throw exception etc
- if(start.getOffset() != end.getOffset())
- {
- // Now compile exception handler.
-
- Label target = new Label();
- mw.visitLabel(target);
-
- mw.visitVarInsn(ASTORE,1);
- mw.visitVarInsn(ALOAD,0);
- mw.visitFieldInsn(GETSTATIC,className,literal(word),
- "Ljava/lang/Object;");
- mw.visitTypeInsn(CHECKCAST,"factor/FactorWord");
- mw.visitVarInsn(ALOAD,1);
-
- mw.visitMethodInsn(INVOKEVIRTUAL,"factor/FactorInterpreter",
- "compiledException",
- "(Lfactor/FactorWord;Ljava/lang/Throwable;)V");
-
- mw.visitVarInsn(ALOAD,1);
- mw.visitInsn(ATHROW);
-
- mw.visitTryCatchBlock(start,end,target,"java/lang/Throwable");
- }
- } //}}}
-
- //{{{ compile() method
- /**
- * Compiles a quotation.
- */
- public void compile(Cons definition, CodeVisitor mw,
- RecursiveState recursiveCheck) throws Exception
- {
- while(definition != null)
- {
- Object obj = definition.car;
- if(obj instanceof FactorWord)
- {
- compileWord((FactorWord)obj,mw,recursiveCheck,
- definition.cdr == null);
- }
- else
- pushLiteral(obj,recursiveCheck);
-
- definition = definition.next();
- }
- } //}}}
-
- //{{{ compileWord() method
- private void compileWord(FactorWord w, CodeVisitor mw,
- RecursiveState recursiveCheck,
- boolean tail) throws Exception
- {
- if(tail && interp != null && interp.verboseCompile)
- System.err.println("Tail: " + recursiveCheck.last());
- recursiveCheck.last().tail = tail;
-
- RecursiveForm rec = recursiveCheck.get(w);
-
- try
- {
- boolean recursiveCall;
- if(rec == null)
- {
- recursiveCall = false;
- recursiveCheck.add(w,
- new StackEffect(),
- className,loader,
- "core");
- recursiveCheck.last().tail
- = (w.def instanceof FactorPrimitiveDefinition);
- }
- else
- {
- recursiveCall = true;
- rec.active = true;
- }
-
- compileCallTo(w,mw,recursiveCheck,recursiveCall);
- }
- finally
- {
- if(rec == null)
- recursiveCheck.remove(w);
- else
- {
- rec.active = false;
- rec.tail = false;
- }
- }
- } //}}}
-
- //{{{ compileCallTo() method
- private void compileCallTo(FactorWord w, CodeVisitor mw,
- RecursiveState recursiveCheck,
- boolean recursiveCall) throws Exception
- {
- if(w.def == null)
- throw new FactorUndefinedWordException(w.name);
-
- FactorWordDefinition d = w.def;
-
- if(mw == null)
- {
- recursiveCheck.last().effect = getStackEffect();
- d.getStackEffect(recursiveCheck,this);
- return;
- }
-
- if(!recursiveCall)
- {
- if(w.inline)
- {
- recursiveCheck.last().effect = getStackEffect();
- d.compileImmediate(mw,this,recursiveCheck);
- return;
- }
- else if(d instanceof FactorCompoundDefinition)
- {
- w.compile(interp,recursiveCheck);
- if(d == w.def)
- {
- throw new FactorCompilerException(word + " depends on " + w + " which cannot be compiled");
- }
- d = w.def;
- }
- }
-
- d.compileCallTo(mw,this,recursiveCheck);
- } //}}}
-
- //{{{ push() method
- /**
- * Generates code for pushing the top of the JVM stack onto the
- * data stack. Also generates code for converting this value to
- * the given type.
- */
- public void push(FactorArray stack, CodeVisitor mw, Class type)
- throws Exception
- {
- int local = allocate();
- Result r = new Result(local,this,null,type);
- stack.push(r);
- r.push(mw,type);
- } //}}}
-
- //{{{ pushLiteral() method
- public void pushLiteral(Object literal, RecursiveState recursiveCheck)
- {
- RecursiveForm word = recursiveCheck.last();
-
- if(literal == null)
- datastack.push(new Null(this,word));
- else if(literal instanceof Cons)
- {
- datastack.push(new CompiledList((Cons)literal,this,
- recursiveCheck));
- }
- else if(literal instanceof String)
- {
- datastack.push(new ConstantPoolString((String)literal,
- this,word));
- }
- else
- datastack.push(new Literal(literal,this, word));
- } //}}}
-
- //{{{ pop() method
- /**
- * Generates code for popping the top of the data stack onto
- * the JVM stack. Also generates code for converting this value to
- * the given type.
- */
- public void pop(FactorArray stack, CodeVisitor mw, Class type)
- throws Exception
- {
- FlowObject obj = (FlowObject)datastack.pop();
- obj.pop(mw,type);
- } //}}}
-
- //{{{ popLiteral() method
- /**
- * Pops a literal off the datastack or throws an exception.
- */
- public Object popLiteral() throws FactorException
- {
- FlowObject obj = (FlowObject)datastack.pop();
- return obj.getLiteral();
- } //}}}
-
- //{{{ allocate() method
- /**
- * Allocate a local variable.
- */
- public int allocate()
- {
- // inefficient!
- int i = base;
- for(;;)
- {
- if(allocate(i,datastack) && allocate(i,callstack))
- return i;
- else
- i++;
- }
- } //}}}
-
- //{{{ allocate() method
- /**
- * Return true if not in use, false if in use.
- */
- private boolean allocate(int local, FactorArray stack)
- {
- for(int i = 0; i < stack.top; i++)
- {
- FlowObject obj = (FlowObject)stack.stack[i];
- if(obj.usingLocal(local))
- return false;
- }
- return true;
- } //}}}
-
- //{{{ literal() method
- public String literal(Object obj)
- {
- Integer i = (Integer)literals.get(obj);
- int literal;
- if(i == null)
- {
- literal = literalCount++;
- literals.put(obj,new Integer(literal));
- }
- else
- literal = i.intValue();
-
- return "literal_" + literal;
- } //}}}
-
- //{{{ auxiliary() method
- public String auxiliary(FactorWord word, Cons code, StackEffect effect,
- RecursiveState recursiveCheck) throws Exception
- {
- FactorArray savedDatastack = (FactorArray)
- datastack.clone();
- FactorArray savedCallstack = (FactorArray)
- callstack.clone();
-
- String method = "aux_" + FactorJava.getSanitizedName(word.name)
- + "_" + (auxCount++);
-
- recursiveCheck.last().method = method;
- aux = new Cons(new AuxiliaryQuotation(
- method,savedDatastack,savedCallstack,
- code,effect,word,this,recursiveCheck),aux);
-
- return method;
- } //}}}
-
- //{{{ generateAuxiliary() method
- public void generateAuxiliary(ClassWriter cw) throws Exception
- {
- while(aux != null)
- {
- AuxiliaryQuotation q = (AuxiliaryQuotation)aux.car;
- // order of these two important, in case
- // compilation of q adds more quotations to aux list
- aux = aux.next();
- q.compile(this,cw);
- }
- } //}}}
-
- //{{{ normalizeStacks() method
- public void normalizeStacks(CodeVisitor mw)
- throws Exception
- {
- int datastackTop = datastack.top;
- datastack.top = 0;
- int callstackTop = callstack.top;
- callstack.top = 0;
-
- localsToStack(callstack,callstackTop,mw);
- localsToStack(datastack,datastackTop,mw);
- stackToLocals(datastack,datastackTop,mw);
- stackToLocals(callstack,callstackTop,mw);
- } //}}}
-
- //{{{ localsToStack() method
- private void localsToStack(FactorArray stack, int top,
- CodeVisitor mw) throws Exception
- {
- for(int i = top - 1; i >= 0; i--)
- {
- FlowObject obj = (FlowObject)stack.stack[i];
- obj.pop(mw,Object.class);
- }
- } //}}}
-
- //{{{ stackToLocals() method
- private void stackToLocals(FactorArray stack, int top,
- CodeVisitor mw) throws Exception
- {
- for(int i = 0; i < top; i++)
- push(stack,mw,Object.class);
- } //}}}
-
- //{{{ generateArgs() method
- /**
- * Generate instructions for copying arguments from the allocated
- * local variables to the JVM stack, doing type conversion in the
- * process.
- */
- public void generateArgs(CodeVisitor mw, int inD, int inR, Class[] args)
- throws Exception
- {
- for(int i = 0; i < inD; i++)
- {
- FlowObject obj = (FlowObject)datastack.stack[
- datastack.top - inD + i];
- obj.pop(mw,args == null ? Object.class : args[i]);
- }
-
- datastack.top -= inD;
-
- for(int i = 0; i < inR; i++)
- {
- FlowObject obj = (FlowObject)callstack.stack[
- callstack.top - inR + i];
- obj.pop(mw,args == null ? Object.class : args[i]);
- }
-
- callstack.top -= inR;
- } //}}}
-
- //{{{ generateReturn() method
- public void generateReturn(CodeVisitor mw, int outD, int outR)
- throws Exception
- {
- if(outD == 0 && outR == 0)
- {
- // do nothing
- }
- else if(outD == 1 && outR == 0)
- {
- push(datastack,mw,Object.class);
- }
- else
- {
- // transfer from data stack to JVM locals
-
- // allocate the appropriate number of locals
-
- if(outD != 0)
- {
- produce(datastack,outD);
-
- // store the datastack instance somewhere
- mw.visitVarInsn(ALOAD,0);
- mw.visitFieldInsn(GETFIELD,
- "factor/FactorInterpreter",
- "datastack",
- "Lfactor/FactorArray;");
- int datastackLocal = allocate();
- mw.visitVarInsn(ASTORE,datastackLocal);
-
- // put all elements from the real datastack
- // into locals
- for(int i = 0; i < outD; i++)
- {
- mw.visitVarInsn(ALOAD,datastackLocal);
- mw.visitMethodInsn(INVOKEVIRTUAL,
- "factor/FactorArray",
- "pop",
- "()Ljava/lang/Object;");
-
- Result destination = (Result)
- datastack.stack[
- datastack.top - i - 1];
-
- destination.push(mw,Object.class);
- }
- }
-
- if(outR != 0)
- {
- produce(callstack,outR);
-
- mw.visitVarInsn(ALOAD,0);
- mw.visitFieldInsn(GETFIELD,
- "factor/FactorInterpreter",
- "callstack",
- "Lfactor/FactorArray;");
- int callstackLocal = allocate();
- mw.visitVarInsn(ASTORE,callstackLocal);
-
- // put all elements from the real callstack
- // into locals
- for(int i = 0; i < outR; i++)
- {
- mw.visitVarInsn(ALOAD,callstackLocal);
- mw.visitMethodInsn(INVOKEVIRTUAL,
- "factor/FactorArray",
- "pop",
- "()Ljava/lang/Object;");
-
- Result destination = (Result)
- callstack.stack[
- callstack.top - i - 1];
-
- destination.push(mw,Object.class);
- }
- }
- }
- } //}}}
-
- //{{{ generateFields() method
- public void generateFields(ClassWriter cw)
- throws Exception
- {
- for(int i = 0; i < literalCount; i++)
- {
- cw.visitField(ACC_PRIVATE | ACC_STATIC,"literal_" + i,
- "Ljava/lang/Object;",null,null);
- }
-
- CodeVisitor mw = cw.visitMethod(ACC_PRIVATE | ACC_STATIC,
- "setFields","(Lfactor/FactorInterpreter;)V",null,null);
-
- Iterator entries = literals.entrySet().iterator();
- while(entries.hasNext())
- {
- Map.Entry entry = (Map.Entry)entries.next();
- Object literal = entry.getKey();
- int index = ((Integer)entry.getValue()).intValue();
-
- generateParse(mw,literal,0);
- mw.visitFieldInsn(PUTSTATIC,
- className,
- "literal_" + index,
- "Ljava/lang/Object;");
- }
-
- mw.visitInsn(RETURN);
-
- mw.visitMaxs(0,0);
- } //}}}
-
- //{{{ generateParse() method
- public void generateParse(CodeVisitor mw, Object obj, int interpLocal)
- {
- mw.visitLdcInsn(FactorReader.getVocabularyDeclaration(obj)
- + FactorReader.unparseObject(obj));
- mw.visitVarInsn(ALOAD,interpLocal);
- mw.visitMethodInsn(INVOKESTATIC,
- "factor/FactorReader",
- "parseObject",
- "(Ljava/lang/String;Lfactor/FactorInterpreter;)"
- + "Ljava/lang/Object;");
- } //}}}
-
- //{{{ getStackEffectOrNull() method
- public StackEffect getStackEffectOrNull(FactorWordDefinition def)
- {
- try
- {
- return def.getStackEffect(interp);
- }
- catch(Exception e)
- {
- //System.err.println("WARNING: " + e);
- //System.err.println(def);
- return null;
- }
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-
-public class FactorCompilerException extends FactorRuntimeException
-{
- public FactorCompilerException(String str)
- {
- super(str);
- }
-
- public FactorCompilerException(String str, Throwable t)
- {
- super(str,t);
- }
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-import java.lang.reflect.*;
-import java.math.BigInteger;
-import java.util.*;
-import org.objectweb.asm.*;
-
-public abstract class FlowObject
-implements Constants, FactorExternalizable, PublicCloneable
-{
- protected FactorCompiler compiler;
- protected RecursiveForm word;
- protected Class expectedType;
-
- //{{{ FlowObject constructor
- FlowObject(FactorCompiler compiler,
- RecursiveForm word)
- {
- this.compiler = compiler;
- this.word = word;
- expectedType = Object.class;
- } //}}}
-
- //{{{ push() method
- protected void push(CodeVisitor mw)
- throws Exception
- {
- throw new FactorCompilerException("Cannot push: " + this);
- } //}}}
-
- //{{{ push() method
- public void push(CodeVisitor mw, Class type)
- throws Exception
- {
- if(type == null)
- throw new NullPointerException();
- expectedType = (type.isPrimitive()
- ? FactorJava.getBoxingType(type)
- : type);
- if(mw != null)
- {
- generateToConversion(mw,type);
- push(mw);
- }
- } //}}}
-
- protected abstract void pop(CodeVisitor mw);
-
- //{{{ pop() method
- public void pop(CodeVisitor mw, Class type)
- throws Exception
- {
- if(mw != null)
- pop(mw);
-
- Class actualType;
- if(type.isPrimitive())
- actualType = FactorJava.getBoxingType(type);
- else
- actualType = type;
-
- // if we're looking for a subclass the expected type,
- // specialize the expected type.
- if(expectedType.isAssignableFrom(actualType))
- expectedType = actualType;
- // if we're looking for a superclass, that is ok too,
- // eg we can generate every flow object as a
- // java.lang.Object instance
- else if(actualType.isAssignableFrom(expectedType))
- /* do nothing */;
- // otherwise, type error!
- else
- {
- /* System.err.println(new TypeInferenceException(
- this,expectedType,actualType)); */
- }
-
- if(mw != null)
- generateFromConversion(mw,type);
- } //}}}
-
- //{{{ getConversionMethodName() method
- /**
- * Returns method name for converting an object to the given type.
- * Only for primitives.
- */
- private static String getConversionMethodName(Class type)
- {
- if(type.isPrimitive())
- {
- String name = type.getName();
- return "to"
- + Character.toUpperCase(name.charAt(0))
- + name.substring(1);
- }
- else
- return null;
- } //}}}
-
- //{{{ generateFromConversion() method
- /**
- * Unbox value at top of the stack.
- */
- private static void generateFromConversion(CodeVisitor mw, Class type)
- throws Exception
- {
- if(type == Object.class)
- return;
-
- String methodName = null;
-
- if(type == Number.class)
- methodName = "toNumber";
- if(type == BigInteger.class)
- methodName = "toBigInteger";
- else if(type == String.class)
- methodName = "toString";
- else if(type == CharSequence.class)
- methodName = "toCharSequence";
- else if(type.isPrimitive())
- methodName = getConversionMethodName(type);
- else if(type == Class.class)
- methodName = "toClass";
- else if(type == FactorNamespace.class)
- methodName = "toNamespace";
- else if(type.isArray())
- {
- Class comp = type.getComponentType();
- if(comp.isPrimitive())
- {
- methodName = getConversionMethodName(comp)
- + "Array";
- }
- else
- methodName = "toArray";
- }
-
- if(methodName == null)
- {
- mw.visitTypeInsn(CHECKCAST,
- type.getName()
- .replace('.','/'));
- }
- else
- {
- String signature;
- if(type.isArray())
- {
- signature = "(Ljava/lang/Object;)"
- + "[Ljava/lang/Object;";
- }
- else
- {
- signature = "(Ljava/lang/Object;)"
- + FactorJava.javaClassToVMClass(type);
- }
- mw.visitMethodInsn(INVOKESTATIC,"factor/FactorJava",
- methodName,signature);
- /* if(type.isArray())
- {
- mw.visitTypeInsn(CHECKCAST,
- type.getName()
- .replace('.','/'));
- } */
- }
- } //}}}
-
- //{{{ generateToConversionPre() method
- /**
- * Avoid having to deal with category 1/2 computational type
- * distinction.
- */
- public static void generateToConversionPre(CodeVisitor mw, Class type)
- throws Exception
- {
- if(type == boolean.class)
- return;
-
- Class boxingType = FactorJava.getBoxingType(type);
- if(boxingType != null)
- {
- String boxingName = boxingType.getName()
- .replace('.','/');
- mw.visitTypeInsn(NEW,boxingName);
- mw.visitInsn(DUP);
- }
- } //}}}
-
- //{{{ generateToConversion() method
- /**
- * Box return value, if needed.
- */
- private static void generateToConversion(CodeVisitor mw, Class type)
- throws Exception
- {
- if(type == boolean.class)
- {
- // this case is handled specially
- mw.visitMethodInsn(INVOKESTATIC,
- "factor/FactorJava",
- "fromBoolean",
- "(Z)Ljava/lang/Object;");
- }
- else
- {
- Class boxingType = FactorJava.getBoxingType(type);
- if(boxingType != null)
- {
- String boxingName = boxingType.getName()
- .replace('.','/');
- mw.visitMethodInsn(INVOKESPECIAL,boxingName,
- "<init>",
- "(" + FactorJava.javaClassToVMClass(
- type) + ")V");
- }
- }
- } //}}}
-
- //{{{ munge() method
- /**
- * Munging transforms the flow object such that it is now stored in
- * a local variable and hence can be mutated by compiled code, however
- * its original compileCallTo() semantics remain (for example, if it is
- * a quotation).
- */
- FlowObject munge(int base, int index,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- throws Exception
- {
- return new Result(index + base,compiler,recursiveCheck.last(),
- expectedType);
- } //}}}
-
- //{{{ usingLocal() method
- boolean usingLocal(int local)
- {
- return false;
- } //}}}
-
- //{{{ getLiteral() method
- Object getLiteral()
- throws FactorCompilerException
- {
- throw new FactorCompilerException("Cannot compile unless literal on stack: " + this);
- } //}}}
-
- //{{{ getLocal() method
- /**
- * @return -1 if the result is not store in a local variable.
- */
- public int getLocal()
- {
- return -1;
- } //}}}
-
- //{{{ compileCallTo() method
- /**
- * Write code for evaluating this. Returns maximum JVM stack
- * usage.
- */
- public void compileCallTo(CodeVisitor mw, RecursiveState recursiveCheck)
- throws Exception
- {
- throw new FactorCompilerException("Cannot compile call to non-literal quotation");
- } //}}}
-
- //{{{ getWord() method
- /**
- * Returns the word where this flow object originated from.
- */
- public RecursiveForm getWord()
- {
- return word;
- } //}}}
-
- //{{{ getType() method
- public Class getType()
- {
- return expectedType;
- } //}}}
-
- //{{{ toString() method
- public String toString()
- {
- try
- {
- return FactorReader.unparseObject(getLiteral());
- }
- catch(Exception e)
- {
- throw new RuntimeException("Override toString() if your getLiteral() bombs!");
- }
- } //}}}
-
- //{{{ clone() method
- public Object clone()
- {
- // cannot be abstract, and cannot be left undefined!
- throw new InternalError();
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-import java.lang.reflect.*;
-import java.util.*;
-import org.objectweb.asm.*;
-
-public class Literal extends FlowObject
-{
- private Object literal;
-
- //{{{ Literal constructor
- Literal(Object literal, FactorCompiler compiler,
- RecursiveForm word)
- {
- super(compiler,word);
- this.literal = literal;
- expectedType = literal.getClass();
- } //}}}
-
- //{{{ pop() method
- public void pop(CodeVisitor mw)
- {
- mw.visitFieldInsn(GETSTATIC,compiler.className,
- compiler.literal(literal),
- "Ljava/lang/Object;");
- } //}}}
-
- //{{{ getLiteral() method
- Object getLiteral()
- {
- return literal;
- } //}}}
-
- //{{{ compileCallTo() method
- /**
- * Write code for evaluating this. Returns maximum JVM stack
- * usage.
- */
- public void compileCallTo(CodeVisitor mw, RecursiveState recursiveCheck)
- throws Exception
- {
- throw new FactorCompilerException("Not a quotation: " + literal);
- } //}}}
-
- //{{{ clone() method
- public Object clone()
- {
- return new Literal(literal,compiler,word);
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-import java.lang.reflect.*;
-import java.util.*;
-import org.objectweb.asm.*;
-
-public class Null extends FlowObject
-{
- //{{{ Null constructor
- Null(FactorCompiler compiler, RecursiveForm word)
- {
- super(compiler,word);
- } //}}}
-
- //{{{ pop() Method
- public void pop(CodeVisitor mw)
- {
- mw.visitInsn(ACONST_NULL);
- } //}}}
-
- //{{{ munge() method
- /**
- * Munging transforms the flow object such that it is now stored in
- * a local variable and hence can be mutated by compiled code, however
- * its original compileCallTo() semantics remain (for example, if it is
- * a quotation).
- */
- FlowObject munge(int base, int index,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- throws Exception
- {
- return new CompiledListResult(index + base,null,
- compiler,recursiveCheck);
- } //}}}
-
- //{{{ getLiteral() method
- Object getLiteral()
- {
- return null;
- } //}}}
-
- //{{{ compileCallTo() method
- /**
- * Write code for evaluating this. Returns maximum JVM stack
- * usage.
- */
- public void compileCallTo(CodeVisitor mw, RecursiveState recursiveCheck)
- throws Exception
- {
- } //}}}
-
- //{{{ equals() method
- public boolean equals(Object o)
- {
- if(o instanceof Null)
- return true;
- else if(o instanceof CompiledList)
- return ((CompiledList)o).getLiteral() == null;
- else
- return false;
- } //}}}
-
- //{{{ clone() method
- public Object clone()
- {
- return new Null(compiler,word);
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-import org.objectweb.asm.Label;
-
-public class RecursiveForm implements PublicCloneable
-{
- /**
- * Word represented by this form.
- */
- public final FactorWord word;
-
- /**
- * The effect on entry into this form.
- * (?) only for immediates
- */
- public StackEffect effect;
-
- /**
- * Base case of recursive form. This is left-composed with the
- * effect above.
- */
- public StackEffect baseCase;
-
- /**
- * Is the word being compiled right now?
- */
- public boolean active;
-
- /**
- * Name of class to call to recurse.
- */
- public String className;
-
- /**
- * Class loader containing this definition.
- */
- public FactorClassLoader loader;
-
- /**
- * Name of method to call to recurse.
- */
- public String method;
-
- /**
- * Are we compiling the last factor in the word right now?
- */
- public boolean tail;
-
- /**
- * A label to jump to the beginning of the definition.
- */
- public Label label = new Label();
-
- /**
- * See RecursiveState.lastCallable().
- */
- public boolean callable = true;
-
- /**
- * The containing recursive form, lexically.
- */
- public RecursiveForm next;
-
- public RecursiveForm(FactorWord word, StackEffect effect,
- String className, FactorClassLoader loader,
- String method)
- {
- this.word = word;
- this.effect = effect;
- this.className = className;
- this.loader = loader;
- this.method = method;
- }
-
- public RecursiveForm(RecursiveForm form)
- {
- this.word = form.word;
- this.effect = form.effect;
- this.baseCase = form.baseCase;
- this.effect = form.effect;
- this.className = form.className;
- this.loader = form.loader;
- this.method = form.method;
- }
-
- public String toString()
- {
- return word.toString() + ",base=" + baseCase
- + ",effect=" + effect
- + (active?",active":"")
- + (tail?",tail":"")
- + "; " + className + "." + method + "()";
- }
-
- public Object clone()
- {
- return new RecursiveForm(this);
- }
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-
-public class RecursiveState implements PublicCloneable
-{
- private Cons words;
-
- //{{{ RecursiveState constructor
- public RecursiveState()
- {
- } //}}}
-
- //{{{ RecursiveState constructor
- public RecursiveState(RecursiveState clone)
- {
- if(clone.words != null)
- words = clone.words;
- } //}}}
-
- //{{{ add() method
- public void add(FactorWord word, StackEffect effect,
- String className, FactorClassLoader loader, String method)
- {
- add(word,effect,className,loader,method,
- words == null ? null : last());
- } //}}}
-
- //{{{ add() method
- public void add(FactorWord word, StackEffect effect,
- String className, FactorClassLoader loader, String method,
- RecursiveForm next)
- {
- if(get(word) != null)
- {
- throw new RuntimeException("Calling add() twice on " + word);
- }
-
- RecursiveForm newForm = new RecursiveForm(
- word,effect,className,loader,method);
- words = new Cons(newForm,words);
- newForm.next = next;
- } //}}}
-
- //{{{ remove() method
- public void remove(FactorWord word)
- {
- //System.err.println(this + ": removing " + word);
- if(last().word != word)
- throw new RuntimeException("Expected " + word + ", found " + last().word);
- words = words.next();
- } //}}}
-
- //{{{ get() method
- public RecursiveForm get(FactorWord word)
- {
- if(words != null)
- {
- RecursiveForm iter = last();
- while(iter != null)
- {
- if(iter.word == word)
- return iter;
- iter = iter.next;
- }
- }
-
- return null;
- } //}}}
-
- //{{{ last() method
- public RecursiveForm last()
- {
- return (RecursiveForm)words.car;
- } //}}}
-
- //{{{ lastCallable() method
- public RecursiveForm lastCallable()
- {
- RecursiveForm word = (RecursiveForm)words.car;
- while(word != null)
- {
- if(word.callable)
- return word;
- word = word.next;
- }
- return null;
- } //}}}
-
- //{{{ allTails() method
- /**
- * Returns if all forms from the given form upward are at their tail,
- * so that we can do a direct GOTO to the given form to recurse on it.
- */
- public boolean allTails(RecursiveForm form)
- {
- Cons iter = words;
- for(;;)
- {
- if(!((RecursiveForm)iter.car).tail)
- return false;
- if(iter.car == form)
- return true;
- iter = iter.next();
- }
- } //}}}
-
- //{{{ toString() method
- public String toString()
- {
- return FactorReader.unparseObject(words);
- } //}}}
-
- //{{{ clone() method
- public Object clone()
- {
- return new RecursiveState(this);
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-import java.util.*;
-import org.objectweb.asm.*;
-
-public class Result extends FlowObject
-{
- private int local;
- private boolean input;
-
- public Result(int local, FactorCompiler compiler,
- RecursiveForm word, Class type)
- {
- this(local,compiler,word,type,false);
- }
-
- /**
- * @param input An input result contains a parameter passed to a
- * compiled word's core() method.
- */
- public Result(int local, FactorCompiler compiler,
- RecursiveForm word, Class type,
- boolean input)
- {
- super(compiler,word);
- this.local = local;
- if(type == null)
- throw new NullPointerException();
- this.expectedType = (type.isPrimitive()
- ? FactorJava.getBoxingType(type)
- : type);
- this.input = input;
- }
-
- public void push(CodeVisitor mw)
- throws Exception
- {
- mw.visitVarInsn(ASTORE,local);
- }
-
- public void pop(CodeVisitor mw)
- {
- mw.visitVarInsn(ALOAD,local);
- }
-
- public int getLocal()
- {
- return local;
- }
-
- boolean usingLocal(int local)
- {
- return (this.local == local);
- }
-
- public boolean isInput()
- {
- return input;
- }
-
- public String toString()
- {
- return expectedType.getName() + "#" + local;
- }
-
- //{{{ clone() method
- public Object clone()
- {
- return new Result(local,compiler,word,expectedType);
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-import java.util.*;
-
-public class StackEffect implements PublicCloneable, FactorExternalizable
-{
- public int inD;
- public Class[] inDtypes;
- public int outD;
- public Class[] outDtypes;
- public int inR;
- public Class[] inRtypes;
- public int outR;
- public Class[] outRtypes;
-
- //{{{ StackEffect constructor
- public StackEffect() {}
- //}}}
-
- //{{{ StackEffect constructor
- public StackEffect(int inD, int outD, int inR, int outR)
- {
- this.inD = inD;
- this.outD = outD;
- this.inR = inR;
- this.outR = outR;
- } //}}}
-
- //{{{ StackEffect constructor
- public StackEffect(int inD, Class[] inDtypes,
- int outD, Class[] outDtypes,
- int inR, Class[] inRtypes,
- int outR, Class[] outRtypes)
- {
- this.inD = inD;
- this.inDtypes = inDtypes;
- this.outD = outD;
- this.outDtypes = outDtypes;
- this.inR = inR;
- this.inRtypes = inRtypes;
- this.outR = outR;
- this.outRtypes = outRtypes;
- } //}}}
-
- //{{{ compose() method
- public static StackEffect compose(StackEffect first,
- StackEffect second)
- {
- if(first == null || second == null)
- return null;
-
- int inD = first.inD + Math.max(0,second.inD - first.outD);
- int outD = second.outD + Math.max(0,first.outD - second.inD);
-
- int inR = first.inR + Math.max(0,second.inR - first.outR);
- int outR = second.outR + Math.max(0,first.outR - second.inR);
-
- return new StackEffect(inD,outD,inR,outR);
- } //}}}
-
- //{{{ decompose() method
- /**
- * Returns a stack effect E such that compose(first,E) == second.
- */
- public static StackEffect decompose(StackEffect first,
- StackEffect second)
- {
- if(first == null)
- throw new NullPointerException("first == null");
- if(second == null)
- throw new NullPointerException("second == null");
- if(second.inD < first.inD || second.inR < first.inR)
- throw new IllegalArgumentException();
-
- return new StackEffect(
- first.outD + second.inD - first.inD,
- second.outD,
- first.outR + second.inR - first.inR,
- second.outR);
- } //}}}
-
- //{{{ getCorePrototype() method
- public String getCorePrototype()
- {
- StringBuffer signatureBuf = new StringBuffer(
- "(Lfactor/FactorInterpreter;");
-
- for(int i = 0; i < inD + inR; i++)
- signatureBuf.append("Ljava/lang/Object;");
-
- if(outD + outR != 1)
- signatureBuf.append(")V");
- else
- signatureBuf.append(")Ljava/lang/Object;");
-
- return signatureBuf.toString();
- } //}}}
-
- //{{{ equals() method
- public boolean equals(Object o)
- {
- if(!(o instanceof StackEffect))
- return false;
- StackEffect effect = (StackEffect)o;
- return effect.inD == inD
- && effect.outD == outD
- && effect.inR == inR
- && effect.outR == outR;
- } //}}}
-
- //{{{ hashCode() method
- public int hashCode()
- {
- return inD + inR + outD + outR;
- } //}}}
-
- //{{{ typespec() method
- private String typespec(int index, Class[] types)
- {
- if(types != null)
- return types[index].getName();
- else
- return "X";
- } //}}}
-
- //{{{ toString() method
- public String toString()
- {
- StringBuffer buf = new StringBuffer("( ");
- for(int i = 0; i < inD; i++)
- {
- buf.append(typespec(i,inDtypes));
- buf.append(' ');
- }
- for(int i = 0; i < inR; i++)
- {
- buf.append("r:");
- buf.append(typespec(i,inRtypes));
- buf.append(' ');
- }
- buf.append("--");
- for(int i = 0; i < outD; i++)
- {
- buf.append(' ');
- buf.append(typespec(i,outDtypes));
- }
- for(int i = 0; i < outR; i++)
- {
- buf.append(" r:");
- buf.append(typespec(i,outRtypes));
- }
- buf.append(" )");
- return buf.toString();
- } //}}}
-
- //{{{ clone() method
- public Object clone()
- {
- return new StackEffect(inD,inDtypes,
- outD,outDtypes,
- inR,inRtypes,
- outR,outRtypes);
- } //}}}
-}
+++ /dev/null
-/* :folding=explicit:collapseFolds=1: */
-
-/*
- * $Id$
- *
- * Copyright (C) 2004 Slava Pestov.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package factor.compiler;
-
-import factor.*;
-
-public class TypeInferenceException extends FactorCompilerException
-{
- public TypeInferenceException(Object obj, Class expected, Class got)
- {
- super(obj + "\n"
- + "Expected: " + expected + "\n"
- + "Got: " + got);
- }
-}
reader.append(w.vocabulary);
reader.append(w.name);
- reader.append(new FactorCompoundDefinition(
- w,state.first,interp));
+ reader.append(new FactorCompoundDefinition(w,state.first));
reader.append(reader.intern("define",false));
}
}
reader.append(newWord.vocabulary);
reader.append(newWord.name);
- reader.append(new FactorShuffleDefinition(
- newWord,first,interp));
+ reader.append(new FactorShuffleDefinition(newWord,first));
reader.append(reader.intern("define",false));
}
}
package factor.primitives;
-import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
-import org.objectweb.asm.*;
public class Call extends FactorPrimitiveDefinition
{
{
interp.call((Cons)interp.datastack.pop());
} //}}}
-
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- compileImmediate(null,compiler,recursiveCheck);
- } //}}}
-
- //{{{ compileImmediate() method
- /**
- * Compile a call to this word. Returns maximum JVM stack use.
- */
- public void compileImmediate(
- CodeVisitor mw,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- throws Exception
- {
- if(mw == null)
- compiler.ensure(compiler.datastack,Cons.class);
- FlowObject quot = (FlowObject)compiler.datastack.pop();
- quot.compileCallTo(mw,recursiveCheck);
- } //}}}
}
package factor.primitives;
-import factor.compiler.*;
import factor.*;
-import org.objectweb.asm.*;
public class Coerce extends FactorPrimitiveDefinition
{
datastack.push(FactorJava.convertToJavaType(
datastack.pop(),type));
} //}}}
-
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- compileImmediate(null,compiler,recursiveCheck);
- } //}}}
-
- //{{{ compileImmediate() method
- public void compileImmediate(
- CodeVisitor mw,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- throws Exception
- {
- if(mw == null)
- compiler.ensure(compiler.datastack,Class.class);
- Class type = FactorJava.toClass(compiler.popLiteral());
- if(mw == null)
- compiler.ensure(compiler.datastack,type);
- else
- FlowObject.generateToConversionPre(mw,type);
- compiler.pop(compiler.datastack,mw,type);
- compiler.push(compiler.datastack,mw,type);
- } //}}}
}
package factor.primitives;
-import factor.compiler.*;
import factor.*;
public class Define extends FactorPrimitiveDefinition
word.define(definition);
interp.last = word;
} //}}}
-
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- compiler.ensure(compiler.datastack,FactorWordDefinition.class);
- compiler.pop(compiler.datastack,null,FactorWordDefinition.class);
- compiler.ensure(compiler.datastack,String.class);
- compiler.pop(compiler.datastack,null,String.class);
- compiler.ensure(compiler.datastack,String.class);
- compiler.pop(compiler.datastack,null,String.class);
- } //}}}
}
package factor.primitives;
-import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Set;
package factor.primitives;
-import factor.compiler.*;
import factor.*;
-import org.objectweb.asm.*;
public class Ifte extends FactorPrimitiveDefinition
{
else
interp.call(f);
} //}}}
-
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- compiler.ensure(compiler.datastack,Cons.class);
-
- boolean fPossiblyRecursive = false;
- FlowObject f = (FlowObject)compiler.datastack.pop();
- compiler.ensure(compiler.datastack,Cons.class);
-
- boolean tPossiblyRecursive = false;
- FlowObject t = (FlowObject)compiler.datastack.pop();
- compiler.ensure(compiler.datastack,Object.class);
- FlowObject cond = (FlowObject)compiler.datastack.pop();
-
- CompilerState savedState = new CompilerState(compiler);
-
- try
- {
- t.compileCallTo(null,recursiveCheck);
- }
- catch(Exception e)
- {
- tPossiblyRecursive = true;
- }
-
- CompilerState tState = new CompilerState(compiler);
-
- savedState.restore(compiler);
-
- try
- {
- f.compileCallTo(null,recursiveCheck);
- }
- catch(Exception e)
- {
- fPossiblyRecursive = true;
- }
-
- CompilerState fState = new CompilerState(compiler);
-
- if(!fPossiblyRecursive && tPossiblyRecursive)
- {
- RecursiveForm rec = t.getWord();
- rec.baseCase = fState.effect;
- savedState.restore(compiler);
- t.compileCallTo(null,recursiveCheck);
- tState = new CompilerState(compiler);
- }
- else if(fPossiblyRecursive && !tPossiblyRecursive)
- {
- RecursiveForm rec = f.getWord();
- rec.baseCase = tState.effect;
- savedState.restore(compiler);
- f.compileCallTo(null,recursiveCheck);
- fState = new CompilerState(compiler);
- }
- else if(fPossiblyRecursive && tPossiblyRecursive)
- throw new FactorCompilerException("Indeterminate ifte effect\ntrue branch: " + t + "\nfalse branch: " + f);
-
- CompilerState.unifyStates(compiler,recursiveCheck,t,f,tState,fState);
- } //}}}
-
- //{{{ compileNonRecursiveImmediate() method
- /**
- * Non-recursive immediate words are inlined.
- */
- protected void compileNonRecursiveImmediate(CodeVisitor mw,
- FactorCompiler compiler,
- RecursiveState recursiveCheck,
- StackEffect immediateEffect) throws Exception
- {
- if(mw == null)
- compiler.ensure(compiler.datastack,Cons.class);
- FlowObject f = (FlowObject)compiler.datastack.pop();
- if(mw == null)
- compiler.ensure(compiler.datastack,Cons.class);
- FlowObject t = (FlowObject)compiler.datastack.pop();
- if(mw == null)
- compiler.ensure(compiler.datastack,Object.class);
- FlowObject cond = (FlowObject)compiler.datastack.pop();
-
- // if null jump to F
- // T
- // jump END
- // F: F
- // END: ...
- Label fl = new Label();
- Label endl = new Label();
-
- cond.pop(mw,Object.class);
-
- mw.visitJumpInsn(IFNULL,fl);
-
- FactorArray datastackCopy = (FactorArray)
- compiler.datastack.clone();
- FactorArray callstackCopy = (FactorArray)
- compiler.callstack.clone();
-
- t.compileCallTo(mw,recursiveCheck);
-
- compiler.normalizeStacks(mw);
-
- compiler.datastack = datastackCopy;
- compiler.callstack = callstackCopy;
-
- mw.visitJumpInsn(GOTO,endl);
- mw.visitLabel(fl);
- f.compileCallTo(mw,recursiveCheck);
-
- compiler.normalizeStacks(mw);
-
- mw.visitLabel(endl);
- } //}}}
-
- //{{{ compileRecursiveImmediate() method
- /**
- * Recursive immediate words are compiled to an auxiliary method
- * inside the compiled class definition.
- *
- * This must be done so that recursion has something to jump to.
- */
- protected void compileRecursiveImmediate(CodeVisitor mw,
- FactorCompiler compiler,
- RecursiveState recursiveCheck,
- StackEffect immediateEffect) throws Exception
- {
- throw new FactorCompilerException("ifte is not recursive");
- } //}}}
}
package factor.primitives;
-import factor.compiler.*;
import factor.*;
import java.util.Set;
-import org.objectweb.asm.*;
public class InterpreterGet extends FactorPrimitiveDefinition
{
{
interp.datastack.push(interp);
} //}}}
-
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- compileImmediate(null,compiler,recursiveCheck);
- } //}}}
-
- //{{{ compileImmediate() method
- public void compileImmediate(
- CodeVisitor mw,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- throws Exception
- {
- if(mw != null)
- mw.visitVarInsn(ALOAD,0);
- compiler.push(compiler.datastack,mw,FactorInterpreter.class);
- } //}}}
}
package factor.primitives;
-import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
-import org.objectweb.asm.*;
public class JInvoke extends FactorPrimitiveDefinition
{
throw new FactorStackException(_args.length);
}
} //}}}
-
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- compileImmediate(null,compiler,recursiveCheck);
- } //}}}
-
- //{{{ compileImmediate() method
- public void compileImmediate(
- CodeVisitor mw,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- throws Exception
- {
- if(mw == null)
- compiler.ensure(compiler.datastack,String.class);
- String name = FactorJava.toString(compiler.popLiteral());
- if(mw == null)
- compiler.ensure(compiler.datastack,Class.class);
- Class clazz = FactorJava.toClass(compiler.popLiteral());
- if(mw == null)
- compiler.ensure(compiler.datastack,Cons.class);
- Cons args = (Cons)compiler.popLiteral();
-
- Class[] _args = FactorJava.classNameToClassList(args);
- Method method = clazz.getMethod(name,_args);
-
- checkStatic(method);
-
- Class returnType = method.getReturnType();
-
- if(mw != null)
- FlowObject.generateToConversionPre(mw,returnType);
-
- if(!staticMethod)
- {
- if(mw == null)
- compiler.ensure(compiler.datastack,clazz);
- compiler.pop(compiler.datastack,mw,clazz);
- }
-
- if(mw == null)
- compiler.ensure(compiler.datastack,_args);
-
- compiler.generateArgs(mw,_args.length,0,_args);
-
- if(mw != null)
- {
- int opcode;
- if(staticMethod)
- opcode = INVOKESTATIC;
- else if(clazz.isInterface())
- opcode = INVOKEINTERFACE;
- else
- opcode = INVOKEVIRTUAL;
- mw.visitMethodInsn(opcode,
- clazz.getName().replace('.','/'),
- name,
- FactorJava.javaSignatureToVMSignature(
- _args,returnType));
- }
-
- if(returnType != Void.TYPE)
- compiler.push(compiler.datastack,mw,returnType);
- } //}}}
}
package factor.primitives;
-import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
-import org.objectweb.asm.*;
public class JNew extends FactorPrimitiveDefinition
{
datastack.push(constructor.newInstance(params));
} //}}}
-
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- compileImmediate(null,compiler,recursiveCheck);
- } //}}}
-
- //{{{ compileImmediate() method
- public void compileImmediate(
- CodeVisitor mw,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- throws Exception
- {
- if(mw == null)
- compiler.ensure(compiler.datastack,Class.class);
- Class clazz = FactorJava.toClass(compiler.popLiteral());
- if(mw == null)
- compiler.ensure(compiler.datastack,Cons.class);
- Cons args = (Cons)compiler.popLiteral();
-
- Class[] _args = FactorJava.classNameToClassList(args);
- Constructor constructor = clazz.getConstructor(_args);
-
- if(mw != null)
- {
- FlowObject.generateToConversionPre(mw,clazz);
- mw.visitTypeInsn(NEW,clazz.getName().replace('.','/'));
- mw.visitInsn(DUP);
- }
-
- if(mw == null)
- compiler.ensure(compiler.datastack,_args);
- compiler.generateArgs(mw,_args.length,0,_args);
-
- if(mw != null)
- {
- mw.visitMethodInsn(INVOKESPECIAL,
- clazz.getName().replace('.','/'),
- "<init>",
- FactorJava.javaSignatureToVMSignature(
- _args,Void.TYPE));
- }
-
- compiler.push(compiler.datastack,mw,clazz);
- } //}}}
}
package factor.primitives;
-import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
-import org.objectweb.asm.*;
public class JVarGet extends FactorPrimitiveDefinition
{
FactorJava.convertFromJavaType(
field.get(obj)));
} //}}}
-
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- compileImmediate(null,compiler,recursiveCheck);
- } //}}}
-
- //{{{ compileImmediate() method
- public void compileImmediate(
- CodeVisitor mw,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- throws Exception
- {
- if(mw == null)
- compiler.ensure(compiler.datastack,String.class);
- String fieldName = FactorJava.toString(compiler.popLiteral());
- if(mw == null)
- compiler.ensure(compiler.datastack,Class.class);
- Class clazz = FactorJava.toClass(compiler.popLiteral());
- Field field = clazz.getField(fieldName);
-
- if(mw != null)
- FlowObject.generateToConversionPre(mw,field.getType());
- if(mw == null)
- compiler.ensure(compiler.datastack,clazz);
- compiler.pop(compiler.datastack,mw,clazz);
-
- if(mw != null)
- {
- mw.visitFieldInsn(GETFIELD,
- clazz.getName().replace('.','/'),
- fieldName,
- FactorJava.javaClassToVMClass(field.getType()));
- }
-
- compiler.push(compiler.datastack,mw,field.getType());
- } //}}}
}
package factor.primitives;
-import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
-import org.objectweb.asm.*;
public class JVarGetStatic extends FactorPrimitiveDefinition
{
FactorJava.convertFromJavaType(
field.get(null)));
} //}}}
-
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- compileImmediate(null,compiler,recursiveCheck);
- } //}}}
-
- //{{{ compileImmediate() method
- public void compileImmediate(
- CodeVisitor mw,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- throws Exception
- {
- if(mw == null)
- compiler.ensure(compiler.datastack,String.class);
- String fieldName = FactorJava.toString(compiler.popLiteral());
- if(mw == null)
- compiler.ensure(compiler.datastack,Class.class);
- Class clazz = FactorJava.toClass(compiler.popLiteral());
- Field field = clazz.getField(fieldName);
-
- if(mw != null)
- {
- FlowObject.generateToConversionPre(mw,field.getType());
- mw.visitFieldInsn(GETSTATIC,
- clazz.getName().replace('.','/'),
- fieldName,
- FactorJava.javaClassToVMClass(field.getType()));
- }
-
- compiler.push(compiler.datastack,mw,field.getType());
- } //}}}
}
package factor.primitives;
-import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
-import org.objectweb.asm.*;
public class JVarSet extends FactorPrimitiveDefinition
{
field.getType());
field.set(obj,value);
} //}}}
-
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- compileImmediate(null,compiler,recursiveCheck);
- } //}}}
-
- //{{{ compileImmediate() method
- public void compileImmediate(
- CodeVisitor mw,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- throws Exception
- {
- if(mw == null)
- compiler.ensure(compiler.datastack,String.class);
- String fieldName = FactorJava.toString(compiler.popLiteral());
- if(mw == null)
- compiler.ensure(compiler.datastack,Class.class);
- Class clazz = FactorJava.toClass(compiler.popLiteral());
- Field field = clazz.getField(fieldName);
- if(mw == null)
- compiler.ensure(compiler.datastack,clazz);
- compiler.pop(compiler.datastack,mw,clazz);
- if(mw == null)
- compiler.ensure(compiler.datastack,field.getType());
- compiler.pop(compiler.datastack,mw,field.getType());
-
- if(mw != null)
- {
- mw.visitFieldInsn(PUTFIELD,
- clazz.getName().replace('.','/'),
- fieldName,
- FactorJava.javaClassToVMClass(field.getType()));
- }
- } //}}}
}
package factor.primitives;
-import factor.compiler.*;
import factor.*;
import java.lang.reflect.*;
import java.util.Map;
-import org.objectweb.asm.*;
public class JVarSetStatic extends FactorPrimitiveDefinition
{
field.getType());
field.set(null,value);
} //}}}
-
- //{{{ getStackEffect() method
- public void getStackEffect(RecursiveState recursiveCheck,
- FactorCompiler compiler) throws Exception
- {
- compileImmediate(null,compiler,recursiveCheck);
- } //}}}
-
- //{{{ compileImmediate() method
- public void compileImmediate(
- CodeVisitor mw,
- FactorCompiler compiler,
- RecursiveState recursiveCheck)
- throws Exception
- {
- if(mw == null)
- compiler.ensure(compiler.datastack,String.class);
- String fieldName = FactorJava.toString(compiler.popLiteral());
- if(mw == null)
- compiler.ensure(compiler.datastack,Class.class);
- Class clazz = FactorJava.toClass(compiler.popLiteral());
- Field field = clazz.getField(fieldName);
- if(mw == null)
- compiler.ensure(compiler.datastack,field.getType());
- compiler.pop(compiler.datastack,mw,field.getType());
-
- if(mw != null)
- {
- mw.visitFieldInsn(PUTSTATIC,
- clazz.getName().replace('.','/'),
- fieldName,
- FactorJava.javaClassToVMClass(field.getType()));
- }
- } //}}}
}
package factor.primitives;
-import factor.compiler.*;
import factor.*;
import java.util.Set;
package factor.primitives;
-import factor.compiler.*;
import factor.*;
import java.util.Set;
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- */
-
-package org.objectweb.asm;
-
-/**
- * A non standard class, field, method or code attribute.
- */
-
-public abstract class Attribute {
-
- /**
- * The type of this attribute.
- */
-
- public final String type;
-
- /**
- * The next attribute in this attribute list. May be <tt>null</tt>.
- */
-
- public Attribute next;
-
- /**
- * Constructs a new empty attribute.
- *
- * @param type the type of the attribute.
- */
-
- public Attribute (final String type) {
- this.type = type;
- }
-
- /**
- * Returns the labels corresponding to this attribute.
- *
- * @return the labels corresponding to this attribute, or <tt>null</tt> if
- * this attribute is not a code attribute that contains labels.
- */
-
- protected Label[] getLabels () {
- return null;
- }
-
- /**
- * Reads a {@link #type type} attribute. This method must return a <i>new</i>
- * {@link Attribute} object, of type {@link #type type}, corresponding to the
- * <tt>len</tt> bytes starting at the given offset, in the given class reader.
- *
- * @param cr the class that contains the attribute to be read.
- * @param off index of the first byte of the attribute's content in {@link
- * ClassReader#b cr.b}. The 6 attribute header bytes, containing the type
- * and the length of the attribute, are not taken into account here.
- * @param len the length of the attribute's content.
- * @param buf buffer to be used to call {@link ClassReader#readUTF8 readUTF8},
- * {@link ClassReader#readClass readClass} or {@link
- * ClassReader#readConst readConst}.
- * @param codeOff index of the first byte of code's attribute content in
- * {@link ClassReader#b cr.b}, or -1 if the attribute to be read is not a
- * code attribute. The 6 attribute header bytes, containing the type and
- * the length of the attribute, are not taken into account here.
- * @param labels the labels of the method's code, or <tt>null</tt> if the
- * attribute to be read is not a code attribute.
- * @return a <i>new</i> {@link Attribute} object corresponding to the given
- * bytes.
- */
-
- protected abstract Attribute read (
- ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels);
-
- /**
- * Returns the byte array form of this attribute.
- *
- * @param cw the class to which this attribute must be added. This parameter
- * can be used to add to the constant pool of this class the items that
- * corresponds to this attribute.
- * @param code the bytecode of the method corresponding to this code
- * attribute, or <tt>null</tt> if this attribute is not a code
- * attributes.
- * @param len the length of the bytecode of the method corresponding to this
- * code attribute, or <tt>null</tt> if this attribute is not a code
- * attribute.
- * @param maxStack the maximum stack size of the method corresponding to this
- * code attribute, or -1 if this attribute is not a code attribute.
- * @param maxLocals the maximum number of local variables of the method
- * corresponding to this code attribute, or -1 if this attribute is not
- * a code attribute.
- * @return the byte array form of this attribute.
- */
-
- protected abstract ByteVector write (
- ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals);
-
- /**
- * Returns the length of the attribute list that begins with this attribute.
- *
- * @return the length of the attribute list that begins with this attribute.
- */
-
- final int getCount () {
- int count = 0;
- Attribute attr = this;
- while (attr != null) {
- count += 1;
- attr = attr.next;
- }
- return count;
- }
-
- /**
- * Returns the size of all the attributes in this attribute list.
- *
- * @param cw the class writer to be used to convert the attributes into byte
- * arrays, with the {@link #write write} method.
- * @param code the bytecode of the method corresponding to these code
- * attributes, or <tt>null</tt> if these attributes are not code
- * attributes.
- * @param len the length of the bytecode of the method corresponding to these
- * code attributes, or <tt>null</tt> if these attributes are not code
- * attributes.
- * @param maxStack the maximum stack size of the method corresponding to these
- * code attributes, or -1 if these attributes are not code attributes.
- * @param maxLocals the maximum number of local variables of the method
- * corresponding to these code attributes, or -1 if these attributes are
- * not code attributes.
- * @return the size of all the attributes in this attribute list. This size
- * includes the size of the attribute headers.
- */
-
- final int getSize (
- final ClassWriter cw,
- final byte[] code,
- final int len,
- final int maxStack,
- final int maxLocals)
- {
- int size = 0;
- Attribute attr = this;
- while (attr != null) {
- cw.newUTF8(attr.type);
- size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
- attr = attr.next;
- }
- return size;
- }
-
- /**
- * Writes all the attributes of this attribute list in the given byte vector.
- *
- * @param cw the class writer to be used to convert the attributes into byte
- * arrays, with the {@link #write write} method.
- * @param code the bytecode of the method corresponding to these code
- * attributes, or <tt>null</tt> if these attributes are not code
- * attributes.
- * @param len the length of the bytecode of the method corresponding to these
- * code attributes, or <tt>null</tt> if these attributes are not code
- * attributes.
- * @param maxStack the maximum stack size of the method corresponding to these
- * code attributes, or -1 if these attributes are not code attributes.
- * @param maxLocals the maximum number of local variables of the method
- * corresponding to these code attributes, or -1 if these attributes are
- * not code attributes.
- * @param out where the attributes must be written.
- */
-
- final void put (
- final ClassWriter cw,
- final byte[] code,
- final int len,
- final int maxStack,
- final int maxLocals,
- final ByteVector out)
- {
- Attribute attr = this;
- while (attr != null) {
- ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
- out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
- out.putByteArray(b.data, 0, b.length);
- attr = attr.next;
- }
- }
-}
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- */
-
-package org.objectweb.asm;
-
-/**
- * A dynamically extensible vector of bytes. This class is roughly equivalent to
- * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
- */
-
-public class ByteVector {
-
- /**
- * The content of this vector.
- */
-
- byte[] data;
-
- /**
- * Actual number of bytes in this vector.
- */
-
- int length;
-
- /**
- * Constructs a new {@link ByteVector ByteVector} with a default initial size.
- */
-
- public ByteVector () {
- data = new byte[64];
- }
-
- /**
- * Constructs a new {@link ByteVector ByteVector} with the given initial size.
- *
- * @param initialSize the initial size of the byte vector to be constructed.
- */
-
- public ByteVector (final int initialSize) {
- data = new byte[initialSize];
- }
-
- /**
- * Puts a byte into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param b a byte.
- * @return this byte vector.
- */
-
- public ByteVector putByte (final int b) {
- int length = this.length;
- if (length + 1 > data.length) {
- enlarge(1);
- }
- data[length++] = (byte)b;
- this.length = length;
- return this;
- }
-
- /**
- * Puts two bytes into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param b1 a byte.
- * @param b2 another byte.
- * @return this byte vector.
- */
-
- ByteVector put11 (final int b1, final int b2) {
- int length = this.length;
- if (length + 2 > data.length) {
- enlarge(2);
- }
- byte[] data = this.data;
- data[length++] = (byte)b1;
- data[length++] = (byte)b2;
- this.length = length;
- return this;
- }
-
- /**
- * Puts a short into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param s a short.
- * @return this byte vector.
- */
-
- public ByteVector putShort (final int s) {
- int length = this.length;
- if (length + 2 > data.length) {
- enlarge(2);
- }
- byte[] data = this.data;
- data[length++] = (byte)(s >>> 8);
- data[length++] = (byte)s;
- this.length = length;
- return this;
- }
-
- /**
- * Puts a byte and a short into this byte vector. The byte vector is
- * automatically enlarged if necessary.
- *
- * @param b a byte.
- * @param s a short.
- * @return this byte vector.
- */
-
- ByteVector put12 (final int b, final int s) {
- int length = this.length;
- if (length + 3 > data.length) {
- enlarge(3);
- }
- byte[] data = this.data;
- data[length++] = (byte)b;
- data[length++] = (byte)(s >>> 8);
- data[length++] = (byte)s;
- this.length = length;
- return this;
- }
-
- /**
- * Puts an int into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param i an int.
- * @return this byte vector.
- */
-
- public ByteVector putInt (final int i) {
- int length = this.length;
- if (length + 4 > data.length) {
- enlarge(4);
- }
- byte[] data = this.data;
- data[length++] = (byte)(i >>> 24);
- data[length++] = (byte)(i >>> 16);
- data[length++] = (byte)(i >>> 8);
- data[length++] = (byte)i;
- this.length = length;
- return this;
- }
-
- /**
- * Puts a long into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param l a long.
- * @return this byte vector.
- */
-
- public ByteVector putLong (final long l) {
- int length = this.length;
- if (length + 8 > data.length) {
- enlarge(8);
- }
- byte[] data = this.data;
- int i = (int)(l >>> 32);
- data[length++] = (byte)(i >>> 24);
- data[length++] = (byte)(i >>> 16);
- data[length++] = (byte)(i >>> 8);
- data[length++] = (byte)i;
- i = (int)l;
- data[length++] = (byte)(i >>> 24);
- data[length++] = (byte)(i >>> 16);
- data[length++] = (byte)(i >>> 8);
- data[length++] = (byte)i;
- this.length = length;
- return this;
- }
-
- /**
- * Puts an UTF8 string into this byte vector. The byte vector is automatically
- * enlarged if necessary.
- *
- * @param s a String.
- * @return this byte vector.
- */
-
- public ByteVector putUTF8 (final String s) {
- int charLength = s.length();
- int byteLength = 0;
- for (int i = 0; i < charLength; ++i) {
- char c = s.charAt(i);
- if (c >= '\001' && c <= '\177') {
- byteLength++;
- } else if (c > '\u07FF') {
- byteLength += 3;
- } else {
- byteLength += 2;
- }
- }
- if (byteLength > 65535) {
- throw new IllegalArgumentException();
- }
- int length = this.length;
- if (length + 2 + byteLength > data.length) {
- enlarge(2 + byteLength);
- }
- byte[] data = this.data;
- data[length++] = (byte)(byteLength >>> 8);
- data[length++] = (byte)(byteLength);
- for (int i = 0; i < charLength; ++i) {
- char c = s.charAt(i);
- if (c >= '\001' && c <= '\177') {
- data[length++] = (byte)c;
- } else if (c > '\u07FF') {
- data[length++] = (byte)(0xE0 | c >> 12 & 0xF);
- data[length++] = (byte)(0x80 | c >> 6 & 0x3F);
- data[length++] = (byte)(0x80 | c & 0x3F);
- } else {
- data[length++] = (byte)(0xC0 | c >> 6 & 0x1F);
- data[length++] = (byte)(0x80 | c & 0x3F);
- }
- }
- this.length = length;
- return this;
- }
-
- /**
- * Puts an array of bytes into this byte vector. The byte vector is
- * automatically enlarged if necessary.
- *
- * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt> null
- * bytes into this byte vector.
- * @param off index of the fist byte of b that must be copied.
- * @param len number of bytes of b that must be copied.
- * @return this byte vector.
- */
-
- public ByteVector putByteArray (
- final byte[] b,
- final int off,
- final int len)
- {
- if (length + len > data.length) {
- enlarge(len);
- }
- if (b != null) {
- System.arraycopy(b, off, data, length, len);
- }
- length += len;
- return this;
- }
-
- /**
- * Enlarge this byte vector so that it can receive n more bytes.
- *
- * @param size number of additional bytes that this byte vector should be
- * able to receive.
- */
-
- private void enlarge (final int size) {
- int length1 = 2 * data.length;
- int length2 = length + size;
- byte[] newData = new byte[length1 > length2 ? length1 : length2];
- System.arraycopy(data, 0, newData, 0, length);
- data = newData;
- }
-}
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- */
-
-package org.objectweb.asm;
-
-/**
- * An empty {@link ClassVisitor ClassVisitor} that delegates to another {@link
- * ClassVisitor ClassVisitor}. This class can be used as a super class to
- * quickly implement usefull class adapter classes, just by overriding the
- * necessary methods.
- */
-
-public class ClassAdapter implements ClassVisitor {
-
- /**
- * The {@link ClassVisitor ClassVisitor} to which this adapter delegates
- * calls.
- */
-
- protected ClassVisitor cv;
-
- /**
- * Constructs a new {@link ClassAdapter ClassAdapter} object.
- *
- * @param cv the class visitor to which this adapter must delegate calls.
- */
-
- public ClassAdapter (final ClassVisitor cv) {
- this.cv = cv;
- }
-
- public void visit (
- final int access,
- final String name,
- final String superName,
- final String[] interfaces,
- final String sourceFile)
- {
- cv.visit(access, name, superName, interfaces, sourceFile);
- }
-
- public void visitInnerClass (
- final String name,
- final String outerName,
- final String innerName,
- final int access)
- {
- cv.visitInnerClass(name, outerName, innerName, access);
- }
-
- public void visitField (
- final int access,
- final String name,
- final String desc,
- final Object value,
- final Attribute attrs)
- {
- cv.visitField(access, name, desc, value, attrs);
- }
-
- public CodeVisitor visitMethod (
- final int access,
- final String name,
- final String desc,
- final String[] exceptions,
- final Attribute attrs)
- {
- return new CodeAdapter(cv.visitMethod(access, name, desc, exceptions, attrs));
- }
-
- public void visitAttribute (final Attribute attr) {
- cv.visitAttribute(attr);
- }
-
- public void visitEnd () {
- cv.visitEnd();
- }
-}
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- */
-
-package org.objectweb.asm;
-
-import java.io.InputStream;
-import java.io.IOException;
-
-/**
- * A Java class parser to make a {@link ClassVisitor ClassVisitor} visit an
- * existing class. This class parses a byte array conforming to the Java class
- * file format and calls the appropriate visit methods of a given class visitor
- * for each field, method and bytecode instruction encountered.
- */
-
-public class ClassReader {
-
- /**
- * The class to be parsed. <i>The content of this array must not be
- * modified. This field is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- */
-
- public final byte[] b;
-
- /**
- * The start index of each constant pool item in {@link #b b}, plus one. The
- * one byte offset skips the constant pool item tag that indicates its type.
- */
-
- private int[] items;
-
- /**
- * The String objects corresponding to the CONSTANT_Utf8 items. This cache
- * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item, which
- * GREATLY improves performances (by a factor 2 to 3). This caching strategy
- * could be extended to all constant pool items, but its benefit would not be
- * so great for these items (because they are much less expensive to parse
- * than CONSTANT_Utf8 items).
- */
-
- private String[] strings;
-
- /**
- * Maximum length of the strings contained in the constant pool of the class.
- */
-
- private int maxStringLength;
-
- /**
- * Start index of the class header information (access, name...) in {@link #b
- * b}.
- */
-
- private int header;
-
- // --------------------------------------------------------------------------
- // Constructors
- // --------------------------------------------------------------------------
-
- /**
- * Constructs a new {@link ClassReader ClassReader} object.
- *
- * @param b the bytecode of the class to be read.
- */
-
- public ClassReader (final byte[] b) {
- this(b, 0, b.length);
- }
-
- /**
- * Constructs a new {@link ClassReader ClassReader} object.
- *
- * @param b the bytecode of the class to be read.
- * @param off the start offset of the class data.
- * @param len the length of the class data.
- */
-
- public ClassReader (final byte[] b, final int off, final int len) {
- this.b = b;
- // parses the constant pool
- items = new int[readUnsignedShort(off + 8)];
- strings = new String[items.length];
- int max = 0;
- int index = off + 10;
- for (int i = 1; i < items.length; ++i) {
- items[i] = index + 1;
- int tag = b[index];
- int size;
- switch (tag) {
- case ClassWriter.FIELD:
- case ClassWriter.METH:
- case ClassWriter.IMETH:
- case ClassWriter.INT:
- case ClassWriter.FLOAT:
- case ClassWriter.NAME_TYPE:
- size = 5;
- break;
- case ClassWriter.LONG:
- case ClassWriter.DOUBLE:
- size = 9;
- ++i;
- break;
- case ClassWriter.UTF8:
- size = 3 + readUnsignedShort(index + 1);
- max = (size > max ? size : max);
- break;
- //case ClassWriter.CLASS:
- //case ClassWriter.STR:
- default:
- size = 3;
- break;
- }
- index += size;
- }
- maxStringLength = max;
- // the class header information starts just after the constant pool
- header = index;
- }
-
- /**
- * Constructs a new {@link ClassReader ClassReader} object.
- *
- * @param is an input stream from which to read the class.
- * @throws IOException if a problem occurs during reading.
- */
-
- public ClassReader (final InputStream is) throws IOException {
- this(readClass(is));
- }
-
- /**
- * Constructs a new {@link ClassReader ClassReader} object.
- *
- * @param name the fully qualified name of the class to be read.
- * @throws IOException if an exception occurs during reading.
- */
-
- public ClassReader (final String name) throws IOException {
- this((ClassReader.class.getClassLoader() == null
- ? ClassLoader.getSystemClassLoader()
- : ClassReader.class.getClassLoader())
- .getSystemResourceAsStream(name.replace('.','/') + ".class"));
- }
-
- /**
- * Reads the bytecode of a class.
- *
- * @param is an input stream from which to read the class.
- * @return the bytecode read from the given input stream.
- * @throws IOException if a problem occurs during reading.
- */
-
- private static byte[] readClass (final InputStream is) throws IOException {
- if (is == null) {
- throw new IOException("Class not found");
- }
- byte[] b = new byte[is.available()];
- int len = 0;
- while (true) {
- int n = is.read(b, len, b.length - len);
- if (n == -1) {
- if (len < b.length) {
- byte[] c = new byte[len];
- System.arraycopy(b, 0, c, 0, len);
- b = c;
- }
- return b;
- } else {
- len += n;
- if (len == b.length) {
- byte[] c = new byte[b.length + 1000];
- System.arraycopy(b, 0, c, 0, len);
- b = c;
- }
- }
- }
- }
-
- // --------------------------------------------------------------------------
- // Public methods
- // --------------------------------------------------------------------------
-
- /**
- * Returns the major and minor version numbers of this class.
- *
- * @return the <tt>int</tt> array { major version, minor version }
- */
-
- public int[] getVersion () {
- return new int[] { readShort(6), readShort(4) };
- }
-
- /**
- * Makes the given visitor visit the Java class of this {@link ClassReader
- * ClassReader}. This class is the one specified in the constructor (see
- * {@link #ClassReader ClassReader}).
- *
- * @param classVisitor the visitor that must visit this class.
- * @param skipDebug <tt>true</tt> if the debug information of the class must
- * not be visited. In this case the {@link CodeVisitor#visitLocalVariable
- * visitLocalVariable} and {@link CodeVisitor#visitLineNumber
- * visitLineNumber} methods will not be called.
- */
-
- public void accept (
- final ClassVisitor classVisitor,
- final boolean skipDebug)
- {
- accept(classVisitor, new Attribute[0], skipDebug);
- }
-
- /**
- * Makes the given visitor visit the Java class of this {@link ClassReader
- * ClassReader}. This class is the one specified in the constructor (see
- * {@link #ClassReader ClassReader}).
- *
- * @param classVisitor the visitor that must visit this class.
- * @param attrs prototypes of the attributes that must be parsed during the
- * visit of the class. Any attribute whose type is not equal to the type
- * of one the prototypes will be ignored.
- * @param skipDebug <tt>true</tt> if the debug information of the class must
- * not be visited. In this case the {@link CodeVisitor#visitLocalVariable
- * visitLocalVariable} and {@link CodeVisitor#visitLineNumber
- * visitLineNumber} methods will not be called.
- */
-
- public void accept (
- final ClassVisitor classVisitor,
- final Attribute[] attrs,
- final boolean skipDebug)
- {
- byte[] b = this.b; // the bytecode array
- char[] c = new char[maxStringLength]; // buffer used to read strings
- int i, j, k; // loop variables
- int u, v, w; // indexes in b
- Attribute attr;
-
- // visits the header
- u = header;
- int access = readUnsignedShort(u);
- String className = readClass(u + 2, c);
- v = items[readUnsignedShort(u + 4)];
- String superClassName = v == 0 ? null : readUTF8(v, c);
- String[] implementedItfs = new String[readUnsignedShort(u + 6)];
- String sourceFile = null;
- Attribute clattrs = null;
- w = 0;
- u += 8;
- for (i = 0; i < implementedItfs.length; ++i) {
- implementedItfs[i] = readClass(u, c); u += 2;
- }
- // skips fields and methods
- v = u;
- i = readUnsignedShort(v); v += 2;
- for ( ; i > 0; --i) {
- j = readUnsignedShort(v + 6);
- v += 8;
- for ( ; j > 0; --j) {
- v += 6 + readInt(v + 2);
- }
- }
- i = readUnsignedShort(v); v += 2;
- for ( ; i > 0; --i) {
- j = readUnsignedShort(v + 6);
- v += 8;
- for ( ; j > 0; --j) {
- v += 6 + readInt(v + 2);
- }
- }
- // reads the class's attributes
- i = readUnsignedShort(v); v += 2;
- for ( ; i > 0; --i) {
- String attrName = readUTF8(v, c);
- if (attrName.equals("SourceFile")) {
- sourceFile = readUTF8(v + 6, c);
- } else if (attrName.equals("Deprecated")) {
- access |= Constants.ACC_DEPRECATED;
- } else if (attrName.equals("InnerClasses")) {
- w = v + 6;
- } else {
- attr = readAttribute(
- attrs, attrName, v + 6, readInt(v + 2), c, -1, null);
- if (attr != null) {
- attr.next = clattrs;
- clattrs = attr;
- }
- }
- v += 6 + readInt(v + 2);
- }
- // calls the visit method
- classVisitor.visit(
- access, className, superClassName, implementedItfs, sourceFile);
-
- // visits the inner classes info
- if (w != 0) {
- i = readUnsignedShort(w); w += 2;
- for ( ; i > 0; --i) {
- classVisitor.visitInnerClass(
- readUnsignedShort(w) == 0 ? null : readClass(w, c),
- readUnsignedShort(w + 2) == 0 ? null : readClass(w + 2, c),
- readUnsignedShort(w + 4) == 0 ? null : readUTF8(w + 4, c),
- readUnsignedShort(w + 6));
- w += 8;
- }
- }
-
- // visits the fields
- i = readUnsignedShort(u); u += 2;
- for ( ; i > 0; --i) {
- access = readUnsignedShort(u);
- String fieldName = readUTF8(u + 2, c);
- String fieldDesc = readUTF8(u + 4, c);
- Attribute fattrs = null;
- // visits the field's attributes and looks for a ConstantValue attribute
- int fieldValueItem = 0;
- j = readUnsignedShort(u + 6);
- u += 8;
- for ( ; j > 0; --j) {
- String attrName = readUTF8(u, c);
- if (attrName.equals("ConstantValue")) {
- fieldValueItem = readUnsignedShort(u + 6);
- } else if (attrName.equals("Synthetic")) {
- access |= Constants.ACC_SYNTHETIC;
- } else if (attrName.equals("Deprecated")) {
- access |= Constants.ACC_DEPRECATED;
- } else {
- attr = readAttribute(
- attrs, attrName, u + 6, readInt(u + 2), c, -1, null);
- if (attr != null) {
- attr.next = fattrs;
- fattrs = attr;
- }
- }
- u += 6 + readInt(u + 2);
- }
- // reads the field's value, if any
- Object value = (fieldValueItem == 0 ? null : readConst(fieldValueItem, c));
- // visits the field
- classVisitor.visitField(access, fieldName, fieldDesc, value, fattrs);
- }
-
- // visits the methods
- i = readUnsignedShort(u); u += 2;
- for ( ; i > 0; --i) {
- access = readUnsignedShort(u);
- String methName = readUTF8(u + 2, c);
- String methDesc = readUTF8(u + 4, c);
- Attribute mattrs = null;
- Attribute cattrs = null;
- v = 0;
- w = 0;
- // looks for Code and Exceptions attributes
- j = readUnsignedShort(u + 6);
- u += 8;
- for ( ; j > 0; --j) {
- String attrName = readUTF8(u, c); u += 2;
- int attrSize = readInt(u); u += 4;
- if (attrName.equals("Code")) {
- v = u;
- } else if (attrName.equals("Exceptions")) {
- w = u;
- } else if (attrName.equals("Synthetic")) {
- access |= Constants.ACC_SYNTHETIC;
- } else if (attrName.equals("Deprecated")) {
- access |= Constants.ACC_DEPRECATED;
- } else {
- attr = readAttribute(attrs, attrName, u, attrSize, c, -1, null);
- if (attr != null) {
- attr.next = mattrs;
- mattrs = attr;
- }
- }
- u += attrSize;
- }
- // reads declared exceptions
- String[] exceptions;
- if (w == 0) {
- exceptions = null;
- } else {
- exceptions = new String[readUnsignedShort(w)]; w += 2;
- for (j = 0; j < exceptions.length; ++j) {
- exceptions[j] = readClass(w, c); w += 2;
- }
- }
-
- // visits the method's code, if any
- CodeVisitor cv;
- cv = classVisitor.visitMethod(
- access, methName, methDesc, exceptions, mattrs);
- if (cv != null && v != 0) {
- int maxStack = readUnsignedShort(v);
- int maxLocals = readUnsignedShort(v + 2);
- int codeLength = readInt(v + 4);
- v += 8;
-
- int codeStart = v;
- int codeEnd = v + codeLength;
-
- // 1st phase: finds the labels
- int label;
- Label[] labels = new Label[codeLength + 1];
- while (v < codeEnd) {
- int opcode = b[v] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- v += 1;
- break;
- case ClassWriter.LABEL_INSN:
- label = v - codeStart + readShort(v + 1);
- if (labels[label] == null) {
- labels[label] = new Label();
- }
- v += 3;
- break;
- case ClassWriter.LABELW_INSN:
- label = v - codeStart + readInt(v + 1);
- if (labels[label] == null) {
- labels[label] = new Label();
- }
- v += 5;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[v + 1] & 0xFF;
- if (opcode == Constants.IINC) {
- v += 6;
- } else {
- v += 4;
- }
- break;
- case ClassWriter.TABL_INSN:
- // skips 0 to 3 padding bytes
- w = v - codeStart;
- v = v + 4 - (w & 3);
- // reads instruction
- label = w + readInt(v); v += 4;
- if (labels[label] == null) {
- labels[label] = new Label();
- }
- j = readInt(v); v += 4;
- j = readInt(v) - j + 1; v += 4;
- for ( ; j > 0; --j) {
- label = w + readInt(v); v += 4;
- if (labels[label] == null) {
- labels[label] = new Label();
- }
- }
- break;
- case ClassWriter.LOOK_INSN:
- // skips 0 to 3 padding bytes
- w = v - codeStart;
- v = v + 4 - (w & 3);
- // reads instruction
- label = w + readInt(v); v += 4;
- if (labels[label] == null) {
- labels[label] = new Label();
- }
- j = readInt(v); v += 4;
- for ( ; j > 0; --j) {
- v += 4; // skips key
- label = w + readInt(v); v += 4;
- if (labels[label] == null) {
- labels[label] = new Label();
- }
- }
- break;
- case ClassWriter.VAR_INSN:
- case ClassWriter.SBYTE_INSN:
- case ClassWriter.LDC_INSN:
- v += 2;
- break;
- case ClassWriter.SHORT_INSN:
- case ClassWriter.LDCW_INSN:
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.TYPE_INSN:
- case ClassWriter.IINC_INSN:
- v += 3;
- break;
- case ClassWriter.ITFMETH_INSN:
- v += 5;
- break;
- // case MANA_INSN:
- default:
- v += 4;
- break;
- }
- }
- // parses the try catch entries
- j = readUnsignedShort(v); v += 2;
- for ( ; j > 0; --j) {
- label = readUnsignedShort(v);
- if (labels[label] == null) {
- labels[label] = new Label();
- }
- label = readUnsignedShort(v + 2);
- if (labels[label] == null) {
- labels[label] = new Label();
- }
- label = readUnsignedShort(v + 4);
- if (labels[label] == null) {
- labels[label] = new Label();
- }
- v += 8;
- }
- // parses the local variable, line number tables, and code attributes
- j = readUnsignedShort(v); v += 2;
- for ( ; j > 0; --j) {
- String attrName = readUTF8(v, c);
- if (attrName.equals("LocalVariableTable")) {
- if (!skipDebug) {
- k = readUnsignedShort(v + 6);
- w = v + 8;
- for ( ; k > 0; --k) {
- label = readUnsignedShort(w);
- if (labels[label] == null) {
- labels[label] = new Label();
- }
- label += readUnsignedShort(w + 2);
- if (labels[label] == null) {
- labels[label] = new Label();
- }
- w += 10;
- }
- }
- } else if (attrName.equals("LineNumberTable")) {
- if (!skipDebug) {
- k = readUnsignedShort(v + 6);
- w = v + 8;
- for ( ; k > 0; --k) {
- label = readUnsignedShort(w);
- if (labels[label] == null) {
- labels[label] = new Label();
- }
- w += 4;
- }
- }
- } else {
- for (k = 0; k < attrs.length; ++k) {
- if (attrs[k].type.equals(attrName)) {
- attr = attrs[k].read(
- this, v + 6, readInt(v + 2), c, codeStart - 8, labels);
- if (attr != null) {
- attr.next = cattrs;
- cattrs = attr;
- }
- }
- }
- }
- v += 6 + readInt(v + 2);
- }
-
- // 2nd phase: visits each instruction
- v = codeStart;
- Label l;
- while (v < codeEnd) {
- w = v - codeStart;
- l = labels[w];
- if (l != null) {
- cv.visitLabel(l);
- }
- int opcode = b[v] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- cv.visitInsn(opcode);
- v += 1;
- break;
- case ClassWriter.IMPLVAR_INSN:
- if (opcode > Constants.ISTORE) {
- opcode -= 59; //ISTORE_0
- cv.visitVarInsn(Constants.ISTORE + (opcode >> 2), opcode & 0x3);
- } else {
- opcode -= 26; //ILOAD_0
- cv.visitVarInsn(Constants.ILOAD + (opcode >> 2), opcode & 0x3);
- }
- v += 1;
- break;
- case ClassWriter.LABEL_INSN:
- cv.visitJumpInsn(opcode, labels[w + readShort(v + 1)]);
- v += 3;
- break;
- case ClassWriter.LABELW_INSN:
- cv.visitJumpInsn(opcode, labels[w + readInt(v + 1)]);
- v += 5;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[v + 1] & 0xFF;
- if (opcode == Constants.IINC) {
- cv.visitIincInsn(readUnsignedShort(v + 2), readShort(v + 4));
- v += 6;
- } else {
- cv.visitVarInsn(opcode, readUnsignedShort(v + 2));
- v += 4;
- }
- break;
- case ClassWriter.TABL_INSN:
- // skips 0 to 3 padding bytes
- v = v + 4 - (w & 3);
- // reads instruction
- label = w + readInt(v); v += 4;
- int min = readInt(v); v += 4;
- int max = readInt(v); v += 4;
- Label[] table = new Label[max - min + 1];
- for (j = 0; j < table.length; ++j) {
- table[j] = labels[w + readInt(v)];
- v += 4;
- }
- cv.visitTableSwitchInsn(min, max, labels[label], table);
- break;
- case ClassWriter.LOOK_INSN:
- // skips 0 to 3 padding bytes
- v = v + 4 - (w & 3);
- // reads instruction
- label = w + readInt(v); v += 4;
- j = readInt(v); v += 4;
- int[] keys = new int[j];
- Label[] values = new Label[j];
- for (j = 0; j < keys.length; ++j) {
- keys[j] = readInt(v); v += 4;
- values[j] = labels[w + readInt(v)]; v += 4;
- }
- cv.visitLookupSwitchInsn(labels[label], keys, values);
- break;
- case ClassWriter.VAR_INSN:
- cv.visitVarInsn(opcode, b[v + 1] & 0xFF);
- v += 2;
- break;
- case ClassWriter.SBYTE_INSN:
- cv.visitIntInsn(opcode, b[v + 1]);
- v += 2;
- break;
- case ClassWriter.SHORT_INSN:
- cv.visitIntInsn(opcode, readShort(v + 1));
- v += 3;
- break;
- case ClassWriter.LDC_INSN:
- cv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
- v += 2;
- break;
- case ClassWriter.LDCW_INSN:
- cv.visitLdcInsn(readConst(readUnsignedShort(v + 1), c));
- v += 3;
- break;
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.ITFMETH_INSN:
- int cpIndex = items[readUnsignedShort(v + 1)];
- String iowner = readClass(cpIndex, c);
- cpIndex = items[readUnsignedShort(cpIndex + 2)];
- String iname = readUTF8(cpIndex, c);
- String idesc = readUTF8(cpIndex + 2, c);
- if (opcode < Constants.INVOKEVIRTUAL) {
- cv.visitFieldInsn(opcode, iowner, iname, idesc);
- } else {
- cv.visitMethodInsn(opcode, iowner, iname, idesc);
- }
- if (opcode == Constants.INVOKEINTERFACE) {
- v += 5;
- } else {
- v += 3;
- }
- break;
- case ClassWriter.TYPE_INSN:
- cv.visitTypeInsn(opcode, readClass(v + 1, c));
- v += 3;
- break;
- case ClassWriter.IINC_INSN:
- cv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
- v += 3;
- break;
- // case MANA_INSN:
- default:
- cv.visitMultiANewArrayInsn(readClass(v + 1, c), b[v + 3] & 0xFF);
- v += 4;
- break;
- }
- }
- l = labels[codeEnd - codeStart];
- if (l != null) {
- cv.visitLabel(l);
- }
- // visits the try catch entries
- j = readUnsignedShort(v); v += 2;
- for ( ; j > 0; --j) {
- Label start = labels[readUnsignedShort(v)];
- Label end = labels[readUnsignedShort(v + 2)];
- Label handler = labels[readUnsignedShort(v + 4)];
- int type = readUnsignedShort(v + 6);
- if (type == 0) {
- cv.visitTryCatchBlock(start, end, handler, null);
- } else {
- cv.visitTryCatchBlock(start, end, handler, readUTF8(items[type], c));
- }
- v += 8;
- }
- // visits the local variable and line number tables
- j = readUnsignedShort(v); v += 2;
- if (!skipDebug) {
- for ( ; j > 0; --j) {
- String attrName = readUTF8(v, c);
- if (attrName.equals("LocalVariableTable")) {
- k = readUnsignedShort(v + 6);
- w = v + 8;
- for ( ; k > 0; --k) {
- label = readUnsignedShort(w);
- Label start = labels[label];
- label += readUnsignedShort(w + 2);
- Label end = labels[label];
- cv.visitLocalVariable(
- readUTF8(w + 4, c),
- readUTF8(w + 6, c),
- start,
- end,
- readUnsignedShort(w + 8));
- w += 10;
- }
- } else if (attrName.equals("LineNumberTable")) {
- k = readUnsignedShort(v + 6);
- w = v + 8;
- for ( ; k > 0; --k) {
- cv.visitLineNumber(
- readUnsignedShort(w + 2),
- labels[readUnsignedShort(w)]);
- w += 4;
- }
- }
- v += 6 + readInt(v + 2);
- }
- }
- // visits the other attributes
- while (cattrs != null) {
- attr = cattrs.next;
- cattrs.next = null;
- cv.visitAttribute(cattrs);
- cattrs = attr;
- }
- // visits the max stack and max locals values
- cv.visitMaxs(maxStack, maxLocals);
- }
- }
- // visits the class attributes
- while (clattrs != null) {
- classVisitor.visitAttribute(clattrs);
- clattrs = clattrs.next;
- }
- // visits the end of the class
- classVisitor.visitEnd();
- }
-
- // --------------------------------------------------------------------------
- // Utility methods: low level parsing
- // --------------------------------------------------------------------------
-
- /**
- * Reads a byte value in {@link #b b}. <i>This method is intended
- * for {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
-
- public int readByte (final int index) {
- return b[index] & 0xFF;
- }
-
- /**
- * Reads an unsigned short value in {@link #b b}. <i>This method is intended
- * for {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
-
- public int readUnsignedShort (final int index) {
- byte[] b = this.b;
- return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
- }
-
- /**
- * Reads a signed short value in {@link #b b}. <i>This method is intended
- * for {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
-
- public short readShort (final int index) {
- byte[] b = this.b;
- return (short)(((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
- }
-
- /**
- * Reads a signed int value in {@link #b b}. <i>This method is intended
- * for {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
-
- public int readInt (final int index) {
- byte[] b = this.b;
- return ((b[index] & 0xFF) << 24) |
- ((b[index + 1] & 0xFF) << 16) |
- ((b[index + 2] & 0xFF) << 8) |
- (b[index + 3] & 0xFF);
- }
-
- /**
- * Reads a signed long value in {@link #b b}. <i>This method is intended
- * for {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @param index the start index of the value to be read in {@link #b b}.
- * @return the read value.
- */
-
- public long readLong (final int index) {
- long l1 = readInt(index);
- long l0 = readInt(index + 4) & 0xFFFFFFFFL;
- return (l1 << 32) | l0;
- }
-
- /**
- * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method is
- * intended for {@link Attribute} sub classes, and is normally not needed by
- * class generators or adapters.</i>
- *
- * @param index the start index of an unsigned short value in {@link #b b},
- * whose value is the index of an UTF8 constant pool item.
- * @param buf buffer to be used to read the item. This buffer must be
- * sufficiently large. It is not automatically resized.
- * @return the String corresponding to the specified UTF8 item.
- */
-
- public String readUTF8 (int index, final char[] buf) {
- // consults cache
- int item = readUnsignedShort(index);
- String s = strings[item];
- if (s != null) {
- return s;
- }
- // computes the start index of the CONSTANT_Utf8 item in b
- index = items[item];
- // reads the length of the string (in bytes, not characters)
- int utfLen = readUnsignedShort(index);
- index += 2;
- // parses the string bytes
- int endIndex = index + utfLen;
- byte[] b = this.b;
- int strLen = 0;
- int c, d, e;
- while (index < endIndex) {
- c = b[index++] & 0xFF;
- switch (c >> 4) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- // 0xxxxxxx
- buf[strLen++] = (char)c;
- break;
- case 12:
- case 13:
- // 110x xxxx 10xx xxxx
- d = b[index++];
- buf[strLen++] = (char)(((c & 0x1F) << 6) | (d & 0x3F));
- break;
- default:
- // 1110 xxxx 10xx xxxx 10xx xxxx
- d = b[index++];
- e = b[index++];
- buf[strLen++] =
- (char)(((c & 0x0F) << 12) | ((d & 0x3F) << 6) | (e & 0x3F));
- break;
- }
- }
- s = new String(buf, 0, strLen);
- strings[item] = s;
- return s;
- }
-
- /**
- * Reads a class constant pool item in {@link #b b}. <i>This method is
- * intended for {@link Attribute} sub classes, and is normally not needed by
- * class generators or adapters.</i>
- *
- * @param index the start index of an unsigned short value in {@link #b b},
- * whose value is the index of a class constant pool item.
- * @param buf buffer to be used to read the item. This buffer must be
- * sufficiently large. It is not automatically resized.
- * @return the String corresponding to the specified class item.
- */
-
- public String readClass (final int index, final char[] buf) {
- // computes the start index of the CONSTANT_Class item in b
- // and reads the CONSTANT_Utf8 item designated by
- // the first two bytes of this CONSTANT_Class item
- return readUTF8(items[readUnsignedShort(index)], buf);
- }
-
- /**
- * Reads a numeric or string constant pool item in {@link #b b}. <i>This
- * method is intended for {@link Attribute} sub classes, and is normally not
- * needed by class generators or adapters.</i>
- *
- * @param item the index of a constant pool item.
- * @param buf buffer to be used to read the item. This buffer must be
- * sufficiently large. It is not automatically resized.
- * @return the {@link java.lang.Integer Integer}, {@link java.lang.Float
- * Float}, {@link java.lang.Long Long}, {@link java.lang.Double Double}
- * or {@link String String} corresponding to the given constant pool
- * item.
- */
-
- public Object readConst (final int item, final char[] buf) {
- int index = items[item];
- switch (b[index - 1]) {
- case ClassWriter.INT:
- return new Integer(readInt(index));
- case ClassWriter.FLOAT:
- return new Float(Float.intBitsToFloat(readInt(index)));
- case ClassWriter.LONG:
- return new Long(readLong(index));
- case ClassWriter.DOUBLE:
- return new Double(Double.longBitsToDouble(readLong(index)));
- //case ClassWriter.STR:
- default:
- return readUTF8(index, buf);
- }
- }
-
- /**
- * Reads an attribute in {@link #b b}. The default implementation of this
- * method returns <tt>null</tt> for all attributes.
- *
- * @param attrs prototypes of the attributes that must be parsed during the
- * visit of the class. Any attribute whose type is not equal to the type
- * of one the prototypes will be ignored.
- * @param type the type of the attribute.
- * @param off index of the first byte of the attribute's content in {@link #b
- * b}. The 6 attribute header bytes, containing the type and the length
- * of the attribute, are not taken into account here (they have already
- * been read).
- * @param len the length of the attribute's content.
- * @param buf buffer to be used to call {@link #readUTF8 readUTF8}, {@link
- * #readClass readClass} or {@link #readConst readConst}.
- * @param codeOff index of the first byte of code's attribute content in
- * {@link #b b}, or -1 if the attribute to be read is not a code
- * attribute. The 6 attribute header bytes, containing the type and the
- * length of the attribute, are not taken into account here.
- * @param labels the labels of the method's code, or <tt>null</tt> if the
- * attribute to be read is not a code attribute.
- * @return the attribute that has been read, or <tt>null</tt> to skip this
- * attribute.
- */
-
- protected Attribute readAttribute (
- final Attribute[] attrs,
- final String type,
- final int off,
- final int len,
- final char[] buf,
- final int codeOff,
- final Label[] labels)
- {
- for (int i = 0; i < attrs.length; ++i) {
- if (attrs[i].type.equals(type)) {
- return attrs[i].read(this, off, len, buf, codeOff, labels);
- }
- }
- return null;
- }
-}
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- */
-
-package org.objectweb.asm;
-
-/**
- * A visitor to visit a Java class. The methods of this interface must be called
- * in the following order: <tt>visit</tt> (<tt>visitField</tt> |
- * <tt>visitMethod</tt> | <tt>visitInnerClass</tt> | <tt>visitAttribute</tt>)*
- * <tt>visitEnd</tt>.
- */
-
-public interface ClassVisitor {
-
- /**
- * Visits the header of the class.
- *
- * @param access the class's access flags (see {@link Constants}). This
- * parameter also indicates if the class is deprecated.
- * @param name the internal name of the class (see {@link Type#getInternalName
- * getInternalName}).
- * @param superName the internal of name of the super class (see {@link
- * Type#getInternalName getInternalName}). For interfaces, the super
- * class is {@link Object}. May be <tt>null</tt>, but only for the {@link
- * Object java.lang.Object} class.
- * @param interfaces the internal names of the class's interfaces (see {@link
- * Type#getInternalName getInternalName}). May be <tt>null</tt>.
- * @param sourceFile the name of the source file from which this class was
- * compiled. May be <tt>null</tt>.
- */
-
- void visit (
- int access,
- String name,
- String superName,
- String[] interfaces,
- String sourceFile);
-
- /**
- * Visits information about an inner class. This inner class is not
- * necessarily a member of the class being visited.
- *
- * @param name the internal name of an inner class (see {@link
- * Type#getInternalName getInternalName}).
- * @param outerName the internal name of the class to which the inner class
- * belongs (see {@link Type#getInternalName getInternalName}). May be
- * <tt>null</tt>.
- * @param innerName the (simple) name of the inner class inside its enclosing
- * class. May be <tt>null</tt> for anonymous inner classes.
- * @param access the access flags of the inner class as originally declared
- * in the enclosing class.
- */
-
- void visitInnerClass (
- String name,
- String outerName,
- String innerName,
- int access);
-
- /**
- * Visits a field of the class.
- *
- * @param access the field's access flags (see {@link Constants}). This
- * parameter also indicates if the field is synthetic and/or deprecated.
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link Type Type}).
- * @param value the field's initial value. This parameter, which may be
- * <tt>null</tt> if the field does not have an initial value, must be an
- * {@link java.lang.Integer Integer}, a {@link java.lang.Float Float}, a
- * {@link java.lang.Long Long}, a {@link java.lang.Double Double} or a
- * {@link String String}. <i>This parameter is only used for static
- * fields</i>. Its value is ignored for non static fields, which must be
- * initialized through bytecode instructions in constructors or methods.
- * @param attrs the non standard method attributes, linked together by their
- * <tt>next</tt> field. May be <tt>null</tt>.
- */
-
- void visitField (
- int access,
- String name,
- String desc,
- Object value,
- Attribute attrs);
-
- /**
- * Visits a method of the class. This method <i>must</i> return a new
- * {@link CodeVisitor CodeVisitor} instance (or <tt>null</tt>) each time it
- * is called, i.e., it should not return a previously returned visitor.
- *
- * @param access the method's access flags (see {@link Constants}). This
- * parameter also indicates if the method is synthetic and/or deprecated.
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type Type}).
- * @param exceptions the internal names of the method's exception
- * classes (see {@link Type#getInternalName getInternalName}). May be
- * <tt>null</tt>.
- * @param attrs the non standard method attributes, linked together by their
- * <tt>next</tt> field. May be <tt>null</tt>.
- * @return an object to visit the byte code of the method, or <tt>null</tt> if
- * this class visitor is not interested in visiting the code of this
- * method.
- */
-
- CodeVisitor visitMethod (
- int access,
- String name,
- String desc,
- String[] exceptions,
- Attribute attrs);
-
- /**
- * Visits a non standard attribute of the class. This method must visit only
- * the first attribute in the given attribute list.
- *
- * @param attr a non standard class attribute. Must not be <tt>null</tt>.
- */
-
- void visitAttribute (Attribute attr);
-
- /**
- * Visits the end of the class. This method, which is the last one to be
- * called, is used to inform the visitor that all the fields and methods of
- * the class have been visited.
- */
-
- void visitEnd ();
-}
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- */
-
-package org.objectweb.asm;
-
-/**
- * A {@link ClassVisitor ClassVisitor} that generates Java class files. More
- * precisely this visitor generates a byte array conforming to the Java class
- * file format. It can be used alone, to generate a Java class "from scratch",
- * or with one or more {@link ClassReader ClassReader} and adapter class
- * visitor to generate a modified class from one or more existing Java classes.
- */
-
-public class ClassWriter implements ClassVisitor {
-
- /**
- * The type of CONSTANT_Class constant pool items.
- */
-
- final static int CLASS = 7;
-
- /**
- * The type of CONSTANT_Fieldref constant pool items.
- */
-
- final static int FIELD = 9;
-
- /**
- * The type of CONSTANT_Methodref constant pool items.
- */
-
- final static int METH = 10;
-
- /**
- * The type of CONSTANT_InterfaceMethodref constant pool items.
- */
-
- final static int IMETH = 11;
-
- /**
- * The type of CONSTANT_String constant pool items.
- */
-
- final static int STR = 8;
-
- /**
- * The type of CONSTANT_Integer constant pool items.
- */
-
- final static int INT = 3;
-
- /**
- * The type of CONSTANT_Float constant pool items.
- */
-
- final static int FLOAT = 4;
-
- /**
- * The type of CONSTANT_Long constant pool items.
- */
-
- final static int LONG = 5;
-
- /**
- * The type of CONSTANT_Double constant pool items.
- */
-
- final static int DOUBLE = 6;
-
- /**
- * The type of CONSTANT_NameAndType constant pool items.
- */
-
- final static int NAME_TYPE = 12;
-
- /**
- * The type of CONSTANT_Utf8 constant pool items.
- */
-
- final static int UTF8 = 1;
-
- /**
- * Minor and major version numbers of the class to be generated.
- */
-
- private int version;
-
- /**
- * Index of the next item to be added in the constant pool.
- */
-
- private short index;
-
- /**
- * The constant pool of this class.
- */
-
- private ByteVector pool;
-
- /**
- * The constant pool's hash table data.
- */
-
- private Item[] items;
-
- /**
- * The threshold of the constant pool's hash table.
- */
-
- private int threshold;
-
- /**
- * The access flags of this class.
- */
-
- private int access;
-
- /**
- * The constant pool item that contains the internal name of this class.
- */
-
- private int name;
-
- /**
- * The constant pool item that contains the internal name of the super class
- * of this class.
- */
-
- private int superName;
-
- /**
- * Number of interfaces implemented or extended by this class or interface.
- */
-
- private int interfaceCount;
-
- /**
- * The interfaces implemented or extended by this class or interface. More
- * precisely, this array contains the indexes of the constant pool items
- * that contain the internal names of these interfaces.
- */
-
- private int[] interfaces;
-
- /**
- * The index of the constant pool item that contains the name of the source
- * file from which this class was compiled.
- */
-
- private int sourceFile;
-
- /**
- * Number of fields of this class.
- */
-
- private int fieldCount;
-
- /**
- * The fields of this class.
- */
-
- private ByteVector fields;
-
- /**
- * <tt>true</tt> if the maximum stack size and number of local variables must
- * be automatically computed.
- */
-
- private boolean computeMaxs;
-
- /**
- * The methods of this class. These methods are stored in a linked list of
- * {@link CodeWriter CodeWriter} objects, linked to each other by their {@link
- * CodeWriter#next} field. This field stores the first element of this list.
- */
-
- CodeWriter firstMethod;
-
- /**
- * The methods of this class. These methods are stored in a linked list of
- * {@link CodeWriter CodeWriter} objects, linked to each other by their {@link
- * CodeWriter#next} field. This field stores the last element of this list.
- */
-
- CodeWriter lastMethod;
-
- /**
- * The number of entries in the InnerClasses attribute.
- */
-
- private int innerClassesCount;
-
- /**
- * The InnerClasses attribute.
- */
-
- private ByteVector innerClasses;
-
- /**
- * The non standard attributes of the class.
- */
-
- private Attribute attrs;
-
- /**
- * A reusable key used to look for items in the hash {@link #items items}.
- */
-
- Item key;
-
- /**
- * A reusable key used to look for items in the hash {@link #items items}.
- */
-
- Item key2;
-
- /**
- * A reusable key used to look for items in the hash {@link #items items}.
- */
-
- Item key3;
-
- /**
- * The type of instructions without any label.
- */
-
- final static int NOARG_INSN = 0;
-
- /**
- * The type of instructions with an signed byte label.
- */
-
- final static int SBYTE_INSN = 1;
-
- /**
- * The type of instructions with an signed short label.
- */
-
- final static int SHORT_INSN = 2;
-
- /**
- * The type of instructions with a local variable index label.
- */
-
- final static int VAR_INSN = 3;
-
- /**
- * The type of instructions with an implicit local variable index label.
- */
-
- final static int IMPLVAR_INSN = 4;
-
- /**
- * The type of instructions with a type descriptor argument.
- */
-
- final static int TYPE_INSN = 5;
-
- /**
- * The type of field and method invocations instructions.
- */
-
- final static int FIELDORMETH_INSN = 6;
-
- /**
- * The type of the INVOKEINTERFACE instruction.
- */
-
- final static int ITFMETH_INSN = 7;
-
- /**
- * The type of instructions with a 2 bytes bytecode offset label.
- */
-
- final static int LABEL_INSN = 8;
-
- /**
- * The type of instructions with a 4 bytes bytecode offset label.
- */
-
- final static int LABELW_INSN = 9;
-
- /**
- * The type of the LDC instruction.
- */
-
- final static int LDC_INSN = 10;
-
- /**
- * The type of the LDC_W and LDC2_W instructions.
- */
-
- final static int LDCW_INSN = 11;
-
- /**
- * The type of the IINC instruction.
- */
-
- final static int IINC_INSN = 12;
-
- /**
- * The type of the TABLESWITCH instruction.
- */
-
- final static int TABL_INSN = 13;
-
- /**
- * The type of the LOOKUPSWITCH instruction.
- */
-
- final static int LOOK_INSN = 14;
-
- /**
- * The type of the MULTIANEWARRAY instruction.
- */
-
- final static int MANA_INSN = 15;
-
- /**
- * The type of the WIDE instruction.
- */
-
- final static int WIDE_INSN = 16;
-
- /**
- * The instruction types of all JVM opcodes.
- */
-
- static byte[] TYPE;
-
- // --------------------------------------------------------------------------
- // Static initializer
- // --------------------------------------------------------------------------
-
- /**
- * Computes the instruction types of JVM opcodes.
- */
-
- static {
- int i;
- byte[] b = new byte[220];
- String s =
- "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADDDDDEEEEEEEEE" +
- "EEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAA" +
- "AAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAAAAAAGGGGGGGHAFBFAAFFAAQPIIJJII" +
- "IIIIIIIIIIIIIIII";
- for (i = 0; i < b.length; ++i) {
- b[i] = (byte)(s.charAt(i) - 'A');
- }
- TYPE = b;
-
- /* code to generate the above string
-
- // SBYTE_INSN instructions
- b[Constants.NEWARRAY] = SBYTE_INSN;
- b[Constants.BIPUSH] = SBYTE_INSN;
-
- // SHORT_INSN instructions
- b[Constants.SIPUSH] = SHORT_INSN;
-
- // (IMPL)VAR_INSN instructions
- b[Constants.RET] = VAR_INSN;
- for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
- b[i] = VAR_INSN;
- }
- for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
- b[i] = VAR_INSN;
- }
- for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
- b[i] = IMPLVAR_INSN;
- }
- for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
- b[i] = IMPLVAR_INSN;
- }
-
- // TYPE_INSN instructions
- b[Constants.NEW] = TYPE_INSN;
- b[Constants.ANEWARRAY] = TYPE_INSN;
- b[Constants.CHECKCAST] = TYPE_INSN;
- b[Constants.INSTANCEOF] = TYPE_INSN;
-
- // (Set)FIELDORMETH_INSN instructions
- for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
- b[i] = FIELDORMETH_INSN;
- }
- b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
-
- // LABEL(W)_INSN instructions
- for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
- b[i] = LABEL_INSN;
- }
- b[Constants.IFNULL] = LABEL_INSN;
- b[Constants.IFNONNULL] = LABEL_INSN;
- b[200] = LABELW_INSN; // GOTO_W
- b[201] = LABELW_INSN; // JSR_W
- // temporary opcodes used internally by ASM - see Label and CodeWriter
- for (i = 202; i < 220; ++i) {
- b[i] = LABEL_INSN;
- }
-
- // LDC(_W) instructions
- b[Constants.LDC] = LDC_INSN;
- b[19] = LDCW_INSN; // LDC_W
- b[20] = LDCW_INSN; // LDC2_W
-
- // special instructions
- b[Constants.IINC] = IINC_INSN;
- b[Constants.TABLESWITCH] = TABL_INSN;
- b[Constants.LOOKUPSWITCH] = LOOK_INSN;
- b[Constants.MULTIANEWARRAY] = MANA_INSN;
- b[196] = WIDE_INSN; // WIDE
-
- for (i = 0; i < b.length; ++i) {
- System.err.print((char)('A' + b[i]));
- }
- System.err.println();
- */
- }
-
- // --------------------------------------------------------------------------
- // Constructor
- // --------------------------------------------------------------------------
-
- /**
- * Constructs a new {@link ClassWriter ClassWriter} object.
- *
- * @param computeMaxs <tt>true</tt> if the maximum stack size and the maximum
- * number of local variables must be automatically computed. If this flag
- * is <tt>true</tt>, then the arguments of the {@link
- * CodeVisitor#visitMaxs visitMaxs} method of the {@link CodeVisitor
- * CodeVisitor} returned by the {@link #visitMethod visitMethod} method
- * will be ignored, and computed automatically from the signature and
- * the bytecode of each method.
- */
-
- public ClassWriter (final boolean computeMaxs) {
- this(computeMaxs, 45, 3);
- }
-
- /**
- * Constructs a new {@link ClassWriter ClassWriter} object.
- *
- * @param computeMaxs <tt>true</tt> if the maximum stack size and the maximum
- * number of local variables must be automatically computed. If this flag
- * is <tt>true</tt>, then the arguments of the {@link
- * CodeVisitor#visitMaxs visitMaxs} method of the {@link CodeVisitor
- * CodeVisitor} returned by the {@link #visitMethod visitMethod} method
- * will be ignored, and computed automatically from the signature and
- * the bytecode of each method.
- * @param major the major version of the class to be generated.
- * @param minor the minor version of the class to be generated.
- */
-
- public ClassWriter (final boolean computeMaxs, final int major, final int minor) {
- index = 1;
- pool = new ByteVector();
- items = new Item[64];
- threshold = (int)(0.75d*items.length);
- key = new Item();
- key2 = new Item();
- key3 = new Item();
- this.computeMaxs = computeMaxs;
- this.version = minor << 16 | major;
- }
-
- // --------------------------------------------------------------------------
- // Implementation of the ClassVisitor interface
- // --------------------------------------------------------------------------
-
- public void visit (
- final int access,
- final String name,
- final String superName,
- final String[] interfaces,
- final String sourceFile)
- {
- this.access = access;
- this.name = newClass(name);
- this.superName = superName == null ? 0 : newClass(superName);
- if (interfaces != null && interfaces.length > 0) {
- interfaceCount = interfaces.length;
- this.interfaces = new int[interfaceCount];
- for (int i = 0; i < interfaceCount; ++i) {
- this.interfaces[i] = newClass(interfaces[i]);
- }
- }
- if (sourceFile != null) {
- newUTF8("SourceFile");
- this.sourceFile = newUTF8(sourceFile);
- }
- if ((access & Constants.ACC_DEPRECATED) != 0) {
- newUTF8("Deprecated");
- }
- }
-
- public void visitInnerClass (
- final String name,
- final String outerName,
- final String innerName,
- final int access)
- {
- if (innerClasses == null) {
- newUTF8("InnerClasses");
- innerClasses = new ByteVector();
- }
- ++innerClassesCount;
- innerClasses.putShort(name == null ? 0 : newClass(name));
- innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
- innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
- innerClasses.putShort(access);
- }
-
- public void visitField (
- final int access,
- final String name,
- final String desc,
- final Object value,
- final Attribute attrs)
- {
- ++fieldCount;
- if (fields == null) {
- fields = new ByteVector();
- }
- fields.putShort(access).putShort(newUTF8(name)).putShort(newUTF8(desc));
- int attributeCount = 0;
- if (value != null) {
- ++attributeCount;
- }
- if ((access & Constants.ACC_SYNTHETIC) != 0) {
- ++attributeCount;
- }
- if ((access & Constants.ACC_DEPRECATED) != 0) {
- ++attributeCount;
- }
- if (attrs != null) {
- attributeCount += attrs.getCount();
- }
- fields.putShort(attributeCount);
- if (value != null) {
- fields.putShort(newUTF8("ConstantValue"));
- fields.putInt(2).putShort(newCst(value).index);
- }
- if ((access & Constants.ACC_SYNTHETIC) != 0) {
- fields.putShort(newUTF8("Synthetic")).putInt(0);
- }
- if ((access & Constants.ACC_DEPRECATED) != 0) {
- fields.putShort(newUTF8("Deprecated")).putInt(0);
- }
- if (attrs != null) {
- attrs.getSize(this, null, 0, -1, -1);
- attrs.put(this, null, 0, -1, -1, fields);
- }
- }
-
- public CodeVisitor visitMethod (
- final int access,
- final String name,
- final String desc,
- final String[] exceptions,
- final Attribute attrs)
- {
- CodeWriter cw = new CodeWriter(this, computeMaxs);
- cw.init(access, name, desc, exceptions, attrs);
- return cw;
- }
-
- public void visitAttribute (final Attribute attr) {
- attr.next = attrs;
- attrs = attr;
- }
-
- public void visitEnd () {
- }
-
- // --------------------------------------------------------------------------
- // Other public methods
- // --------------------------------------------------------------------------
-
- /**
- * Returns the bytecode of the class that was build with this class writer.
- *
- * @return the bytecode of the class that was build with this class writer.
- */
-
- public byte[] toByteArray () {
- // computes the real size of the bytecode of this class
- int size = 24 + 2*interfaceCount;
- if (fields != null) {
- size += fields.length;
- }
- int nbMethods = 0;
- CodeWriter cb = firstMethod;
- while (cb != null) {
- ++nbMethods;
- size += cb.getSize();
- cb = cb.next;
- }
- int attributeCount = 0;
- if (sourceFile != 0) {
- ++attributeCount;
- size += 8;
- }
- if ((access & Constants.ACC_DEPRECATED) != 0) {
- ++attributeCount;
- size += 6;
- }
- if (innerClasses != null) {
- ++attributeCount;
- size += 8 + innerClasses.length;
- }
- if (attrs != null) {
- attributeCount += attrs.getCount();
- size += attrs.getSize(this, null, 0, -1, -1);
- }
- size += pool.length;
- // allocates a byte vector of this size, in order to avoid unnecessary
- // arraycopy operations in the ByteVector.enlarge() method
- ByteVector out = new ByteVector(size);
- out.putInt(0xCAFEBABE).putInt(version);
- out.putShort(index).putByteArray(pool.data, 0, pool.length);
- out.putShort(access).putShort(name).putShort(superName);
- out.putShort(interfaceCount);
- for (int i = 0; i < interfaceCount; ++i) {
- out.putShort(interfaces[i]);
- }
- out.putShort(fieldCount);
- if (fields != null) {
- out.putByteArray(fields.data, 0, fields.length);
- }
- out.putShort(nbMethods);
- cb = firstMethod;
- while (cb != null) {
- cb.put(out);
- cb = cb.next;
- }
- out.putShort(attributeCount);
- if (sourceFile != 0) {
- out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
- }
- if ((access & Constants.ACC_DEPRECATED) != 0) {
- out.putShort(newUTF8("Deprecated")).putInt(0);
- }
- if (innerClasses != null) {
- out.putShort(newUTF8("InnerClasses"));
- out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
- out.putByteArray(innerClasses.data, 0, innerClasses.length);
- }
- if (attrs != null) {
- attrs.put(this, null, 0, -1, -1, out);
- }
- return out.data;
- }
-
- // --------------------------------------------------------------------------
- // Utility methods: constant pool management
- // --------------------------------------------------------------------------
-
- /**
- * Adds a number or string constant to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- *
- * @param cst the value of the constant to be added to the constant pool. This
- * parameter must be an {@link java.lang.Integer Integer}, a {@link
- * java.lang.Float Float}, a {@link java.lang.Long Long}, a {@link
- java.lang.Double Double} or a {@link String String}.
- * @return a new or already existing constant item with the given value.
- */
-
- Item newCst (final Object cst) {
- if (cst instanceof Integer) {
- int val = ((Integer)cst).intValue();
- return newInteger(val);
- } else if (cst instanceof Float) {
- float val = ((Float)cst).floatValue();
- return newFloat(val);
- } else if (cst instanceof Long) {
- long val = ((Long)cst).longValue();
- return newLong(val);
- } else if (cst instanceof Double) {
- double val = ((Double)cst).doubleValue();
- return newDouble(val);
- } else if (cst instanceof String) {
- return newString((String)cst);
- } else {
- throw new IllegalArgumentException("value " + cst);
- }
- }
-
- /**
- * Adds a number or string constant to the constant pool of the class being
- * build. Does nothing if the constant pool already contains a similar item.
- * <i>This method is intended for {@link Attribute} sub classes, and is
- * normally not needed by class generators or adapters.</i>
- *
- * @param cst the value of the constant to be added to the constant pool. This
- * parameter must be an {@link java.lang.Integer Integer}, a {@link
- * java.lang.Float Float}, a {@link java.lang.Long Long}, a {@link
- java.lang.Double Double} or a {@link String String}.
- * @return the index of a new or already existing constant item with the given
- * value.
- */
-
- public int newConst (final Object cst) {
- return newCst(cst).index;
- }
-
- /**
- * Adds an UTF8 string to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item. <i>This
- * method is intended for {@link Attribute} sub classes, and is normally not
- * needed by class generators or adapters.</i>
- *
- * @param value the String value.
- * @return the index of a new or already existing UTF8 item.
- */
-
- public int newUTF8 (final String value) {
- key.set(UTF8, value, null, null);
- Item result = get(key);
- if (result == null) {
- pool.putByte(UTF8).putUTF8(value);
- result = new Item(index++, key);
- put(result);
- }
- return result.index;
- }
-
- /**
- * Adds a class reference to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item. <i>This
- * method is intended for {@link Attribute} sub classes, and is normally not
- * needed by class generators or adapters.</i>
- *
- * @param value the internal name of the class.
- * @return the index of a new or already existing class reference item.
- */
-
- public int newClass (final String value) {
- key2.set(CLASS, value, null, null);
- Item result = get(key2);
- if (result == null) {
- pool.put12(CLASS, newUTF8(value));
- result = new Item(index++, key2);
- put(result);
- }
- return result.index;
- }
-
- /**
- * Adds a field reference to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item. <i>This
- * method is intended for {@link Attribute} sub classes, and is normally not
- * needed by class generators or adapters.</i>
- *
- * @param owner the internal name of the field's owner class.
- * @param name the field's name.
- * @param desc the field's descriptor.
- * @return the index of a new or already existing field reference item.
- */
-
- public int newField (
- final String owner,
- final String name,
- final String desc)
- {
- key3.set(FIELD, owner, name, desc);
- Item result = get(key3);
- if (result == null) {
- put122(FIELD, newClass(owner), newNameType(name, desc));
- result = new Item(index++, key3);
- put(result);
- }
- return result.index;
- }
-
- /**
- * Adds a method reference to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item.
- *
- * @param owner the internal name of the method's owner class.
- * @param name the method's name.
- * @param desc the method's descriptor.
- * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
- * @return a new or already existing method reference item.
- */
-
- Item newMethodItem (
- final String owner,
- final String name,
- final String desc,
- final boolean itf)
- {
- key3.set(itf ? IMETH : METH, owner, name, desc);
- Item result = get(key3);
- if (result == null) {
- put122(itf ? IMETH : METH, newClass(owner), newNameType(name, desc));
- result = new Item(index++, key3);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a method reference to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item. <i>This
- * method is intended for {@link Attribute} sub classes, and is normally not
- * needed by class generators or adapters.</i>
- *
- * @param owner the internal name of the method's owner class.
- * @param name the method's name.
- * @param desc the method's descriptor.
- * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
- * @return the index of a new or already existing method reference item.
- */
-
- public int newMethod (
- final String owner,
- final String name,
- final String desc,
- final boolean itf)
- {
- return newMethodItem(owner, name, desc, itf).index;
- }
-
- /**
- * Adds an integer to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item.
- *
- * @param value the int value.
- * @return a new or already existing int item.
- */
-
- private Item newInteger (final int value) {
- key.set(value);
- Item result = get(key);
- if (result == null) {
- pool.putByte(INT).putInt(value);
- result = new Item(index++, key);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a float to the constant pool of the class being build. Does nothing if
- * the constant pool already contains a similar item.
- *
- * @param value the float value.
- * @return a new or already existing float item.
- */
-
- private Item newFloat (final float value) {
- key.set(value);
- Item result = get(key);
- if (result == null) {
- pool.putByte(FLOAT).putInt(Float.floatToIntBits(value));
- result = new Item(index++, key);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a long to the constant pool of the class being build. Does nothing if
- * the constant pool already contains a similar item.
- *
- * @param value the long value.
- * @return a new or already existing long item.
- */
-
- private Item newLong (final long value) {
- key.set(value);
- Item result = get(key);
- if (result == null) {
- pool.putByte(LONG).putLong(value);
- result = new Item(index, key);
- put(result);
- index += 2;
- }
- return result;
- }
-
- /**
- * Adds a double to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item.
- *
- * @param value the double value.
- * @return a new or already existing double item.
- */
-
- private Item newDouble (final double value) {
- key.set(value);
- Item result = get(key);
- if (result == null) {
- pool.putByte(DOUBLE).putLong(Double.doubleToLongBits(value));
- result = new Item(index, key);
- put(result);
- index += 2;
- }
- return result;
- }
-
- /**
- * Adds a string to the constant pool of the class being build. Does nothing
- * if the constant pool already contains a similar item.
- *
- * @param value the String value.
- * @return a new or already existing string item.
- */
-
- private Item newString (final String value) {
- key2.set(STR, value, null, null);
- Item result = get(key2);
- if (result == null) {
- pool.put12(STR, newUTF8(value));
- result = new Item(index++, key2);
- put(result);
- }
- return result;
- }
-
- /**
- * Adds a name and type to the constant pool of the class being build. Does
- * nothing if the constant pool already contains a similar item.
- *
- * @param name a name.
- * @param desc a type descriptor.
- * @return the index of a new or already existing name and type item.
- */
-
- private int newNameType (final String name, final String desc) {
- key2.set(NAME_TYPE, name, desc, null);
- Item result = get(key2);
- if (result == null) {
- put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
- result = new Item(index++, key2);
- put(result);
- }
- return result.index;
- }
-
- /**
- * Returns the constant pool's hash table item which is equal to the given
- * item.
- *
- * @param key a constant pool item.
- * @return the constant pool's hash table item which is equal to the given
- * item, or <tt>null</tt> if there is no such item.
- */
-
- private Item get (final Item key) {
- int h = key.hashCode;
- Item i = items[h % items.length];
- while (i != null) {
- if (i.hashCode == h && key.isEqualTo(i)) {
- return i;
- }
- i = i.next;
- }
- return null;
- }
-
- /**
- * Puts the given item in the constant pool's hash table. The hash table
- * <i>must</i> not already contains this item.
- *
- * @param i the item to be added to the constant pool's hash table.
- */
-
- private void put (final Item i) {
- if (index > threshold) {
- Item[] newItems = new Item[items.length * 2 + 1];
- for (int l = items.length - 1; l >= 0; --l) {
- Item j = items[l];
- while (j != null) {
- int index = j.hashCode % newItems.length;
- Item k = j.next;
- j.next = newItems[index];
- newItems[index] = j;
- j = k;
- }
- }
- items = newItems;
- threshold = (int)(items.length * 0.75);
- }
- int index = i.hashCode % items.length;
- i.next = items[index];
- items[index] = i;
- }
-
- /**
- * Puts one byte and two shorts into the constant pool.
- *
- * @param b a byte.
- * @param s1 a short.
- * @param s2 another short.
- */
-
- private void put122 (final int b, final int s1, final int s2) {
- pool.put12(b, s1).putShort(s2);
- }
-}
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- */
-
-package org.objectweb.asm;
-
-/**
- * An empty {@link CodeVisitor CodeVisitor} that delegates to another {@link
- * CodeVisitor CodeVisitor}. This class can be used as a super class to quickly
- * implement usefull code adapter classes, just by overriding the necessary
- * methods.
- */
-
-public class CodeAdapter implements CodeVisitor {
-
- /**
- * The {@link CodeVisitor CodeVisitor} to which this adapter delegates calls.
- */
-
- protected CodeVisitor cv;
-
- /**
- * Constructs a new {@link CodeAdapter CodeAdapter} object.
- *
- * @param cv the code visitor to which this adapter must delegate calls.
- */
-
- public CodeAdapter (final CodeVisitor cv) {
- this.cv = cv;
- }
-
- public void visitInsn (final int opcode) {
- cv.visitInsn(opcode);
- }
-
- public void visitIntInsn (final int opcode, final int operand) {
- cv.visitIntInsn(opcode, operand);
- }
-
- public void visitVarInsn (final int opcode, final int var) {
- cv.visitVarInsn(opcode, var);
- }
-
- public void visitTypeInsn (final int opcode, final String desc) {
- cv.visitTypeInsn(opcode, desc);
- }
-
- public void visitFieldInsn (
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
- cv.visitFieldInsn(opcode, owner, name, desc);
- }
-
- public void visitMethodInsn (
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
- cv.visitMethodInsn(opcode, owner, name, desc);
- }
-
- public void visitJumpInsn (final int opcode, final Label label) {
- cv.visitJumpInsn(opcode, label);
- }
-
- public void visitLabel (final Label label) {
- cv.visitLabel(label);
- }
-
- public void visitLdcInsn (final Object cst) {
- cv.visitLdcInsn(cst);
- }
-
- public void visitIincInsn (final int var, final int increment) {
- cv.visitIincInsn(var, increment);
- }
-
- public void visitTableSwitchInsn (
- final int min,
- final int max,
- final Label dflt,
- final Label labels[])
- {
- cv.visitTableSwitchInsn(min, max, dflt, labels);
- }
-
- public void visitLookupSwitchInsn (
- final Label dflt,
- final int keys[],
- final Label labels[])
- {
- cv.visitLookupSwitchInsn(dflt, keys, labels);
- }
-
- public void visitMultiANewArrayInsn (final String desc, final int dims) {
- cv.visitMultiANewArrayInsn(desc, dims);
- }
-
- public void visitTryCatchBlock (
- final Label start,
- final Label end,
- final Label handler,
- final String type)
- {
- cv.visitTryCatchBlock(start, end, handler, type);
- }
-
- public void visitMaxs (final int maxStack, final int maxLocals) {
- cv.visitMaxs(maxStack, maxLocals);
- }
-
- public void visitLocalVariable (
- final String name,
- final String desc,
- final Label start,
- final Label end,
- final int index)
- {
- cv.visitLocalVariable(name, desc, start, end, index);
- }
-
- public void visitLineNumber (final int line, final Label start) {
- cv.visitLineNumber(line, start);
- }
-
- public void visitAttribute (final Attribute attr) {
- cv.visitAttribute(attr);
- }
-}
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- */
-
-package org.objectweb.asm;
-
-/**
- * A visitor to visit the bytecode instructions of a Java method. The methods
- * of this visitor must be called in the sequential order of the bytecode
- * instructions of the visited code. The {@link #visitMaxs visitMaxs} method
- * must be called after all the instructions have been visited. The {@link
- * #visitTryCatchBlock visitTryCatchBlock}, {@link #visitLocalVariable
- * visitLocalVariable} and {@link #visitLineNumber visitLineNumber} methods may
- * be called in any order, at any time (provided the labels passed as arguments
- * have already been visited with {@link #visitLabel visitLabel}).
- */
-
-public interface CodeVisitor {
-
- /**
- * Visits a zero operand instruction.
- *
- * @param opcode the opcode of the instruction to be visited. This opcode is
- * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2,
- * ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1,
- * FCONST_2, DCONST_0, DCONST_1,
- *
- * IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
- * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
- * SASTORE,
- *
- * POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP,
- *
- * IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL,
- * DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG,
- * FNEG, DNEG, ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR,
- * LOR, IXOR, LXOR,
- *
- * I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C,
- * I2S,
- *
- * LCMP, FCMPL, FCMPG, DCMPL, DCMPG,
- *
- * IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, RETURN,
- *
- * ARRAYLENGTH,
- *
- * ATHROW,
- *
- * MONITORENTER, or MONITOREXIT.
- */
-
- void visitInsn (int opcode);
-
- /**
- * Visits an instruction with a single int operand.
- *
- * @param opcode the opcode of the instruction to be visited. This opcode is
- * either BIPUSH, SIPUSH or NEWARRAY.
- * @param operand the operand of the instruction to be visited.
- */
-
- void visitIntInsn (int opcode, int operand);
-
- /**
- * Visits a local variable instruction. A local variable instruction is an
- * instruction that loads or stores the value of a local variable.
- *
- * @param opcode the opcode of the local variable instruction to be visited.
- * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE,
- * LSTORE, FSTORE, DSTORE, ASTORE or RET.
- * @param var the operand of the instruction to be visited. This operand is
- * the index of a local variable.
- */
-
- void visitVarInsn (int opcode, int var);
-
- /**
- * Visits a type instruction. A type instruction is an instruction that
- * takes a type descriptor as parameter.
- *
- * @param opcode the opcode of the type instruction to be visited. This opcode
- * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
- * @param desc the operand of the instruction to be visited. This operand is
- * must be a fully qualified class name in internal form, or the type
- * descriptor of an array type (see {@link Type Type}).
- */
-
- void visitTypeInsn (int opcode, String desc);
-
- /**
- * Visits a field instruction. A field instruction is an instruction that
- * loads or stores the value of a field of an object.
- *
- * @param opcode the opcode of the type instruction to be visited. This opcode
- * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
- * @param owner the internal name of the field's owner class (see {@link
- * Type#getInternalName getInternalName}).
- * @param name the field's name.
- * @param desc the field's descriptor (see {@link Type Type}).
- */
-
- void visitFieldInsn (int opcode, String owner, String name, String desc);
-
- /**
- * Visits a method instruction. A method instruction is an instruction that
- * invokes a method.
- *
- * @param opcode the opcode of the type instruction to be visited. This opcode
- * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
- * INVOKEINTERFACE.
- * @param owner the internal name of the method's owner class (see {@link
- * Type#getInternalName getInternalName}).
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type Type}).
- */
-
- void visitMethodInsn (int opcode, String owner, String name, String desc);
-
- /**
- * Visits a jump instruction. A jump instruction is an instruction that may
- * jump to another instruction.
- *
- * @param opcode the opcode of the type instruction to be visited. This opcode
- * is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE,
- * IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE,
- * GOTO, JSR, IFNULL or IFNONNULL.
- * @param label the operand of the instruction to be visited. This operand is
- * a label that designates the instruction to which the jump instruction
- * may jump.
- */
-
- void visitJumpInsn (int opcode, Label label);
-
- /**
- * Visits a label. A label designates the instruction that will be visited
- * just after it.
- *
- * @param label a {@link Label Label} object.
- */
-
- void visitLabel (Label label);
-
- // -------------------------------------------------------------------------
- // Special instructions
- // -------------------------------------------------------------------------
-
- /**
- * Visits a LDC instruction.
- *
- * @param cst the constant to be loaded on the stack. This parameter must be
- * a non null {@link java.lang.Integer Integer}, a {@link java.lang.Float
- * Float}, a {@link java.lang.Long Long}, a {@link java.lang.Double
- * Double} or a {@link String String}.
- */
-
- void visitLdcInsn (Object cst);
-
- /**
- * Visits an IINC instruction.
- *
- * @param var index of the local variable to be incremented.
- * @param increment amount to increment the local variable by.
- */
-
- void visitIincInsn (int var, int increment);
-
- /**
- * Visits a TABLESWITCH instruction.
- *
- * @param min the minimum key value.
- * @param max the maximum key value.
- * @param dflt beginning of the default handler block.
- * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is the
- * beginning of the handler block for the <tt>min + i</tt> key.
- */
-
- void visitTableSwitchInsn (int min, int max, Label dflt, Label labels[]);
-
- /**
- * Visits a LOOKUPSWITCH instruction.
- *
- * @param dflt beginning of the default handler block.
- * @param keys the values of the keys.
- * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is the
- * beginning of the handler block for the <tt>keys[i]</tt> key.
- */
-
- void visitLookupSwitchInsn (Label dflt, int keys[], Label labels[]);
-
- /**
- * Visits a MULTIANEWARRAY instruction.
- *
- * @param desc an array type descriptor (see {@link Type Type}).
- * @param dims number of dimensions of the array to allocate.
- */
-
- void visitMultiANewArrayInsn (String desc, int dims);
-
- // -------------------------------------------------------------------------
- // Exceptions table entries, max stack size and max locals
- // -------------------------------------------------------------------------
-
- /**
- * Visits a try catch block.
- *
- * @param start beginning of the exception handler's scope (inclusive).
- * @param end end of the exception handler's scope (exclusive).
- * @param handler beginning of the exception handler's code.
- * @param type internal name of the type of exceptions handled by the handler,
- * or <tt>null</tt> to catch any exceptions (for "finally" blocks).
- * @throws IllegalArgumentException if one of the labels has not already been
- * visited by this visitor (by the {@link #visitLabel visitLabel}
- * method).
- */
-
- void visitTryCatchBlock (Label start, Label end, Label handler, String type);
-
- /**
- * Visits the maximum stack size and the maximum number of local variables of
- * the method.
- *
- * @param maxStack maximum stack size of the method.
- * @param maxLocals maximum number of local variables for the method.
- */
-
- void visitMaxs (int maxStack, int maxLocals);
-
- // -------------------------------------------------------------------------
- // Debug information
- // -------------------------------------------------------------------------
-
- /**
- * Visits a local variable declaration.
- *
- * @param name the name of a local variable.
- * @param desc the type descriptor of this local variable.
- * @param start the first instruction corresponding to the scope of this
- * local variable (inclusive).
- * @param end the last instruction corresponding to the scope of this
- * local variable (exclusive).
- * @param index the local variable's index.
- * @throws IllegalArgumentException if one of the labels has not already been
- * visited by this visitor (by the {@link #visitLabel visitLabel}
- * method).
- */
-
- void visitLocalVariable (
- String name,
- String desc,
- Label start,
- Label end,
- int index);
-
- /**
- * Visits a line number declaration.
- *
- * @param line a line number. This number refers to the source file
- * from which the class was compiled.
- * @param start the first instruction corresponding to this line number.
- * @throws IllegalArgumentException if <tt>start</tt> has not already been
- * visited by this visitor (by the {@link #visitLabel visitLabel}
- * method).
- */
-
- void visitLineNumber (int line, Label start);
-
- // -------------------------------------------------------------------------
- // Non standard attributes
- // -------------------------------------------------------------------------
-
- /**
- * Visits a non standard attribute of the code. This method must visit only
- * the first attribute in the given attribute list.
- *
- * @param attr a non standard code attribute. Must not be <tt>null</tt>.
- */
-
- void visitAttribute (Attribute attr);
-}
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- */
-
-package org.objectweb.asm;
-
-/**
- * A {@link CodeVisitor CodeVisitor} that generates Java bytecode instructions.
- * Each visit method of this class appends the bytecode corresponding to the
- * visited instruction to a byte vector, in the order these methods are called.
- */
-
-public class CodeWriter implements CodeVisitor {
-
- /**
- * <tt>true</tt> if preconditions must be checked at runtime or not.
- */
-
- final static boolean CHECK = false;
-
- /**
- * Next code writer (see {@link ClassWriter#firstMethod firstMethod}).
- */
-
- CodeWriter next;
-
- /**
- * The class writer to which this method must be added.
- */
-
- private ClassWriter cw;
-
- /**
- * The index of the constant pool item that contains the name of this method.
- */
-
- private int name;
-
- /**
- * The index of the constant pool item that contains the descriptor of this
- * method.
- */
-
- private int desc;
-
- /**
- * Access flags of this method.
- */
-
- private int access;
-
- /**
- * Maximum stack size of this method.
- */
-
- private int maxStack;
-
- /**
- * Maximum number of local variables for this method.
- */
-
- private int maxLocals;
-
- /**
- * The bytecode of this method.
- */
-
- private ByteVector code = new ByteVector();
-
- /**
- * Number of entries in the catch table of this method.
- */
-
- private int catchCount;
-
- /**
- * The catch table of this method.
- */
-
- private ByteVector catchTable;
-
- /**
- * Number of exceptions that can be thrown by this method.
- */
-
- private int exceptionCount;
-
- /**
- * The exceptions that can be thrown by this method. More
- * precisely, this array contains the indexes of the constant pool items
- * that contain the internal names of these exception classes.
- */
-
- private int[] exceptions;
-
- /**
- * The non standard attributes of the method.
- */
-
- private Attribute attrs;
-
- /**
- * Number of entries in the LocalVariableTable attribute.
- */
-
- private int localVarCount;
-
- /**
- * The LocalVariableTable attribute.
- */
-
- private ByteVector localVar;
-
- /**
- * Number of entries in the LineNumberTable attribute.
- */
-
- private int lineNumberCount;
-
- /**
- * The LineNumberTable attribute.
- */
-
- private ByteVector lineNumber;
-
- /**
- * The non standard attributes of the method's code.
- */
-
- private Attribute cattrs;
-
- /**
- * Indicates if some jump instructions are too small and need to be resized.
- */
-
- private boolean resize;
-
- // --------------------------------------------------------------------------
- // Fields for the control flow graph analysis algorithm (used to compute the
- // maximum stack size). A control flow graph contains one node per "basic
- // block", and one edge per "jump" from one basic block to another. Each node
- // (i.e., each basic block) is represented by the Label object that
- // corresponds to the first instruction of this basic block. Each node also
- // stores the list of its successors in the graph, as a linked list of Edge
- // objects.
- // --------------------------------------------------------------------------
-
- /**
- * <tt>true</tt> if the maximum stack size and number of local variables must
- * be automatically computed.
- */
-
- private final boolean computeMaxs;
-
- /**
- * The (relative) stack size after the last visited instruction. This size is
- * relative to the beginning of the current basic block, i.e., the true stack
- * size after the last visited instruction is equal to the {@link
- * Label#beginStackSize beginStackSize} of the current basic block plus
- * <tt>stackSize</tt>.
- */
-
- private int stackSize;
-
- /**
- * The (relative) maximum stack size after the last visited instruction. This
- * size is relative to the beginning of the current basic block, i.e., the
- * true maximum stack size after the last visited instruction is equal to the
- * {@link Label#beginStackSize beginStackSize} of the current basic block plus
- * <tt>stackSize</tt>.
- */
-
- private int maxStackSize;
-
- /**
- * The current basic block. This block is the basic block to which the next
- * instruction to be visited must be added.
- */
-
- private Label currentBlock;
-
- /**
- * The basic block stack used by the control flow analysis algorithm. This
- * stack is represented by a linked list of {@link Label Label} objects,
- * linked to each other by their {@link Label#next} field. This stack must
- * not be confused with the JVM stack used to execute the JVM instructions!
- */
-
- private Label blockStack;
-
- /**
- * The stack size variation corresponding to each JVM instruction. This stack
- * variation is equal to the size of the values produced by an instruction,
- * minus the size of the values consumed by this instruction.
- */
-
- private final static int[] SIZE;
-
- // --------------------------------------------------------------------------
- // Fields to optimize the creation of {@link Edge Edge} objects by using a
- // pool of reusable objects. The (shared) pool is a linked list of Edge
- // objects, linked to each other by their {@link Edge#poolNext} field. Each
- // time a CodeWriter needs to allocate an Edge, it removes the first Edge
- // of the pool and adds it to a private list of Edge objects. After the end
- // of the control flow analysis algorithm, the Edge objects in the private
- // list of the CodeWriter are added back to the pool (by appending this
- // private list to the pool list; in order to do this in constant time, both
- // head and tail of the private list are stored in this CodeWriter).
- // --------------------------------------------------------------------------
-
- /**
- * The head of the list of {@link Edge Edge} objects used by this {@link
- * CodeWriter CodeWriter}. These objects, linked to each other by their
- * {@link Edge#poolNext} field, are added back to the shared pool at the
- * end of the control flow analysis algorithm.
- */
-
- private Edge head;
-
- /**
- * The tail of the list of {@link Edge Edge} objects used by this {@link
- * CodeWriter CodeWriter}. These objects, linked to each other by their
- * {@link Edge#poolNext} field, are added back to the shared pool at the
- * end of the control flow analysis algorithm.
- */
-
- private Edge tail;
-
- /**
- * The shared pool of {@link Edge Edge} objects. This pool is a linked list
- * of Edge objects, linked to each other by their {@link Edge#poolNext} field.
- */
-
- private static Edge pool;
-
- // --------------------------------------------------------------------------
- // Static initializer
- // --------------------------------------------------------------------------
-
- /**
- * Computes the stack size variation corresponding to each JVM instruction.
- */
-
- static {
- int i;
- int[] b = new int[202];
- String s =
- "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDDCDCDEEEEEEEEE" +
- "EEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCDCDCEEEEDDDDDDDCDCDCEFEF" +
- "DDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFEDDDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
- for (i = 0; i < b.length; ++i) {
- b[i] = s.charAt(i) - 'E';
- }
- SIZE = b;
-
- /* code to generate the above string
-
- int NA = 0; // not applicable (unused opcode or variable size opcode)
-
- b = new int[] {
- 0, //NOP, // visitInsn
- 1, //ACONST_NULL, // -
- 1, //ICONST_M1, // -
- 1, //ICONST_0, // -
- 1, //ICONST_1, // -
- 1, //ICONST_2, // -
- 1, //ICONST_3, // -
- 1, //ICONST_4, // -
- 1, //ICONST_5, // -
- 2, //LCONST_0, // -
- 2, //LCONST_1, // -
- 1, //FCONST_0, // -
- 1, //FCONST_1, // -
- 1, //FCONST_2, // -
- 2, //DCONST_0, // -
- 2, //DCONST_1, // -
- 1, //BIPUSH, // visitIntInsn
- 1, //SIPUSH, // -
- 1, //LDC, // visitLdcInsn
- NA, //LDC_W, // -
- NA, //LDC2_W, // -
- 1, //ILOAD, // visitVarInsn
- 2, //LLOAD, // -
- 1, //FLOAD, // -
- 2, //DLOAD, // -
- 1, //ALOAD, // -
- NA, //ILOAD_0, // -
- NA, //ILOAD_1, // -
- NA, //ILOAD_2, // -
- NA, //ILOAD_3, // -
- NA, //LLOAD_0, // -
- NA, //LLOAD_1, // -
- NA, //LLOAD_2, // -
- NA, //LLOAD_3, // -
- NA, //FLOAD_0, // -
- NA, //FLOAD_1, // -
- NA, //FLOAD_2, // -
- NA, //FLOAD_3, // -
- NA, //DLOAD_0, // -
- NA, //DLOAD_1, // -
- NA, //DLOAD_2, // -
- NA, //DLOAD_3, // -
- NA, //ALOAD_0, // -
- NA, //ALOAD_1, // -
- NA, //ALOAD_2, // -
- NA, //ALOAD_3, // -
- -1, //IALOAD, // visitInsn
- 0, //LALOAD, // -
- -1, //FALOAD, // -
- 0, //DALOAD, // -
- -1, //AALOAD, // -
- -1, //BALOAD, // -
- -1, //CALOAD, // -
- -1, //SALOAD, // -
- -1, //ISTORE, // visitVarInsn
- -2, //LSTORE, // -
- -1, //FSTORE, // -
- -2, //DSTORE, // -
- -1, //ASTORE, // -
- NA, //ISTORE_0, // -
- NA, //ISTORE_1, // -
- NA, //ISTORE_2, // -
- NA, //ISTORE_3, // -
- NA, //LSTORE_0, // -
- NA, //LSTORE_1, // -
- NA, //LSTORE_2, // -
- NA, //LSTORE_3, // -
- NA, //FSTORE_0, // -
- NA, //FSTORE_1, // -
- NA, //FSTORE_2, // -
- NA, //FSTORE_3, // -
- NA, //DSTORE_0, // -
- NA, //DSTORE_1, // -
- NA, //DSTORE_2, // -
- NA, //DSTORE_3, // -
- NA, //ASTORE_0, // -
- NA, //ASTORE_1, // -
- NA, //ASTORE_2, // -
- NA, //ASTORE_3, // -
- -3, //IASTORE, // visitInsn
- -4, //LASTORE, // -
- -3, //FASTORE, // -
- -4, //DASTORE, // -
- -3, //AASTORE, // -
- -3, //BASTORE, // -
- -3, //CASTORE, // -
- -3, //SASTORE, // -
- -1, //POP, // -
- -2, //POP2, // -
- 1, //DUP, // -
- 1, //DUP_X1, // -
- 1, //DUP_X2, // -
- 2, //DUP2, // -
- 2, //DUP2_X1, // -
- 2, //DUP2_X2, // -
- 0, //SWAP, // -
- -1, //IADD, // -
- -2, //LADD, // -
- -1, //FADD, // -
- -2, //DADD, // -
- -1, //ISUB, // -
- -2, //LSUB, // -
- -1, //FSUB, // -
- -2, //DSUB, // -
- -1, //IMUL, // -
- -2, //LMUL, // -
- -1, //FMUL, // -
- -2, //DMUL, // -
- -1, //IDIV, // -
- -2, //LDIV, // -
- -1, //FDIV, // -
- -2, //DDIV, // -
- -1, //IREM, // -
- -2, //LREM, // -
- -1, //FREM, // -
- -2, //DREM, // -
- 0, //INEG, // -
- 0, //LNEG, // -
- 0, //FNEG, // -
- 0, //DNEG, // -
- -1, //ISHL, // -
- -1, //LSHL, // -
- -1, //ISHR, // -
- -1, //LSHR, // -
- -1, //IUSHR, // -
- -1, //LUSHR, // -
- -1, //IAND, // -
- -2, //LAND, // -
- -1, //IOR, // -
- -2, //LOR, // -
- -1, //IXOR, // -
- -2, //LXOR, // -
- 0, //IINC, // visitIincInsn
- 1, //I2L, // visitInsn
- 0, //I2F, // -
- 1, //I2D, // -
- -1, //L2I, // -
- -1, //L2F, // -
- 0, //L2D, // -
- 0, //F2I, // -
- 1, //F2L, // -
- 1, //F2D, // -
- -1, //D2I, // -
- 0, //D2L, // -
- -1, //D2F, // -
- 0, //I2B, // -
- 0, //I2C, // -
- 0, //I2S, // -
- -3, //LCMP, // -
- -1, //FCMPL, // -
- -1, //FCMPG, // -
- -3, //DCMPL, // -
- -3, //DCMPG, // -
- -1, //IFEQ, // visitJumpInsn
- -1, //IFNE, // -
- -1, //IFLT, // -
- -1, //IFGE, // -
- -1, //IFGT, // -
- -1, //IFLE, // -
- -2, //IF_ICMPEQ, // -
- -2, //IF_ICMPNE, // -
- -2, //IF_ICMPLT, // -
- -2, //IF_ICMPGE, // -
- -2, //IF_ICMPGT, // -
- -2, //IF_ICMPLE, // -
- -2, //IF_ACMPEQ, // -
- -2, //IF_ACMPNE, // -
- 0, //GOTO, // -
- 1, //JSR, // -
- 0, //RET, // visitVarInsn
- -1, //TABLESWITCH, // visiTableSwitchInsn
- -1, //LOOKUPSWITCH, // visitLookupSwitch
- -1, //IRETURN, // visitInsn
- -2, //LRETURN, // -
- -1, //FRETURN, // -
- -2, //DRETURN, // -
- -1, //ARETURN, // -
- 0, //RETURN, // -
- NA, //GETSTATIC, // visitFieldInsn
- NA, //PUTSTATIC, // -
- NA, //GETFIELD, // -
- NA, //PUTFIELD, // -
- NA, //INVOKEVIRTUAL, // visitMethodInsn
- NA, //INVOKESPECIAL, // -
- NA, //INVOKESTATIC, // -
- NA, //INVOKEINTERFACE, // -
- NA, //UNUSED, // NOT VISITED
- 1, //NEW, // visitTypeInsn
- 0, //NEWARRAY, // visitIntInsn
- 0, //ANEWARRAY, // visitTypeInsn
- 0, //ARRAYLENGTH, // visitInsn
- NA, //ATHROW, // -
- 0, //CHECKCAST, // visitTypeInsn
- 0, //INSTANCEOF, // -
- -1, //MONITORENTER, // visitInsn
- -1, //MONITOREXIT, // -
- NA, //WIDE, // NOT VISITED
- NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
- -1, //IFNULL, // visitJumpInsn
- -1, //IFNONNULL, // -
- NA, //GOTO_W, // -
- NA, //JSR_W, // -
- };
- for (i = 0; i < b.length; ++i) {
- System.err.print((char)('E' + b[i]));
- }
- System.err.println();
- */
- }
-
- // --------------------------------------------------------------------------
- // Constructor
- // --------------------------------------------------------------------------
-
- /**
- * Constructs a CodeWriter.
- *
- * @param cw the class writer in which the method must be added.
- * @param computeMaxs <tt>true</tt> if the maximum stack size and number of
- * local variables must be automatically computed.
- */
-
- protected CodeWriter (final ClassWriter cw, final boolean computeMaxs) {
- if (cw.firstMethod == null) {
- cw.firstMethod = this;
- cw.lastMethod = this;
- } else {
- cw.lastMethod.next = this;
- cw.lastMethod = this;
- }
- this.cw = cw;
- this.computeMaxs = computeMaxs;
- if (computeMaxs) {
- // pushes the first block onto the stack of blocks to be visited
- currentBlock = new Label();
- currentBlock.pushed = true;
- blockStack = currentBlock;
- }
- }
-
- /**
- * Initializes this CodeWriter to define the bytecode of the specified method.
- *
- * @param access the method's access flags (see {@link Constants}).
- * @param name the method's name.
- * @param desc the method's descriptor (see {@link Type Type}).
- * @param exceptions the internal names of the method's exceptions. May be
- * <tt>null</tt>.
- * @param attrs the non standard attributes of the method.
- */
-
- protected void init (
- final int access,
- final String name,
- final String desc,
- final String[] exceptions,
- final Attribute attrs)
- {
- this.access = access;
- this.name = cw.newUTF8(name);
- this.desc = cw.newUTF8(desc);
- if (exceptions != null && exceptions.length > 0) {
- exceptionCount = exceptions.length;
- this.exceptions = new int[exceptionCount];
- for (int i = 0; i < exceptionCount; ++i) {
- this.exceptions[i] = cw.newClass(exceptions[i]);
- }
- }
- this.attrs = attrs;
- if (computeMaxs) {
- // updates maxLocals
- int size = getArgumentsAndReturnSizes(desc) >> 2;
- if ((access & Constants.ACC_STATIC) != 0) {
- --size;
- }
- if (size > maxLocals) {
- maxLocals = size;
- }
- }
- }
-
- // --------------------------------------------------------------------------
- // Implementation of the CodeVisitor interface
- // --------------------------------------------------------------------------
-
- public void visitInsn (final int opcode) {
- if (computeMaxs) {
- // updates current and max stack sizes
- int size = stackSize + SIZE[opcode];
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- // if opcode == ATHROW or xRETURN, ends current block (no successor)
- if ((opcode >= Constants.IRETURN && opcode <= Constants.RETURN) ||
- opcode == Constants.ATHROW)
- {
- if (currentBlock != null) {
- currentBlock.maxStackSize = maxStackSize;
- currentBlock = null;
- }
- }
- }
- // adds the instruction to the bytecode of the method
- code.putByte(opcode);
- }
-
- public void visitIntInsn (final int opcode, final int operand) {
- if (computeMaxs && opcode != Constants.NEWARRAY) {
- // updates current and max stack sizes only if opcode == NEWARRAY
- // (stack size variation = 0 for BIPUSH or SIPUSH)
- int size = stackSize + 1;
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- // adds the instruction to the bytecode of the method
- if (opcode == Constants.SIPUSH) {
- code.put12(opcode, operand);
- } else { // BIPUSH or NEWARRAY
- code.put11(opcode, operand);
- }
- }
-
- public void visitVarInsn (final int opcode, final int var) {
- if (computeMaxs) {
- // updates current and max stack sizes
- if (opcode == Constants.RET) {
- // no stack change, but end of current block (no successor)
- if (currentBlock != null) {
- currentBlock.maxStackSize = maxStackSize;
- currentBlock = null;
- }
- } else { // xLOAD or xSTORE
- int size = stackSize + SIZE[opcode];
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- // updates max locals
- int n;
- if (opcode == Constants.LLOAD || opcode == Constants.DLOAD ||
- opcode == Constants.LSTORE || opcode == Constants.DSTORE)
- {
- n = var + 2;
- } else {
- n = var + 1;
- }
- if (n > maxLocals) {
- maxLocals = n;
- }
- }
- // adds the instruction to the bytecode of the method
- if (var < 4 && opcode != Constants.RET) {
- int opt;
- if (opcode < Constants.ISTORE) {
- opt = 26 /*ILOAD_0*/ + ((opcode - Constants.ILOAD) << 2) + var;
- } else {
- opt = 59 /*ISTORE_0*/ + ((opcode - Constants.ISTORE) << 2) + var;
- }
- code.putByte(opt);
- } else if (var >= 256) {
- code.putByte(196 /*WIDE*/).put12(opcode, var);
- } else {
- code.put11(opcode, var);
- }
- }
-
- public void visitTypeInsn (final int opcode, final String desc) {
- if (computeMaxs && opcode == Constants.NEW) {
- // updates current and max stack sizes only if opcode == NEW
- // (stack size variation = 0 for ANEWARRAY, CHECKCAST, INSTANCEOF)
- int size = stackSize + 1;
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- // adds the instruction to the bytecode of the method
- code.put12(opcode, cw.newClass(desc));
- }
-
- public void visitFieldInsn (
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
- if (computeMaxs) {
- int size;
- // computes the stack size variation
- char c = desc.charAt(0);
- switch (opcode) {
- case Constants.GETSTATIC:
- size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
- break;
- case Constants.PUTSTATIC:
- size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
- break;
- case Constants.GETFIELD:
- size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
- break;
- //case Constants.PUTFIELD:
- default:
- size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
- break;
- }
- // updates current and max stack sizes
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- // adds the instruction to the bytecode of the method
- code.put12(opcode, cw.newField(owner, name, desc));
- }
-
- public void visitMethodInsn (
- final int opcode,
- final String owner,
- final String name,
- final String desc)
- {
- boolean itf = opcode == Constants.INVOKEINTERFACE;
- Item i = cw.newMethodItem(owner, name, desc, itf);
- int argSize = i.intVal;
- if (computeMaxs) {
- // computes the stack size variation. In order not to recompute several
- // times this variation for the same Item, we use the intVal field of
- // this item to store this variation, once it has been computed. More
- // precisely this intVal field stores the sizes of the arguments and of
- // the return value corresponding to desc.
- if (argSize == 0) {
- // the above sizes have not been computed yet, so we compute them...
- argSize = getArgumentsAndReturnSizes(desc);
- // ... and we save them in order not to recompute them in the future
- i.intVal = argSize;
- }
- int size;
- if (opcode == Constants.INVOKESTATIC) {
- size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
- } else {
- size = stackSize - (argSize >> 2) + (argSize & 0x03);
- }
- // updates current and max stack sizes
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- // adds the instruction to the bytecode of the method
- if (itf) {
- if (!computeMaxs) {
- if (argSize == 0) {
- argSize = getArgumentsAndReturnSizes(desc);
- i.intVal = argSize;
- }
- }
- code.put12(Constants.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0);
- } else {
- code.put12(opcode, i.index);
- }
- }
-
- public void visitJumpInsn (final int opcode, final Label label) {
- if (CHECK) {
- if (label.owner == null) {
- label.owner = this;
- } else if (label.owner != this) {
- throw new IllegalArgumentException();
- }
- }
- if (computeMaxs) {
- if (opcode == Constants.GOTO) {
- // no stack change, but end of current block (with one new successor)
- if (currentBlock != null) {
- currentBlock.maxStackSize = maxStackSize;
- addSuccessor(stackSize, label);
- currentBlock = null;
- }
- } else if (opcode == Constants.JSR) {
- if (currentBlock != null) {
- addSuccessor(stackSize + 1, label);
- }
- } else {
- // updates current stack size (max stack size unchanged because stack
- // size variation always negative in this case)
- stackSize += SIZE[opcode];
- if (currentBlock != null) {
- addSuccessor(stackSize, label);
- }
- }
- }
- // adds the instruction to the bytecode of the method
- if (label.resolved && label.position - code.length < Short.MIN_VALUE) {
- // case of a backward jump with an offset < -32768. In this case we
- // automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx <l>
- // with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the "opposite" opcode
- // of IFxxx (i.e., IFNE for IFEQ) and where <l'> designates the
- // instruction just after the GOTO_W.
- if (opcode == Constants.GOTO) {
- code.putByte(200); // GOTO_W
- } else if (opcode == Constants.JSR) {
- code.putByte(201); // JSR_W
- } else {
- code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1);
- code.putShort(8); // jump offset
- code.putByte(200); // GOTO_W
- }
- label.put(this, code, code.length - 1, true);
- } else {
- // case of a backward jump with an offset >= -32768, or of a forward jump
- // with, of course, an unknown offset. In these cases we store the offset
- // in 2 bytes (which will be increased in resizeInstructions, if needed).
- code.putByte(opcode);
- label.put(this, code, code.length - 1, false);
- }
- }
-
- public void visitLabel (final Label label) {
- if (CHECK) {
- if (label.owner == null) {
- label.owner = this;
- } else if (label.owner != this) {
- throw new IllegalArgumentException();
- }
- }
- if (computeMaxs) {
- if (currentBlock != null) {
- // ends current block (with one new successor)
- currentBlock.maxStackSize = maxStackSize;
- addSuccessor(stackSize, label);
- }
- // begins a new current block,
- // resets the relative current and max stack sizes
- currentBlock = label;
- stackSize = 0;
- maxStackSize = 0;
- }
- // resolves previous forward references to label, if any
- resize |= label.resolve(this, code.length, code.data);
- }
-
- public void visitLdcInsn (final Object cst) {
- Item i = cw.newCst(cst);
- if (computeMaxs) {
- int size;
- // computes the stack size variation
- if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
- size = stackSize + 2;
- } else {
- size = stackSize + 1;
- }
- // updates current and max stack sizes
- if (size > maxStackSize) {
- maxStackSize = size;
- }
- stackSize = size;
- }
- // adds the instruction to the bytecode of the method
- int index = i.index;
- if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
- code.put12(20 /*LDC2_W*/, index);
- } else if (index >= 256) {
- code.put12(19 /*LDC_W*/, index);
- } else {
- code.put11(Constants.LDC, index);
- }
- }
-
- public void visitIincInsn (final int var, final int increment) {
- if (computeMaxs) {
- // updates max locals only (no stack change)
- int n = var + 1;
- if (n > maxLocals) {
- maxLocals = n;
- }
- }
- // adds the instruction to the bytecode of the method
- if ((var > 255) || (increment > 127) || (increment < -128)) {
- code.putByte(196 /*WIDE*/).put12(Constants.IINC, var).putShort(increment);
- } else {
- code.putByte(Constants.IINC).put11(var, increment);
- }
- }
-
- public void visitTableSwitchInsn (
- final int min,
- final int max,
- final Label dflt,
- final Label labels[])
- {
- if (computeMaxs) {
- // updates current stack size (max stack size unchanged)
- --stackSize;
- // ends current block (with many new successors)
- if (currentBlock != null) {
- currentBlock.maxStackSize = maxStackSize;
- addSuccessor(stackSize, dflt);
- for (int i = 0; i < labels.length; ++i) {
- addSuccessor(stackSize, labels[i]);
- }
- currentBlock = null;
- }
- }
- // adds the instruction to the bytecode of the method
- int source = code.length;
- code.putByte(Constants.TABLESWITCH);
- while (code.length % 4 != 0) {
- code.putByte(0);
- }
- dflt.put(this, code, source, true);
- code.putInt(min).putInt(max);
- for (int i = 0; i < labels.length; ++i) {
- labels[i].put(this, code, source, true);
- }
- }
-
- public void visitLookupSwitchInsn (
- final Label dflt,
- final int keys[],
- final Label labels[])
- {
- if (computeMaxs) {
- // updates current stack size (max stack size unchanged)
- --stackSize;
- // ends current block (with many new successors)
- if (currentBlock != null) {
- currentBlock.maxStackSize = maxStackSize;
- addSuccessor(stackSize, dflt);
- for (int i = 0; i < labels.length; ++i) {
- addSuccessor(stackSize, labels[i]);
- }
- currentBlock = null;
- }
- }
- // adds the instruction to the bytecode of the method
- int source = code.length;
- code.putByte(Constants.LOOKUPSWITCH);
- while (code.length % 4 != 0) {
- code.putByte(0);
- }
- dflt.put(this, code, source, true);
- code.putInt(labels.length);
- for (int i = 0; i < labels.length; ++i) {
- code.putInt(keys[i]);
- labels[i].put(this, code, source, true);
- }
- }
-
- public void visitMultiANewArrayInsn (final String desc, final int dims) {
- if (computeMaxs) {
- // updates current stack size (max stack size unchanged because stack
- // size variation always negative or null)
- stackSize += 1 - dims;
- }
- // adds the instruction to the bytecode of the method
- code.put12(Constants.MULTIANEWARRAY, cw.newClass(desc)).putByte(dims);
- }
-
- public void visitTryCatchBlock (
- final Label start,
- final Label end,
- final Label handler,
- final String type)
- {
- if (CHECK) {
- if (start.owner != this || end.owner != this || handler.owner != this) {
- throw new IllegalArgumentException();
- }
- if (!start.resolved || !end.resolved || !handler.resolved) {
- throw new IllegalArgumentException();
- }
- }
- if (computeMaxs) {
- // pushes handler block onto the stack of blocks to be visited
- if (!handler.pushed) {
- handler.beginStackSize = 1;
- handler.pushed = true;
- handler.next = blockStack;
- blockStack = handler;
- }
- }
- ++catchCount;
- if (catchTable == null) {
- catchTable = new ByteVector();
- }
- catchTable.putShort(start.position);
- catchTable.putShort(end.position);
- catchTable.putShort(handler.position);
- catchTable.putShort(type != null ? cw.newClass(type) : 0);
- }
-
- public void visitMaxs (final int maxStack, final int maxLocals) {
- if (computeMaxs) {
- // true (non relative) max stack size
- int max = 0;
- // control flow analysis algorithm: while the block stack is not empty,
- // pop a block from this stack, update the max stack size, compute
- // the true (non relative) begin stack size of the successors of this
- // block, and push these successors onto the stack (unless they have
- // already been pushed onto the stack). Note: by hypothesis, the {@link
- // Label#beginStackSize} of the blocks in the block stack are the true
- // (non relative) beginning stack sizes of these blocks.
- Label stack = blockStack;
- while (stack != null) {
- // pops a block from the stack
- Label l = stack;
- stack = stack.next;
- // computes the true (non relative) max stack size of this block
- int start = l.beginStackSize;
- int blockMax = start + l.maxStackSize;
- // updates the global max stack size
- if (blockMax > max) {
- max = blockMax;
- }
- // analyses the successors of the block
- Edge b = l.successors;
- while (b != null) {
- l = b.successor;
- // if this successor has not already been pushed onto the stack...
- if (!l.pushed) {
- // computes the true beginning stack size of this successor block
- l.beginStackSize = start + b.stackSize;
- // pushes this successor onto the stack
- l.pushed = true;
- l.next = stack;
- stack = l;
- }
- b = b.next;
- }
- }
- this.maxStack = max;
- // releases all the Edge objects used by this CodeWriter
- synchronized (SIZE) {
- // appends the [head ... tail] list at the beginning of the pool list
- if (tail != null) {
- tail.poolNext = pool;
- pool = head;
- }
- }
- } else {
- this.maxStack = maxStack;
- this.maxLocals = maxLocals;
- }
- }
-
- public void visitLocalVariable (
- final String name,
- final String desc,
- final Label start,
- final Label end,
- final int index)
- {
- if (CHECK) {
- if (start.owner != this || !start.resolved) {
- throw new IllegalArgumentException();
- }
- if (end.owner != this || !end.resolved) {
- throw new IllegalArgumentException();
- }
- }
- if (localVar == null) {
- cw.newUTF8("LocalVariableTable");
- localVar = new ByteVector();
- }
- ++localVarCount;
- localVar.putShort(start.position);
- localVar.putShort(end.position - start.position);
- localVar.putShort(cw.newUTF8(name));
- localVar.putShort(cw.newUTF8(desc));
- localVar.putShort(index);
- }
-
- public void visitLineNumber (final int line, final Label start) {
- if (CHECK) {
- if (start.owner != this || !start.resolved) {
- throw new IllegalArgumentException();
- }
- }
- if (lineNumber == null) {
- cw.newUTF8("LineNumberTable");
- lineNumber = new ByteVector();
- }
- ++lineNumberCount;
- lineNumber.putShort(start.position);
- lineNumber.putShort(line);
- }
-
- public void visitAttribute (final Attribute attr) {
- attr.next = cattrs;
- cattrs = attr;
- }
-
- // --------------------------------------------------------------------------
- // Utility methods: control flow analysis algorithm
- // --------------------------------------------------------------------------
-
- /**
- * Computes the size of the arguments and of the return value of a method.
- *
- * @param desc the descriptor of a method.
- * @return the size of the arguments of the method (plus one for the implicit
- * this argument), argSize, and the size of its return value, retSize,
- * packed into a single int i = <tt>(argSize << 2) | retSize</tt>
- * (argSize is therefore equal to <tt>i >> 2</tt>, and retSize to
- * <tt>i & 0x03</tt>).
- */
-
- private static int getArgumentsAndReturnSizes (final String desc) {
- int n = 1;
- int c = 1;
- while (true) {
- char car = desc.charAt(c++);
- if (car == ')') {
- car = desc.charAt(c);
- return n << 2 | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));
- } else if (car == 'L') {
- while (desc.charAt(c++) != ';') {
- }
- n += 1;
- } else if (car == '[') {
- while ((car = desc.charAt(c)) == '[') {
- ++c;
- }
- if (car == 'D' || car == 'J') {
- n -= 1;
- }
- } else if (car == 'D' || car == 'J') {
- n += 2;
- } else {
- n += 1;
- }
- }
- }
-
- /**
- * Adds a successor to the {@link #currentBlock currentBlock} block.
- *
- * @param stackSize the current (relative) stack size in the current block.
- * @param successor the successor block to be added to the current block.
- */
-
- private void addSuccessor (final int stackSize, final Label successor) {
- Edge b;
- // creates a new Edge object or reuses one from the shared pool
- synchronized (SIZE) {
- if (pool == null) {
- b = new Edge();
- } else {
- b = pool;
- // removes b from the pool
- pool = pool.poolNext;
- }
- }
- // adds the previous Edge to the list of Edges used by this CodeWriter
- if (tail == null) {
- tail = b;
- }
- b.poolNext = head;
- head = b;
- // initializes the previous Edge object...
- b.stackSize = stackSize;
- b.successor = successor;
- // ...and adds it to the successor list of the currentBlock block
- b.next = currentBlock.successors;
- currentBlock.successors = b;
- }
-
- // --------------------------------------------------------------------------
- // Utility methods: dump bytecode array
- // --------------------------------------------------------------------------
-
- /**
- * Returns the size of the bytecode of this method.
- *
- * @return the size of the bytecode of this method.
- */
-
- final int getSize () {
- if (resize) {
- // replaces the temporary jump opcodes introduced by Label.resolve.
- resizeInstructions(new int[0], new int[0], 0);
- }
- int size = 8;
- if (code.length > 0) {
- cw.newUTF8("Code");
- size += 18 + code.length + 8 * catchCount;
- if (localVar != null) {
- size += 8 + localVar.length;
- }
- if (lineNumber != null) {
- size += 8 + lineNumber.length;
- }
- if (cattrs != null) {
- size += cattrs.getSize(cw, code.data, code.length, maxStack, maxLocals);
- }
- }
- if (exceptionCount > 0) {
- cw.newUTF8("Exceptions");
- size += 8 + 2 * exceptionCount;
- }
- if ((access & Constants.ACC_SYNTHETIC) != 0) {
- cw.newUTF8("Synthetic");
- size += 6;
- }
- if ((access & Constants.ACC_DEPRECATED) != 0) {
- cw.newUTF8("Deprecated");
- size += 6;
- }
- if (attrs != null) {
- size += attrs.getSize(cw, null, 0, -1, -1);
- }
- return size;
- }
-
- /**
- * Puts the bytecode of this method in the given byte vector.
- *
- * @param out the byte vector into which the bytecode of this method must be
- * copied.
- */
-
- final void put (final ByteVector out) {
- out.putShort(access).putShort(name).putShort(desc);
- int attributeCount = 0;
- if (code.length > 0) {
- ++attributeCount;
- }
- if (exceptionCount > 0) {
- ++attributeCount;
- }
- if ((access & Constants.ACC_SYNTHETIC) != 0) {
- ++attributeCount;
- }
- if ((access & Constants.ACC_DEPRECATED) != 0) {
- ++attributeCount;
- }
- if (attrs != null) {
- attributeCount += attrs.getCount();
- }
- out.putShort(attributeCount);
- if (code.length > 0) {
- int size = 12 + code.length + 8 * catchCount;
- if (localVar != null) {
- size += 8 + localVar.length;
- }
- if (lineNumber != null) {
- size += 8 + lineNumber.length;
- }
- if (cattrs != null) {
- size += cattrs.getSize(cw, code.data, code.length, maxStack, maxLocals);
- }
- out.putShort(cw.newUTF8("Code")).putInt(size);
- out.putShort(maxStack).putShort(maxLocals);
- out.putInt(code.length).putByteArray(code.data, 0, code.length);
- out.putShort(catchCount);
- if (catchCount > 0) {
- out.putByteArray(catchTable.data, 0, catchTable.length);
- }
- attributeCount = 0;
- if (localVar != null) {
- ++attributeCount;
- }
- if (lineNumber != null) {
- ++attributeCount;
- }
- if (cattrs != null) {
- attributeCount += cattrs.getCount();
- }
- out.putShort(attributeCount);
- if (localVar != null) {
- out.putShort(cw.newUTF8("LocalVariableTable"));
- out.putInt(localVar.length + 2).putShort(localVarCount);
- out.putByteArray(localVar.data, 0, localVar.length);
- }
- if (lineNumber != null) {
- out.putShort(cw.newUTF8("LineNumberTable"));
- out.putInt(lineNumber.length + 2).putShort(lineNumberCount);
- out.putByteArray(lineNumber.data, 0, lineNumber.length);
- }
- if (cattrs != null) {
- cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out);
- }
- }
- if (exceptionCount > 0) {
- out.putShort(cw.newUTF8("Exceptions")).putInt(2 * exceptionCount + 2);
- out.putShort(exceptionCount);
- for (int i = 0; i < exceptionCount; ++i) {
- out.putShort(exceptions[i]);
- }
- }
- if ((access & Constants.ACC_SYNTHETIC) != 0) {
- out.putShort(cw.newUTF8("Synthetic")).putInt(0);
- }
- if ((access & Constants.ACC_DEPRECATED) != 0) {
- out.putShort(cw.newUTF8("Deprecated")).putInt(0);
- }
- if (attrs != null) {
- attrs.put(cw, null, 0, -1, -1, out);
- }
- }
-
- // --------------------------------------------------------------------------
- // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W)
- // --------------------------------------------------------------------------
-
- /**
- * Resizes the designated instructions, while keeping jump offsets and
- * instruction addresses consistent. This may require to resize other existing
- * instructions, or even to introduce new instructions: for example,
- * increasing the size of an instruction by 2 at the middle of a method can
- * increases the offset of an IFEQ instruction from 32766 to 32768, in which
- * case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W 32765. This, in turn,
- * may require to increase the size of another jump instruction, and so on...
- * All these operations are handled automatically by this method.
- * <p>
- * <i>This method must be called after all the method that is being built has
- * been visited</i>. In particular, the {@link Label Label} objects used to
- * construct the method are no longer valid after this method has been called.
- *
- * @param indexes current positions of the instructions to be resized. Each
- * instruction must be designated by the index of its <i>last</i> byte,
- * plus one (or, in other words, by the index of the <i>first</i> byte of
- * the <i>next</i> instruction).
- * @param sizes the number of bytes to be <i>added</i> to the above
- * instructions. More precisely, for each i < <tt>len</tt>,
- * <tt>sizes</tt>[i] bytes will be added at the end of the instruction
- * designated by <tt>indexes</tt>[i] or, if <tt>sizes</tt>[i] is
- * negative, the <i>last</i> |<tt>sizes[i]</tt>| bytes of the instruction
- * will be removed (the instruction size <i>must not</i> become negative
- * or null). The gaps introduced by this method must be filled in
- * "manually" in the array returned by the {@link #getCode getCode}
- * method.
- * @param len the number of instruction to be resized. Must be smaller than or
- * equal to <tt>indexes</tt>.length and <tt>sizes</tt>.length.
- * @return the <tt>indexes</tt> array, which now contains the new positions of
- * the resized instructions (designated as above).
- */
-
- protected int[] resizeInstructions (
- final int[] indexes,
- final int[] sizes,
- final int len)
- {
- byte[] b = code.data; // bytecode of the method
- int u, v, label; // indexes in b
- int i, j; // loop indexes
-
- // 1st step:
- // As explained above, resizing an instruction may require to resize another
- // one, which may require to resize yet another one, and so on. The first
- // step of the algorithm consists in finding all the instructions that
- // need to be resized, without modifying the code. This is done by the
- // following "fix point" algorithm:
- // - parse the code to find the jump instructions whose offset will need
- // more than 2 bytes to be stored (the future offset is computed from the
- // current offset and from the number of bytes that will be inserted or
- // removed between the source and target instructions). For each such
- // instruction, adds an entry in (a copy of) the indexes and sizes arrays
- // (if this has not already been done in a previous iteration!)
- // - if at least one entry has been added during the previous step, go back
- // to the beginning, otherwise stop.
- // In fact the real algorithm is complicated by the fact that the size of
- // TABLESWITCH and LOOKUPSWITCH instructions depends on their position in
- // the bytecode (because of padding). In order to ensure the convergence of
- // the algorithm, the number of bytes to be added or removed from these
- // instructions is over estimated during the previous loop, and computed
- // exactly only after the loop is finished (this requires another pass to
- // parse the bytecode of the method).
-
- int[] allIndexes = new int[len]; // copy of indexes
- int[] allSizes = new int[len]; // copy of sizes
- boolean[] resize; // instructions to be resized
- int newOffset; // future offset of a jump instruction
-
- System.arraycopy(indexes, 0, allIndexes, 0, len);
- System.arraycopy(sizes, 0, allSizes, 0, len);
- resize = new boolean[code.length];
-
- int state = 3; // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done
- do {
- if (state == 3) {
- state = 2;
- }
- u = 0;
- while (u < b.length) {
- int opcode = b[u] & 0xFF; // opcode of current instruction
- int insert = 0; // bytes to be added after this instruction
-
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- u += 1;
- break;
- case ClassWriter.LABEL_INSN:
- if (opcode > 201) {
- // converts temporary opcodes 202 to 217 (inclusive), 218 and 219
- // to IFEQ ... JSR (inclusive), IFNULL and IFNONNULL
- opcode = opcode < 218 ? opcode - 49 : opcode - 20;
- label = u + readUnsignedShort(b, u + 1);
- } else {
- label = u + readShort(b, u + 1);
- }
- newOffset = getNewOffset(allIndexes, allSizes, u, label);
- if (newOffset < Short.MIN_VALUE || newOffset > Short.MAX_VALUE) {
- if (!resize[u]) {
- if (opcode == Constants.GOTO || opcode == Constants.JSR) {
- // two additional bytes will be required to replace this
- // GOTO or JSR instruction with a GOTO_W or a JSR_W
- insert = 2;
- } else {
- // five additional bytes will be required to replace this
- // IFxxx <l> instruction with IFNOTxxx <l'> GOTO_W <l>, where
- // IFNOTxxx is the "opposite" opcode of IFxxx (i.e., IFNE for
- // IFEQ) and where <l'> designates the instruction just after
- // the GOTO_W.
- insert = 5;
- }
- resize[u] = true;
- }
- }
- u += 3;
- break;
- case ClassWriter.LABELW_INSN:
- u += 5;
- break;
- case ClassWriter.TABL_INSN:
- if (state == 1) {
- // true number of bytes to be added (or removed) from this
- // instruction = (future number of padding bytes - current number
- // of padding byte) - previously over estimated variation =
- // = ((3 - newOffset%4) - (3 - u%4)) - u%4
- // = (-newOffset%4 + u%4) - u%4
- // = -(newOffset & 3)
- newOffset = getNewOffset(allIndexes, allSizes, 0, u);
- insert = -(newOffset & 3);
- } else if (!resize[u]) {
- // over estimation of the number of bytes to be added to this
- // instruction = 3 - current number of padding bytes = 3 - (3 -
- // u%4) = u%4 = u & 3
- insert = u & 3;
- resize[u] = true;
- }
- // skips instruction
- u = u + 4 - (u & 3);
- u += 4*(readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
- break;
- case ClassWriter.LOOK_INSN:
- if (state == 1) {
- // like TABL_INSN
- newOffset = getNewOffset(allIndexes, allSizes, 0, u);
- insert = -(newOffset & 3);
- } else if (!resize[u]) {
- // like TABL_INSN
- insert = u & 3;
- resize[u] = true;
- }
- // skips instruction
- u = u + 4 - (u & 3);
- u += 8*readInt(b, u + 4) + 8;
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[u + 1] & 0xFF;
- if (opcode == Constants.IINC) {
- u += 6;
- } else {
- u += 4;
- }
- break;
- case ClassWriter.VAR_INSN:
- case ClassWriter.SBYTE_INSN:
- case ClassWriter.LDC_INSN:
- u += 2;
- break;
- case ClassWriter.SHORT_INSN:
- case ClassWriter.LDCW_INSN:
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.TYPE_INSN:
- case ClassWriter.IINC_INSN:
- u += 3;
- break;
- case ClassWriter.ITFMETH_INSN:
- u += 5;
- break;
- // case ClassWriter.MANA_INSN:
- default:
- u += 4;
- break;
- }
- if (insert != 0) {
- // adds a new (u, insert) entry in the allIndexes and allSizes arrays
- int[] newIndexes = new int[allIndexes.length + 1];
- int[] newSizes = new int[allSizes.length + 1];
- System.arraycopy(allIndexes, 0, newIndexes, 0, allIndexes.length);
- System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
- newIndexes[allIndexes.length] = u;
- newSizes[allSizes.length] = insert;
- allIndexes = newIndexes;
- allSizes = newSizes;
- if (insert > 0) {
- state = 3;
- }
- }
- }
- if (state < 3) {
- --state;
- }
- } while (state != 0);
-
- // 2nd step:
- // copies the bytecode of the method into a new bytevector, updates the
- // offsets, and inserts (or removes) bytes as requested.
-
- ByteVector newCode = new ByteVector(code.length);
-
- u = 0;
- while (u < code.length) {
- for (i = allIndexes.length - 1; i >= 0; --i) {
- if (allIndexes[i] == u) {
- if (i < len) {
- if (sizes[i] > 0) {
- newCode.putByteArray(null, 0, sizes[i]);
- } else {
- newCode.length += sizes[i];
- }
- indexes[i] = newCode.length;
- }
- }
- }
- int opcode = b[u] & 0xFF;
- switch (ClassWriter.TYPE[opcode]) {
- case ClassWriter.NOARG_INSN:
- case ClassWriter.IMPLVAR_INSN:
- newCode.putByte(opcode);
- u += 1;
- break;
- case ClassWriter.LABEL_INSN:
- if (opcode > 201) {
- // changes temporary opcodes 202 to 217 (inclusive), 218 and 219
- // to IFEQ ... JSR (inclusive), IFNULL and IFNONNULL
- opcode = opcode < 218 ? opcode - 49 : opcode - 20;
- label = u + readUnsignedShort(b, u + 1);
- } else {
- label = u + readShort(b, u + 1);
- }
- newOffset = getNewOffset(allIndexes, allSizes, u, label);
- if (resize[u]) {
- // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx <l> with
- // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the "opposite" opcode
- // of IFxxx (i.e., IFNE for IFEQ) and where <l'> designates the
- // instruction just after the GOTO_W.
- if (opcode == Constants.GOTO) {
- newCode.putByte(200); // GOTO_W
- } else if (opcode == Constants.JSR) {
- newCode.putByte(201); // JSR_W
- } else {
- newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1 : opcode ^ 1);
- newCode.putShort(8); // jump offset
- newCode.putByte(200); // GOTO_W
- newOffset -= 3; // newOffset now computed from start of GOTO_W
- }
- newCode.putInt(newOffset);
- } else {
- newCode.putByte(opcode);
- newCode.putShort(newOffset);
- }
- u += 3;
- break;
- case ClassWriter.LABELW_INSN:
- label = u + readInt(b, u + 1);
- newOffset = getNewOffset(allIndexes, allSizes, u, label);
- newCode.putByte(opcode);
- newCode.putInt(newOffset);
- u += 5;
- break;
- case ClassWriter.TABL_INSN:
- // skips 0 to 3 padding bytes
- v = u;
- u = u + 4 - (v & 3);
- // reads and copies instruction
- int source = newCode.length;
- newCode.putByte(Constants.TABLESWITCH);
- while (newCode.length % 4 != 0) {
- newCode.putByte(0);
- }
- label = v + readInt(b, u); u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- j = readInt(b, u); u += 4;
- newCode.putInt(j);
- j = readInt(b, u) - j + 1; u += 4;
- newCode.putInt(readInt(b, u - 4));
- for ( ; j > 0; --j) {
- label = v + readInt(b, u); u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- }
- break;
- case ClassWriter.LOOK_INSN:
- // skips 0 to 3 padding bytes
- v = u;
- u = u + 4 - (v & 3);
- // reads and copies instruction
- source = newCode.length;
- newCode.putByte(Constants.LOOKUPSWITCH);
- while (newCode.length % 4 != 0) {
- newCode.putByte(0);
- }
- label = v + readInt(b, u); u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- j = readInt(b, u); u += 4;
- newCode.putInt(j);
- for ( ; j > 0; --j) {
- newCode.putInt(readInt(b, u)); u += 4;
- label = v + readInt(b, u); u += 4;
- newOffset = getNewOffset(allIndexes, allSizes, v, label);
- newCode.putInt(newOffset);
- }
- break;
- case ClassWriter.WIDE_INSN:
- opcode = b[u + 1] & 0xFF;
- if (opcode == Constants.IINC) {
- newCode.putByteArray(b, u, 6);
- u += 6;
- } else {
- newCode.putByteArray(b, u, 4);
- u += 4;
- }
- break;
- case ClassWriter.VAR_INSN:
- case ClassWriter.SBYTE_INSN:
- case ClassWriter.LDC_INSN:
- newCode.putByteArray(b, u, 2);
- u += 2;
- break;
- case ClassWriter.SHORT_INSN:
- case ClassWriter.LDCW_INSN:
- case ClassWriter.FIELDORMETH_INSN:
- case ClassWriter.TYPE_INSN:
- case ClassWriter.IINC_INSN:
- newCode.putByteArray(b, u, 3);
- u += 3;
- break;
- case ClassWriter.ITFMETH_INSN:
- newCode.putByteArray(b, u, 5);
- u += 5;
- break;
- // case MANA_INSN:
- default:
- newCode.putByteArray(b, u, 4);
- u += 4;
- break;
- }
- }
-
- // updates the instructions addresses in the
- // catch, local var and line number tables
- if (catchTable != null) {
- b = catchTable.data;
- u = 0;
- while (u < catchTable.length) {
- writeShort(b, u, getNewOffset(
- allIndexes, allSizes, 0, readUnsignedShort(b, u)));
- writeShort(b, u + 2, getNewOffset(
- allIndexes, allSizes, 0, readUnsignedShort(b, u + 2)));
- writeShort(b, u + 4, getNewOffset(
- allIndexes, allSizes, 0, readUnsignedShort(b, u + 4)));
- u += 8;
- }
- }
- if (localVar != null) {
- b = localVar.data;
- u = 0;
- while (u < localVar.length) {
- label = readUnsignedShort(b, u);
- newOffset = getNewOffset(allIndexes, allSizes, 0, label);
- writeShort(b, u, newOffset);
- label += readUnsignedShort(b, u + 2);
- newOffset = getNewOffset(allIndexes, allSizes, 0, label) - newOffset;
- writeShort(b, u, newOffset);
- u += 10;
- }
- }
- if (lineNumber != null) {
- b = lineNumber.data;
- u = 0;
- while (u < lineNumber.length) {
- writeShort(b, u, getNewOffset(
- allIndexes, allSizes, 0, readUnsignedShort(b, u)));
- u += 4;
- }
- }
- // updates the labels of the other attributes
- while (cattrs != null) {
- Label[] labels = cattrs.getLabels();
- if (labels != null) {
- for (i = labels.length - 1; i >= 0; --i) {
- if (!labels[i].resized) {
- labels[i].position =
- getNewOffset(allIndexes, allSizes, 0, labels[i].position);
- labels[i].resized = true;
- }
- }
- }
- }
-
- // replaces old bytecodes with new ones
- code = newCode;
-
- // returns the positions of the resized instructions
- return indexes;
- }
-
- /**
- * Reads an unsigned short value in the given byte array.
- *
- * @param b a byte array.
- * @param index the start index of the value to be read.
- * @return the read value.
- */
-
- static int readUnsignedShort (final byte[] b, final int index) {
- return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
- }
-
- /**
- * Reads a signed short value in the given byte array.
- *
- * @param b a byte array.
- * @param index the start index of the value to be read.
- * @return the read value.
- */
-
- static short readShort (final byte[] b, final int index) {
- return (short)(((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
- }
-
- /**
- * Reads a signed int value in the given byte array.
- *
- * @param b a byte array.
- * @param index the start index of the value to be read.
- * @return the read value.
- */
-
- static int readInt (final byte[] b, final int index) {
- return ((b[index] & 0xFF) << 24) |
- ((b[index + 1] & 0xFF) << 16) |
- ((b[index + 2] & 0xFF) << 8) |
- (b[index + 3] & 0xFF);
- }
-
- /**
- * Writes a short value in the given byte array.
- *
- * @param b a byte array.
- * @param index where the first byte of the short value must be written.
- * @param s the value to be written in the given byte array.
- */
-
- static void writeShort (final byte[] b, final int index, final int s) {
- b[index] = (byte)(s >>> 8);
- b[index + 1] = (byte)s;
- }
-
- /**
- * Computes the future value of a bytecode offset.
- * <p>
- * Note: it is possible to have several entries for the same instruction
- * in the <tt>indexes</tt> and <tt>sizes</tt>: two entries (index=a,size=b)
- * and (index=a,size=b') are equivalent to a single entry (index=a,size=b+b').
- *
- * @param indexes current positions of the instructions to be resized. Each
- * instruction must be designated by the index of its <i>last</i> byte,
- * plus one (or, in other words, by the index of the <i>first</i> byte of
- * the <i>next</i> instruction).
- * @param sizes the number of bytes to be <i>added</i> to the above
- * instructions. More precisely, for each i < <tt>len</tt>,
- * <tt>sizes</tt>[i] bytes will be added at the end of the instruction
- * designated by <tt>indexes</tt>[i] or, if <tt>sizes</tt>[i] is
- * negative, the <i>last</i> |<tt>sizes[i]</tt>| bytes of the instruction
- * will be removed (the instruction size <i>must not</i> become negative
- * or null).
- * @param begin index of the first byte of the source instruction.
- * @param end index of the first byte of the target instruction.
- * @return the future value of the given bytecode offset.
- */
-
- static int getNewOffset (
- final int[] indexes,
- final int[] sizes,
- final int begin,
- final int end)
- {
- int offset = end - begin;
- for (int i = 0; i < indexes.length; ++i) {
- if (begin < indexes[i] && indexes[i] <= end) { // forward jump
- offset += sizes[i];
- } else if (end < indexes[i] && indexes[i] <= begin) { // backward jump
- offset -= sizes[i];
- }
- }
- return offset;
- }
-
- /**
- * Returns the current size of the bytecode of this method. This size just
- * includes the size of the bytecode instructions: it does not include the
- * size of the Exceptions, LocalVariableTable, LineNumberTable, Synthetic
- * and Deprecated attributes, if present.
- *
- * @return the current size of the bytecode of this method.
- */
-
- protected int getCodeSize () {
- return code.length;
- }
-
- /**
- * Returns the current bytecode of this method. This bytecode only contains
- * the instructions: it does not include the Exceptions, LocalVariableTable,
- * LineNumberTable, Synthetic and Deprecated attributes, if present.
- *
- * @return the current bytecode of this method. The bytecode is contained
- * between the index 0 (inclusive) and the index {@link #getCodeSize
- * getCodeSize} (exclusive).
- */
-
- protected byte[] getCode () {
- return code.data;
- }
-}
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- */
-
-package org.objectweb.asm;
-
-/**
- * Defines the JVM opcodes, access flags and array type codes. This interface
- * does not define all the JVM opcodes because some opcodes are automatically
- * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced
- * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n
- * opcodes are therefore not defined in this interface. Likewise for LDC,
- * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
- * JSR_W.
- */
-
-public interface Constants {
-
- // access flags
-
- int ACC_PUBLIC = 1;
- int ACC_PRIVATE = 2;
- int ACC_PROTECTED = 4;
- int ACC_STATIC = 8;
- int ACC_FINAL = 16;
- int ACC_SYNCHRONIZED = 32;
- int ACC_VOLATILE = 64; // fields
- int ACC_BRIDGE = 64; // methods
- int ACC_VARARGS = 128; // methods
- int ACC_TRANSIENT = 128; // fields
- int ACC_NATIVE = 256; // methods
- int ACC_ENUM = 256; // classes and fields
- // TODO find out what is the value for ACC_ANNOTATION constant
-
- int ACC_INTERFACE = 512;
- int ACC_ABSTRACT = 1024;
- int ACC_STRICT = 2048;
- int ACC_SUPER = 32;
-
- int ACC_SYNTHETIC = 65536;
- int ACC_DEPRECATED = 131072;
-
- // types for NEWARRAY
-
- int T_BOOLEAN = 4;
- int T_CHAR = 5;
- int T_FLOAT = 6;
- int T_DOUBLE = 7;
- int T_BYTE = 8;
- int T_SHORT = 9;
- int T_INT = 10;
- int T_LONG = 11;
-
- // opcodes // visit method (- = idem)
-
- int NOP = 0; // visitInsn
- int ACONST_NULL = 1; // -
- int ICONST_M1 = 2; // -
- int ICONST_0 = 3; // -
- int ICONST_1 = 4; // -
- int ICONST_2 = 5; // -
- int ICONST_3 = 6; // -
- int ICONST_4 = 7; // -
- int ICONST_5 = 8; // -
- int LCONST_0 = 9; // -
- int LCONST_1 = 10; // -
- int FCONST_0 = 11; // -
- int FCONST_1 = 12; // -
- int FCONST_2 = 13; // -
- int DCONST_0 = 14; // -
- int DCONST_1 = 15; // -
- int BIPUSH = 16; // visitIntInsn
- int SIPUSH = 17; // -
- int LDC = 18; // visitLdcInsn
- //int LDC_W = 19; // -
- //int LDC2_W = 20; // -
- int ILOAD = 21; // visitVarInsn
- int LLOAD = 22; // -
- int FLOAD = 23; // -
- int DLOAD = 24; // -
- int ALOAD = 25; // -
- //int ILOAD_0 = 26; // -
- //int ILOAD_1 = 27; // -
- //int ILOAD_2 = 28; // -
- //int ILOAD_3 = 29; // -
- //int LLOAD_0 = 30; // -
- //int LLOAD_1 = 31; // -
- //int LLOAD_2 = 32; // -
- //int LLOAD_3 = 33; // -
- //int FLOAD_0 = 34; // -
- //int FLOAD_1 = 35; // -
- //int FLOAD_2 = 36; // -
- //int FLOAD_3 = 37; // -
- //int DLOAD_0 = 38; // -
- //int DLOAD_1 = 39; // -
- //int DLOAD_2 = 40; // -
- //int DLOAD_3 = 41; // -
- //int ALOAD_0 = 42; // -
- //int ALOAD_1 = 43; // -
- //int ALOAD_2 = 44; // -
- //int ALOAD_3 = 45; // -
- int IALOAD = 46; // visitInsn
- int LALOAD = 47; // -
- int FALOAD = 48; // -
- int DALOAD = 49; // -
- int AALOAD = 50; // -
- int BALOAD = 51; // -
- int CALOAD = 52; // -
- int SALOAD = 53; // -
- int ISTORE = 54; // visitVarInsn
- int LSTORE = 55; // -
- int FSTORE = 56; // -
- int DSTORE = 57; // -
- int ASTORE = 58; // -
- //int ISTORE_0 = 59; // -
- //int ISTORE_1 = 60; // -
- //int ISTORE_2 = 61; // -
- //int ISTORE_3 = 62; // -
- //int LSTORE_0 = 63; // -
- //int LSTORE_1 = 64; // -
- //int LSTORE_2 = 65; // -
- //int LSTORE_3 = 66; // -
- //int FSTORE_0 = 67; // -
- //int FSTORE_1 = 68; // -
- //int FSTORE_2 = 69; // -
- //int FSTORE_3 = 70; // -
- //int DSTORE_0 = 71; // -
- //int DSTORE_1 = 72; // -
- //int DSTORE_2 = 73; // -
- //int DSTORE_3 = 74; // -
- //int ASTORE_0 = 75; // -
- //int ASTORE_1 = 76; // -
- //int ASTORE_2 = 77; // -
- //int ASTORE_3 = 78; // -
- int IASTORE = 79; // visitInsn
- int LASTORE = 80; // -
- int FASTORE = 81; // -
- int DASTORE = 82; // -
- int AASTORE = 83; // -
- int BASTORE = 84; // -
- int CASTORE = 85; // -
- int SASTORE = 86; // -
- int POP = 87; // -
- int POP2 = 88; // -
- int DUP = 89; // -
- int DUP_X1 = 90; // -
- int DUP_X2 = 91; // -
- int DUP2 = 92; // -
- int DUP2_X1 = 93; // -
- int DUP2_X2 = 94; // -
- int SWAP = 95; // -
- int IADD = 96; // -
- int LADD = 97; // -
- int FADD = 98; // -
- int DADD = 99; // -
- int ISUB = 100; // -
- int LSUB = 101; // -
- int FSUB = 102; // -
- int DSUB = 103; // -
- int IMUL = 104; // -
- int LMUL = 105; // -
- int FMUL = 106; // -
- int DMUL = 107; // -
- int IDIV = 108; // -
- int LDIV = 109; // -
- int FDIV = 110; // -
- int DDIV = 111; // -
- int IREM = 112; // -
- int LREM = 113; // -
- int FREM = 114; // -
- int DREM = 115; // -
- int INEG = 116; // -
- int LNEG = 117; // -
- int FNEG = 118; // -
- int DNEG = 119; // -
- int ISHL = 120; // -
- int LSHL = 121; // -
- int ISHR = 122; // -
- int LSHR = 123; // -
- int IUSHR = 124; // -
- int LUSHR = 125; // -
- int IAND = 126; // -
- int LAND = 127; // -
- int IOR = 128; // -
- int LOR = 129; // -
- int IXOR = 130; // -
- int LXOR = 131; // -
- int IINC = 132; // visitIincInsn
- int I2L = 133; // visitInsn
- int I2F = 134; // -
- int I2D = 135; // -
- int L2I = 136; // -
- int L2F = 137; // -
- int L2D = 138; // -
- int F2I = 139; // -
- int F2L = 140; // -
- int F2D = 141; // -
- int D2I = 142; // -
- int D2L = 143; // -
- int D2F = 144; // -
- int I2B = 145; // -
- int I2C = 146; // -
- int I2S = 147; // -
- int LCMP = 148; // -
- int FCMPL = 149; // -
- int FCMPG = 150; // -
- int DCMPL = 151; // -
- int DCMPG = 152; // -
- int IFEQ = 153; // visitJumpInsn
- int IFNE = 154; // -
- int IFLT = 155; // -
- int IFGE = 156; // -
- int IFGT = 157; // -
- int IFLE = 158; // -
- int IF_ICMPEQ = 159; // -
- int IF_ICMPNE = 160; // -
- int IF_ICMPLT = 161; // -
- int IF_ICMPGE = 162; // -
- int IF_ICMPGT = 163; // -
- int IF_ICMPLE = 164; // -
- int IF_ACMPEQ = 165; // -
- int IF_ACMPNE = 166; // -
- int GOTO = 167; // -
- int JSR = 168; // -
- int RET = 169; // visitVarInsn
- int TABLESWITCH = 170; // visiTableSwitchInsn
- int LOOKUPSWITCH = 171; // visitLookupSwitch
- int IRETURN = 172; // visitInsn
- int LRETURN = 173; // -
- int FRETURN = 174; // -
- int DRETURN = 175; // -
- int ARETURN = 176; // -
- int RETURN = 177; // -
- int GETSTATIC = 178; // visitFieldInsn
- int PUTSTATIC = 179; // -
- int GETFIELD = 180; // -
- int PUTFIELD = 181; // -
- int INVOKEVIRTUAL = 182; // visitMethodInsn
- int INVOKESPECIAL = 183; // -
- int INVOKESTATIC = 184; // -
- int INVOKEINTERFACE = 185; // -
- //int UNUSED = 186; // NOT VISITED
- int NEW = 187; // visitTypeInsn
- int NEWARRAY = 188; // visitIntInsn
- int ANEWARRAY = 189; // visitTypeInsn
- int ARRAYLENGTH = 190; // visitInsn
- int ATHROW = 191; // -
- int CHECKCAST = 192; // visitTypeInsn
- int INSTANCEOF = 193; // -
- int MONITORENTER = 194; // visitInsn
- int MONITOREXIT = 195; // -
- //int WIDE = 196; // NOT VISITED
- int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
- int IFNULL = 198; // visitJumpInsn
- int IFNONNULL = 199; // -
- //int GOTO_W = 200; // -
- //int JSR_W = 201; // -
-}
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- */
-
-package org.objectweb.asm;
-
-/**
- * An edge in the control flow graph of a method body. See {@link Label Label}.
- */
-
-class Edge {
-
- /**
- * The (relative) stack size in the basic block from which this edge
- * originates. This size is equal to the stack size at the "jump" instruction
- * to which this edge corresponds, relatively to the stack size at the
- * beginning of the originating basic block.
- */
-
- int stackSize;
-
- /**
- * The successor block of the basic block from which this edge originates.
- */
-
- Label successor;
-
- /**
- * The next edge in the list of successors of the originating basic block.
- * See {@link Label#successors successors}.
- */
-
- Edge next;
-
- /**
- * The next available edge in the pool. See {@link CodeWriter#pool pool}.
- */
-
- Edge poolNext;
-}
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- */
-
-package org.objectweb.asm;
-
-/**
- * A constant pool item. Constant pool items can be created with the 'newXXX'
- * methods in the {@link ClassWriter} class.
- */
-
-final class Item {
-
- /**
- * Index of this item in the constant pool.
- */
-
- short index;
-
- /**
- * Type of this constant pool item. A single class is used to represent all
- * constant pool item types, in order to minimize the bytecode size of this
- * package. The value of this field is one of the constants defined in the
- * {@link ClassWriter ClassWriter} class.
- */
-
- int type;
-
- /**
- * Value of this item, for a {@link ClassWriter#INT INT} item.
- */
-
- int intVal;
-
- /**
- * Value of this item, for a {@link ClassWriter#LONG LONG} item.
- */
-
- long longVal;
-
- /**
- * Value of this item, for a {@link ClassWriter#FLOAT FLOAT} item.
- */
-
- float floatVal;
-
- /**
- * Value of this item, for a {@link ClassWriter#DOUBLE DOUBLE} item.
- */
-
- double doubleVal;
-
- /**
- * First part of the value of this item, for items that do not hold a
- * primitive value.
- */
-
- String strVal1;
-
- /**
- * Second part of the value of this item, for items that do not hold a
- * primitive value.
- */
-
- String strVal2;
-
- /**
- * Third part of the value of this item, for items that do not hold a
- * primitive value.
- */
-
- String strVal3;
-
- /**
- * The hash code value of this constant pool item.
- */
-
- int hashCode;
-
- /**
- * Link to another constant pool item, used for collision lists in the
- * constant pool's hash table.
- */
-
- Item next;
-
- /**
- * Constructs an uninitialized {@link Item Item} object.
- */
-
- Item () {
- }
-
- /**
- * Constructs a copy of the given item.
- *
- * @param index index of the item to be constructed.
- * @param i the item that must be copied into the item to be constructed.
- */
-
- Item (final short index, final Item i) {
- this.index = index;
- type = i.type;
- intVal = i.intVal;
- longVal = i.longVal;
- floatVal = i.floatVal;
- doubleVal = i.doubleVal;
- strVal1 = i.strVal1;
- strVal2 = i.strVal2;
- strVal3 = i.strVal3;
- hashCode = i.hashCode;
- }
-
- /**
- * Sets this item to an {@link ClassWriter#INT INT} item.
- *
- * @param intVal the value of this item.
- */
-
- void set (final int intVal) {
- this.type = ClassWriter.INT;
- this.intVal = intVal;
- this.hashCode = 0x7FFFFFFF & (type + intVal);
- }
-
- /**
- * Sets this item to a {@link ClassWriter#LONG LONG} item.
- *
- * @param longVal the value of this item.
- */
-
- void set (final long longVal) {
- this.type = ClassWriter.LONG;
- this.longVal = longVal;
- this.hashCode = 0x7FFFFFFF & (type + (int)longVal);
- }
-
- /**
- * Sets this item to a {@link ClassWriter#FLOAT FLOAT} item.
- *
- * @param floatVal the value of this item.
- */
-
- void set (final float floatVal) {
- this.type = ClassWriter.FLOAT;
- this.floatVal = floatVal;
- this.hashCode = 0x7FFFFFFF & (type + (int)floatVal);
- }
-
- /**
- * Sets this item to a {@link ClassWriter#DOUBLE DOUBLE} item.
- *
- * @param doubleVal the value of this item.
- */
-
- void set (final double doubleVal) {
- this.type = ClassWriter.DOUBLE;
- this.doubleVal = doubleVal;
- this.hashCode = 0x7FFFFFFF & (type + (int)doubleVal);
- }
-
- /**
- * Sets this item to an item that do not hold a primitive value.
- *
- * @param type the type of this item.
- * @param strVal1 first part of the value of this item.
- * @param strVal2 second part of the value of this item.
- * @param strVal3 third part of the value of this item.
- */
-
- void set (
- final int type,
- final String strVal1,
- final String strVal2,
- final String strVal3)
- {
- this.type = type;
- this.strVal1 = strVal1;
- this.strVal2 = strVal2;
- this.strVal3 = strVal3;
- switch (type) {
- case ClassWriter.UTF8:
- case ClassWriter.STR:
- case ClassWriter.CLASS:
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
- return;
- case ClassWriter.NAME_TYPE:
- hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()*strVal2.hashCode());
- return;
- //case ClassWriter.FIELD:
- //case ClassWriter.METH:
- //case ClassWriter.IMETH:
- default:
- hashCode = 0x7FFFFFFF & (type +
- strVal1.hashCode()*strVal2.hashCode()*strVal3.hashCode());
- }
- }
-
- /**
- * Indicates if the given item is equal to this one.
- *
- * @param i the item to be compared to this one.
- * @return <tt>true</tt> if the given item if equal to this one,
- * <tt>false</tt> otherwise.
- */
-
- boolean isEqualTo (final Item i) {
- if (i.type == type) {
- switch (type) {
- case ClassWriter.INT:
- return i.intVal == intVal;
- case ClassWriter.LONG:
- return i.longVal == longVal;
- case ClassWriter.FLOAT:
- return i.floatVal == floatVal;
- case ClassWriter.DOUBLE:
- return i.doubleVal == doubleVal;
- case ClassWriter.UTF8:
- case ClassWriter.STR:
- case ClassWriter.CLASS:
- return i.strVal1.equals(strVal1);
- case ClassWriter.NAME_TYPE:
- return i.strVal1.equals(strVal1) &&
- i.strVal2.equals(strVal2);
- //case ClassWriter.FIELD:
- //case ClassWriter.METH:
- //case ClassWriter.IMETH:
- default:
- return i.strVal1.equals(strVal1) &&
- i.strVal2.equals(strVal2) &&
- i.strVal3.equals(strVal3);
- }
- }
- return false;
- }
-}
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- */
-
-package org.objectweb.asm;
-
-/**
- * A label represents a position in the bytecode of a method. Labels are used
- * for jump, goto, and switch instructions, and for try catch blocks.
- */
-
-public class Label {
-
- /**
- * The code writer to which this label belongs, or <tt>null</tt> if unknown.
- */
-
- CodeWriter owner;
-
- /**
- * Indicates if the position of this label is known.
- */
-
- boolean resolved;
-
- /**
- * The position of this label in the code, if known.
- */
-
- int position;
-
- /**
- * If the label position has been updated, after instruction resizing.
- */
-
- boolean resized;
-
- /**
- * Number of forward references to this label, times two.
- */
-
- private int referenceCount;
-
- /**
- * Informations about forward references. Each forward reference is described
- * by two consecutive integers in this array: the first one is the position
- * of the first byte of the bytecode instruction that contains the forward
- * reference, while the second is the position of the first byte of the
- * forward reference itself. In fact the sign of the first integer indicates
- * if this reference uses 2 or 4 bytes, and its absolute value gives the
- * position of the bytecode instruction.
- */
-
- private int[] srcAndRefPositions;
-
- // --------------------------------------------------------------------------
- // Fields for the control flow graph analysis algorithm (used to compute the
- // maximum stack size). A control flow graph contains one node per "basic
- // block", and one edge per "jump" from one basic block to another. Each node
- // (i.e., each basic block) is represented by the Label object that
- // corresponds to the first instruction of this basic block. Each node also
- // stores the list of it successors in the graph, as a linked list of Edge
- // objects.
- // --------------------------------------------------------------------------
-
- /**
- * The stack size at the beginning of this basic block.
- * This size is initially unknown. It is computed by the control flow
- * analysis algorithm (see {@link CodeWriter#visitMaxs visitMaxs}).
- */
-
- int beginStackSize;
-
- /**
- * The (relative) maximum stack size corresponding to this basic block. This
- * size is relative to the stack size at the beginning of the basic block,
- * i.e., the true maximum stack size is equal to {@link #beginStackSize
- * beginStackSize} + {@link #maxStackSize maxStackSize}.
- */
-
- int maxStackSize;
-
- /**
- * The successors of this node in the control flow graph. These successors
- * are stored in a linked list of {@link Edge Edge} objects, linked to each
- * other by their {@link Edge#next} field.
- */
-
- Edge successors;
-
- /**
- * The next basic block in the basic block stack.
- * See {@link CodeWriter#visitMaxs visitMaxs}.
- */
-
- Label next;
-
- /**
- * <tt>true</tt> if this basic block has been pushed in the basic block stack.
- * See {@link CodeWriter#visitMaxs visitMaxs}.
- */
-
- boolean pushed;
-
- // --------------------------------------------------------------------------
- // Constructor
- // --------------------------------------------------------------------------
-
- /**
- * Constructs a new label.
- */
-
- public Label () {
- }
-
- // --------------------------------------------------------------------------
- // Methods to compute offsets and to manage forward references
- // --------------------------------------------------------------------------
-
- /**
- * Returns the offset corresponding to this label. This offset is computed
- * from the start of the method's bytecode. <i>This method is intended for
- * {@link Attribute} sub classes, and is normally not needed by class
- * generators or adapters.</i>
- *
- * @return the offset corresponding to this label.
- * @throws IllegalStateException if this label is not resolved yet.
- */
-
- public int getOffset () {
- if (!resolved) {
- throw new IllegalStateException(
- "Label offset position has not been resolved yet");
- }
- return position;
- }
-
- /**
- * Puts a reference to this label in the bytecode of a method. If the position
- * of the label is known, the offset is computed and written directly.
- * Otherwise, a null offset is written and a new forward reference is declared
- * for this label.
- *
- * @param owner the code writer that calls this method.
- * @param out the bytecode of the method.
- * @param source the position of first byte of the bytecode instruction that
- * contains this label.
- * @param wideOffset <tt>true</tt> if the reference must be stored in 4 bytes,
- * or <tt>false</tt> if it must be stored with 2 bytes.
- * @throws IllegalArgumentException if this label has not been created by the
- * given code writer.
- */
-
- void put (
- final CodeWriter owner,
- final ByteVector out,
- final int source,
- final boolean wideOffset)
- {
- if (CodeWriter.CHECK) {
- if (this.owner == null) {
- this.owner = owner;
- } else if (this.owner != owner) {
- throw new IllegalArgumentException();
- }
- }
- if (resolved) {
- if (wideOffset) {
- out.putInt(position - source);
- } else {
- out.putShort(position - source);
- }
- } else {
- if (wideOffset) {
- addReference(-1 - source, out.length);
- out.putInt(-1);
- } else {
- addReference(source, out.length);
- out.putShort(-1);
- }
- }
- }
-
- /**
- * Adds a forward reference to this label. This method must be called only for
- * a true forward reference, i.e. only if this label is not resolved yet. For
- * backward references, the offset of the reference can be, and must be,
- * computed and stored directly.
- *
- * @param sourcePosition the position of the referencing instruction. This
- * position will be used to compute the offset of this forward reference.
- * @param referencePosition the position where the offset for this forward
- * reference must be stored.
- */
-
- private void addReference (
- final int sourcePosition,
- final int referencePosition)
- {
- if (srcAndRefPositions == null) {
- srcAndRefPositions = new int[6];
- }
- if (referenceCount >= srcAndRefPositions.length) {
- int[] a = new int[srcAndRefPositions.length + 6];
- System.arraycopy(srcAndRefPositions, 0, a, 0, srcAndRefPositions.length);
- srcAndRefPositions = a;
- }
- srcAndRefPositions[referenceCount++] = sourcePosition;
- srcAndRefPositions[referenceCount++] = referencePosition;
- }
-
- /**
- * Resolves all forward references to this label. This method must be called
- * when this label is added to the bytecode of the method, i.e. when its
- * position becomes known. This method fills in the blanks that where left in
- * the bytecode by each forward reference previously added to this label.
- *
- * @param owner the code writer that calls this method.
- * @param position the position of this label in the bytecode.
- * @param data the bytecode of the method.
- * @return <tt>true</tt> if a blank that was left for this label was to small
- * to store the offset. In such a case the corresponding jump instruction
- * is replaced with a pseudo instruction (using unused opcodes) using an
- * unsigned two bytes offset. These pseudo instructions will need to be
- * replaced with true instructions with wider offsets (4 bytes instead of
- * 2). This is done in {@link CodeWriter#resizeInstructions}.
- * @throws IllegalArgumentException if this label has already been resolved,
- * or if it has not been created by the given code writer.
- */
-
- boolean resolve (
- final CodeWriter owner,
- final int position,
- final byte[] data)
- {
- if (CodeWriter.CHECK) {
- if (this.owner == null) {
- this.owner = owner;
- }
- if (resolved || this.owner != owner) {
- throw new IllegalArgumentException();
- }
- }
- boolean needUpdate = false;
- this.resolved = true;
- this.position = position;
- int i = 0;
- while (i < referenceCount) {
- int source = srcAndRefPositions[i++];
- int reference = srcAndRefPositions[i++];
- int offset;
- if (source >= 0) {
- offset = position - source;
- if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
- // changes the opcode of the jump instruction, in order to be able to
- // find it later (see resizeInstructions in CodeWriter). These
- // temporary opcodes are similar to jump instruction opcodes, except
- // that the 2 bytes offset is unsigned (and can therefore represent
- // values from 0 to 65535, which is sufficient since the size of a
- // method is limited to 65535 bytes).
- int opcode = data[reference - 1] & 0xFF;
- if (opcode <= Constants.JSR) {
- // changes IFEQ ... JSR to opcodes 202 to 217 (inclusive)
- data[reference - 1] = (byte)(opcode + 49);
- } else {
- // changes IFNULL and IFNONNULL to opcodes 218 and 219 (inclusive)
- data[reference - 1] = (byte)(opcode + 20);
- }
- needUpdate = true;
- }
- data[reference++] = (byte)(offset >>> 8);
- data[reference] = (byte)offset;
- } else {
- offset = position + source + 1;
- data[reference++] = (byte)(offset >>> 24);
- data[reference++] = (byte)(offset >>> 16);
- data[reference++] = (byte)(offset >>> 8);
- data[reference] = (byte)offset;
- }
- }
- return needUpdate;
- }
-
- // --------------------------------------------------------------------------
- // Overriden Object methods
- // --------------------------------------------------------------------------
-
- /**
- * Returns a string representation of this label.
- *
- * @return a string representation of this label.
- */
-
- public String toString () {
- return "L" + System.identityHashCode(this);
- }
-}
+++ /dev/null
-/***
- * ASM: a very small and fast Java bytecode manipulation framework
- * Copyright (c) 2000,2002,2003 INRIA, France Telecom
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Contact: Eric.Bruneton@rd.francetelecom.com
- *
- * Author: Eric Bruneton
- * with contributions from: Chris Nokleberg
- */
-
-package org.objectweb.asm;
-
-import java.lang.reflect.Method;
-
-/**
- * A Java type. This class can be used to make it easier to manipulate type
- * and method descriptors.
- */
-
-public class Type {
-
- /**
- * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
- */
-
- public final static int VOID = 0;
-
- /**
- * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
- */
-
- public final static int BOOLEAN = 1;
-
- /**
- * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
- */
-
- public final static int CHAR = 2;
-
- /**
- * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
- */
-
- public final static int BYTE = 3;
-
- /**
- * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
- */
-
- public final static int SHORT = 4;
-
- /**
- * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
- */
-
- public final static int INT = 5;
-
- /**
- * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
- */
-
- public final static int FLOAT = 6;
-
- /**
- * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
- */
-
- public final static int LONG = 7;
-
- /**
- * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
- */
-
- public final static int DOUBLE = 8;
-
- /**
- * The sort of array reference types. See {@link #getSort getSort}.
- */
-
- public final static int ARRAY = 9;
-
- /**
- * The sort of object reference type. See {@link #getSort getSort}.
- */
-
- public final static int OBJECT = 10;
-
- /**
- * The <tt>void</tt> type.
- */
-
- public final static Type VOID_TYPE = new Type(VOID);
-
- /**
- * The <tt>boolean</tt> type.
- */
-
- public final static Type BOOLEAN_TYPE = new Type(BOOLEAN);
-
- /**
- * The <tt>char</tt> type.
- */
-
- public final static Type CHAR_TYPE = new Type(CHAR);
-
- /**
- * The <tt>byte</tt> type.
- */
-
- public final static Type BYTE_TYPE = new Type(BYTE);
-
- /**
- * The <tt>short</tt> type.
- */
-
- public final static Type SHORT_TYPE = new Type(SHORT);
-
- /**
- * The <tt>int</tt> type.
- */
-
- public final static Type INT_TYPE = new Type(INT);
-
- /**
- * The <tt>float</tt> type.
- */
-
- public final static Type FLOAT_TYPE = new Type(FLOAT);
-
- /**
- * The <tt>long</tt> type.
- */
-
- public final static Type LONG_TYPE = new Type(LONG);
-
- /**
- * The <tt>double</tt> type.
- */
-
- public final static Type DOUBLE_TYPE = new Type(DOUBLE);
-
- // --------------------------------------------------------------------------
- // Fields
- // --------------------------------------------------------------------------
-
- /**
- * The sort of this Java type.
- */
-
- private final int sort;
-
- /**
- * A buffer containing the descriptor of this Java type.
- * This field is only used for reference types.
- */
-
- private char[] buf;
-
- /**
- * The offset of the descriptor of this Java type in {@link #buf buf}.
- * This field is only used for reference types.
- */
-
- private int off;
-
- /**
- * The length of the descriptor of this Java type.
- */
-
- private int len;
-
- // --------------------------------------------------------------------------
- // Constructors
- // --------------------------------------------------------------------------
-
- /**
- * Constructs a primitive type.
- *
- * @param sort the sort of the primitive type to be constructed.
- */
-
- private Type (final int sort) {
- this.sort = sort;
- this.len = 1;
- }
-
- /**
- * Constructs a reference type.
- *
- * @param sort the sort of the reference type to be constructed.
- * @param buf a buffer containing the descriptor of the previous type.
- * @param off the offset of this descriptor in the previous buffer.
- * @param len the length of this descriptor.
- */
-
- private Type (
- final int sort,
- final char[] buf,
- final int off,
- final int len)
- {
- this.sort = sort;
- this.buf = buf;
- this.off = off;
- this.len = len;
- }
-
- /**
- * Returns the Java type corresponding to the given type descriptor.
- *
- * @param typeDescriptor a type descriptor.
- * @return the Java type corresponding to the given type descriptor.
- */
-
- public static Type getType (final String typeDescriptor) {
- return getType(typeDescriptor.toCharArray(), 0);
- }
-
- /**
- * Returns the Java type corresponding to the given class.
- *
- * @param c a class.
- * @return the Java type corresponding to the given class.
- */
-
- public static Type getType (final Class c) {
- if (c.isPrimitive()) {
- if (c == Integer.TYPE) {
- return INT_TYPE;
- } else if (c == Void.TYPE) {
- return VOID_TYPE;
- } else if (c == Boolean.TYPE) {
- return BOOLEAN_TYPE;
- } else if (c == Byte.TYPE) {
- return BYTE_TYPE;
- } else if (c == Character.TYPE) {
- return CHAR_TYPE;
- } else if (c == Short.TYPE) {
- return SHORT_TYPE;
- } else if (c == Double.TYPE) {
- return DOUBLE_TYPE;
- } else if (c == Float.TYPE) {
- return FLOAT_TYPE;
- } else /*if (c == Long.TYPE)*/ {
- return LONG_TYPE;
- }
- } else {
- return getType(getDescriptor(c));
- }
- }
-
- /**
- * Returns the Java types corresponding to the argument types of the given
- * method descriptor.
- *
- * @param methodDescriptor a method descriptor.
- * @return the Java types corresponding to the argument types of the given
- * method descriptor.
- */
-
- public static Type[] getArgumentTypes (final String methodDescriptor) {
- char[] buf = methodDescriptor.toCharArray();
- int off = 1;
- int size = 0;
- while (true) {
- char car = buf[off++];
- if (car == ')') {
- break;
- } else if (car == 'L') {
- while (buf[off++] != ';') {
- }
- ++size;
- } else if (car != '[') {
- ++size;
- }
- }
- Type[] args = new Type[size];
- off = 1;
- size = 0;
- while (buf[off] != ')') {
- args[size] = getType(buf, off);
- off += args[size].len;
- size += 1;
- }
- return args;
- }
-
- /**
- * Returns the Java types corresponding to the argument types of the given
- * method.
- *
- * @param method a method.
- * @return the Java types corresponding to the argument types of the given
- * method.
- */
-
- public static Type[] getArgumentTypes (final Method method) {
- Class[] classes = method.getParameterTypes();
- Type[] types = new Type[classes.length];
- for (int i = classes.length - 1; i >= 0; --i) {
- types[i] = getType(classes[i]);
- }
- return types;
- }
-
- /**
- * Returns the Java type corresponding to the return type of the given
- * method descriptor.
- *
- * @param methodDescriptor a method descriptor.
- * @return the Java type corresponding to the return type of the given
- * method descriptor.
- */
-
- public static Type getReturnType (final String methodDescriptor) {
- char[] buf = methodDescriptor.toCharArray();
- return getType(buf, methodDescriptor.indexOf(')') + 1);
- }
-
- /**
- * Returns the Java type corresponding to the return type of the given
- * method.
- *
- * @param method a method.
- * @return the Java type corresponding to the return type of the given
- * method.
- */
-
- public static Type getReturnType (final Method method) {
- return getType(method.getReturnType());
- }
-
- /**
- * Returns the Java type corresponding to the given type descriptor.
- *
- * @param buf a buffer containing a type descriptor.
- * @param off the offset of this descriptor in the previous buffer.
- * @return the Java type corresponding to the given type descriptor.
- */
-
- private static Type getType (final char[] buf, final int off) {
- int len;
- switch (buf[off]) {
- case 'V': return VOID_TYPE;
- case 'Z': return BOOLEAN_TYPE;
- case 'C': return CHAR_TYPE;
- case 'B': return BYTE_TYPE;
- case 'S': return SHORT_TYPE;
- case 'I': return INT_TYPE;
- case 'F': return FLOAT_TYPE;
- case 'J': return LONG_TYPE;
- case 'D': return DOUBLE_TYPE;
- case '[':
- len = 1;
- while (buf[off + len] == '[') {
- ++len;
- }
- if (buf[off + len] == 'L') {
- ++len;
- while (buf[off + len] != ';') {
- ++len;
- }
- }
- return new Type(ARRAY, buf, off, len + 1);
- //case 'L':
- default:
- len = 1;
- while (buf[off + len] != ';') {
- ++len;
- }
- return new Type(OBJECT, buf, off, len + 1);
- }
- }
-
- // --------------------------------------------------------------------------
- // Accessors
- // --------------------------------------------------------------------------
-
- /**
- * Returns the sort of this Java type.
- *
- * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR},
- * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT}, {@link
- * #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE}, {@link
- * #ARRAY ARRAY} or {@link #OBJECT OBJECT}.
- */
-
- public int getSort () {
- return sort;
- }
-
- /**
- * Returns the number of dimensions of this array type.
- * This method should only be used for an array type.
- *
- * @return the number of dimensions of this array type.
- */
-
- public int getDimensions () {
- int i = 1;
- while (buf[off + i] == '[') {
- ++i;
- }
- return i;
- }
-
- /**
- * Returns the type of the elements of this array type.
- * This method should only be used for an array type.
- *
- * @return Returns the type of the elements of this array type.
- */
-
- public Type getElementType () {
- return getType(buf, off + getDimensions());
- }
-
- /**
- * Returns the name of the class corresponding to this object type.
- * This method should only be used for an object type.
- *
- * @return the fully qualified name of the class corresponding to this object
- * type.
- */
-
- public String getClassName () {
- return new String(buf, off + 1, len - 2).replace('/', '.');
- }
-
- /**
- * Returns the internal name of the class corresponding to this object type.
- * The internal name of a class is its fully qualified name, where '.' are
- * replaced by '/'. * This method should only be used for an object type.
- *
- * @return the internal name of the class corresponding to this object type.
- */
-
- public String getInternalName () {
- return new String(buf, off + 1, len - 2);
- }
-
- // --------------------------------------------------------------------------
- // Conversion to type descriptors
- // --------------------------------------------------------------------------
-
- /**
- * Returns the descriptor corresponding to this Java type.
- *
- * @return the descriptor corresponding to this Java type.
- */
-
- public String getDescriptor () {
- StringBuffer buf = new StringBuffer();
- getDescriptor(buf);
- return buf.toString();
- }
-
- /**
- * Returns the descriptor corresponding to the given argument and return
- * types.
- *
- * @param returnType the return type of the method.
- * @param argumentTypes the argument types of the method.
- * @return the descriptor corresponding to the given argument and return
- * types.
- */
-
- public static String getMethodDescriptor (
- final Type returnType,
- final Type[] argumentTypes)
- {
- StringBuffer buf = new StringBuffer();
- buf.append('(');
- for (int i = 0; i < argumentTypes.length; ++i) {
- argumentTypes[i].getDescriptor(buf);
- }
- buf.append(')');
- returnType.getDescriptor(buf);
- return buf.toString();
- }
-
- /**
- * Appends the descriptor corresponding to this Java type to the given string
- * buffer.
- *
- * @param buf the string buffer to which the descriptor must be appended.
- */
-
- private void getDescriptor (final StringBuffer buf) {
- switch (sort) {
- case VOID: buf.append('V'); return;
- case BOOLEAN: buf.append('Z'); return;
- case CHAR: buf.append('C'); return;
- case BYTE: buf.append('B'); return;
- case SHORT: buf.append('S'); return;
- case INT: buf.append('I'); return;
- case FLOAT: buf.append('F'); return;
- case LONG: buf.append('J'); return;
- case DOUBLE: buf.append('D'); return;
- //case ARRAY:
- //case OBJECT:
- default: buf.append(this.buf, off, len);
- }
- }
-
- // --------------------------------------------------------------------------
- // Direct conversion from classes to type descriptors,
- // without intermediate Type objects
- // --------------------------------------------------------------------------
-
- /**
- * Returns the internal name of the given class. The internal name of a class
- * is its fully qualified name, where '.' are replaced by '/'.
- *
- * @param c an object class.
- * @return the internal name of the given class.
- */
-
- public static String getInternalName (final Class c) {
- return c.getName().replace('.', '/');
- }
-
- /**
- * Returns the descriptor corresponding to the given Java type.
- *
- * @param c an object class, a primitive class or an array class.
- * @return the descriptor corresponding to the given class.
- */
-
- public static String getDescriptor (final Class c) {
- StringBuffer buf = new StringBuffer();
- getDescriptor(buf, c);
- return buf.toString();
- }
-
- /**
- * Returns the descriptor corresponding to the given method.
- *
- * @param m a {@link Method Method} object.
- * @return the descriptor of the given method.
- */
-
- public static String getMethodDescriptor (final Method m) {
- Class[] parameters = m.getParameterTypes();
- StringBuffer buf = new StringBuffer();
- buf.append('(');
- for (int i = 0; i < parameters.length; ++i) {
- getDescriptor(buf, parameters[i]);
- }
- buf.append(')');
- getDescriptor(buf, m.getReturnType());
- return buf.toString();
- }
-
- /**
- * Appends the descriptor of the given class to the given string buffer.
- *
- * @param buf the string buffer to which the descriptor must be appended.
- * @param c the class whose descriptor must be computed.
- */
-
- private static void getDescriptor (final StringBuffer buf, final Class c) {
- Class d = c;
- while (true) {
- if (d.isPrimitive()) {
- char car;
- if (d == Integer.TYPE) {
- car = 'I';
- } else if (d == Void.TYPE) {
- car = 'V';
- } else if (d == Boolean.TYPE) {
- car = 'Z';
- } else if (d == Byte.TYPE) {
- car = 'B';
- } else if (d == Character.TYPE) {
- car = 'C';
- } else if (d == Short.TYPE) {
- car = 'S';
- } else if (d == Double.TYPE) {
- car = 'D';
- } else if (d == Float.TYPE) {
- car = 'F';
- } else /*if (d == Long.TYPE)*/ {
- car = 'J';
- }
- buf.append(car);
- return;
- } else if (d.isArray()) {
- buf.append('[');
- d = d.getComponentType();
- } else {
- buf.append('L');
- String name = d.getName();
- int len = name.length();
- for (int i = 0; i < len; ++i) {
- char car = name.charAt(i);
- buf.append(car == '.' ? '/' : car);
- }
- buf.append(';');
- return;
- }
- }
- }
-
- // --------------------------------------------------------------------------
- // Corresponding size and opcodes
- // --------------------------------------------------------------------------
-
- /**
- * Returns the size of values of this type.
- *
- * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
- * <tt>double</tt>, and 1 otherwise.
- */
-
- public int getSize () {
- return (sort == LONG || sort == DOUBLE ? 2 : 1);
- }
-
- /**
- * Returns a JVM instruction opcode adapted to this Java type.
- *
- * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
- * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
- * ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
- * @return an opcode that is similar to the given opcode, but adapted to this
- * Java type. For example, if this type is <tt>float</tt> and
- * <tt>opcode</tt> is IRETURN, this method returns FRETURN.
- */
-
- public int getOpcode (final int opcode) {
- if (opcode == Constants.IALOAD || opcode == Constants.IASTORE) {
- switch (sort) {
- case BOOLEAN:
- case BYTE:
- return opcode + 5;
- case CHAR:
- return opcode + 6;
- case SHORT:
- return opcode + 7;
- case INT:
- return opcode;
- case FLOAT:
- return opcode + 2;
- case LONG:
- return opcode + 1;
- case DOUBLE:
- return opcode + 3;
- //case ARRAY:
- //case OBJECT:
- default:
- return opcode + 4;
- }
- } else {
- switch (sort) {
- case VOID:
- return opcode + 5;
- case BOOLEAN:
- case CHAR:
- case BYTE:
- case SHORT:
- case INT:
- return opcode;
- case FLOAT:
- return opcode + 2;
- case LONG:
- return opcode + 1;
- case DOUBLE:
- return opcode + 3;
- //case ARRAY:
- //case OBJECT:
- default:
- return opcode + 4;
- }
- }
- }
-
- // --------------------------------------------------------------------------
- // Equals, hashCode and toString
- // --------------------------------------------------------------------------
-
- /**
- * Tests if the given object is equal to this type.
- *
- * @param o the object to be compared to this type.
- * @return <tt>true</tt> if the given object is equal to this type.
- */
-
- public boolean equals (final Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || !(o instanceof Type)) {
- return false;
- }
- Type t = (Type)o;
- if (sort != t.sort) {
- return false;
- }
- if (sort == Type.OBJECT || sort == Type.ARRAY) {
- if (len != t.len) {
- return false;
- }
- for (int i = off, j = t.off, end = i + len; i < end; i++, j++) {
- if (buf[i] != t.buf[j]) {
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * Returns a hash code value for this type.
- *
- * @return a hash code value for this type.
- */
-
- public int hashCode () {
- int hc = 13 * sort;
- if (sort == Type.OBJECT || sort == Type.ARRAY) {
- for (int i = off, end = i + len; i < end; i++) {
- hc = 17 * (hc + buf[i]);
- }
- }
- return hc;
- }
-
- /**
- * Returns a string representation of this type.
- *
- * @return the descriptor of this type.
- */
-
- public String toString () {
- return getDescriptor();
- }
-}