Removed JVM compiler
parent
d9f39dbe2e
commit
8e51df2c81
|
@ -29,19 +29,14 @@
|
|||
|
||||
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;
|
||||
|
||||
|
@ -49,11 +44,10 @@ public class FactorCompoundDefinition extends FactorWordDefinition
|
|||
/**
|
||||
* 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
|
||||
|
@ -63,272 +57,8 @@ public class FactorCompoundDefinition extends FactorWordDefinition
|
|||
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)
|
||||
|
@ -343,7 +73,7 @@ public class FactorCompoundDefinition extends FactorWordDefinition
|
|||
} //}}}
|
||||
|
||||
//{{{ toList() method
|
||||
public Cons toList(FactorInterpreter interp)
|
||||
public Cons toList()
|
||||
{
|
||||
return definition;
|
||||
} //}}}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
package factor;
|
||||
|
||||
import factor.compiler.FactorCompiler;
|
||||
import factor.math.*;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.*;
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
package factor;
|
||||
|
||||
import factor.compiler.*;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -47,7 +46,7 @@ public abstract class FactorPrimitiveDefinition extends FactorWordDefinition
|
|||
} //}}}
|
||||
|
||||
//{{{ fromList() method
|
||||
public void fromList(Cons cons, FactorInterpreter interp)
|
||||
public void fromList(Cons cons)
|
||||
{
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,7 @@
|
|||
|
||||
package factor;
|
||||
|
||||
import factor.compiler.*;
|
||||
import java.util.*;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
/**
|
||||
* ~<< name ... -- >>~
|
||||
|
@ -59,11 +57,11 @@ public class FactorShuffleDefinition extends FactorWordDefinition
|
|||
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
|
||||
|
@ -113,32 +111,6 @@ public class FactorShuffleDefinition extends FactorWordDefinition
|
|||
}
|
||||
} //}}}
|
||||
|
||||
//{{{ 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
|
||||
|
@ -223,7 +195,7 @@ public class FactorShuffleDefinition extends FactorWordDefinition
|
|||
} //}}}
|
||||
|
||||
//{{{ fromList() method
|
||||
public void fromList(Cons definition, FactorInterpreter interp)
|
||||
public void fromList(Cons definition)
|
||||
throws FactorRuntimeException
|
||||
{
|
||||
String f = "--";
|
||||
|
@ -345,7 +317,7 @@ public class FactorShuffleDefinition extends FactorWordDefinition
|
|||
} //}}}
|
||||
|
||||
//{{{ toList() method
|
||||
public Cons toList(FactorInterpreter interp)
|
||||
public Cons toList()
|
||||
{
|
||||
Cons list = null;
|
||||
|
||||
|
|
|
@ -29,9 +29,6 @@
|
|||
|
||||
package factor;
|
||||
|
||||
import factor.compiler.*;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
/**
|
||||
* SYMBOL: name
|
||||
*
|
||||
|
@ -58,38 +55,14 @@ public class FactorSymbolDefinition extends FactorWordDefinition
|
|||
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);
|
||||
} //}}}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
package factor;
|
||||
|
||||
import factor.compiler.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
|
@ -52,11 +51,6 @@ public class FactorWord implements FactorExternalizable, FactorObject
|
|||
*/
|
||||
public FactorParsingDefinition parsing;
|
||||
|
||||
/**
|
||||
* Is this word referenced from a compiled word?
|
||||
*/
|
||||
public boolean compileRef;
|
||||
|
||||
/**
|
||||
* Should this word be inlined when compiling?
|
||||
*/
|
||||
|
@ -67,12 +61,6 @@ public class FactorWord implements FactorExternalizable, FactorObject
|
|||
*/
|
||||
public boolean interpretOnly;
|
||||
|
||||
/**
|
||||
* Only compiled words have this.
|
||||
*/
|
||||
public FactorClassLoader loader;
|
||||
public String className;
|
||||
|
||||
/**
|
||||
* For text editor integration.
|
||||
*/
|
||||
|
@ -127,72 +115,9 @@ public class FactorWord implements FactorExternalizable, FactorObject
|
|||
} //}}}
|
||||
|
||||
//{{{ 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
|
||||
|
|
|
@ -29,18 +29,15 @@
|
|||
|
||||
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
|
||||
/**
|
||||
|
@ -55,273 +52,18 @@ public abstract class FactorWordDefinition implements Constants
|
|||
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()
|
||||
{
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
/* :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;
|
||||
} //}}}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/* :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 });
|
||||
} //}}}
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
/* :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);
|
||||
} //}}}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
/* :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);
|
||||
} //}}}
|
||||
}
|
|
@ -1,231 +0,0 @@
|
|||
/* :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);
|
||||
} //}}}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/* :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);
|
||||
} //}}}
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
/* :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);
|
||||
}
|
||||
} //}}}
|
||||
}
|
|
@ -1,899 +0,0 @@
|
|||
/* :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;
|
||||
}
|
||||
} //}}}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/* :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);
|
||||
}
|
||||
}
|
|
@ -1,332 +0,0 @@
|
|||
/* :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();
|
||||
} //}}}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
/* :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);
|
||||
} //}}}
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
/* :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);
|
||||
} //}}}
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
/* :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);
|
||||
}
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
/* :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);
|
||||
} //}}}
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
/* :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);
|
||||
} //}}}
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
/* :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);
|
||||
} //}}}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
/* :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);
|
||||
}
|
||||
}
|
|
@ -56,8 +56,7 @@ public class Ine extends FactorParsingDefinition
|
|||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,8 +71,7 @@ public class Shuffle extends FactorParsingDefinition
|
|||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,9 @@
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -52,27 +50,4 @@ 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);
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,7 @@
|
|||
|
||||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.*;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class Coerce extends FactorPrimitiveDefinition
|
||||
{
|
||||
|
@ -54,29 +52,4 @@ 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);
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.*;
|
||||
|
||||
public class Define extends FactorPrimitiveDefinition
|
||||
|
@ -66,16 +65,4 @@ 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);
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Set;
|
||||
|
|
|
@ -29,9 +29,7 @@
|
|||
|
||||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.*;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class Ifte extends FactorPrimitiveDefinition
|
||||
{
|
||||
|
@ -58,134 +56,4 @@ 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");
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -29,10 +29,8 @@
|
|||
|
||||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.*;
|
||||
import java.util.Set;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
public class InterpreterGet extends FactorPrimitiveDefinition
|
||||
{
|
||||
|
@ -52,23 +50,4 @@ 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);
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,9 @@
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -112,70 +110,4 @@ 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);
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,9 @@
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -66,51 +64,4 @@ 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);
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,9 @@
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -61,43 +59,4 @@ 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());
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,9 @@
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -59,38 +57,4 @@ 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());
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,9 @@
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -61,41 +59,4 @@ 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()));
|
||||
}
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,9 @@
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -59,38 +57,4 @@ 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()));
|
||||
}
|
||||
} //}}}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.*;
|
||||
import java.util.Set;
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
package factor.primitives;
|
||||
|
||||
import factor.compiler.*;
|
||||
import factor.*;
|
||||
import java.util.Set;
|
||||
|
||||
|
|
|
@ -1,213 +0,0 @@
|
|||
/***
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,293 +0,0 @@
|
|||
/***
|
||||
* 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;
|
||||
}
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
/***
|
||||
* 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();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,158 +0,0 @@
|
|||
/***
|
||||
* 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 ();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,163 +0,0 @@
|
|||
/***
|
||||
* 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);
|
||||
}
|
||||
}
|
|
@ -1,310 +0,0 @@
|
|||
/***
|
||||
* 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);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,288 +0,0 @@
|
|||
/***
|
||||
* 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; // -
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/***
|
||||
* 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;
|
||||
}
|
|
@ -1,266 +0,0 @@
|
|||
/***
|
||||
* 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;
|
||||
}
|
||||
}
|
|
@ -1,327 +0,0 @@
|
|||
/***
|
||||
* 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);
|
||||
}
|
||||
}
|
|
@ -1,763 +0,0 @@
|
|||
/***
|
||||
* 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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue