You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ge...@apache.org on 2005/10/05 04:20:10 UTC
svn commit: r294974 [8/25] - in
/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm: ./ jchevm/
jchevm/doc/ jchevm/etc/ jchevm/include/ jchevm/java/ jchevm/java/org/
jchevm/java/org/dellroad/ jchevm/java/org/dellroad/jc/
jchevm/java/org/dellroad/...
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/SootCodeGenerator.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/SootCodeGenerator.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/SootCodeGenerator.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/SootCodeGenerator.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,201 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: SootCodeGenerator.java,v 1.7 2005/02/22 15:14:02 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen;
+
+import java.io.BufferedWriter;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import org.dellroad.jc.ClassfileFinder;
+import org.dellroad.jc.Generate;
+import org.dellroad.jc.SearchpathFinder;
+import soot.G;
+import soot.PackManager;
+import soot.PhaseOptions;
+import soot.Scene;
+import soot.SootClass;
+import soot.Transform;
+import soot.jimple.toolkits.pointer.CastCheckEliminatorDumper;
+import soot.options.Options;
+
+/**
+ * JC's default source file generator. This class generates C code by
+ * first analyzing class files using the
+ * <a href="http://www.sable.mcgill.ca/soot/">Soot</a> framework, and
+ * then converting byte code into C statements using the various other
+ * helper classes in this package.
+ */
+public class SootCodeGenerator implements CodeGenerator {
+
+ private static final String DEFAULT_METHOD_OPTIMIZER
+ = "org.dellroad.jc.cgen.DefaultMethodOptimizer";
+
+ /**
+ * Current class file finder. This field is made package-visible
+ * because other classes in this package need access to it.
+ */
+ static ClassfileFinder finder;
+
+ private final SourceLocator sourceLocator;
+ private final MethodOptimizer optimizer;
+ private final boolean includeLineNumbers;
+
+ /**
+ * Instantiate. Only one instance of this class should
+ * be used at a time.
+ *
+ * @param sourceLocator How Soot should retrieve class files,
+ * or <code>null</code> in which case the <code>finder</code>
+ * parameter to {@link #generateC generateC()} and
+ * {@link #generateH generateH()} must be an instance of
+ * {@link SearchpathFinder SearchpathFinder}.
+ * @param optimizer Object for optimizing method bodies, or
+ * <code>null</code> to use the default.
+ */
+ public SootCodeGenerator(SourceLocator sourceLocator,
+ MethodOptimizer optimizer, boolean includeLineNumbers) {
+
+ // Get default optimizer
+ if (optimizer == null) {
+ try {
+ optimizer = (MethodOptimizer)Class.forName(
+ System.getProperty("jc.method.optimizer",
+ DEFAULT_METHOD_OPTIMIZER)).newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // Save parameters
+ this.sourceLocator = sourceLocator;
+ this.optimizer = optimizer;
+ this.includeLineNumbers = includeLineNumbers;
+ }
+
+ /**
+ * Reset Soot.
+ */
+ public void reset() {
+
+ // Reset Soot
+ G.reset();
+ System.gc();
+
+ // Set global Soot options
+ Options.v().set_keep_line_number(true);
+ Options.v().set_keep_offset(true);
+
+ // Set Jimple optimization options
+ PhaseOptions.v().setPhaseOption("jop", "enabled:true");
+ PhaseOptions.v().setPhaseOption("tag.ln", "on");
+ PhaseOptions.v().setPhaseOption("jb.lp", "on");
+ PhaseOptions.v().setPhaseOption("jap", "enabled:true");
+ PhaseOptions.v().setPhaseOption("jap.npc", "on");
+ //PhaseOptions.v().setPhaseOption("jap.abc", "with-cse:true");
+ PhaseOptions.v().setPhaseOption("jap.abc", "on");
+ PhaseOptions.v().setPhaseOption("jap.abc",
+ "with-classfield:true");
+
+ // Include cast check elimination tagging
+ PackManager.v().getPack("jap").add(
+ new Transform("jap.cce", CastCheckEliminatorDumper.v()));
+ PhaseOptions.v().setPhaseOption("jap.cce", "on");
+
+ // We have to force Soot to use our custom SourceLocator
+ // using a native method because Soot doesn't let you
+ if (sourceLocator != null) {
+ setField(G.v(), "instanceSourceLocator",
+ "Lsoot/util/SourceLocator;", sourceLocator);
+ }
+ }
+
+ /**
+ * Wrapper for {@link #genH genH()} that handles properly
+ * configuring Soot to find class files.
+ */
+ public final void generateH(String className,
+ ClassfileFinder finder, OutputStream output) throws Exception {
+ if (sourceLocator != null)
+ sourceLocator.setFinder(finder);
+ else if (finder instanceof SearchpathFinder) {
+ Options.v().set_soot_classpath(
+ ((SearchpathFinder)finder).getPath());
+ } else
+ throw new Exception("can't set Soot class finder");
+ SootCodeGenerator.finder = finder;
+ genH(className.replace('/', '.'), output);
+ }
+
+ /**
+ * Wrapper for {@link #genC genC()} that handles properly
+ * configuring Soot to find class files.
+ */
+ public final void generateC(String className,
+ ClassfileFinder finder, OutputStream output) throws Exception {
+ if (sourceLocator != null)
+ sourceLocator.setFinder(finder);
+ else if (finder instanceof SearchpathFinder) {
+ Options.v().set_soot_classpath(
+ ((SearchpathFinder)finder).getPath());
+ } else
+ throw new Exception("can't set Soot class finder");
+ SootCodeGenerator.finder = finder;
+ genC(className.replace('/', '.'), output);
+ }
+
+ /**
+ * Generate the C header file for the class using the Soot framework.
+ * Subclasses should override this method instead of
+ # {@link #generateH generateH()}.
+ *
+ * @param className Class name with dots instead of slashes
+ */
+ public void genH(String className, OutputStream output)
+ throws Exception {
+ SootClass c = Scene.v().loadClassAndSupport(className);
+ c.setApplicationClass();
+ new HFile(c,
+ new BufferedWriter(
+ new OutputStreamWriter(output, "8859_1"))).output();
+ }
+
+ /**
+ * Generate the C source file for the class using the Soot framework.
+ * Subclasses should override this method instead of
+ * {@link #generateC generateC()}.
+ *
+ * @param className Class name with dots instead of slashes
+ */
+ public void genC(String className, OutputStream output)
+ throws Exception {
+ SootClass c = Scene.v().loadClassAndSupport(className);
+ c.setApplicationClass();
+ new CFile(c,
+ new BufferedWriter(
+ new OutputStreamWriter(output, "8859_1")),
+ optimizer, includeLineNumbers).output();
+ }
+
+ // This method is required to set a custom SourceLocator in Soot
+ private static native void setField(Object o,
+ String name, String signature, Object val);
+}
+
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/SourceFile.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/SourceFile.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/SourceFile.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/SourceFile.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,302 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: SourceFile.java,v 1.7 2005/03/13 00:18:50 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen;
+
+import soot.*;
+import soot.tagkit.*;
+import java.util.*;
+import java.io.*;
+
+/**
+ * Represents a Java class file being converted into C source
+ * and/or header files. Contains analysis and formatting code
+ * common to both C source and C header file generation.
+ */
+public abstract class SourceFile implements Constants {
+ protected SootClass c;
+ protected String cname;
+ protected String prefix;
+ protected ArrayList superclasses;
+ protected CodeWriter out;
+ protected int numVirtualRefFields;
+ protected String sourceFile;
+ protected boolean hasStaticInitializer;
+ protected SootField[] virtualFields;
+ protected SootField[] staticFields;
+ protected SootMethod[] virtualMethods;
+ protected SootMethod[] staticMethods;
+ protected SootMethod[] constructors;
+ protected InnerClass innerClasses[];
+ protected SootClass outerClass;
+
+ static class InnerClass {
+ final SootClass inner;
+ final int flags;
+ InnerClass(String inner, int flags) {
+ this.inner = Scene.v().loadClassAndSupport(
+ inner.replace('/', '.'));
+ this.flags = flags;
+ }
+ }
+
+ public SourceFile(SootClass c, Writer out) {
+ if (c == null)
+ throw new IllegalArgumentException();
+ this.c = c;
+ this.out = new CodeWriter(out);
+ this.cname = C.name(c);
+ this.prefix = "_jc_" + cname;
+ prepare();
+ }
+
+ private void prepare() {
+
+ // Generate list containing class and superclasses
+ superclasses = new ArrayList();
+ for (SootClass s = c; true; s = s.getSuperclass()) {
+ superclasses.add(s);
+ if (!s.hasSuperclass())
+ break;
+ }
+
+ // Get source file name
+ try {
+ sourceFile = new String(c.getTag(
+ "SourceFileTag").getValue(), "UTF8");
+ } catch (Exception e) {
+ sourceFile = "unknown";
+ }
+
+ // Locate inner and outer classes
+ ArrayList ilist = new ArrayList();
+ for (Iterator i = c.getTags().iterator(); i.hasNext(); ) {
+ Tag nextTag = (Tag)i.next();
+ if (!(nextTag instanceof InnerClassTag))
+ continue;
+ InnerClassTag tag = (InnerClassTag)nextTag;
+ String inner = tag.getInnerClass();
+ String outer = tag.getOuterClass();
+ String myName = c.getName().replace('.', '/');
+ if (myName.equals(inner) && outer != null) {
+ outerClass = Scene.v().loadClassAndSupport(
+ outer.replace('/', '.'));
+ } else if (myName.equals(outer) && inner != null) {
+ ilist.add(new InnerClass(inner,
+ tag.getAccessFlags()));
+ }
+ }
+ innerClasses = (InnerClass[])ilist.toArray(
+ new InnerClass[ilist.size()]);
+
+ // Prepare fields and methods
+ prepareFieldsAndMethods();
+ }
+
+ // Sort fields and methods into static and non-static,
+ // then sort each list alphabetically by name
+ private void prepareFieldsAndMethods() {
+
+ // Compute virtualFields
+ ArrayList temp = new ArrayList();
+ for (Iterator i = c.getFields().iterator(); i.hasNext(); ) {
+ SootField f = (SootField)i.next();
+ if (!f.isStatic())
+ temp.add(f);
+ }
+ virtualFields = (SootField[])temp.toArray(
+ new SootField[temp.size()]);
+ Arrays.sort(virtualFields, Util.fieldComparator);
+
+ // Count number of reference virtual fields in an instance.
+ // We must include fields declared in all superclasses.
+ numVirtualRefFields = 0;
+ for (int i = 0; i < superclasses.size(); i++) {
+ SootClass sc = (SootClass)superclasses.get(i);
+ for (Iterator j = sc.getFields().iterator();
+ j.hasNext(); ) {
+ SootField f = (SootField)j.next();
+ if (!f.isStatic() && Util.isReference(f))
+ numVirtualRefFields++;
+ }
+ }
+
+ // Compute staticFields
+ temp = new ArrayList();
+ for (Iterator i = c.getFields().iterator(); i.hasNext(); ) {
+ SootField f = (SootField)i.next();
+ if (f.isStatic())
+ temp.add(f);
+ }
+ staticFields = (SootField[])temp.toArray(
+ new SootField[temp.size()]);
+ Arrays.sort(staticFields, Util.fieldComparator);
+
+ // Compute virtualMethods and look for <clinit>
+ temp = new ArrayList();
+ for (Iterator i = c.getMethods().iterator(); i.hasNext(); ) {
+ SootMethod m = (SootMethod)i.next();
+ if (Util.isVirtual(m))
+ temp.add(m);
+ if (Util.isClassInit(m))
+ hasStaticInitializer = true;
+ }
+ virtualMethods = (SootMethod[])temp.toArray(
+ new SootMethod[temp.size()]);
+ Arrays.sort(virtualMethods, Util.methodComparator);
+
+ // Compute staticMethods
+ temp = new ArrayList();
+ for (Iterator i = c.getMethods().iterator(); i.hasNext(); ) {
+ SootMethod m = (SootMethod)i.next();
+ if (m.isStatic())
+ temp.add(m);
+ }
+ staticMethods = (SootMethod[])temp.toArray(
+ new SootMethod[temp.size()]);
+ Arrays.sort(staticMethods, Util.methodComparator);
+
+ // Compute constructors
+ temp = new ArrayList();
+ for (Iterator i = c.getMethods().iterator(); i.hasNext(); ) {
+ SootMethod m = (SootMethod)i.next();
+ if (Util.isConstructor(m))
+ temp.add(m);
+ }
+ constructors = (SootMethod[])temp.toArray(
+ new SootMethod[temp.size()]);
+ Arrays.sort(constructors, Util.methodComparator);
+ }
+
+ public void include(String filename) {
+ out.println("#include " + C.string(filename));
+ }
+
+ public void include(SootClass sc) {
+ StringBuffer b = new StringBuffer();
+ String name = sc.getName();
+ int next;
+ for (int i = 0; i < name.length(); i = next + 1) {
+ if ((next = name.indexOf('.', i)) == -1)
+ next = name.length();
+ if (i > 0)
+ b.append('/');
+ b.append(C.encode(name.substring(i, next)));
+ }
+ b.append(".h");
+ out.println("#include " + C.string(b.toString()));
+ }
+
+ public abstract void output();
+
+ public void outputInitialStuff(SootClass[] hlist,
+ SootClass[] dlist, boolean defs) {
+
+ // Output initial comment
+// outputCommentLine("generated by "
+// + this.getClass().getName() + " " + new Date()
+// + " (" + System.getProperty("java.vm.name") + ")");
+ String modString = Modifier.toString(c.getModifiers());
+ outputCommentLine(modString
+ + (modString.equals("") ? "" : " ")
+ + (c.isInterface() ? "" : "class ")
+ + C.string(c.getName(), false));
+ out.println();
+
+ // Output classfile @dep_class tags
+ if (dlist.length > 0) {
+ Arrays.sort(dlist, Util.classComparator);
+ outputCommentLine("class file dependencies");
+ for (int i = 0; i < dlist.length; i++) {
+ outputCommentLine("@dep_class "
+ + Long.toHexString(Util.classHash(dlist[i]))
+ + " " + C.encode(dlist[i].getName(), true));
+ }
+ out.println();
+ }
+
+ // Output header file @dep_header tags
+ Arrays.sort(hlist, Util.classComparator);
+ if (hlist.length > 0) {
+ outputCommentLine("header file dependencies");
+ for (int i = 0; i < hlist.length; i++) {
+ outputCommentLine("@dep_header "
+ + C.encode(hlist[i].getName(), true));
+ }
+ out.println();
+ }
+
+ // #include files: JC definitions
+ if (defs) {
+ include("jc_defs.h");
+ out.println();
+ }
+
+ // #include files: other classes
+ if (hlist.length > 0) {
+ for (int i = 0; i < hlist.length; i++)
+ include(hlist[i]);
+ out.println();
+ }
+ }
+
+ public void outputFinalStuff() {
+ out.flush();
+ }
+
+ public void outputCommentLine(String s) {
+ out.print("// ");
+ out.println(s);
+ }
+
+ public void outputBanner(String s) {
+ out.print('/');
+ for (int i = 0; i < 8; i++)
+ out.print("*********");
+ out.println();
+ out.print(" *");
+ int start = 2 + (70 - s.length()) / 2;
+ spaceFillTo(2, start);
+ out.print(s);
+ spaceFillTo(start + s.length(), 72);
+ out.println('*');
+ out.print(' ');
+ for (int i = 0; i < 8; i++)
+ out.print("*********");
+ out.println('/');
+ out.println();
+ }
+
+ public void spaceFillTo(int posn, int target) {
+ while (posn < target) {
+ int remain = target - posn;
+ int modpos = posn % 8;
+
+ if (remain >= 8 - modpos) {
+ out.print('\t');
+ posn += 8 - modpos;
+ } else {
+ out.print(' ');
+ posn++;
+ }
+ }
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/SourceLocator.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/SourceLocator.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/SourceLocator.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/SourceLocator.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,61 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: SourceLocator.java,v 1.1.1.1 2004/02/20 05:15:26 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import soot.Singletons;
+import soot.util.ClassInputStream;
+import org.dellroad.jc.ClassfileFinder;
+
+/**
+ * Implementation of Soot's {@link soot.util.SourceLocator} interface
+ * used by the {@link SootCodeGenerator} class. In order for
+ * Soot to pick up and analyze the correct class files, we must
+ * provide our own implementation which retrieves them from the
+ * JC virtual machine. This ensures that no matter how any particular
+ * ClassLoader retrieves a class file, that exact same class file
+ * will be made available to Soot for analysis.
+ */
+public class SourceLocator extends soot.util.SourceLocator {
+
+ private ClassfileFinder finder;
+
+ public SourceLocator(Singletons.Global g) {
+ super(g);
+ }
+
+ public void setFinder(ClassfileFinder finder) {
+ this.finder = finder;
+ }
+
+ /**
+ * Retrieve the classfile contents for the named class,
+ * as loaded by the ClassLoader associated with this object.
+ */
+ public InputStream getInputStreamOf(String className)
+ throws ClassNotFoundException {
+ return new ClassInputStream(
+ new ByteArrayInputStream(
+ finder.getClassfile(className)));
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/StmtTagCopierSwitch.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/StmtTagCopierSwitch.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/StmtTagCopierSwitch.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/StmtTagCopierSwitch.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,72 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: StmtTagCopierSwitch.java,v 1.2 2004/12/21 01:54:03 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen;
+
+import soot.jimple.*;
+
+/**
+ * Copies tags from Jimple Stmt's to ValueBoxes.
+ * All tags are copied.
+ */
+public class StmtTagCopierSwitch extends AbstractStmtSwitch {
+
+ public void caseInvokeStmt(InvokeStmt stmt) {
+ stmt.getInvokeExprBox().addAllTagsOf(stmt);
+ }
+
+ public void caseAssignStmt(AssignStmt stmt) {
+ stmt.getRightOpBox().addAllTagsOf(stmt);
+ stmt.getLeftOpBox().addAllTagsOf(stmt);
+ }
+
+ public void caseIdentityStmt(IdentityStmt stmt) {
+ stmt.getRightOpBox().addAllTagsOf(stmt);
+ }
+
+ public void caseEnterMonitorStmt(EnterMonitorStmt stmt) {
+ stmt.getOpBox().addAllTagsOf(stmt);
+ }
+
+ public void caseExitMonitorStmt(ExitMonitorStmt stmt) {
+ stmt.getOpBox().addAllTagsOf(stmt);
+ }
+
+ public void caseIfStmt(IfStmt stmt) {
+ stmt.getConditionBox().addAllTagsOf(stmt);
+ }
+
+ public void caseLookupSwitchStmt(LookupSwitchStmt stmt) {
+ stmt.getKeyBox().addAllTagsOf(stmt);
+ }
+
+ public void caseReturnStmt(ReturnStmt stmt) {
+ stmt.getOpBox().addAllTagsOf(stmt);
+ }
+
+ public void caseTableSwitchStmt(TableSwitchStmt stmt) {
+ stmt.getKeyBox().addAllTagsOf(stmt);
+ }
+
+ public void caseThrowStmt(ThrowStmt stmt) {
+ stmt.getOpBox().addAllTagsOf(stmt);
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/Util.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/Util.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/Util.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/Util.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,611 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: Util.java,v 1.6 2005/03/13 00:18:50 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen;
+
+import soot.*;
+import soot.tagkit.*;
+import soot.jimple.*;
+import java.util.*;
+import java.io.*;
+import org.dellroad.jc.Generate;
+
+/**
+ * Various utility stuff used when analyzing class files and generating code.
+ */
+public class Util {
+
+ public static final int ACC_SUPER = 0x0020;
+
+ private Util() {
+ }
+
+ /**
+ * Utility class that passes the appropriate string ("byte",
+ * "char", etc.) to the {@link #prim prim()} method depending
+ * on the primitive type.
+ */
+ public static abstract class PrimTypeSwitch extends TypeSwitch {
+ public void caseBooleanType(BooleanType t) {
+ prim("boolean");
+ }
+ public void caseByteType(ByteType t) {
+ prim("byte");
+ }
+ public void caseCharType(CharType t) {
+ prim("char");
+ }
+ public void caseShortType(ShortType t) {
+ prim("short");
+ }
+ public void caseIntType(IntType t) {
+ prim("int");
+ }
+ public void caseLongType(LongType t) {
+ prim("long");
+ }
+ public void caseFloatType(FloatType t) {
+ prim("float");
+ }
+ public void caseDoubleType(DoubleType t) {
+ prim("double");
+ }
+ public void caseVoidType(VoidType t) {
+ prim("void");
+ }
+ public abstract void prim(String ptype);
+ public void defaultCase(Type t) {
+ Util.panic("non-primitive type " + t);
+ }
+ }
+
+ /**
+ * Utility class that computes ordering preference in a C structure
+ * of the various types. We want longer types first, then shorter
+ * types, to avoid "holes". We always sort reference types first.
+ */
+ public static abstract class OrderTypeSwitch extends TypeSwitch {
+ public void caseBooleanType(BooleanType t) {
+ order(4);
+ }
+ public void caseByteType(ByteType t) {
+ order(4);
+ }
+ public void caseCharType(CharType t) {
+ order(3);
+ }
+ public void caseShortType(ShortType t) {
+ order(3);
+ }
+ public void caseIntType(IntType t) {
+ order(2);
+ }
+ public void caseFloatType(FloatType t) {
+ order(2);
+ }
+ public void caseLongType(LongType t) {
+ order(1);
+ }
+ public void caseDoubleType(DoubleType t) {
+ order(1);
+ }
+ public void defaultCase(Type t) {
+ order(0);
+ }
+ public abstract void order(int order);
+ }
+
+ /**
+ * Return the _JC_TYPE_* macro appropriate for the given type.
+ */
+ public static String _JC_TYPE(Type t) {
+ if (isReference(t))
+ return "_JC_TYPE_REFERENCE";
+ TypeSwitch ts = new Util.PrimTypeSwitch() {
+ public void prim(String name) {
+ setResult("_JC_TYPE_" + name.toUpperCase());
+ }
+ };
+ t.apply(ts);
+ return (String)ts.getResult();
+ }
+
+ /**
+ * Sorts Strings in the same way that strcmp() does on their
+ * UTF-8 encodings.
+ */
+ public static final Comparator utf8Comparator = new Comparator() {
+ public int compare(Object x, Object y) {
+ byte[] b1 = utf8Encode((String)x);
+ byte[] b2 = utf8Encode((String)y);
+ for (int i = 0; i < b1.length && i < b2.length; i++) {
+ int diff = (b1[i] & 0xff) - (b2[i] & 0xff);
+ if (diff != 0)
+ return diff;
+ }
+ return b1.length - b2.length;
+ }
+ };
+
+ /**
+ * Sorts methods by name, then by signature.
+ */
+ public static final Comparator methodComparator = new Comparator() {
+ public int compare(Object x, Object y) {
+ SootMethod mx = (SootMethod)x;
+ SootMethod my = (SootMethod)y;
+ int diff;
+ if ((diff = utf8Comparator.compare(mx.getName(),
+ my.getName())) != 0)
+ return diff;
+ return utf8Comparator.compare(
+ signature(mx), signature(my));
+ }
+ };
+
+ /**
+ * Sorts local variables by name.
+ */
+ public static final Comparator localComparator = new Comparator() {
+ public int compare(Object x, Object y) {
+ Local lx = (Local)x;
+ Local ly = (Local)y;
+ return lx.getName().compareTo(ly.getName());
+ }
+ };
+
+ /**
+ * Sorts fields by staticness, basic type, name, then signature.
+ */
+ public static final Comparator fieldComparator = new Comparator() {
+ private int ots_order;
+ private final OrderTypeSwitch ots = new OrderTypeSwitch() {
+ public void order(int order) {
+ ots_order = order;
+ }
+ };
+ private int getOrder(Type t) {
+ t.apply(ots);
+ return ots_order;
+ }
+ public int compare(Object x, Object y) {
+ SootField fx = (SootField)x;
+ SootField fy = (SootField)y;
+ int diff;
+
+ if (fx.isStatic() != fy.isStatic())
+ return fx.isStatic() ? -1 : 1;
+ if ((diff = getOrder(fx.getType())
+ - getOrder(fy.getType())) != 0)
+ return diff;
+ if ((diff = utf8Comparator.compare(fx.getName(),
+ fy.getName())) != 0)
+ return diff;
+ return utf8Comparator.compare(signature(fx),
+ signature(fy));
+ }
+ };
+
+ /**
+ * Sorts classes by their names' UTF-8 encoding.
+ */
+ public static final Comparator classComparator = new Comparator() {
+ public int compare(Object x, Object y) {
+ SootClass cx = (SootClass)x;
+ SootClass cy = (SootClass)y;
+ return utf8Comparator.compare(
+ cx.getName(), cy.getName());
+ }
+ };
+
+ public static boolean isReference(SootClass c) {
+ return (isReference(c.getType()));
+ }
+
+ public static boolean isReference(SootField f) {
+ return (isReference(f.getType()));
+ }
+
+ public static boolean isReference(SootMethod m) {
+ return (isReference(m.getReturnType()));
+ }
+
+ public static boolean isPrimitive(Type type) {
+ return type instanceof PrimType || type instanceof VoidType;
+ }
+
+ public static boolean isPrimitiveArray(Type type) {
+ return type instanceof ArrayType
+ && isPrimitive(((ArrayType)type).getElementType());
+ }
+
+ public static boolean isFinal(SootClass c) {
+ return Modifier.isFinal(c.getModifiers());
+ }
+
+ public static boolean isFinal(SootField f) {
+ return Modifier.isFinal(f.getModifiers());
+ }
+
+ public static boolean isFinal(SootMethod m) {
+ return Modifier.isFinal(m.getModifiers());
+ }
+
+ public static boolean isVirtual(SootMethod m) {
+ return !m.isStatic() && m.getName().charAt(0) != '<';
+ }
+
+ public static boolean isConstructor(SootMethod m) {
+ return !m.isStatic() && m.getName().equals("<init>");
+ }
+
+ public static boolean isClassInit(SootMethod m) {
+ return m.isStatic() && m.getName().equals("<clinit>");
+ }
+
+ public static boolean hasSubtypes(SootClass c) {
+ return !isFinal(c);
+ }
+
+ public static boolean hasSubtypes(SootField f) {
+ return !isFinal(f);
+ }
+
+ public static boolean hasSubtypes(SootMethod m) {
+ return !isFinal(m);
+ }
+
+ public static boolean hasSubtypes(Type t) {
+ if (isPrimitive(t))
+ return false;
+ if (t instanceof RefType) {
+ SootClass c = ((RefType)t).getSootClass();
+ if (c.isInterface())
+ return true;
+ return !isFinal(c);
+ }
+ return hasSubtypes(((ArrayType)t).baseType);
+ }
+
+ /**
+ * Return whether type <code>t</code> is a reference type or not.
+ * <code>t</code> must be a normal Java type, i.e., a type that can
+ * be the type of a variable.
+ */
+ public static boolean isReference(Type t) {
+ return (t instanceof RefLikeType);
+ }
+
+ public static char typeLetter(Type t) {
+ TypeSwitch ts = new TypeSwitch() {
+ public void caseBooleanType(BooleanType t) {
+ setResult("z");
+ }
+ public void caseByteType(ByteType t) {
+ setResult("b");
+ }
+ public void caseCharType(CharType t) {
+ setResult("c");
+ }
+ public void caseShortType(ShortType t) {
+ setResult("s");
+ }
+ public void caseIntType(IntType t) {
+ setResult("i");
+ }
+ public void caseLongType(LongType t) {
+ setResult("j");
+ }
+ public void caseFloatType(FloatType t) {
+ setResult("f");
+ }
+ public void caseDoubleType(DoubleType t) {
+ setResult("d");
+ }
+ public void caseArrayType(ArrayType t) {
+ setResult("l");
+ }
+ public void caseRefType(RefType t) {
+ setResult("l");
+ }
+ public void defaultCase(Type t) {
+ Util.panic("bogus type " + t);
+ }
+ };
+ t.apply(ts);
+ return ((String)ts.getResult()).charAt(0);
+ }
+
+ public static String fieldDescriptor(Type t) {
+ TypeSwitch ts = new TypeSwitch() {
+ public void caseBooleanType(BooleanType t) {
+ setResult("Z");
+ }
+ public void caseByteType(ByteType t) {
+ setResult("B");
+ }
+ public void caseCharType(CharType t) {
+ setResult("C");
+ }
+ public void caseShortType(ShortType t) {
+ setResult("S");
+ }
+ public void caseIntType(IntType t) {
+ setResult("I");
+ }
+ public void caseLongType(LongType t) {
+ setResult("J");
+ }
+ public void caseFloatType(FloatType t) {
+ setResult("F");
+ }
+ public void caseDoubleType(DoubleType t) {
+ setResult("D");
+ }
+ public void caseArrayType(ArrayType t) {
+ setResult("["
+ + fieldDescriptor(t.getElementType()));
+ }
+ public void caseRefType(RefType t) {
+ setResult("L"
+ + t.getSootClass().getName().replace('.', '/')
+ + ";");
+ }
+ public void caseVoidType(VoidType t) {
+ setResult("V");
+ }
+ public void defaultCase(Type t) {
+ Util.panic("bogus type " + t);
+ }
+ };
+ t.apply(ts);
+ return (String)ts.getResult();
+ }
+
+ public static String typeWord(Type t) {
+ if (Util.isReference(t))
+ return "object";
+ TypeSwitch ts = new Util.PrimTypeSwitch() {
+ public void prim(String name) {
+ setResult(name);
+ }
+ };
+ t.apply(ts);
+ return (String)ts.getResult();
+ }
+
+ public static String signature(SootField f) {
+ return fieldDescriptor(f.getType());
+ }
+
+ public static String signature(SootMethod m) {
+ StringBuffer b = new StringBuffer(24);
+ b.append('(');
+ for (int i = 0; i < m.getParameterCount(); i++)
+ b.append(fieldDescriptor(m.getParameterType(i)));
+ b.append(')');
+ b.append(fieldDescriptor(m.getReturnType()));
+ return b.toString();
+ }
+
+ public static String fullSignature(SootMethod m) {
+ return m.getName() + signature(m);
+ }
+
+ public static String paramTypes(SootMethod m) {
+ StringBuffer b = new StringBuffer();
+ for (int i = 0; i < m.getParameterCount(); i++) {
+ b.append(fieldDescriptor(
+ m.getParameterType(i)).charAt(0));
+ }
+ b.append(fieldDescriptor(m.getReturnType()));
+ return b.toString();
+ }
+
+ public static long hash(String s) {
+ return Generate.hash(new ByteArrayInputStream(utf8Encode(s)));
+ }
+
+ public static long sigHash(SootMethod m) {
+ return hash(fullSignature(m));
+ }
+
+ public static long classHash(SootClass sc) {
+ try {
+ return SootCodeGenerator.finder.getClassfileHash(
+ sc.getName().replace('.', '/'));
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e); // should never happen
+ }
+ }
+
+ /**
+ * Determine if an INVOKESPECIAL can be implemented
+ * like the old INVOKENONVIRTUAL.
+ */
+ public static boolean isNonvirtual(SpecialInvokeExpr v,
+ SootMethod callingMethod) {
+
+ // Get info
+ SootMethod targetMethod = v.getMethod();
+ SootClass callingClass = callingMethod.getDeclaringClass();
+
+ // Check the easy stuff first
+ if (targetMethod.getName().equals("<init>")
+ || targetMethod.isPrivate()
+ || (callingClass.getModifiers() & Util.ACC_SUPER) == 0)
+ return true;
+
+ // Determine if called method's class is a superclass
+ boolean isSuperclass = false;
+ SootClass calledClass = targetMethod.getDeclaringClass();
+ for (SootClass cls = callingClass; cls.hasSuperclass(); ) {
+ cls = cls.getSuperclass();
+ if (cls.equals(calledClass))
+ return false;
+ }
+
+ // OK
+ return true;
+ }
+
+ /**
+ * Get the instanceof hash table hash.
+ */
+ public static int instanceofHash(SootClass sc) {
+ return ((int)classHash(sc) & 0x7fffffff)
+ % Constants.INSTANCEOF_HASHSIZE;
+ }
+
+ /**
+ * Get the interface method hash table hash.
+ */
+ public static int imethodHash(SootMethod m) {
+ return ((int)sigHash(m) & 0x7fffffff)
+ % Constants.IMETHOD_HASHSIZE;
+ }
+
+ public static String sigHashString(SootMethod m) {
+ long hash = sigHash(m);
+ String s = Long.toHexString(hash);
+ if ((hash & 0xf000000000000000L) != 0)
+ return s;
+ StringBuffer b = new StringBuffer(s);
+ while (b.length() < 16)
+ b.insert(0, '0');
+ return b.toString();
+ }
+
+ /**
+ * Find a method declared by a SootClass or any of its superclasses.
+ */
+ public static SootMethod findMethod(SootClass c, String subSig) {
+ for (SootClass oc = c; true; c = c.getSuperclass()) {
+ try {
+ return c.getMethod(subSig);
+ } catch (RuntimeException e) {
+ }
+ if (!c.hasSuperclass()) {
+ throw new RuntimeException("no such method in "
+ + "class " + oc.getName() + ": " + subSig);
+ }
+ }
+ }
+
+ public static Set getAllInterfaces(SootClass c) {
+ HashSet set = new HashSet();
+ addInterfaces(c, set);
+ return set;
+ }
+
+ private static void addInterfaces(SootClass c, Set set) {
+ if (c.isInterface())
+ set.add(c);
+ /* else */ if (c.hasSuperclass())
+ addInterfaces(c.getSuperclass(), set);
+ for (Iterator i = c.getInterfaces().iterator(); i.hasNext(); )
+ addInterfaces((SootClass)i.next(), set);
+ }
+
+ public static Set getAllSupertypes(SootClass c) {
+ HashSet set = new HashSet();
+ addSupertypes(c, set);
+ return set;
+ }
+
+ public static void addSupertypes(SootClass cls, Set set) {
+
+ // Add this class
+ set.add(cls);
+
+ // Recurse on superclass
+ if (cls.hasSuperclass()) {
+ SootClass superclass = cls.getSuperclass();
+ addSupertypes(superclass, set);
+ }
+
+ // Recurse on superinterfaces
+ for (Iterator i = cls.getInterfaces().iterator();
+ i.hasNext(); ) {
+ SootClass superinterface = (SootClass)i.next();
+ addSupertypes(superinterface, set);
+ }
+ }
+
+ public static void require(boolean value) {
+ require(value, "assertion failure");
+ }
+
+ /**
+ * Poor man's assert().
+ */
+ public static void require(boolean value, String msg) {
+ if (!value)
+ throw new RuntimeException(msg);
+ }
+
+ /**
+ * This method is required to work around a stupid bug
+ * in Sun's JDK String.getBytes("UTF-8") (bug #4628881).
+ */
+ public static byte[] utf8Encode(String s) {
+ final char[] chars = s.toCharArray();
+ int elen;
+
+ // Compute encoded length
+ elen = 0;
+ for (int i = 0; i < s.length(); i++) {
+ int ch = chars[i];
+ if (ch >= 0x0001 && ch <= 0x007f)
+ elen++;
+ else if (ch == 0x0000 || (ch >= 0x0080 && ch <= 0x07ff))
+ elen += 2;
+ else
+ elen += 3;
+ }
+
+ // Do the actual encoding
+ byte[] data = new byte[elen];
+ elen = 0;
+ for (int i = 0; i < s.length(); i++) {
+ int ch = chars[i];
+ if (ch >= 0x0001 && ch <= 0x007f)
+ data[elen++] = (byte)ch;
+ else if (ch == 0x0000
+ || (ch >= 0x0080 && ch <= 0x07ff)) {
+ data[elen++]
+ = (byte)(0xc0 | ((ch >> 6) & 0x1f));
+ data[elen++] = (byte)(0x80 | (ch & 0x3f));
+ } else {
+ data[elen++]
+ = (byte)(0xe0 | ((ch >> 12) & 0x0f));
+ data[elen++]
+ = (byte)(0x80 | ((ch >> 6) & 0x3f));
+ data[elen++] = (byte)(0x80 | (ch & 0x3f));
+ }
+ }
+ return data;
+ }
+
+ public static void panic(String msg) {
+ throw new RuntimeException("Panic: " + msg);
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseAnalysis.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseAnalysis.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseAnalysis.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseAnalysis.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,129 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: ActiveUseAnalysis.java,v 1.3 2004/12/24 21:55:56 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen.analysis;
+
+import java.util.Iterator;
+import org.dellroad.jc.cgen.ActiveUseCheckStmt;
+import org.dellroad.jc.cgen.Util;
+import soot.Body;
+import soot.Scene;
+import soot.SootClass;
+import soot.Unit;
+import soot.ValueBox;
+import soot.jimple.Stmt;
+import soot.toolkits.graph.CompleteUnitGraph;
+import soot.toolkits.graph.UnitGraph;
+import soot.toolkits.scalar.ArraySparseSet;
+import soot.toolkits.scalar.FlowSet;
+import soot.toolkits.scalar.ForwardFlowAnalysis;
+
+/**
+ * Analysis used by {@link ActiveUseTagger ActiveUseTagger}.
+ */
+public class ActiveUseAnalysis extends ForwardFlowAnalysis {
+
+ private final UnitGraph graph;
+
+ /**
+ * Equivalent to
+ * <code>ActiveUseAnalysis(new CompleteUnitGraph(body))</code>.
+ *
+ * @param body method body to analyze
+ */
+ public ActiveUseAnalysis(Body body) {
+ this(new CompleteUnitGraph(body));
+ }
+
+ /**
+ * Do active use analysis on body using the supplied unit graph.
+ *
+ * @param graph method body to analyze
+ */
+ public ActiveUseAnalysis(UnitGraph graph) {
+ super(graph);
+ this.graph = graph;
+ doAnalysis();
+ }
+
+ /**
+ * Determine if a first active use check for class <code>cl</code>
+ * would be needed before executing <code>unit</code>.
+ */
+ public boolean isCheckNeeded(Unit unit, SootClass cl) {
+ FlowSet inSet = (FlowSet)unitToBeforeFlow.get(unit);
+ return !inSet.contains(cl);
+ }
+
+ protected Object entryInitialFlow() {
+ ArraySparseSet set = new ArraySparseSet();
+ addTransitive(set, graph.getBody()
+ .getMethod().getDeclaringClass());
+ addTransitive(set, Scene.v().getSootClass("java.lang.Class"));
+ return set;
+ }
+
+ protected Object newInitialFlow() {
+ return new ArraySparseSet();
+ }
+
+ protected void flowThrough(Object in, Object obj, Object out) {
+ Stmt stmt = (Stmt)obj;
+ FlowSet inFlow = (FlowSet)in;
+ FlowSet outFlow = (FlowSet)out;
+ inFlow.copy(outFlow);
+ if (ActiveUseCheckStmt.isActiveUseCheck(stmt)) {
+ addTransitive(outFlow,
+ ActiveUseCheckStmt.getSootClass(stmt));
+ return;
+ }
+ ActiveUseValueSwitch sw = new ActiveUseValueSwitch();
+ for (Iterator i = stmt.getUseBoxes().iterator();
+ i.hasNext(); ) {
+ ((ValueBox)i.next()).getValue().apply(sw);
+ SootClass cl = (SootClass)sw.getResult();
+ if (cl != null)
+ addTransitive(outFlow, cl);
+ }
+ }
+
+ protected void merge(Object in1, Object in2, Object out) {
+ FlowSet inSet1 = (FlowSet)in1;
+ FlowSet inSet2 = (FlowSet)in2;
+ FlowSet outSet = (FlowSet)out;
+ inSet1.intersection(inSet2, outSet);
+ }
+
+ protected void copy(Object src, Object dst) {
+ FlowSet srcSet = (FlowSet)src;
+ FlowSet dstSet = (FlowSet)dst;
+ srcSet.copy(dstSet);
+ }
+
+ // Add class and all superclasses
+ private void addTransitive(FlowSet set, SootClass cl) {
+ set.add(cl);
+ while (cl.hasSuperclass()) {
+ cl = cl.getSuperclass();
+ set.add(cl);
+ }
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseTag.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseTag.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseTag.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseTag.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,61 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: ActiveUseTag.java,v 1.1 2004/12/19 21:01:04 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen.analysis;
+
+import soot.tagkit.Tag;
+
+/**
+ * Tag for ``first active use'' class initialization checks.
+ */
+public class ActiveUseTag implements Tag {
+
+ private final static String NAME = "ActiveUseTag";
+
+ private final static ActiveUseTag NEEDED = new ActiveUseTag(true);
+ private final static ActiveUseTag NOT_NEEDED = new ActiveUseTag(false);
+
+ private final boolean checkNeeded;
+
+ public ActiveUseTag(boolean checkNeeded) {
+ this.checkNeeded = checkNeeded;
+ }
+
+ public boolean isCheckNeeded() {
+ return checkNeeded;
+ }
+
+ public byte[] getValue() {
+ return new byte[] { checkNeeded ? (byte)1 : (byte)0 };
+ }
+
+ public String getName() {
+ return NAME;
+ }
+
+ public String toString() {
+ return NAME;
+ }
+
+ public static ActiveUseTag v(boolean checkNeeded) {
+ return checkNeeded ? NEEDED : NOT_NEEDED;
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseTagger.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseTagger.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseTagger.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseTagger.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,90 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: ActiveUseTagger.java,v 1.2 2004/12/24 21:55:56 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen.analysis;
+
+import java.util.Iterator;
+import org.dellroad.jc.cgen.Util;
+import org.dellroad.jc.cgen.ActiveUseCheckStmt;
+import soot.Body;
+import soot.SootClass;
+import soot.SootField;
+import soot.Value;
+import soot.ValueBox;
+import soot.jimple.*;
+import soot.Unit;
+import soot.toolkits.graph.UnitGraph;
+
+/**
+ * Tags static field and method references which are known to not
+ * be the first ``active use'' of the associated class, and so for which
+ * it is not necessary to check if the class needs to be initialized.
+ */
+public class ActiveUseTagger {
+
+ private final ActiveUseAnalysis analysis;
+
+ public ActiveUseTagger(Body body) {
+ analysis = new ActiveUseAnalysis(body);
+ tag(body);
+ }
+
+ public ActiveUseTagger(UnitGraph graph) {
+ analysis = new ActiveUseAnalysis(graph);
+ tag(graph.getBody());
+ }
+
+ public ActiveUseAnalysis getAnalysis() {
+ return analysis;
+ }
+
+ private void tag(Body body) {
+ for (Iterator i = body.getUnits().iterator(); i.hasNext(); ) {
+ Stmt stmt = (Stmt)i.next();
+ if (stmt.containsInvokeExpr())
+ tagInvoke(stmt, stmt.getInvokeExprBox());
+ if (stmt.containsFieldRef())
+ tagField(stmt, stmt.getFieldRefBox());
+ }
+ }
+
+ private void tagInvoke(Stmt stmt, ValueBox box) {
+ Value value = box.getValue();
+ if (!(value instanceof StaticInvokeExpr))
+ return;
+ StaticInvokeExpr expr = (StaticInvokeExpr)value;
+ SootClass cl = expr.getMethod().getDeclaringClass();
+ if (ActiveUseCheckStmt.isActiveUseCheck(stmt))
+ cl = ActiveUseCheckStmt.getSootClass(stmt);
+ if (!analysis.isCheckNeeded(stmt, cl))
+ box.addTag(ActiveUseTag.v(false));
+ }
+
+ private void tagField(Stmt stmt, ValueBox box) {
+ Value value = box.getValue();
+ if (!(value instanceof FieldRef))
+ return;
+ SootField field = ((FieldRef)value).getField();
+ if (field.isStatic()
+ && !analysis.isCheckNeeded(stmt, field.getDeclaringClass()))
+ box.addTag(ActiveUseTag.v(false));
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseValueSwitch.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseValueSwitch.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseValueSwitch.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ActiveUseValueSwitch.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,62 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: ActiveUseValueSwitch.java,v 1.2 2004/12/22 23:39:06 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen.analysis;
+
+import soot.jimple.*;
+import soot.grimp.AbstractGrimpValueSwitch;
+import soot.grimp.NewInvokeExpr;
+import soot.toolkits.scalar.FlowSet;
+
+/**
+ * Determine the SootClass which will definitely be initialized after
+ * evaluating the value, if any.
+ */
+public class ActiveUseValueSwitch extends AbstractGrimpValueSwitch {
+
+ public void caseNewInvokeExpr(NewInvokeExpr v) {
+ setResult(v.getMethod().getDeclaringClass());
+ }
+
+ public void caseSpecialInvokeExpr(SpecialInvokeExpr v) {
+ setResult(v.getMethod().getDeclaringClass());
+ }
+
+ public void caseStaticInvokeExpr(StaticInvokeExpr v) {
+ setResult(v.getMethod().getDeclaringClass());
+ }
+
+ public void caseVirtualInvokeExpr(VirtualInvokeExpr v) {
+ setResult(v.getMethod().getDeclaringClass());
+ }
+
+ public void caseNewExpr(NewExpr v) {
+ setResult(v.getBaseType().getSootClass());
+ }
+
+ public void caseInstanceFieldRef(InstanceFieldRef v) {
+ setResult(v.getField().getDeclaringClass());
+ }
+
+ public void caseStaticFieldRef(StaticFieldRef v) {
+ setResult(v.getField().getDeclaringClass());
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/FinalizeDetector.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/FinalizeDetector.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/FinalizeDetector.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/FinalizeDetector.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,48 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: FinalizeDetector.java,v 1.1 2004/12/17 15:35:46 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen.analysis;
+
+import java.util.*;
+import org.dellroad.jc.cgen.*;
+import soot.*;
+import soot.jimple.*;
+
+/**
+ * Instance of this class detect 'new' expressions of objects that
+ * override finalize(). The result is either <code>Boolean.TRUE</code>
+ * or <code>Boolean.FALSE</code>.
+ */
+public class FinalizeDetector extends AbstractJimpleValueSwitch {
+
+ public void caseNewExpr(NewExpr v) {
+ SootClass sc = v.getBaseType().getSootClass();
+ SootMethod finalize = sc.getMethod("finalize",
+ Collections.EMPTY_LIST, VoidType.v());
+ setResult(Boolean.valueOf(
+ !finalize.getDeclaringClass().getName()
+ .equals("java.lang.Object")));
+ }
+
+ public void defaultCase(Object obj) {
+ setResult(Boolean.FALSE);
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/FollowsAnalysis.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/FollowsAnalysis.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/FollowsAnalysis.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/FollowsAnalysis.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,87 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: FollowsAnalysis.java,v 1.2 2004/12/19 21:01:04 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen.analysis;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import soot.Body;
+import soot.Unit;
+import soot.toolkits.graph.CompleteUnitGraph;
+import soot.toolkits.scalar.ArraySparseSet;
+import soot.toolkits.scalar.FlowSet;
+import soot.toolkits.scalar.ForwardFlowAnalysis;
+
+/**
+ * Analysis that determines which statements can be executed
+ * after which other statements.
+ */
+public class FollowsAnalysis extends ForwardFlowAnalysis {
+
+ public FollowsAnalysis(Body body) {
+ super(new CompleteUnitGraph(body));
+ doAnalysis();
+ }
+
+ public FollowsAnalysis(CompleteUnitGraph graph) {
+ super(graph);
+ doAnalysis();
+ }
+
+ /**
+ * Determine if <code>after</code> can execute after
+ * <code>before</code>.
+ */
+ public boolean canFollow(Unit before, Unit after) {
+ FlowSet inSet = (FlowSet)unitToBeforeFlow.get(after);
+ return inSet.contains(before);
+ }
+
+ protected Object entryInitialFlow() {
+ return new ArraySparseSet();
+ }
+
+ protected Object newInitialFlow() {
+ return new ArraySparseSet();
+ }
+
+ protected void flowThrough(Object in, Object stmt, Object out) {
+ FlowSet inFlow = (FlowSet)in;
+ FlowSet outFlow = (FlowSet)out;
+ inFlow.copy(outFlow);
+ outFlow.add(stmt);
+ }
+
+ protected void merge(Object in1, Object in2, Object out) {
+ FlowSet inSet1 = (FlowSet)in1;
+ FlowSet inSet2 = (FlowSet)in2;
+ FlowSet outSet = (FlowSet)out;
+ inSet1.union(inSet2, outSet);
+ }
+
+ protected void copy(Object src, Object dst) {
+ FlowSet srcSet = (FlowSet)src;
+ FlowSet dstSet = (FlowSet)dst;
+ srcSet.copy(dstSet);
+ }
+
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/Makefile.am
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/Makefile.am?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/Makefile.am (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/Makefile.am Tue Oct 4 19:19:16 2005
@@ -0,0 +1,12 @@
+## $Id: Makefile.am,v 1.5 2005/02/20 21:14:31 archiecobbs Exp $
+
+EXTRA_DIST= ActiveUseAnalysis.java \
+ ActiveUseTag.java \
+ ActiveUseTagger.java \
+ ActiveUseValueSwitch.java \
+ FinalizeDetector.java \
+ FollowsAnalysis.java \
+ ReferenceDetector.java \
+ TypeAnalysis.java \
+ package.html
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ReferenceDetector.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ReferenceDetector.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ReferenceDetector.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/ReferenceDetector.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,54 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: ReferenceDetector.java,v 1.1 2004/12/17 15:35:46 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen.analysis;
+
+import java.util.*;
+import org.dellroad.jc.cgen.*;
+import soot.*;
+import soot.jimple.*;
+
+/**
+ * Instances of this class detect 'new' expressions of
+ * objects that subclass <code>java.lang.ref.Reference</code>.
+ * The result is either <code>Boolean.TRUE</code>
+ * or <code>Boolean.FALSE</code>.
+ */
+public class ReferenceDetector extends AbstractJimpleValueSwitch {
+
+ public void caseNewExpr(NewExpr v) {
+ SootClass sc = v.getBaseType().getSootClass();
+ while (true) {
+ if (sc.getName().equals("java.lang.ref.Reference")) {
+ setResult(Boolean.TRUE);
+ return;
+ }
+ if (!sc.hasSuperclass())
+ break;
+ sc = sc.getSuperclass();
+ }
+ setResult(Boolean.FALSE);
+ }
+
+ public void defaultCase(Object obj) {
+ setResult(Boolean.FALSE);
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/TypeAnalysis.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/TypeAnalysis.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/TypeAnalysis.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/TypeAnalysis.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,89 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: TypeAnalysis.java,v 1.6 2005/03/19 22:18:20 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen.analysis;
+
+import java.util.*;
+import org.dellroad.jc.cgen.Util;
+import soot.*;
+import soot.jimple.*;
+import soot.toolkits.scalar.*;
+
+/**
+ * Determines the run-time type of a reference local as best we can based on
+ * information provided by a {@link LocalDefs LocalDefs} object.
+ */
+public class TypeAnalysis {
+
+ private final LocalDefs localDefs;
+
+ private final AbstractJimpleValueSwitch vs
+ = new AbstractJimpleValueSwitch() {
+ public void caseNewArrayExpr(NewArrayExpr v) {
+ setResult(v.getType());
+ }
+ public void caseNewMultiArrayExpr(NewMultiArrayExpr v) {
+ setResult(v.getType());
+ }
+ public void caseNewExpr(NewExpr v) {
+ setResult(v.getType());
+ }
+ public void caseNullConstant(NullConstant v) {
+ setResult(v.getType());
+ }
+ public void defaultCase(Object obj) {
+ Value v = (Value)obj;
+ Type type = v.getType();
+ if (!(v.getType() instanceof RefType))
+ return;
+ SootClass c = ((RefType)type).getSootClass();
+ if (!Util.isFinal(c))
+ return;
+ setResult(type);
+ }
+ };
+
+ public TypeAnalysis(LocalDefs localDefs) {
+ this.localDefs = localDefs;
+ }
+
+ /**
+ * Return the exact type of the reference local def if it's a reference
+ * type and the Java class is known exactly, else <code>null</code>.
+ */
+ public RefLikeType getExactType(Local local, Unit unit) {
+ RefLikeType type = null;
+ for (Iterator i = localDefs.getDefsOfAt(local, unit).iterator();
+ i.hasNext(); ) {
+ DefinitionStmt def = (DefinitionStmt)i.next();
+ vs.setResult(null);
+ def.getRightOp().apply(vs);
+ RefLikeType type2 = (RefLikeType)vs.getResult();
+ if (type2 == null)
+ return null;
+ if (type == null)
+ type = type2;
+ else if (!type.equals(type2))
+ return null;
+ }
+ return type;
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/package.html
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/package.html?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/package.html (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/analysis/package.html Tue Oct 4 19:19:16 2005
@@ -0,0 +1,13 @@
+<html>
+<head>
+<title>
+Package description
+</title>
+</head>
+<body>
+
+<p>
+Classes used for general analysis.
+
+</body>
+</html>
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/EscapeAnalysis.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/EscapeAnalysis.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/EscapeAnalysis.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/EscapeAnalysis.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,350 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: EscapeAnalysis.java,v 1.6 2005/02/20 21:14:31 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen.escape;
+
+import java.util.*;
+import soot.*;
+import soot.jimple.*;
+import soot.jimple.toolkits.scalar.*;
+import soot.toolkits.graph.*;
+import soot.toolkits.scalar.*;
+import org.dellroad.jc.cgen.analysis.ReferenceDetector;
+import org.dellroad.jc.cgen.analysis.FinalizeDetector;
+import org.dellroad.jc.cgen.analysis.FollowsAnalysis;
+
+/**
+ * Class that performs escape analysis to determine objects that
+ * may be allocated on the stack (instead of the heap).
+ */
+public class EscapeAnalysis {
+
+ private static final boolean DEBUG = false;
+
+ private EscapeAnalysis() {
+ }
+
+ /**
+ *
+ * Find allocations of non-escaping objects. Our requirements:
+ *
+ * <ol>
+ * <li>Object must not be thrown, returned, assigned to any field,
+ * assigned to any array element, or passed to any method.
+ * MONITORENTER is allowed, hence these must be balanced.</li>
+ * <li>Allocation size must be known a priori.</li>
+ * <li>Object must not override <code>finalize()</code>.</li>
+ * <li>Object must not subclass
+ * <code>java.lang.ref.Reference</code>.</li>
+ * <li>The allocation must not be within a loop</li>
+ * </ol>
+ *
+ * <p>
+ * We impose a maximum total size for all stack allocations in the
+ * method. We prioritize allocations by size (smallest first).
+ * </p>
+ *
+ * <p>
+ * All allocations that may be stack allocated are tagged with
+ * a {@link StackAllocTag StackAllocTag}.
+ * </p>
+ *
+ * @param graph graph computed from method
+ * @param maxAlloc max number of bytes of stack allocated objects
+ */
+ public static void analyze(CompleteUnitGraph graph, int maxAlloc) {
+
+ // Avoid useless work if stack allocation is disabled
+ if (maxAlloc == 0)
+ return;
+
+ // Get method body
+ Body body = graph.getBody();
+
+ // Debug
+ HashMap indexMap = null;
+ if (DEBUG) {
+ System.out.println("NEW ESCAPE ANALYSIS");
+ indexMap = new HashMap();
+ int index = 0;
+ for (Iterator i = body.getUnits().iterator();
+ i.hasNext(); ) {
+ Stmt stmt = (Stmt)i.next();
+ indexMap.put(stmt, new Integer(++index));
+ System.out.println(" [" + index + "] " + stmt);
+ }
+ }
+
+ // Our stack allocatable 'new' statements
+ HashSet stackAllocs = new HashSet();
+
+ // Find all new statements with a known size
+ KnownSizeDetector knownSizeDetector = new KnownSizeDetector();
+ for (Iterator i = body.getUnits().iterator(); i.hasNext(); ) {
+ Stmt stmt = (Stmt)i.next();
+ if (!(stmt instanceof AssignStmt))
+ continue;
+ AssignStmt astmt = (AssignStmt)stmt;
+ if (!(astmt.getLeftOp() instanceof Local))
+ continue;
+ astmt.getRightOp().apply(knownSizeDetector);
+ Integer size = (Integer)knownSizeDetector.getResult();
+ if (size != null)
+ stackAllocs.add(new StackAlloc(stmt));
+ }
+
+ // Debug
+ if (DEBUG) {
+ System.out.println(stackAllocs.size()
+ + " FIXED SIZE ALLOCATIONS");
+ for (Iterator i = stackAllocs.iterator();
+ i.hasNext(); ) {
+ StackAlloc alloc = (StackAlloc)i.next();
+ System.out.println(" ["
+ + indexMap.get(alloc.stmt) + "] "
+ + alloc.stmt);
+ }
+ }
+
+ // Eliminate new expressions of objects that override finalize() // or that are instances of java.lang.ref.Reference.
+ FinalizeDetector finalizeDetector = new FinalizeDetector();
+ ReferenceDetector referenceDetector = new ReferenceDetector();
+ for (Iterator i = stackAllocs.iterator(); i.hasNext(); ) {
+ StackAlloc alloc = (StackAlloc)i.next();
+ alloc.value.apply(finalizeDetector);
+ if (((Boolean)finalizeDetector.getResult())
+ .booleanValue()) {
+ if (DEBUG) {
+ System.out.println("FINALIZE: ["
+ + indexMap.get(alloc.stmt) + "] "
+ + alloc.stmt);
+ }
+ i.remove();
+ }
+ alloc.value.apply(referenceDetector);
+ if (((Boolean)referenceDetector.getResult())
+ .booleanValue()) {
+ if (DEBUG) {
+ System.out.println("REFERENCE: ["
+ + indexMap.get(alloc.stmt) + "] "
+ + alloc.stmt);
+ }
+ i.remove();
+ }
+ }
+
+ // Do follows flow analysis to eliminate looped allocations
+ FollowsAnalysis follows = new FollowsAnalysis(body);
+ for (Iterator i = stackAllocs.iterator(); i.hasNext(); ) {
+ StackAlloc alloc = (StackAlloc)i.next();
+ if (follows.canFollow(alloc.stmt, alloc.stmt)) {
+ if (DEBUG) {
+ System.out.println("LOOPED: ["
+ + indexMap.get(alloc.stmt) + "] "
+ + alloc.stmt);
+ }
+ i.remove();
+ }
+ }
+
+ // If there are no more candidates, bail out early
+ if (stackAllocs.isEmpty())
+ return;
+
+ // Compute uses of each local
+ SimpleLocalUses localUses = new SimpleLocalUses(graph,
+ new SimpleLocalDefs(graph));
+
+ // Initialize set of defs with known escape status
+ HashMap knowns = new HashMap();
+
+ // Initialize set of defs with unknown escape status
+ HashSet unknowns = new HashSet();
+ for (Iterator i = stackAllocs.iterator(); i.hasNext(); ) {
+ StackAlloc alloc = (StackAlloc)i.next();
+ unknowns.add(alloc.stmt);
+ }
+
+ // Keep eliminating unknowns until we're done
+ EscapingStmtSwitch ess = new EscapingStmtSwitch();
+ while (!unknowns.isEmpty()) {
+
+ // Debug
+ if (DEBUG) {
+ System.out.println(unknowns.size()
+ + " remaining unknowns...");
+ for (Iterator i = unknowns.iterator();
+ i.hasNext(); ) {
+ Stmt stmt = (Stmt)i.next();
+ System.out.println(" ["
+ + indexMap.get(stmt) + "] " + stmt);
+ }
+ System.out.println("------------------------");
+ }
+
+ // Detect forward progress
+ boolean doMore = false;
+
+ // For each unknown def, check for escape
+ unknown_loop:
+ for (Iterator i = ((HashSet)unknowns.clone())
+ .iterator(); i.hasNext(); ) {
+
+ // Get next unknown def statment
+ AssignStmt stmt = (AssignStmt)i.next();
+ Local defLocal = (Local)stmt.getLeftOp();
+
+ // Look for uses that themselves escape
+ boolean anyUknowns = false;
+ for (Iterator j = localUses.getUsesOf(stmt)
+ .iterator(); j.hasNext(); ) {
+
+ // Get next use of the local
+ UnitValueBoxPair up
+ = (UnitValueBoxPair)j.next();
+ Stmt use = (Stmt)up.getUnit();
+
+ // Test if local escapes via this use
+ ess.setLocal(defLocal);
+ use.apply(ess);
+ Object result = ess.getResult();
+
+ // Only escapes maybe via this use?
+ // If so, and the escape of the use
+ // is unknown, then add the use to
+ // the set of unknowns we need to check
+ if (result == null) {
+ result = knowns.get(use);
+ if (result == null) {
+ if (DEBUG) {
+ System.out.println(
+ " UNKNOWN USE ["
+ + indexMap.get(
+ use) + "]");
+ }
+ unknowns.add(use);
+ anyUknowns = true;
+ doMore = true;
+ continue;
+ }
+ }
+
+ // Does local escape via this use?
+ if (result == Boolean.TRUE) {
+ if (DEBUG) {
+ System.out.println("["
+ + indexMap.get(stmt)
+ + "] ESCAPES via ["
+ + indexMap.get(use)
+ + "]");
+ }
+ unknowns.remove(stmt);
+ knowns.put(stmt, result);
+ doMore = true;
+ continue unknown_loop;
+ }
+
+ // Defintely does not escape this use
+ if (result != Boolean.FALSE)
+ throw new RuntimeException();
+ }
+
+ // Are all uses non-escaping?
+ if (!anyUknowns) {
+ if (DEBUG) {
+ System.out.println("["
+ + indexMap.get(stmt)
+ + "] NO ESCAPE");
+ }
+ unknowns.remove(stmt);
+ knowns.put(stmt, Boolean.FALSE);
+ doMore = true;
+ continue;
+ }
+
+ // This def is still unknown
+ if (DEBUG) {
+ System.out.println("["
+ + indexMap.get(stmt)
+ + "] STILL UNKNOWN");
+ }
+ }
+
+ // See if we're no longer making progress
+ if (!doMore) {
+ if (DEBUG)
+ System.out.println("NO FURTHER PROGRESS");
+ for (Iterator i = unknowns.iterator();
+ i.hasNext(); ) {
+ AssignStmt stmt = (AssignStmt)i.next();
+ knowns.put(stmt, Boolean.FALSE);
+ }
+ unknowns.clear();
+ }
+ }
+
+ // Now eliminate allocations whose locals can escape
+ for (Iterator i = stackAllocs.iterator(); i.hasNext(); ) {
+ AssignStmt stmt = ((StackAlloc)i.next()).stmt;
+ if (((Boolean)knowns.get(stmt)).booleanValue())
+ i.remove();
+ }
+
+ // Debug
+ if (DEBUG) {
+ System.out.println(stackAllocs.size()
+ + " STACK ALLOCATABLES");
+ for (Iterator i = stackAllocs.iterator();
+ i.hasNext(); ) {
+ StackAlloc alloc = (StackAlloc)i.next();
+ System.out.println(" ["
+ + indexMap.get(alloc.stmt) + "] "
+ + alloc.stmt);
+ }
+ }
+
+ // Sort the remaining allocations by size
+ StackAlloc[] allocs = (StackAlloc[])stackAllocs.toArray(
+ new StackAlloc[stackAllocs.size()]);
+ Arrays.sort(allocs, new Comparator() {
+ public int compare(Object o1, Object o2) {
+ StackAlloc a1 = (StackAlloc)o1;
+ StackAlloc a2 = (StackAlloc)o2;
+ return a1.size < a2.size ? -1
+ : a1.size > a2.size ? 1 : 0;
+ }
+ });
+
+ // Include as many as we can, up to maximum total size
+ int total = 0;
+ HashSet stmts = new HashSet();
+ for (int i = 0; i < allocs.length; i++) {
+ StackAlloc alloc = allocs[i];
+ if (total + alloc.cost <= maxAlloc) {
+ alloc.stmt.getRightOpBox().addTag(
+ new StackAllocTag(i));
+ total += alloc.cost;
+ } else
+ break;
+ }
+ }
+}
+
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/EscapingStmtSwitch.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/EscapingStmtSwitch.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/EscapingStmtSwitch.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/EscapingStmtSwitch.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,117 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: EscapingStmtSwitch.java,v 1.1 2004/11/27 23:11:04 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen.escape;
+
+import java.util.*;
+import org.dellroad.jc.cgen.*;
+import soot.*;
+import soot.jimple.*;
+
+/**
+ * Checks for statements where the local can escape. The result
+ * is <code>Boolean.TRUE</code> if so, <code>Boolean.FALSE</code> if not,
+ * or <code>null</code> if the statement assigns the local to another local.
+ */
+public class EscapingStmtSwitch extends AbstractStmtSwitch {
+
+ private final EscapingValueSwitch escapingValueSwitch;
+ private Local local;
+
+ public EscapingStmtSwitch() {
+ escapingValueSwitch = new EscapingValueSwitch();
+ }
+
+ public Local getLocal() {
+ return local;
+ }
+
+ public void setLocal(Local local) {
+ this.local = local;
+ escapingValueSwitch.setLocal(local);
+ }
+
+ public void caseAssignStmt(AssignStmt stmt) {
+ Value lhs = stmt.getLeftOp();
+ Value rhs = stmt.getRightOp();
+
+ // Check if local can escape via the expression itself
+ rhs.apply(escapingValueSwitch);
+ Object valueResult = escapingValueSwitch.getResult();
+ if (valueResult != null) {
+ setResult(valueResult);
+ return;
+ }
+
+ // If we get here, the expression is the local..
+
+ // Check for assignment of local to a field
+ // XXX OK if field is in another non-escaping local
+ if (lhs instanceof FieldRef) {
+ setResult(Boolean.TRUE);
+ return;
+ }
+
+ // Check for assignment of local to an array element
+ // XXX OK if field is in another non-escaping array
+ if (lhs instanceof ArrayRef) {
+ setResult(Boolean.TRUE);
+ return;
+ }
+
+ // Assignment must be to some (possibly the same) local
+ if (!(lhs instanceof Local))
+ throw new RuntimeException("unexpected");
+
+ // Check for assignment of local to itself
+ if (lhs.equals(local)) {
+ setResult(Boolean.FALSE);
+ return;
+ }
+
+ // Escape depends on whether the assigned-to local can escape
+ setResult(null);
+ }
+
+ public void caseInvokeStmt(InvokeStmt stmt) {
+ if (NullCheckStmt.isNullCheck(stmt)) {
+ setResult(Boolean.FALSE);
+ return;
+ }
+ stmt.getInvokeExpr().apply(escapingValueSwitch);
+ Boolean result = (Boolean)escapingValueSwitch.getResult();
+ if (result == null)
+ result = Boolean.FALSE; // return value is ignored
+ setResult(result);
+ }
+
+ public void caseReturnStmt(ReturnStmt stmt) {
+ setResult(Boolean.TRUE);
+ }
+
+ public void caseThrowStmt(ThrowStmt stmt) {
+ setResult(Boolean.TRUE);
+ }
+
+ public void defaultCase(Object obj) {
+ setResult(Boolean.FALSE);
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/EscapingValueSwitch.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/EscapingValueSwitch.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/EscapingValueSwitch.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/EscapingValueSwitch.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,95 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: EscapingValueSwitch.java,v 1.1 2004/11/27 23:11:04 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen.escape;
+
+import java.util.*;
+import org.dellroad.jc.cgen.*;
+import soot.*;
+import soot.jimple.*;
+
+/**
+ * Checks for values where the local can escape. The result
+ * is <code>Boolean.TRUE</code> if so, <code>Boolean.FALSE</code> if not,
+ * or <code>null</code> if the local can only escape as the 'return value'
+ * of the <code>Value</code> itself.
+ */
+public class EscapingValueSwitch extends AbstractJimpleValueSwitch {
+
+ private Local local;
+
+ public Local getLocal() {
+ return local;
+ }
+
+ public void setLocal(Local local) {
+ this.local = local;
+ }
+
+ public void caseCastExpr(CastExpr v) {
+ v.getOp().apply(this);
+ }
+
+ public void caseLocal(Local v) {
+ setResult(v.equals(local) ? null : Boolean.FALSE);
+ }
+
+ public void caseInterfaceInvokeExpr(InterfaceInvokeExpr expr) {
+ caseInstanceInvokeExpr(expr);
+ }
+
+ public void caseSpecialInvokeExpr(SpecialInvokeExpr expr) {
+ caseInstanceInvokeExpr(expr);
+ }
+
+ public void caseVirtualInvokeExpr(VirtualInvokeExpr expr) {
+ caseInstanceInvokeExpr(expr);
+ }
+
+ public void caseStaticInvokeExpr(StaticInvokeExpr expr) {
+ handleInvokeParameters(expr);
+ }
+
+ private void caseInstanceInvokeExpr(InstanceInvokeExpr expr) {
+ expr.getBase().apply(this);
+ if (getResult() != Boolean.FALSE) {
+ setResult(Boolean.TRUE);
+ return;
+ }
+ handleInvokeParameters(expr);
+ }
+
+ private void handleInvokeParameters(InvokeExpr expr) {
+ int argCount = expr.getArgCount();
+ for (int i = 0; i < argCount; i++) {
+ expr.getArg(i).apply(this);
+ if (getResult() != Boolean.FALSE) {
+ setResult(Boolean.TRUE);
+ return;
+ }
+ }
+ setResult(Boolean.FALSE);
+ }
+
+ public void defaultCase(Object obj) {
+ setResult(Boolean.FALSE);
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/KnownSizeDetector.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/KnownSizeDetector.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/KnownSizeDetector.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/KnownSizeDetector.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,146 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: KnownSizeDetector.java,v 1.1 2004/11/27 23:11:04 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen.escape;
+
+import java.util.*;
+import org.dellroad.jc.cgen.*;
+import soot.*;
+import soot.jimple.*;
+
+/**
+ * Instances of this class detect 'new' expressions with a known
+ * instance size. The result is an <code>Integer</code> with the
+ * estimated size, or <code>null</code> if the type of the 'new'
+ * expression does not have a fixed size (or the value is not
+ * some kind of 'new' expression).
+ */
+public class KnownSizeDetector extends AbstractJimpleValueSwitch {
+
+ public static final int REFERENCE_SIZE = 4;
+ public static final int OBJECT_HEADER_SIZE = 8;
+
+ public void caseNewExpr(NewExpr v) {
+ setResult(new Integer(size(v.getBaseType())));
+ }
+
+ public void caseNewArrayExpr(NewArrayExpr v) {
+ doArray(v.getSize(), (ArrayType)v.getType());
+ }
+
+ public void caseNewMultiArrayExpr(NewMultiArrayExpr v) {
+ doArray(v.getSize(0), (ArrayType)v.getType());
+ }
+
+ private void doArray(Value length, ArrayType atype) {
+ if (!(length instanceof IntConstant)) {
+ setResult(null);
+ return;
+ }
+ Type etype = atype.getElementType();
+ int size = etype instanceof RefLikeType ?
+ REFERENCE_SIZE : size(etype);
+ setResult(new Integer(((IntConstant)length).value * size));
+ }
+
+ public void defaultCase(Object obj) {
+ setResult(null);
+ }
+
+ /**
+ * Computes the size in bytes of an instance of a type.
+ *
+ * @see KnownSizeDetector#size KnownSizeDetector.size()
+ */
+ public static class SizeTypeSwitch extends TypeSwitch {
+ public void caseBooleanType(BooleanType t) {
+ setResult(new Integer(1));
+ }
+ public void caseByteType(ByteType t) {
+ setResult(new Integer(1));
+ }
+ public void caseCharType(CharType t) {
+ setResult(new Integer(2));
+ }
+ public void caseShortType(ShortType t) {
+ setResult(new Integer(2));
+ }
+ public void caseIntType(IntType t) {
+ setResult(new Integer(4));
+ }
+ public void caseFloatType(FloatType t) {
+ setResult(new Integer(4));
+ }
+ public void caseLongType(LongType t) {
+ setResult(new Integer(8));
+ }
+ public void caseDoubleType(DoubleType t) {
+ setResult(new Integer(8));
+ }
+ public void defaultCase(Type t) {
+ if (!(t instanceof RefType)) {
+ throw new IllegalArgumentException(
+ "non-reference type: " + t);
+ }
+ SootClass c = ((RefType)t).getSootClass();
+ if (c.isInterface()) {
+ throw new IllegalArgumentException(
+ "interface type: " + t);
+ }
+ int sz = OBJECT_HEADER_SIZE;
+ while (true) {
+ for (Iterator i = c.getFields().iterator();
+ i.hasNext(); ) {
+ SootField f = (SootField)i.next();
+ if (f.isStatic())
+ continue;
+ Type ftype = f.getType();
+ if (ftype instanceof RefLikeType) {
+ sz += REFERENCE_SIZE;
+ continue;
+ }
+ ftype.apply(this);
+ sz += ((Integer)getResult()).intValue();
+ }
+ if (!c.hasSuperclass())
+ break;
+ c = c.getSuperclass();
+ }
+ setResult(new Integer(sz));
+ }
+ }
+
+
+ /**
+ * Return our best guess of the size of an instance of the given type,
+ * in bytes. We include {@link #OBJECT_HEADER_SIZE OBJECT_HEADER_SIZE}
+ * for object overhead, but don't include any gaps for alignment.
+ *
+ * @param type a primitive type, or a non-interface, non-array
+ * reference type.
+ * @throws IllegalArgumentException if <code>type</code>
+ */
+ public static int size(Type type) {
+ SizeTypeSwitch sw = new SizeTypeSwitch();
+ type.apply(sw);
+ return ((Integer)sw.getResult()).intValue();
+ }
+}
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/Makefile.am
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/Makefile.am?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/Makefile.am (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/Makefile.am Tue Oct 4 19:19:16 2005
@@ -0,0 +1,10 @@
+## $Id: Makefile.am,v 1.3 2004/12/28 22:28:26 archiecobbs Exp $
+
+EXTRA_DIST= EscapeAnalysis.java \
+ EscapingStmtSwitch.java \
+ EscapingValueSwitch.java \
+ KnownSizeDetector.java \
+ StackAlloc.java \
+ StackAllocTag.java \
+ package.html
+
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/StackAlloc.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/StackAlloc.java?rev=294974&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/StackAlloc.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/jchevm/jchevm/java/org/dellroad/jc/cgen/escape/StackAlloc.java Tue Oct 4 19:19:16 2005
@@ -0,0 +1,45 @@
+
+//
+// Copyright 2005 The Apache Software Foundation or its licensors,
+// as applicable.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// $Id: StackAlloc.java,v 1.2 2004/12/17 15:35:46 archiecobbs Exp $
+//
+
+package org.dellroad.jc.cgen.escape;
+
+import java.util.*;
+import soot.*;
+import soot.jimple.*;
+
+/**
+ * Holds information about a potential stack-allocatable 'new' statement.
+ */
+class StackAlloc {
+
+ AssignStmt stmt;
+ Local local;
+ Value value; // the 'new' expression
+ Boolean escapes; // TRUE = yes, FALSE = no, null = unknown
+ int size;
+ int cost;
+
+ public StackAlloc(Stmt ostmt) {
+ this.stmt = (AssignStmt)ostmt;
+ this.local = (Local)stmt.getLeftOp();
+ this.value = stmt.getRightOp();
+ }
+}
+