Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenJ9 Shared Class Cache read feature #1501

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion doc/soot_options.htm
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,9 @@ <H2><A name="section_2">Input Options</A></H2>
</tr>
<tr>
<td><tt>-src-prec <var>format</var></tt><br></td>
<td><tt>c&nbsp;
<td><tt>cache&nbsp;
</tt><br><tt>only-cache&nbsp;
</tt><br><tt>c&nbsp;
</tt><tt>class&nbsp;
</tt><br><tt>only-class&nbsp;
</tt><br><tt>J&nbsp;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8772,6 +8772,14 @@ private Composite Input_OptionsCreate(Composite parent) {

data = new OptionData [] {

new OptionData("Cache",
"cache",
"\nTry to resolve classes first from the shared class cache found \nin the Soot classpath. Fall back to .class and then .jimple \nfiles only when unable to find a class in the cache.",
false),
new OptionData("Only Cache Source",
"only-cache",
"\nTry to resolve classes first from the shared class cache found \nin the Soot classpath. Do not try any other types of files even \nwhen unable to find a class in the cache.",
false),
new OptionData("Class File",
"c class",
"\nTry to resolve classes first from .class files found in the Soot \nclasspath. Fall back to .jimple files only when unable to find a \n.class file.",
Expand Down
57 changes: 55 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
<url>https://github.com/soot-oss/soot</url>
</scm>
<properties>
<openj9-build-root>/root/openj9-openjdk-jdk8/build/linux-x86_64-normal-server-release</openj9-build-root>
<cpfile>cp.txt</cpfile>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<xml-maven-plugin.version>1.0.2</xml-maven-plugin.version>
Expand All @@ -78,6 +80,42 @@
<build>
<finalName>sootclasses-trunk</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
def file = new File(project.properties.cpfile)
project.properties.cp = file.getText()
</source>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.9</version>
<executions>
<execution>
<id>build-classpath</id>
<phase>generate-sources</phase>
<goals>
<goal>build-classpath</goal>
</goals>
<configuration>
<outputFile>${cpfile}</outputFile>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xml-maven-plugin</artifactId>
Expand Down Expand Up @@ -255,8 +293,23 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<verbose>true</verbose>
<fork>true</fork>
<executable>${openj9-build-root}/images/j2sdk-image/bin/javac</executable>
<compilerVersion>1.8</compilerVersion>
<compilerArgs>
<arg>-classpath</arg><arg>${cp}:${openj9-build-root}/images/j2sdk-image/jre/lib/ddr/j9ddr.jar</arg>
<arg>-d</arg><arg>${basedir}/target/classes</arg>
<arg>-s</arg><arg>${basedir}/target/generated-sources/annotations</arg>
<arg>-g</arg>
<arg>-verbose</arg>
<arg>-nowarn</arg>
<arg>-target</arg><arg>1.8</arg>
<arg>-source</arg><arg>1.8</arg>
<arg>-encoding</arg><arg>UTF-8</arg>
</compilerArgs>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
<executions>
<execution>
Expand Down
2 changes: 2 additions & 0 deletions src/main/generated/options/soot/AntTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ public void setast_metrics(boolean arg) {
public void setsrc_prec(String arg) {
if(false

|| arg.equals( "cache" )
|| arg.equals( "only-cache" )
|| arg.equals( "c" )
|| arg.equals( "class" )
|| arg.equals( "only-class" )
Expand Down
40 changes: 31 additions & 9 deletions src/main/generated/options/soot/options/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,17 @@ public static Options v() {
return G.v().soot_options_Options();
}

public static final int src_prec_c = 1;
public static final int src_prec_class = 1;
public static final int src_prec_only_class = 2;
public static final int src_prec_J = 3;
public static final int src_prec_jimple = 3;
public static final int src_prec_java = 4;
public static final int src_prec_apk = 5;
public static final int src_prec_apk_class_jimple = 6;
public static final int src_prec_apk_c_j = 6;
public static final int src_prec_cache = 1;
public static final int src_prec_only_cache = 2;
public static final int src_prec_c = 3;
public static final int src_prec_class = 3;
public static final int src_prec_only_class = 4;
public static final int src_prec_J = 5;
public static final int src_prec_jimple = 5;
public static final int src_prec_java = 6;
public static final int src_prec_apk = 7;
public static final int src_prec_apk_class_jimple = 8;
public static final int src_prec_apk_c_j = 8;
public static final int output_format_J = 1;
public static final int output_format_jimple = 1;
public static final int output_format_j = 2;
Expand Down Expand Up @@ -368,6 +370,24 @@ else if (false
String value = nextOption();

if (false);
else if (false
|| value.equals("cache")
) {
if (src_prec != 0 && src_prec != src_prec_cache) {
G.v().out.println("Multiple values given for option " + option);
return false;
}
src_prec = src_prec_cache;
}
else if (false
|| value.equals("only-cache")
) {
if (src_prec != 0 && src_prec != src_prec_only_cache) {
G.v().out.println("Multiple values given for option " + option);
return false;
}
src_prec = src_prec_only_cache;
}
else if (false
|| value.equals("c")
|| value.equals("class")
Expand Down Expand Up @@ -1742,6 +1762,8 @@ public String getUsage() {
+ padOpt("-force-android-jar ARG", "Force Soot to use ARG as the path for the android.jar file.")
+ padOpt("-ast-metrics", "Compute AST Metrics if performing java to jimple")
+ padOpt("-src-prec ARG", "Sets source precedence to ARG files")
+ padVal("cache", "Favour shared class cache as Soot source")
+ padVal("only-cache", "Use only shared class cache as Soot source")
+ padVal("c class (default)", "Favour class files as Soot source")
+ padVal("only-class", "Use only class files as Soot source")
+ padVal("J jimple", "Favour Jimple files as Soot source")
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/soot/SourceLocator.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import soot.JavaClassProvider.JarException;
import soot.asm.AsmClassProvider;
import soot.asm.AsmJava9ClassProvider;
import soot.cache.CacheClassProvider;
import soot.dexpler.DexFileProvider;
import soot.options.Options;

Expand Down Expand Up @@ -245,6 +246,17 @@ protected void setupClassProviders() {
classProviders.add(new AsmJava9ClassProvider());
}
switch (Options.v().src_prec()) {
case Options.src_prec_cache:
System.out.println("Using the cache with default source provider chain.");
classProviders.add(new CacheClassProvider());
classProviders.add(classFileClassProvider);
classProviders.add(new JimpleClassProvider());
classProviders.add(new JavaClassProvider());
break;
case Options.src_prec_only_cache:
System.out.println("Using the cache only source provider chain.");
classProviders.add(new CacheClassProvider());
break;
case Options.src_prec_class:
classProviders.add(classFileClassProvider);
classProviders.add(new JimpleClassProvider());
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/soot/asm/SootClassBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public class SootClassBuilder extends ClassVisitor {
* @param klass
* Soot class to build.
*/
protected SootClassBuilder(SootClass klass) {
public SootClassBuilder(SootClass klass) {
super(Opcodes.ASM8);
this.klass = klass;
this.deps = new HashSet();
Expand All @@ -97,6 +97,10 @@ protected SootClass getKlass() {
return klass;
}

public Set<soot.Type> getDeps() {
return deps;
}

void addDep(String s) {
String className = AsmUtil.baseTypeName(s);
RefType refType = makeRefType(className);
Expand Down
156 changes: 156 additions & 0 deletions src/main/java/soot/cache/CacheClassProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package soot.cache;

/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 2020 Kristen Newbury
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
* #L%
*/

import com.ibm.oti.shared.HelperAlreadyDefinedException;
import com.ibm.oti.shared.Shared;
import com.ibm.oti.shared.SharedClassHelperFactory;
import com.ibm.oti.shared.SharedClassURLClasspathHelper;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import soot.ClassProvider;
import soot.ClassSource;

/**
* OpenJ9 Shared Cache Class class provider.
*
* @author Kristen Newbury
*/

public class CacheClassProvider implements ClassProvider {

private static URL testClassUrl;

public CacheClassProvider() {
if (!System.getProperty("java.vm.name").contains("OpenJ9")) {
throw new RuntimeException("CacheClassProvider feature only works with OpenJ9 JVM running Soot");
}
}

public static void setTestClassUrl(String url) {
try {
testClassUrl = new URL("file://" + url);
System.out.println("CacheClassProvider: setting testClassUrl: " + url);
} catch (MalformedURLException e) {
System.out.println("Bad URL provided, not using url: " + url);
e.printStackTrace();
}
}

public ClassSource find(String cls) {

byte[] romCookie = null;
CacheMemorySingleton cacheMem = null;
ByteBuffer wrapper = null;

SharedClassHelperFactory factory = Shared.getSharedClassHelperFactory();
if (factory != null) {
URL[] urlsForRuntime = null;
URL[] urlsForApp = null;
URL[] urlsForJCE = null;
URL jceurl = null;
URL rturl = null;
SharedClassURLClasspathHelper helperForAppClasses = null;
SharedClassURLClasspathHelper helperForRuntimeClasses = null;
SharedClassURLClasspathHelper helperForJCE = null;
try {
rturl = new URL("file://" + System.getProperty("java.home") + File.separator + "lib" + File.separator + "rt.jar");
jceurl = new URL("file://" + System.getProperty("java.home") + File.separator + "lib" + File.separator + "jce.jar");
urlsForRuntime = new URL[] { rturl };
if (testClassUrl != null) {
urlsForApp = new URL[] { testClassUrl };
} else {
System.out.println("No test class url set");
return null;
}

urlsForJCE = new URL[] { jceurl };
} catch (MalformedURLException e) {
System.out.println("Bad URL provided");
e.printStackTrace();
}
URLClassLoader loaderForRuntime = new URLClassLoader(urlsForRuntime);
URLClassLoader loaderForApp = new URLClassLoader(urlsForApp);
URLClassLoader loaderForJCE = new URLClassLoader(urlsForJCE);

// get helper to find classes in cache
try {
helperForRuntimeClasses = factory.getURLClasspathHelper(loaderForRuntime, urlsForRuntime);
helperForAppClasses = factory.getURLClasspathHelper(loaderForApp, urlsForApp);
helperForJCE = factory.getURLClasspathHelper(loaderForJCE, urlsForJCE);
} catch (HelperAlreadyDefinedException e) {
System.out.println("Helper already defined?" + e.getMessage());
e.printStackTrace();
}

helperForAppClasses.confirmAllEntries();
helperForRuntimeClasses.confirmAllEntries();
helperForJCE.confirmAllEntries();

try {
// for now this part happens every time
// maybe consider avoiding that later
byte[] cacheInfo = helperForAppClasses.findSharedCache();
if (cacheInfo != null) {
wrapper = ByteBuffer.wrap(cacheInfo);
// jni filled byte array
wrapper.order(ByteOrder.nativeOrder());
cacheMem = CacheMemorySingleton.getInstance();
} else {
System.out.println("Cannot get cache start");
}
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}

romCookie = helperForAppClasses.findSharedClass(cls, null);
if (romCookie == null) {
romCookie = helperForRuntimeClasses.findSharedClass(cls, null);
if (romCookie == null) {
romCookie = helperForJCE.findSharedClass(cls, null);
if (romCookie == null) {
System.out.println("Cannot find class in cache: " + cls);
} else {
System.out.println("Located the class in the cache: " + cls);
}
} else {
System.out.println("Located the class in the cache: " + cls);
}
} else {
System.out.println("Located the class in the cache: " + cls);
}

} else {
System.out.println("Cache helper null, cannot find class in cache: " + cls);
System.out.println("Is Shared Class Cache enabled on command line?");
}
return romCookie == null ? null : new CacheClassSource(cls, romCookie, cacheMem, wrapper.getLong(), wrapper.getInt());
}
}
Loading