am 008da7d4: Descriptor references are direct references
* commit '008da7d42d529761ab85b8e92d3dd366f1fad195':
Descriptor references are direct references
diff --git a/dexdump/Android.mk b/dexdump/Android.mk
index 9aa4ae9..d9a06d1 100644
--- a/dexdump/Android.mk
+++ b/dexdump/Android.mk
@@ -43,6 +43,7 @@
LOCAL_MODULE_TAGS := optional
LOCAL_LDLIBS +=
LOCAL_32_BIT_ONLY := true
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
@@ -53,6 +54,7 @@
LOCAL_SHARED_LIBRARIES := libutils
LOCAL_MODULE_TAGS := optional
LOCAL_32_BIT_ONLY := true
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_STATIC_LIBRARY)
endif # !SDK_ONLY
@@ -69,11 +71,12 @@
LOCAL_SRC_FILES := $(dexdump_src_files)
LOCAL_C_INCLUDES := $(dexdump_c_includes)
LOCAL_STATIC_LIBRARIES := $(dexdump_static_libraries) liblog libutils
-
ifneq ($(strip $(USE_MINGW)),)
LOCAL_STATIC_LIBRARIES += libz
else
LOCAL_LDLIBS += -lpthread -lz
endif
-
+# TODO: Move dexdump from libdex to libart and lose the 32-bit limitation.
+LOCAL_32_BIT_ONLY := true
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_HOST_EXECUTABLE)
diff --git a/dexlist/Android.mk b/dexlist/Android.mk
index 19b52d0..4d4a709 100644
--- a/dexlist/Android.mk
+++ b/dexlist/Android.mk
@@ -35,6 +35,7 @@
LOCAL_STATIC_LIBRARIES := $(dexdump_static_libraries)
LOCAL_LDLIBS +=
LOCAL_32_BIT_ONLY := true
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
#include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
@@ -44,4 +45,7 @@
LOCAL_C_INCLUDES := $(dexdump_c_includes)
LOCAL_STATIC_LIBRARIES := $(dexdump_static_libraries) libcutils liblog libutils
LOCAL_LDLIBS += -lpthread -lz
+# TODO: Move dexlist from libdex to libart and lose the 32-bit limitation.
+LOCAL_32_BIT_ONLY := true
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_HOST_EXECUTABLE)
diff --git a/docs/hello-world.html b/docs/hello-world.html
index 7491a28..d988e2f 100644
--- a/docs/hello-world.html
+++ b/docs/hello-world.html
@@ -88,127 +88,6 @@
about using debuggers with Dalvik.
-
-<h2>Working with the desktop build</h2>
-
-<!-- largely lifted from
-http://groups.google.com/group/android-porting/browse_thread/thread/ab553116dbc960da/29167c58b3b49051#29167c58b3b49051
--->
-
-<p>
-The Dalvik VM can also be used directly on the desktop. This is somewhat
-more complicated however, because you won't have certain things set up in
-your environment, and several native code libraries are required to support
-the core Dalvik libs.
-</p><p>
-Start with:
-
-<pre>
- . build/envsetup.sh
- lunch sim-eng
-</pre>
-
-You should see something like:
-
-<pre>
- ============================================
- TARGET_PRODUCT=sim
- TARGET_BUILD_VARIANT=eng
- TARGET_SIMULATOR=true
- TARGET_BUILD_TYPE=debug
- TARGET_ARCH=x86
- HOST_ARCH=x86
- HOST_OS=linux
- HOST_BUILD_TYPE=release
- BUILD_ID=
- ============================================
-</pre>
-
-</p></p>
-This configures you to build for the desktop, linking against glibc.
-This mode is NOT recommended for anything but experimental use. It
-may go away in the future.
-</p></p>
-You may see <code>TARGET_BUILD_TYPE=release</code> or <code>=debug</code>
-or possibly nothing there at all. You may want to replace the
-<code>lunch</code> command with
-<code>choosecombo Simulator debug sim eng</code>.
-</p></p>
-Build the world (add a <code>-j4</code> if you have multiple cores):
-
-<pre>
- make
-</pre>
-
-</p></p>
-When that completes, you have a working dalvikm on your desktop
-machine:
-
-<pre>
- % dalvikvm
- E/dalvikvm(19521): ERROR: must specify non-'.' bootclasspath
- W/dalvikvm(19521): JNI_CreateJavaVM failed
- Dalvik VM init failed (check log file)
-</pre>
-
-</p></p>
-To actually do something, you need to specify the bootstrap class path
-and give it a place to put DEX data that it uncompresses from jar
-files. You can do that with a script like this:
-
-<blockquote><pre>
-#!/bin/sh
-
-# base directory, at top of source tree; replace with absolute path
-base=`pwd`
-
-# configure root dir of interesting stuff
-root=$base/out/debug/host/linux-x86/product/sim/system
-export ANDROID_ROOT=$root
-
-# configure bootclasspath
-bootpath=$root/framework
-export BOOTCLASSPATH=$bootpath/core.jar:$bootpath/ext.jar:$bootpath/framework.jar:$bootpath/android.policy.jar:$bootpath/services.jar
-
-# this is where we create the dalvik-cache directory; make sure it exists
-export ANDROID_DATA=/tmp/dalvik_$USER
-mkdir -p $ANDROID_DATA/dalvik-cache
-
-exec dalvikvm $@
-</pre></blockquote>
-
-</p></p>
-The preparation with <code>dx</code> is the same as before:
-
-<pre>
- % cat > Foo.java
- class Foo { public static void main(String[] args) {
- System.out.println("Hello, world");
- } }
- (ctrl-D)
- % javac Foo.java
- % dx --dex --output=foo.jar Foo.class
- % ./rund -cp foo.jar Foo
- Hello, world
-</pre>
-
-As above, you can get some info about valid arguments like this:
-
-<pre>
- % ./rund -help
-</pre>
-
-</p></p>
-This also shows what options the VM was configured with. The sim "debug"
-build has all sorts of additional assertions and checks enabled,
-which slows the VM down, but since this is just for experiments it
-doesn't matter.
-
-</p></p>
-All of the above applies to x86 Linux. Anything else will likely
-require a porting effort. If libffi supports your system, the amount of
-work required should be minor.
-
</p></p>
<address>Copyright © 2009 The Android Open Source Project</address>
diff --git a/dx/src/com/android/dx/Version.java b/dx/src/com/android/dx/Version.java
index 5f02e47..1e15d55 100644
--- a/dx/src/com/android/dx/Version.java
+++ b/dx/src/com/android/dx/Version.java
@@ -21,5 +21,5 @@
*/
public class Version {
/** {@code non-null;} version string */
- public static final String VERSION = "1.10";
+ public static final String VERSION = "1.11";
}
diff --git a/dx/src/com/android/dx/cf/direct/ClassPathOpener.java b/dx/src/com/android/dx/cf/direct/ClassPathOpener.java
index c9fe275..26fbca0 100644
--- a/dx/src/com/android/dx/cf/direct/ClassPathOpener.java
+++ b/dx/src/com/android/dx/cf/direct/ClassPathOpener.java
@@ -242,9 +242,6 @@
*/
private boolean processArchive(File file) throws IOException {
ZipFile zip = new ZipFile(file);
- ByteArrayOutputStream baos = new ByteArrayOutputStream(40000);
- byte[] buf = new byte[20000];
- boolean any = false;
ArrayList<? extends java.util.zip.ZipEntry> entriesList
= Collections.list(zip.entries());
@@ -259,28 +256,31 @@
consumer.onProcessArchiveStart(file);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream(40000);
+ byte[] buf = new byte[20000];
+ boolean any = false;
+
for (ZipEntry one : entriesList) {
- if (one.isDirectory()) {
- continue;
- }
+ final boolean isDirectory = one.isDirectory();
String path = one.getName();
if (filter.accept(path)) {
- InputStream in = zip.getInputStream(one);
+ final byte[] bytes;
+ if (!isDirectory) {
+ InputStream in = zip.getInputStream(one);
- baos.reset();
- for (;;) {
- int amt = in.read(buf);
- if (amt < 0) {
- break;
+ baos.reset();
+ int read;
+ while ((read = in.read(buf)) != -1) {
+ baos.write(buf, 0, read);
}
- baos.write(buf, 0, amt);
+ in.close();
+ bytes = baos.toByteArray();
+ } else {
+ bytes = new byte[0];
}
- in.close();
-
- byte[] bytes = baos.toByteArray();
any |= consumer.processFileBytes(path, one.getTime(), bytes);
}
}
diff --git a/dx/src/com/android/dx/command/DxConsole.java b/dx/src/com/android/dx/command/DxConsole.java
index 9ce9836..919de8c 100644
--- a/dx/src/com/android/dx/command/DxConsole.java
+++ b/dx/src/com/android/dx/command/DxConsole.java
@@ -16,6 +16,8 @@
package com.android.dx.command;
+import java.io.IOException;
+import java.io.OutputStream;
import java.io.PrintStream;
/**
@@ -34,4 +36,15 @@
* Error output stream. Links to {@code System.err} by default.
*/
public static PrintStream err = System.err;
+
+ /**
+ * Output stream which prints to nowhere.
+ */
+ public static final PrintStream noop = new PrintStream(new OutputStream() {
+
+ @Override
+ public void write(int b) throws IOException {
+ // noop
+ }
+ });
}
diff --git a/dx/src/com/android/dx/command/Main.java b/dx/src/com/android/dx/command/Main.java
index 9834987..a0be5bd 100644
--- a/dx/src/com/android/dx/command/Main.java
+++ b/dx/src/com/android/dx/command/Main.java
@@ -33,7 +33,7 @@
"[--dump-width=<n>]\n" +
" [--dump-method=<name>[*]] [--verbose-dump] [--no-files] " +
"[--core-library]\n" +
- " [--num-threads=<n>] [--incremental] [--force-jumbo]\n" +
+ " [--num-threads=<n>] [--incremental] [--force-jumbo] [--no-warning]\n" +
" [--multi-dex [--main-dex-list=<file> [--minimal-main-dex]]\n" +
" [--input-list=<file>]\n" +
" [<file>.class | <file>.{zip,jar,apk} | <directory>] ...\n" +
diff --git a/dx/src/com/android/dx/command/dexer/Main.java b/dx/src/com/android/dx/command/dexer/Main.java
index 4a3d195..b9c6ec9 100644
--- a/dx/src/com/android/dx/command/dexer/Main.java
+++ b/dx/src/com/android/dx/command/dexer/Main.java
@@ -64,12 +64,14 @@
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.jar.Attributes;
@@ -179,11 +181,39 @@
/** Library .dex files to merge into the output .dex. */
private static final List<byte[]> libraryDexBuffers = new ArrayList<byte[]>();
- /** thread pool object used for multi-threaded file processing */
- private static ExecutorService threadPool;
+ /** Thread pool object used for multi-thread class translation. */
+ private static ExecutorService classTranslatorPool;
- /** used to handle Errors for multi-threaded file processing */
- private static List<Future<Void>> parallelProcessorFutures;
+ /** Single thread executor, for collecting results of parallel translation,
+ * and adding classes to dex file in original input file order. */
+ private static ExecutorService classDefItemConsumer;
+
+ /** Futures for {@code classDefItemConsumer} tasks. */
+ private static List<Future<Boolean>> addToDexFutures =
+ new ArrayList<Future<Boolean>>();
+
+ /** Thread pool object used for multi-thread dex conversion (to byte array).
+ * Used in combination with multi-dex support, to allow outputing
+ * a completed dex file, in parallel with continuing processing. */
+ private static ExecutorService dexOutPool;
+
+ /** Futures for {@code dexOutPool} task. */
+ private static List<Future<byte[]>> dexOutputFutures =
+ new ArrayList<Future<byte[]>>();
+
+ /** Lock object used to to coordinate dex file rotation, and
+ * multi-threaded translation. */
+ private static Object dexRotationLock = new Object();
+
+ /** Record the number if method indices "reserved" for files
+ * committed to translation in the context of the current dex
+ * file, but not yet added. */
+ private static int maxMethodIdsInProcess = 0;
+
+ /** Record the number if field indices "reserved" for files
+ * committed to translation in the context of the current dex
+ * file, but not yet added. */
+ private static int maxFieldIdsInProcess = 0;
/** true if any files are successfully processed */
private static volatile boolean anyFilesProcessed;
@@ -224,6 +254,7 @@
* @return 0 if success > 0 otherwise.
*/
public static int run(Arguments arguments) throws IOException {
+
// Reset the error count to start fresh.
errors.set(0);
// empty the list, so that tools that load dx and keep it around
@@ -289,7 +320,7 @@
byte[] outArray = null;
if (!outputDex.isEmpty() || (args.humanOutName != null)) {
- outArray = writeDex();
+ outArray = writeDex(outputDex);
if (outArray == null) {
return 2;
@@ -324,13 +355,14 @@
private static int runMultiDex() throws IOException {
assert !args.incremental;
- assert args.numThreads == 1;
if (args.mainDexListFile != null) {
classesInMainDex = new HashSet<String>();
readPathsFromFile(args.mainDexListFile, classesInMainDex);
}
+ dexOutPool = Executors.newFixedThreadPool(args.numThreads);
+
if (!processAllFiles()) {
return 1;
}
@@ -341,14 +373,31 @@
if (outputDex != null) {
// this array is null if no classes were defined
- dexOutputArrays.add(writeDex());
+
+ dexOutputFutures.add(dexOutPool.submit(new DexWriter(outputDex)));
// Effectively free up the (often massive) DexFile memory.
outputDex = null;
}
+ try {
+ dexOutPool.shutdown();
+ if (!dexOutPool.awaitTermination(600L, TimeUnit.SECONDS)) {
+ throw new RuntimeException("Timed out waiting for dex writer threads.");
+ }
+
+ for (Future<byte[]> f : dexOutputFutures) {
+ dexOutputArrays.add(f.get());
+ }
+
+ } catch (InterruptedException ex) {
+ dexOutPool.shutdownNow();
+ throw new RuntimeException("A dex writer thread has been interrupted.");
+ } catch (Exception e) {
+ dexOutPool.shutdownNow();
+ throw new RuntimeException("Unexpected exception in dex writer thread");
+ }
if (args.jarOutput) {
-
for (int i = 0; i < dexOutputArrays.size(); i++) {
outputResources.put(getDexFileName(i),
dexOutputArrays.get(i));
@@ -368,7 +417,6 @@
closeOutput(out);
}
}
-
}
return 0;
@@ -474,10 +522,14 @@
anyFilesProcessed = false;
String[] fileNames = args.fileNames;
- if (args.numThreads > 1) {
- threadPool = Executors.newFixedThreadPool(args.numThreads);
- parallelProcessorFutures = new ArrayList<Future<Void>>();
- }
+ // translate classes in parallel
+ classTranslatorPool = new ThreadPoolExecutor(args.numThreads,
+ args.numThreads, 0, TimeUnit.SECONDS,
+ new ArrayBlockingQueue<Runnable>(2 * args.numThreads, true),
+ new ThreadPoolExecutor.CallerRunsPolicy());
+ // collect translated and write to dex in order
+ classDefItemConsumer = Executors.newSingleThreadExecutor();
+
try {
if (args.mainDexListFile != null) {
@@ -490,14 +542,26 @@
processOne(fileNames[i], mainPassFilter);
}
- if (dexOutputArrays.size() > 0) {
+ if (dexOutputFutures.size() > 0) {
throw new DexException("Too many classes in " + Arguments.MAIN_DEX_LIST_OPTION
+ ", main dex capacity exceeded");
}
if (args.minimalMainDex) {
// start second pass directly in a secondary dex file.
- createDexFile();
+
+ // Wait for classes in progress to complete
+ synchronized(dexRotationLock) {
+ while(maxMethodIdsInProcess > 0 || maxFieldIdsInProcess > 0) {
+ try {
+ dexRotationLock.wait();
+ } catch(InterruptedException ex) {
+ /* ignore */
+ }
+ }
+ }
+
+ rotateDexFile();
}
// remaining files
@@ -517,35 +581,36 @@
*/
}
- if (args.numThreads > 1) {
- try {
- threadPool.shutdown();
- if (!threadPool.awaitTermination(600L, TimeUnit.SECONDS)) {
- throw new RuntimeException("Timed out waiting for threads.");
+ try {
+ classTranslatorPool.shutdown();
+ classTranslatorPool.awaitTermination(600L, TimeUnit.SECONDS);
+ classDefItemConsumer.shutdown();
+ classDefItemConsumer.awaitTermination(600L, TimeUnit.SECONDS);
+
+ for (Future<Boolean> f : addToDexFutures) {
+ try {
+ f.get();
+ } catch(ExecutionException ex) {
+ // Catch any previously uncaught exceptions from
+ // class translation and adding to dex.
+ int count = errors.incrementAndGet();
+ if (count < 10) {
+ DxConsole.err.println("Uncaught translation error: " + ex.getCause());
+ } else {
+ throw new InterruptedException("Too many errors");
+ }
}
- } catch (InterruptedException ex) {
- threadPool.shutdownNow();
- throw new RuntimeException("A thread has been interrupted.");
}
- try {
- for (Future<?> future : parallelProcessorFutures) {
- future.get();
- }
- } catch (ExecutionException e) {
- Throwable cause = e.getCause();
- // All Exceptions should have been handled in the ParallelProcessor, only Errors
- // should remain
- if (cause instanceof Error) {
- throw (Error) e.getCause();
- } else {
- throw new AssertionError(e.getCause());
- }
- } catch (InterruptedException e) {
- // If we're here, it means all threads have completed cleanly, so there should not be
- // any InterruptedException
- throw new AssertionError(e);
- }
+ } catch (InterruptedException ie) {
+ classTranslatorPool.shutdownNow();
+ classDefItemConsumer.shutdownNow();
+ throw new RuntimeException("Translation has been interrupted", ie);
+ } catch (Exception e) {
+ classTranslatorPool.shutdownNow();
+ classDefItemConsumer.shutdownNow();
+ e.printStackTrace(System.out);
+ throw new RuntimeException("Unexpected exception in translator thread.", e);
}
int errorNum = errors.get();
@@ -572,10 +637,6 @@
}
private static void createDexFile() {
- if (outputDex != null) {
- dexOutputArrays.add(writeDex());
- }
-
outputDex = new DexFile(args.dexOptions);
if (args.dumpWidth != 0) {
@@ -583,6 +644,18 @@
}
}
+ private static void rotateDexFile() {
+ if (outputDex != null) {
+ if (dexOutPool != null) {
+ dexOutputFutures.add(dexOutPool.submit(new DexWriter(outputDex)));
+ } else {
+ dexOutputArrays.add(writeDex(outputDex));
+ }
+ }
+
+ createDexFile();
+ }
+
/**
* Processes one pathname element.
*
@@ -594,47 +667,18 @@
private static void processOne(String pathname, FileNameFilter filter) {
ClassPathOpener opener;
- opener = new ClassPathOpener(pathname, false, filter,
- new ClassPathOpener.Consumer() {
+ opener = new ClassPathOpener(pathname, false, filter, new FileBytesConsumer());
- @Override
- public boolean processFileBytes(String name, long lastModified, byte[] bytes) {
- return Main.processFileBytes(name, lastModified, bytes);
- }
-
- @Override
- public void onException(Exception ex) {
- if (ex instanceof StopProcessing) {
- throw (StopProcessing) ex;
- } else if (ex instanceof SimException) {
- DxConsole.err.println("\nEXCEPTION FROM SIMULATION:");
- DxConsole.err.println(ex.getMessage() + "\n");
- DxConsole.err.println(((SimException) ex).getContext());
- } else {
- DxConsole.err.println("\nUNEXPECTED TOP-LEVEL EXCEPTION:");
- ex.printStackTrace(DxConsole.err);
- }
- errors.incrementAndGet();
- }
-
- @Override
- public void onProcessArchiveStart(File file) {
- if (args.verbose) {
- DxConsole.out.println("processing archive " + file +
- "...");
- }
- }
- });
-
- if (args.numThreads > 1) {
- parallelProcessorFutures.add(threadPool.submit(new ParallelProcessor(opener)));
- } else {
- if (opener.process()) {
- anyFilesProcessed = true;
- }
+ if (opener.process()) {
+ updateStatus(true);
}
}
+ private static void updateStatus(boolean res) {
+ anyFilesProcessed |= res;
+ }
+
+
/**
* Processes one file, which may be either a class or a resource.
*
@@ -643,6 +687,7 @@
* @return whether processing was successful
*/
private static boolean processFileBytes(String name, long lastModified, byte[] bytes) {
+
boolean isClass = name.endsWith(".class");
boolean isClassesDex = name.equals(DexFormat.DEX_IN_JAR_NAME);
boolean keepResources = (outputResources != null);
@@ -670,7 +715,10 @@
if (lastModified < minimumFileAge) {
return true;
}
- return processClass(fixedName, bytes);
+ processClass(fixedName, bytes);
+ // Assume that an exception may occur. Status will be updated
+ // asynchronously, if the class compiles without error.
+ return false;
} else if (isClassesDex) {
synchronized (libraryDexBuffers) {
libraryDexBuffers.add(bytes);
@@ -697,42 +745,30 @@
checkClassName(name);
}
- DirectClassFile cf =
- new DirectClassFile(bytes, name, args.cfOptions.strictNameCheck);
-
- cf.setAttributeFactory(StdAttributeFactory.THE_ONE);
- cf.getMagic();
-
- int numMethodIds = outputDex.getMethodIds().items().size();
- int numFieldIds = outputDex.getFieldIds().items().size();
- int constantPoolSize = cf.getConstantPool().size();
-
- int maxMethodIdsInDex = numMethodIds + constantPoolSize + cf.getMethods().size() +
- MAX_METHOD_ADDED_DURING_DEX_CREATION;
- int maxFieldIdsInDex = numFieldIds + constantPoolSize + cf.getFields().size() +
- MAX_FIELD_ADDED_DURING_DEX_CREATION;
-
- if (args.multiDex
- // Never switch to the next dex if current dex is already empty
- && (outputDex.getClassDefs().items().size() > 0)
- && ((maxMethodIdsInDex > args.maxNumberOfIdxPerDex) ||
- (maxFieldIdsInDex > args.maxNumberOfIdxPerDex))) {
- DexFile completeDex = outputDex;
- createDexFile();
- assert (completeDex.getMethodIds().items().size() <= numMethodIds +
- MAX_METHOD_ADDED_DURING_DEX_CREATION) &&
- (completeDex.getFieldIds().items().size() <= numFieldIds +
- MAX_FIELD_ADDED_DURING_DEX_CREATION);
+ try {
+ new DirectClassFileConsumer(name, bytes, null).call(
+ new ClassParserTask(name, bytes).call());
+ } catch(Exception ex) {
+ throw new RuntimeException("Exception parsing classes", ex);
}
- try {
- ClassDefItem clazz =
- CfTranslator.translate(cf, bytes, args.cfOptions, args.dexOptions, outputDex);
- synchronized (outputDex) {
- outputDex.add(clazz);
- }
- return true;
+ return true;
+ }
+
+ private static DirectClassFile parseClass(String name, byte[] bytes) {
+
+ DirectClassFile cf = new DirectClassFile(bytes, name,
+ args.cfOptions.strictNameCheck);
+ cf.setAttributeFactory(StdAttributeFactory.THE_ONE);
+ cf.getMagic(); // triggers the actual parsing
+ return cf;
+ }
+
+ private static ClassDefItem translateClass(byte[] bytes, DirectClassFile cf) {
+ try {
+ return CfTranslator.translate(cf, bytes, args.cfOptions,
+ args.dexOptions, outputDex);
} catch (ParseException ex) {
DxConsole.err.println("\ntrouble processing:");
if (args.debug) {
@@ -742,7 +778,14 @@
}
}
errors.incrementAndGet();
- return false;
+ return null;
+ }
+
+ private static boolean addClassToDex(ClassDefItem clazz) {
+ synchronized (outputDex) {
+ outputDex.add(clazz);
+ }
+ return true;
}
/**
@@ -792,7 +835,7 @@
* @return {@code null-ok;} the converted {@code byte[]} or {@code null}
* if there was a problem
*/
- private static byte[] writeDex() {
+ private static byte[] writeDex(DexFile outputDex) {
byte[] outArray = null;
try {
@@ -831,7 +874,6 @@
}
return null;
}
-
return outArray;
}
@@ -1199,6 +1241,9 @@
/** whether to run in debug mode */
public boolean debug = false;
+ /** whether to emit warning messages */
+ public boolean warnings = true;
+
/** whether to emit high-level verbose human-oriented output */
public boolean verbose = false;
@@ -1409,6 +1454,8 @@
while(parser.getNext()) {
if (parser.isArg("--debug")) {
debug = true;
+ } else if (parser.isArg("--no-warning")) {
+ warnings = false;
} else if (parser.isArg("--verbose")) {
verbose = true;
} else if (parser.isArg("--verbose-dump")) {
@@ -1542,12 +1589,6 @@
throw new UsageException();
}
- if (multiDex && numThreads != 1) {
- System.out.println(NUM_THREADS_OPTION + " is ignored when used with "
- + MULTI_DEX_OPTION);
- numThreads = 1;
- }
-
if (multiDex && incremental) {
System.err.println(INCREMENTAL_OPTION + " is not supported with "
+ MULTI_DEX_OPTION);
@@ -1580,28 +1621,272 @@
cfOptions.optimizeListFile = optimizeListFile;
cfOptions.dontOptimizeListFile = dontOptimizeListFile;
cfOptions.statistics = statistics;
- cfOptions.warn = DxConsole.err;
+
+ if (warnings) {
+ cfOptions.warn = DxConsole.err;
+ } else {
+ cfOptions.warn = DxConsole.noop;
+ }
dexOptions = new DexOptions();
dexOptions.forceJumbo = forceJumbo;
}
}
- /** Callable helper class to process files in multiple threads */
- private static class ParallelProcessor implements Callable<Void> {
+ /**
+ * Callback class for processing input file bytes, produced by the
+ * ClassPathOpener.
+ */
+ private static class FileBytesConsumer implements ClassPathOpener.Consumer {
- ClassPathOpener classPathOpener;
-
- private ParallelProcessor(ClassPathOpener classPathOpener) {
- this.classPathOpener = classPathOpener;
+ @Override
+ public boolean processFileBytes(String name, long lastModified,
+ byte[] bytes) {
+ return Main.processFileBytes(name, lastModified, bytes);
}
@Override
- public Void call() throws Exception {
- if (classPathOpener.process()) {
- anyFilesProcessed = true;
+ public void onException(Exception ex) {
+ if (ex instanceof StopProcessing) {
+ throw (StopProcessing) ex;
+ } else if (ex instanceof SimException) {
+ DxConsole.err.println("\nEXCEPTION FROM SIMULATION:");
+ DxConsole.err.println(ex.getMessage() + "\n");
+ DxConsole.err.println(((SimException) ex).getContext());
+ } else {
+ DxConsole.err.println("\nUNEXPECTED TOP-LEVEL EXCEPTION:");
+ ex.printStackTrace(DxConsole.err);
}
- return null;
+ errors.incrementAndGet();
+ }
+
+ @Override
+ public void onProcessArchiveStart(File file) {
+ if (args.verbose) {
+ DxConsole.out.println("processing archive " + file + "...");
+ }
+ }
+ }
+
+ /** Callable helper class to parse class bytes. */
+ private static class ClassParserTask implements Callable<DirectClassFile> {
+
+ String name;
+ byte[] bytes;
+
+ private ClassParserTask(String name, byte[] bytes) {
+ this.name = name;
+ this.bytes = bytes;
+ }
+
+ @Override
+ public DirectClassFile call() throws Exception {
+ DirectClassFile cf = parseClass(name, bytes);
+
+ return cf;
+ }
+ }
+
+ /**
+ * Callable helper class used to sequentially collect the results of
+ * the (optionally parallel) translation phase, in correct input file order.
+ * This class is also responsible for coordinating dex file rotation
+ * with the ClassDefItemConsumer class.
+ * We maintain invariant that the number of indices used in the current
+ * dex file plus the max number of indices required by classes passed to
+ * the translation phase and not yet added to the dex file, is less than
+ * or equal to the dex file limit.
+ * For each parsed file, we estimate the maximum number of indices it may
+ * require. If passing the file to the translation phase would invalidate
+ * the invariant, we wait, until the next class is added to the dex file,
+ * and then reevaluate the invariant. If there are no further classes in
+ * the translation phase, we rotate the dex file.
+ */
+ private static class DirectClassFileConsumer implements Callable<Boolean> {
+
+ String name;
+ byte[] bytes;
+ Future<DirectClassFile> dcff;
+
+ private DirectClassFileConsumer(String name, byte[] bytes,
+ Future<DirectClassFile> dcff) {
+ this.name = name;
+ this.bytes = bytes;
+ this.dcff = dcff;
+ }
+
+ @Override
+ public Boolean call() throws Exception {
+
+ DirectClassFile cf = dcff.get();
+ return call(cf);
+ }
+
+ private Boolean call(DirectClassFile cf) {
+
+ int maxMethodIdsInClass = 0;
+ int maxFieldIdsInClass = 0;
+
+ if (args.multiDex) {
+
+ // Calculate max number of indices this class will add to the
+ // dex file.
+ // The possibility of overloading means that we can't easily
+ // know how many constant are needed for declared methods and
+ // fields. We therefore make the simplifying assumption that
+ // all constants are external method or field references.
+
+ int constantPoolSize = cf.getConstantPool().size();
+ maxMethodIdsInClass = constantPoolSize + cf.getMethods().size()
+ + MAX_METHOD_ADDED_DURING_DEX_CREATION;
+ maxFieldIdsInClass = constantPoolSize + cf.getFields().size()
+ + MAX_FIELD_ADDED_DURING_DEX_CREATION;
+ synchronized(dexRotationLock) {
+
+ int numMethodIds;
+ int numFieldIds;
+ // Number of indices used in current dex file.
+ synchronized(outputDex) {
+ numMethodIds = outputDex.getMethodIds().items().size();
+ numFieldIds = outputDex.getFieldIds().items().size();
+ }
+ // Wait until we're sure this class will fit in the current
+ // dex file.
+ while(((numMethodIds + maxMethodIdsInClass + maxMethodIdsInProcess
+ > args.maxNumberOfIdxPerDex) ||
+ (numFieldIds + maxFieldIdsInClass + maxFieldIdsInProcess
+ > args.maxNumberOfIdxPerDex))) {
+
+ if (maxMethodIdsInProcess > 0 || maxFieldIdsInProcess > 0) {
+ // There are classes in the translation phase that
+ // have not yet been added to the dex file, so we
+ // wait for the next class to complete.
+ try {
+ dexRotationLock.wait();
+ } catch(InterruptedException ex) {
+ /* ignore */
+ }
+ } else if (outputDex.getClassDefs().items().size() > 0) {
+ // There are no further classes in the translation
+ // phase, and we have a full dex file. Rotate!
+ rotateDexFile();
+ } else {
+ // The estimated number of indices is too large for
+ // an empty dex file. We proceed hoping the actual
+ // number of indices needed will fit.
+ break;
+ }
+ synchronized(outputDex) {
+ numMethodIds = outputDex.getMethodIds().items().size();
+ numFieldIds = outputDex.getFieldIds().items().size();
+ }
+ }
+ // Add our estimate to the total estimate for
+ // classes under translation.
+ maxMethodIdsInProcess += maxMethodIdsInClass;
+ maxFieldIdsInProcess += maxFieldIdsInClass;
+ }
+ }
+
+ // Submit class to translation phase.
+ Future<ClassDefItem> cdif = classTranslatorPool.submit(
+ new ClassTranslatorTask(name, bytes, cf));
+ Future<Boolean> res = classDefItemConsumer.submit(new ClassDefItemConsumer(
+ name, cdif, maxMethodIdsInClass, maxFieldIdsInClass));
+ addToDexFutures.add(res);
+
+ return true;
+ }
+ }
+
+
+ /** Callable helper class to translate classes in parallel */
+ private static class ClassTranslatorTask implements Callable<ClassDefItem> {
+
+ String name;
+ byte[] bytes;
+ DirectClassFile classFile;
+
+ private ClassTranslatorTask(String name, byte[] bytes,
+ DirectClassFile classFile) {
+ this.name = name;
+ this.bytes = bytes;
+ this.classFile = classFile;
+ }
+
+ @Override
+ public ClassDefItem call() {
+ ClassDefItem clazz = translateClass(bytes, classFile);
+ return clazz;
+ }
+ }
+
+ /**
+ * Callable helper class used to collect the results of
+ * the parallel translation phase, adding the translated classes to
+ * the current dex file in correct (deterministic) file order.
+ * This class is also responsible for coordinating dex file rotation
+ * with the DirectClassFileConsumer class.
+ */
+ private static class ClassDefItemConsumer implements Callable<Boolean> {
+
+ String name;
+ Future<ClassDefItem> futureClazz;
+ int maxMethodIdsInClass;
+ int maxFieldIdsInClass;
+
+ private ClassDefItemConsumer(String name, Future<ClassDefItem> futureClazz,
+ int maxMethodIdsInClass, int maxFieldIdsInClass) {
+ this.name = name;
+ this.futureClazz = futureClazz;
+ this.maxMethodIdsInClass = maxMethodIdsInClass;
+ this.maxFieldIdsInClass = maxFieldIdsInClass;
+ }
+
+ @Override
+ public Boolean call() throws Exception {
+ try {
+ ClassDefItem clazz = futureClazz.get();
+ if (clazz != null) {
+ addClassToDex(clazz);
+ updateStatus(true);
+ }
+ return true;
+ } catch(ExecutionException ex) {
+ // Rethrow previously uncaught translation exceptions.
+ // These, as well as any exceptions from addClassToDex,
+ // are handled and reported in processAllFiles().
+ Throwable t = ex.getCause();
+ throw (t instanceof Exception) ? (Exception) t : ex;
+ } finally {
+ if (args.multiDex) {
+ // Having added our actual indicies to the dex file,
+ // we subtract our original estimate from the total estimate,
+ // and signal the translation phase, which may be paused
+ // waiting to determine if more classes can be added to the
+ // current dex file, or if a new dex file must be created.
+ synchronized(dexRotationLock) {
+ maxMethodIdsInProcess -= maxMethodIdsInClass;
+ maxFieldIdsInProcess -= maxFieldIdsInClass;
+ dexRotationLock.notifyAll();
+ }
+ }
+ }
+ }
+ }
+
+ /** Callable helper class to convert dex files in worker threads */
+ private static class DexWriter implements Callable<byte[]> {
+
+ private DexFile dexFile;
+
+ private DexWriter(DexFile dexFile) {
+ this.dexFile = dexFile;
+ }
+
+ @Override
+ public byte[] call() throws IOException {
+ return writeDex(dexFile);
}
}
}
diff --git a/dx/src/com/android/dx/dex/file/MixedItemSection.java b/dx/src/com/android/dx/dex/file/MixedItemSection.java
index 4edc6b6..9053043 100644
--- a/dx/src/com/android/dx/dex/file/MixedItemSection.java
+++ b/dx/src/com/android/dx/dex/file/MixedItemSection.java
@@ -189,7 +189,7 @@
* @param item {@code non-null;} the item to intern
* @return {@code non-null;} the equivalent interned instance
*/
- public <T extends OffsettedItem> T intern(T item) {
+ public synchronized <T extends OffsettedItem> T intern(T item) {
throwIfPrepared();
OffsettedItem result = interns.get(item);
diff --git a/dx/src/com/android/dx/dex/file/ProtoIdsSection.java b/dx/src/com/android/dx/dex/file/ProtoIdsSection.java
index 4b1303b..b7df10c 100644
--- a/dx/src/com/android/dx/dex/file/ProtoIdsSection.java
+++ b/dx/src/com/android/dx/dex/file/ProtoIdsSection.java
@@ -86,7 +86,7 @@
* @param prototype {@code non-null;} the prototype to intern
* @return {@code non-null;} the interned reference
*/
- public ProtoIdItem intern(Prototype prototype) {
+ public synchronized ProtoIdItem intern(Prototype prototype) {
if (prototype == null) {
throw new NullPointerException("prototype == null");
}
diff --git a/dx/src/com/android/dx/dex/file/StringIdsSection.java b/dx/src/com/android/dx/dex/file/StringIdsSection.java
index 7aff82e..6826c5a 100644
--- a/dx/src/com/android/dx/dex/file/StringIdsSection.java
+++ b/dx/src/com/android/dx/dex/file/StringIdsSection.java
@@ -117,7 +117,7 @@
* @param string {@code non-null;} the string to intern
* @return {@code non-null;} the interned string
*/
- public StringIdItem intern(StringIdItem string) {
+ public synchronized StringIdItem intern(StringIdItem string) {
if (string == null) {
throw new NullPointerException("string == null");
}
@@ -140,7 +140,7 @@
*
* @param nat {@code non-null;} the name-and-type
*/
- public void intern(CstNat nat) {
+ public synchronized void intern(CstNat nat) {
intern(nat.getName());
intern(nat.getDescriptor());
}
diff --git a/dx/src/com/android/dx/dex/file/TypeIdsSection.java b/dx/src/com/android/dx/dex/file/TypeIdsSection.java
index c3380f4..35d8e66 100644
--- a/dx/src/com/android/dx/dex/file/TypeIdsSection.java
+++ b/dx/src/com/android/dx/dex/file/TypeIdsSection.java
@@ -106,7 +106,7 @@
* @param type {@code non-null;} the type to intern
* @return {@code non-null;} the interned reference
*/
- public TypeIdItem intern(Type type) {
+ public synchronized TypeIdItem intern(Type type) {
if (type == null) {
throw new NullPointerException("type == null");
}
diff --git a/dx/tests/113-old-style-inner-class/run b/dx/tests/113-old-style-inner-class/run
index c93661f..ecb6497 100644
--- a/dx/tests/113-old-style-inner-class/run
+++ b/dx/tests/113-old-style-inner-class/run
@@ -16,7 +16,7 @@
# We compile for a 1.4 target to suppress the use of EnclosingMethod
# attributes.
-${JAVAC} -source 1.4 -target 1.4 -d . Blort.java
+${JAVAC} -source 1.4 -target 1.4 -d . Blort.java &> /dev/null
# We expect there to be two warning lines, one for each of the inner classes.
dx --debug --dex *.class 2>&1 | awk '/^warning:/ { print $1 }'
diff --git a/dx/tests/118-find-usages/expected.txt b/dx/tests/118-find-usages/expected.txt
index aca2bf1..9b11110 100644
--- a/dx/tests/118-find-usages/expected.txt
+++ b/dx/tests/118-find-usages/expected.txt
@@ -1,9 +1,9 @@
StreamTokenizer.nval
-LFoo;.readStreamTokenizerNval: field reference (iget-wide)
-LFoo;.writeStreamTokenizerNval: field reference (iput-wide)
+LFoo;.readStreamTokenizerNval: field reference D.nval (iget-wide)
+LFoo;.writeStreamTokenizerNval: field reference D.nval (iput-wide)
ArrayList.remove()
-LFoo;.callArrayListRemoveIndex: method reference (invoke-virtual)
-LFoo;.callArrayListRemoveValue: method reference (invoke-virtual)
+LFoo;.callArrayListRemoveIndex: method reference Ljava/util/ArrayList;.remove(I) (invoke-virtual)
+LFoo;.callArrayListRemoveValue: method reference Ljava/util/ArrayList;.remove(Ljava/lang/Object;) (invoke-virtual)
Collection.remove()
String.valueOf()
-LFoo;.callStringValueOf: method reference (invoke-static)
+LFoo;.callStringValueOf: method reference Ljava/lang/String;.valueOf(I) (invoke-static)
diff --git a/dx/tests/124-multidex-option-no-overflow/run b/dx/tests/124-multidex-option-no-overflow/run
index 4cd14bc..d9097fc 100644
--- a/dx/tests/124-multidex-option-no-overflow/run
+++ b/dx/tests/124-multidex-option-no-overflow/run
@@ -17,7 +17,7 @@
# Stop if something fails.
set -e
-# Write out files with 25500 total static fields, instance fields, and methods
+# Write out files with many static fields, instance fields, and methods but
# not exceeding the dex format's limits.
mkdir src
awk '
@@ -29,7 +29,7 @@
function writeFileField(name, type) {
fileName = "src/" name ".java";
printf("public class %s {\n", name) > fileName;
- for (i = 1; i <= 25500; i++) {
+ for (i = 1; i <= 21000; i++) {
printf(" %s%d;\n", type, i) > fileName;
}
printf("}\n") > fileName;
@@ -37,7 +37,7 @@
function writeFileMethod(name) {
fileName = "src/" name ".java";
printf("public class %s {\n", name) > fileName;
- for (i = 1; i <= 25500; i++) {
+ for (i = 1; i <= 32000; i++) {
printf(" public void meth%d() { }\n", i) > fileName;
}
printf("}\n") > fileName;
diff --git a/dx/tests/127-merge-stress/run b/dx/tests/127-merge-stress/run
old mode 100644
new mode 100755
index c8308cf..d66beb4
--- a/dx/tests/127-merge-stress/run
+++ b/dx/tests/127-merge-stress/run
@@ -19,11 +19,21 @@
progdir=`dirname "${prog}"`
dxjar=$progdir/../framework/dx.jar
-# Find dex files in tree
+# Find dex files in the tree
dexes=`find $ANDROID_BUILD_TOP/out -name '*.dex' -printf '%p '`
dexesinjars=`find $ANDROID_BUILD_TOP/libcore $ANDROID_BUILD_TOP/out -name '*.jar' -exec sh -c 'unzip -l "{}" 2>/dev/null | grep -q classes.dex ' \; -printf '%p '`
dexesinapks=`find $ANDROID_BUILD_TOP/libcore $ANDROID_BUILD_TOP/out -name '*.apk' -exec sh -c 'unzip -l "{}" 2>/dev/null | grep -q classes.dex ' \; -printf '%p '`
+# Select only the valid dex files
+validdexes=""
+for dex in $dexes $dexesinjars $dexesinapks; do
+ dexdump -c $dex &> /dev/null
+ if [ $? -eq 0 ]; then
+ validdexes="$validdexes $dex"
+ fi
+done
+
+# Compile and run java merging test
$JAVAC -cp $dxjar -d . com/android/dx/merge/MergeTest.java
-java -cp .:$dxjar com.android.dx.merge.MergeTest $dexes $dexesinjars $dexesinapks >/dev/null
+java -cp .:$dxjar com.android.dx.merge.MergeTest $validdexes >/dev/null
diff --git a/dx/tests/129-numthread-deterministic/expected.txt b/dx/tests/129-numthread-deterministic/expected.txt
new file mode 100644
index 0000000..5418338
--- /dev/null
+++ b/dx/tests/129-numthread-deterministic/expected.txt
@@ -0,0 +1 @@
+Yay!
diff --git a/dx/tests/129-numthread-deterministic/info.txt b/dx/tests/129-numthread-deterministic/info.txt
new file mode 100644
index 0000000..e4885fa
--- /dev/null
+++ b/dx/tests/129-numthread-deterministic/info.txt
@@ -0,0 +1,2 @@
+Test that dx generates deterministic output when using --num-threads
+
diff --git a/dx/tests/129-numthread-deterministic/run b/dx/tests/129-numthread-deterministic/run
new file mode 100644
index 0000000..fdc0506
--- /dev/null
+++ b/dx/tests/129-numthread-deterministic/run
@@ -0,0 +1,54 @@
+#!/bin/bash
+#
+# Copyright (C) 2013 The Android Open Source Project
+#
+# 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.
+
+# Stop if something fails.
+set -e
+
+# Write out classes
+mkdir src
+awk '
+BEGIN {
+ for (c = 1; c <= 500; c++) {
+ writeClass(c);
+ }
+}
+function writeClass(name) {
+ fileName = "src/Clazz" name ".java";
+ printf("public class Clazz%s {\n", name) > fileName;
+ for (i = 1; i <= 100; i++) {
+ printf(" int field%d;\n", i) > fileName;
+ }
+ for (i = 1; i <= 100; i++) {
+ printf(" void method%d(int param) { }\n", i) > fileName;
+ }
+ printf("}\n") > fileName;
+}'
+
+
+mkdir classes
+${JAVAC} -d classes `find src -name '*.java'`
+mkdir out
+dx -JXmx4g -JXms4g --dex --no-optimize --output=out classes
+mkdir out-multi
+dx -JXmx4g -JXms4g --dex --no-optimize --num-threads=4 --output=out-multi classes
+diff -r out out-multi > unit-out.txt
+
+if [ "$?" = "0" ]; then
+ echo "Yay!"
+else
+ cat unit-out.txt
+fi
+
diff --git a/dx/tests/130-numthread-multidex-deterministic/expected.txt b/dx/tests/130-numthread-multidex-deterministic/expected.txt
new file mode 100644
index 0000000..5418338
--- /dev/null
+++ b/dx/tests/130-numthread-multidex-deterministic/expected.txt
@@ -0,0 +1 @@
+Yay!
diff --git a/dx/tests/130-numthread-multidex-deterministic/info.txt b/dx/tests/130-numthread-multidex-deterministic/info.txt
new file mode 100644
index 0000000..e4885fa
--- /dev/null
+++ b/dx/tests/130-numthread-multidex-deterministic/info.txt
@@ -0,0 +1,2 @@
+Test that dx generates deterministic output when using --num-threads
+
diff --git a/dx/tests/130-numthread-multidex-deterministic/run b/dx/tests/130-numthread-multidex-deterministic/run
new file mode 100644
index 0000000..b43ba1f
--- /dev/null
+++ b/dx/tests/130-numthread-multidex-deterministic/run
@@ -0,0 +1,54 @@
+#!/bin/bash
+#
+# Copyright (C) 2013 The Android Open Source Project
+#
+# 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.
+
+# Stop if something fails.
+set -e
+
+# Write out classes
+mkdir src
+awk '
+BEGIN {
+ for (c = 1; c <= 1000; c++) {
+ writeClass(c);
+ }
+}
+function writeClass(name) {
+ fileName = "src/Clazz" name ".java";
+ printf("public class Clazz%s {\n", name) > fileName;
+ for (i = 1; i <= 100; i++) {
+ printf(" int field%d;\n", i) > fileName;
+ }
+ for (i = 1; i <= 100; i++) {
+ printf(" void method%d(int param) { }\n", i) > fileName;
+ }
+ printf("}\n") > fileName;
+}'
+
+
+mkdir classes
+${JAVAC} -d classes `find src -name '*.java'`
+mkdir out
+dx -JXmx4g -JXms4g --dex --no-optimize --multi-dex --output=out classes
+mkdir out-multi
+dx -JXmx4g -JXms4g --dex --no-optimize --multi-dex --num-threads=4 --output=out-multi classes
+diff -r out out-multi > unit-out.txt
+
+if [ "$?" = "0" ]; then
+ echo "Yay!"
+else
+ cat unit-out.txt
+fi
+
diff --git a/dx/tests/131-perf/ClassGen.java b/dx/tests/131-perf/ClassGen.java
new file mode 100644
index 0000000..c35bbcf
--- /dev/null
+++ b/dx/tests/131-perf/ClassGen.java
@@ -0,0 +1,53 @@
+import java.io.File;
+import java.io.PrintWriter;
+
+public class ClassGen {
+
+ public static void main(String... args) {
+
+ int start = 1;
+ int end = 8024;
+ int fields = 4;
+ int methods = 6;
+ if (args.length > 0) {
+ start = Integer.parseInt(args[0]);
+ }
+ if (args.length > 1) {
+ end = Integer.parseInt(args[1]);
+ }
+ if (args.length > 2) {
+ fields = Integer.parseInt(args[2]);
+ }
+ if (args.length > 3) {
+ methods = Integer.parseInt(args[3]);
+ }
+
+ for (int file = start; file <= end; file++) {
+ try {
+ File f = new File("src/Clazz" + file + ".java");
+ PrintWriter pw = new PrintWriter(f);
+ pw.println("class Clazz" + file + " {");
+ for (int field = 1; field <= fields; field++) {
+ pw.println(" public static int f" + field + ";");
+ }
+ for (int method = 1; method <= methods; method++) {
+ pw.println(" boolean m" + method + "_" + (file%(end/2)) + "() {"
+);
+ pw.println(" int max = Thread.MAX_PRIORITY;");
+ pw.println(" for (int i = 0; i < max; i++) {");
+ pw.println(" System.out.println(\"Hello from: \" + Clazz"
+ + file + ".class + \".method" + method
+ + "() \" + Clazz" + (end-file+1) + ".f1);");
+ pw.println(" Thread.dumpStack();");
+ pw.println(" }");
+ pw.println(" return Thread.holdsLock(this);");
+ pw.println(" }");
+ }
+ pw.println("}");
+ pw.close();
+ } catch(Exception ex) {
+ System.out.println("Ups");
+ }
+ }
+ }
+}
diff --git a/dx/tests/131-perf/expected.txt b/dx/tests/131-perf/expected.txt
new file mode 100644
index 0000000..5418338
--- /dev/null
+++ b/dx/tests/131-perf/expected.txt
@@ -0,0 +1 @@
+Yay!
diff --git a/dx/tests/131-perf/info.txt b/dx/tests/131-perf/info.txt
new file mode 100644
index 0000000..f5b6a0c
--- /dev/null
+++ b/dx/tests/131-perf/info.txt
@@ -0,0 +1,2 @@
+Script for --multi-dex --num-threads performance testing, default just test options can be used together
+
diff --git a/dx/tests/131-perf/run b/dx/tests/131-perf/run
new file mode 100644
index 0000000..e57545c
--- /dev/null
+++ b/dx/tests/131-perf/run
@@ -0,0 +1,88 @@
+#!/bin/bash
+#
+# Copyright (C) 2013 The Android Open Source Project
+#
+# 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.
+
+# Stop if something fails.
+set -e
+
+# Write out classes
+
+${JAVAC} ClassGen.java
+
+mkdir src
+mkdir classes
+
+# Heap size, min and max
+MEM=4g
+
+MULTIDEX="--multi-dex"
+THREADS="--num-threads=5"
+
+# Extra statistics, use to calibrate test.
+#EXTRA="--profile-concurrency"
+
+# Test smaller dex files
+#EXTRA="--set-max-idx-number=20000"
+
+# Test GC options
+#GC="-JXX:+UseConcMarkSweepGC"
+
+# Limit HW threads
+#TASKSET="taskset 0x00000fff
+
+# Number of classes, initial
+TEST_SIZE=1000
+
+# number of classes, max
+LIMIT=1000
+
+# Number of additional classes per test
+STEP=100
+
+# Number of fields per classes
+FIELDS=4
+
+# Number of methods per class
+METHODS=6
+
+
+first=1;
+while [ $TEST_SIZE -le $LIMIT ]; do
+ rm -rf out
+ mkdir out
+
+ sleep 2
+ java -classpath . ClassGen $first $TEST_SIZE $FIELDS $METHODS
+ first=`expr $TEST_SIZE + 1`
+
+ ${JAVAC} -d classes `find src -name '*.java'`
+ (cd classes; jar cf ../x.jar `find . -name '*.class'`)
+ sleep 3
+
+ start=`date +'%s%N'`
+ $TASKSET dx -JXmx$MEM -JXms$MEM $GC --dex $EXTRA --no-optimize $MULTIDEX $THREADS --output=out x.jar
+ end=`date +'%s%N'`
+ nsec=`expr $end - $start`
+ msec=`expr $nsec / 1000000`
+ echo "Classes/msec $TEST_SIZE $msec"
+
+ TEST_SIZE=`expr $TEST_SIZE + $STEP`
+done
+
+if [ "$?" = "1" ]; then
+ echo "Yay!"
+else
+ cat unit-out.txt
+fi
diff --git a/hit/samples/android.hprof b/hit/samples/android.hprof
deleted file mode 100644
index bb8d2e0..0000000
--- a/hit/samples/android.hprof
+++ /dev/null
Binary files differ
diff --git a/hit/src/com/android/hit/ArrayInstance.java b/hit/src/com/android/hit/ArrayInstance.java
deleted file mode 100644
index 42e8803..0000000
--- a/hit/src/com/android/hit/ArrayInstance.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.util.Set;
-
-public class ArrayInstance extends Instance {
- private int mType;
- private int mNumEntries;
- private byte[] mData;
-
- public ArrayInstance(long id, StackTrace stack, int type, int numEntries,
- byte[] data) {
- mId = id;
- mStack = stack;
- mType = type;
- mNumEntries = numEntries;
- mData = data;
- }
-
- public final void resolveReferences(State state) {
- if (mType != Types.OBJECT) {
- return;
- }
-
- /*
- * mData holds a stream of object instance ids
- * Spin through them all and list ourselves as a reference holder.
- */
- int idSize = Types.getTypeSize(mType);
- final int N = mNumEntries;
-
- ByteArrayInputStream bais = new ByteArrayInputStream(mData);
- DataInputStream dis = new DataInputStream(bais);
-
- for (int i = 0; i < N; i++) {
- long id;
-
- try {
- if (idSize == 4) {
- id = dis.readInt();
- } else {
- id = dis.readLong();
- }
-
- Instance instance = state.findReference(id);
-
- if (instance != null) {
- instance.addParent(this);
- }
- } catch (java.io.IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- @Override
- public final int getSize() {
- return mData.length;
- }
-
- @Override
- public final void visit(Set<Instance> resultSet, Filter filter) {
- // If we're in the set then we and our children have been visited
- if (resultSet.contains(this)) {
- return;
- }
-
- if (null != filter) {
- if (filter.accept(this)) {
- resultSet.add(this);
- }
- } else {
- resultSet.add(this);
- }
-
- if (mType != Types.OBJECT) {
- return;
- }
-
- /*
- * mData holds a stream of object instance ids
- * Spin through them all and visit them
- */
- int idSize = Types.getTypeSize(mType);
- final int N = mNumEntries;
-
- ByteArrayInputStream bais = new ByteArrayInputStream(mData);
- DataInputStream dis = new DataInputStream(bais);
- State state = mHeap.mState;
-
- for (int i = 0; i < N; i++) {
- long id;
-
- try {
- if (idSize == 4) {
- id = dis.readInt();
- } else {
- id = dis.readLong();
- }
-
- Instance instance = state.findReference(id);
-
- if (instance != null) {
- instance.visit(resultSet, filter);
- }
- } catch (java.io.IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- @Override
- public final String getTypeName() {
- return Types.getTypeName(mType) + "[" + mNumEntries + "]";
- }
-
- public final String toString() {
- return String.format("%s@0x08x", getTypeName(), mId);
- }
-
- @Override
- public String describeReferenceTo(long referent) {
- // If this isn't an object array then we can't refer to an object
- if (mType != Types.OBJECT) {
- return super.describeReferenceTo(referent);
- }
-
- int idSize = Types.getTypeSize(mType);
- final int N = mNumEntries;
- int numRefs = 0;
- StringBuilder result = new StringBuilder("Elements [");
- ByteArrayInputStream bais = new ByteArrayInputStream(mData);
- DataInputStream dis = new DataInputStream(bais);
-
- /*
- * Spin through all the objects and build up a string describing
- * all of the array elements that refer to the target object.
- */
- for (int i = 0; i < N; i++) {
- long id;
-
- try {
- if (idSize == 4) {
- id = dis.readInt();
- } else {
- id = dis.readLong();
- }
-
- if (id == referent) {
- numRefs++;
-
- if (numRefs > 1) {
- result.append(", ");
- }
-
- result.append(i);
- }
- } catch (java.io.IOException e) {
- e.printStackTrace();
- }
- }
-
- if (numRefs == 0) {
- return super.describeReferenceTo(referent);
- }
-
- result.append("]");
-
- return result.toString();
- }
-}
diff --git a/hit/src/com/android/hit/ClassInstance.java b/hit/src/com/android/hit/ClassInstance.java
deleted file mode 100644
index 0869769..0000000
--- a/hit/src/com/android/hit/ClassInstance.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.util.Set;
-
-public class ClassInstance extends Instance {
- private byte[] mFieldValues;
-
- public ClassInstance(long id, StackTrace stack, long classId) {
- mId = id;
- mStack = stack;
- mClassId = classId;
- }
-
- public final void loadFieldData(DataInputStream in, int numBytes)
- throws IOException {
- mFieldValues = new byte[numBytes];
- in.readFully(mFieldValues);
- }
-
- @Override
- public void resolveReferences(State state) {
- ClassObj isa = mHeap.mState.findClass(mClassId);
-
- resolve(state, isa, isa.mStaticFieldTypes, isa.mStaticFieldValues);
- resolve(state, isa, isa.mFieldTypes, mFieldValues);
- }
-
- private void resolve(State state, ClassObj isa, int[] types,
- byte[] values) {
- ByteArrayInputStream bais = new ByteArrayInputStream(values);
- DataInputStream dis = new DataInputStream(bais);
- final int N = types.length;
-
- /*
- * Spin through the list of fields, find all object references,
- * and list ourselves as a reference holder.
- */
- try {
- for (int i = 0; i < N; i++) {
- int type = types[i];
- int size = Types.getTypeSize(type);
-
- if (type == Types.OBJECT) {
- long id;
-
- if (size == 4) {
- id = dis.readInt();
- } else {
- id = dis.readLong();
- }
-
- Instance instance = state.findReference(id);
-
- if (instance != null) {
- instance.addParent(this);
- }
- } else {
- dis.skipBytes(size);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public final int getSize() {
- ClassObj isa = mHeap.mState.findClass(mClassId);
-
- return isa.getSize();
- }
-
- @Override
- public final void visit(Set<Instance> resultSet, Filter filter) {
- if (resultSet.contains(this)) {
- return;
- }
-
- if (filter != null) {
- if (filter.accept(this)) {
- resultSet.add(this);
- }
- } else {
- resultSet.add(this);
- }
-
- State state = mHeap.mState;
- ClassObj isa = state.findClass(mClassId);
- int[] types = isa.mFieldTypes;
- ByteArrayInputStream bais = new ByteArrayInputStream(mFieldValues);
- DataInputStream dis = new DataInputStream(bais);
- final int N = types.length;
-
- /*
- * Spin through the list of fields, find all object references,
- * and list ourselves as a reference holder.
- */
- try {
- for (int i = 0; i < N; i++) {
- int type = types[i];
- int size = Types.getTypeSize(type);
-
- if (type == Types.OBJECT) {
- long id;
-
- if (size == 4) {
- id = dis.readInt();
- } else {
- id = dis.readLong();
- }
-
- Instance instance = state.findReference(id);
-
- if (instance != null) {
- instance.visit(resultSet, filter);
- }
- } else {
- dis.skipBytes(size);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- @Override
- public final String getTypeName() {
- ClassObj theClass = mHeap.mState.findClass(mClassId);
-
- return theClass.mClassName;
- }
-
- public final String toString() {
- return String.format("%s@0x%08x", getTypeName(), mId);
- }
-
- @Override
- public String describeReferenceTo(long referent) {
- ClassObj isa = mHeap.mState.findClass(mClassId);
- int[] types = isa.mFieldTypes;
- String[] fieldNames = isa.mFieldNames;
- ByteArrayInputStream bais = new ByteArrayInputStream(mFieldValues);
- DataInputStream dis = new DataInputStream(bais);
- final int N = types.length;
- StringBuilder result = new StringBuilder("Referenced in field(s):");
- int numReferences = 0;
-
- /*
- * Spin through the list of fields, add info about the field
- * references to the output text.
- */
- try {
- for (int i = 0; i < N; i++) {
- int type = types[i];
- int size = Types.getTypeSize(type);
-
- if (type == Types.OBJECT) {
- long id;
-
- if (size == 4) {
- id = dis.readInt();
- } else {
- id = dis.readLong();
- }
-
- if (id == referent) {
- numReferences++;
- result.append("\n ");
- result.append(fieldNames[i]);
- }
- } else {
- dis.skipBytes(size);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- /*
- * TODO: perform a similar loop over the static fields of isa
- */
-
- if (numReferences == 0) {
- return super.describeReferenceTo(referent);
- }
-
- return result.toString();
- }
-}
diff --git a/hit/src/com/android/hit/ClassObj.java b/hit/src/com/android/hit/ClassObj.java
deleted file mode 100644
index 1e3ac28..0000000
--- a/hit/src/com/android/hit/ClassObj.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-
-public class ClassObj extends Instance implements Comparable<ClassObj> {
- String mClassName;
- long mSuperclassId;
-
- String[] mFieldNames;
- int[] mFieldTypes;
-
- String[] mStaticFieldNames;
- int[] mStaticFieldTypes;
- byte[] mStaticFieldValues;
-
- ArrayList<Instance> mInstances = new ArrayList<Instance>();
- Set<ClassObj> mSubclasses = new HashSet<ClassObj>();
-
- int mSize;
-
- public ClassObj(long id, StackTrace stack, String className) {
- mId = id;
- mStack = stack;
- mClassName = className;
- }
-
- @Override
- public final void resolveReferences(State state) {
- ByteArrayInputStream bais =
- new ByteArrayInputStream(mStaticFieldValues);
- DataInputStream dis = new DataInputStream(bais);
- int[] types = mStaticFieldTypes;
- final int N = types.length;
-
- /*
- * Spin through the list of static fields, find all object references,
- * and list ourselves as a reference holder. Also add them to
- * the list of root objects.
- */
- try {
- for (int i = 0; i < N; i++) {
- int type = types[i];
- int size = Types.getTypeSize(type);
-
- if (type == Types.OBJECT) {
- long id;
-
- if (size == 4) {
- id = dis.readInt();
- } else {
- id = dis.readLong();
- }
-
- RootObj root = new RootObj(RootType.JAVA_STATIC, id);
-
- if (id == 0) {
- root.mComment = String.format(
- "Static field %s:%s null",
- mClassName,
- mStaticFieldNames[i]);
- } else {
- Instance instance = state.findReference(id);
-
- instance.addParent(this);
-
- root.mComment = String.format(
- "Static field %s:%s %s [%s] 0x%08x",
- mClassName,
- mStaticFieldNames[i],
- instance.getTypeName(),
- instance.mHeap.mName,
- id);
- }
-
- mHeap.addRoot(root);
- } else {
- dis.skipBytes(size);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- System.exit(1);
- }
-
- // Lastly, add ourself as a subclass of our superclass
- if (mSuperclassId != 0) {
- ClassObj superclass = state.findClass(mSuperclassId);
-
- superclass.addSubclass(this);
- }
- }
-
- public final void addSubclass(ClassObj subclass) {
- mSubclasses.add(subclass);
- }
-
- public final void dumpSubclasses() {
- for (ClassObj subclass: mSubclasses) {
- System.out.println(" " + subclass.mClassName);
- }
- }
-
- public final String toString() {
- return mClassName.replace('/', '.');
- }
-
- public final void addInstance(Instance instance) {
- mInstances.add(instance);
- }
-
- public final void setSuperclassId(long id) {
- mSuperclassId = id;
- }
-
- public final void setFieldNames(String[] names) {
- mFieldNames = names;
- }
-
- public final void setFieldTypes(int[] types) {
- mFieldTypes = types;
- }
-
- public final void setStaticFieldNames(String[] names) {
- mStaticFieldNames = names;
- }
-
- public final void setStaticFieldTypes(int[] types) {
- mStaticFieldTypes = types;
- }
-
- public final void setStaticFieldValues(byte[] values) {
- mStaticFieldValues = values;
- }
-
- public final void dump() {
- System.out.println("+---------- ClassObj dump for: " + mClassName);
-
- System.out.println("+----- Static fields");
-
- for (int i = 0; i < mStaticFieldNames.length; i++) {
- System.out.println(mStaticFieldNames[i] + ": "
- + mStaticFieldTypes[i]);
- }
-
- System.out.println("+----- Instance fields");
-
- for (int i = 0; i < mFieldNames.length; i++) {
- System.out.println(mFieldNames[i] + ": " + mFieldTypes[i]);
- }
- }
-
- @Override
- public final String getTypeName() {
- return "class " + mClassName;
- }
-
- @Override
- public final void visit(Set<Instance> resultSet, Filter filter) {
- if (resultSet.contains(this)) {
- return;
- }
-
- if (filter != null) {
- if (filter.accept(this)) {
- resultSet.add(this);
- }
- } else {
- resultSet.add(this);
- }
-
- ByteArrayInputStream bais =
- new ByteArrayInputStream(mStaticFieldValues);
- DataInputStream dis = new DataInputStream(bais);
- int[] types = mStaticFieldTypes;
- final int N = types.length;
- State state = mHeap.mState;
-
- /*
- * Spin through the list of static fields, find all object references,
- * and visit them.
- */
- try {
- for (int i = 0; i < N; i++) {
- int type = types[i];
- int size = Types.getTypeSize(type);
-
- if (type == Types.OBJECT) {
- long id;
-
- if (size == 4) {
- id = dis.readInt();
- } else {
- id = dis.readLong();
- }
-
- Instance instance = state.findReference(id);
-
- if (instance != null) {
- instance.visit(resultSet, filter);
- }
- } else {
- dis.skipBytes(size);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public final int compareTo(ClassObj o) {
- return mClassName.compareTo(o.mClassName);
- }
-
- public final boolean equals(Object o) {
- if (! (o instanceof ClassObj)) {
- return false;
- }
-
- return 0 == compareTo((ClassObj) o);
- }
-}
diff --git a/hit/src/com/android/hit/Heap.java b/hit/src/com/android/hit/Heap.java
deleted file mode 100644
index 37b15dd..0000000
--- a/hit/src/com/android/hit/Heap.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-public class Heap {
- String mName;
-
- // List of individual stack frames
- HashMap<Long, StackFrame> mFrames = new HashMap<Long, StackFrame>();
-
- // List stack traces, which are lists of stack frames
- HashMap<Integer, StackTrace> mTraces = new HashMap<Integer, StackTrace>();
-
- // Root objects such as interned strings, jni locals, etc
- ArrayList<RootObj> mRoots = new ArrayList<RootObj>();
-
- // List of threads
- HashMap<Integer, ThreadObj> mThreads = new HashMap<Integer, ThreadObj>();
-
- // Class definitions
- HashMap<Long, ClassObj> mClassesById = new HashMap<Long, ClassObj>();
- HashMap<String, ClassObj> mClassesByName = new HashMap<String, ClassObj>();
-
- // List of instances of above class definitions
- HashMap<Long, Instance> mInstances = new HashMap<Long, Instance>();
-
- // The super-state that this heap is part of
- State mState;
-
- public Heap(String name) {
- mName = name;
- }
-
- public final void addStackFrame(StackFrame theFrame) {
- mFrames.put(theFrame.mId, theFrame);
- }
-
- public final StackFrame getStackFrame(long id) {
- return mFrames.get(id);
- }
-
- public final void addStackTrace(StackTrace theTrace) {
- mTraces.put(theTrace.mSerialNumber, theTrace);
- }
-
- public final StackTrace getStackTrace(int traceSerialNumber) {
- return mTraces.get(traceSerialNumber);
- }
-
- public final StackTrace getStackTraceAtDepth(int traceSerialNumber,
- int depth) {
- StackTrace trace = mTraces.get(traceSerialNumber);
-
- if (trace != null) {
- trace = trace.fromDepth(depth);
- }
-
- return trace;
- }
-
- public final void addRoot(RootObj root) {
- root.mIndex = mRoots.size();
- mRoots.add(root);
- }
-
- public final void addThread(ThreadObj thread, int serialNumber) {
- mThreads.put(serialNumber, thread);
- }
-
- public final ThreadObj getThread(int serialNumber) {
- return mThreads.get(serialNumber);
- }
-
- public final void addInstance(long id, Instance instance) {
- mInstances.put(id, instance);
- }
-
- public final Instance getInstance(long id) {
- return mInstances.get(id);
- }
-
- public final void addClass(long id, ClassObj theClass) {
- mClassesById.put(id, theClass);
- mClassesByName.put(theClass.mClassName, theClass);
- }
-
- public final ClassObj getClass(long id) {
- return mClassesById.get(id);
- }
-
- public final ClassObj getClass(String name) {
- return mClassesByName.get(name);
- }
-
- public final void dumpInstanceCounts() {
- for (ClassObj theClass: mClassesById.values()) {
- int count = theClass.mInstances.size();
-
- if (count > 0) {
- System.out.println(theClass + ": " + count);
- }
- }
- }
-
- public final void dumpSubclasses() {
- for (ClassObj theClass: mClassesById.values()) {
- int count = theClass.mSubclasses.size();
-
- if (count > 0) {
- System.out.println(theClass);
- theClass.dumpSubclasses();
- }
- }
- }
-
- public final void dumpSizes() {
- for (ClassObj theClass: mClassesById.values()) {
- int size = 0;
-
- for (Instance instance: theClass.mInstances) {
- size += instance.getCompositeSize();
- }
-
- if (size > 0) {
- System.out.println(theClass + ": base " + theClass.getSize()
- + ", composite " + size);
- }
- }
- }
-
- /*
- * Spin through all of the class instances and link them to their
- * parent class definition objects. Then have each instance resolve
- * its own internal object references.
- */
- public final void resolveInstanceRefs(State state) {
- for (Instance instance : mInstances.values()) {
- ClassObj theClass = mClassesById.get(instance.mClassId);
-
- if (theClass == null) {
- continue;
- }
-
- String name = theClass.mClassName;
- String superclassName = "none";
- ClassObj superClass = mClassesById.get(theClass.mSuperclassId);
-
- if (superClass != null) {
- superclassName = superClass.mClassName;
- }
-
- theClass.addInstance(instance);
- instance.resolveReferences(state);
- }
- }
-
- public final void resolveClassStatics(State state) {
- for (ClassObj theClass: mClassesById.values()) {
- theClass.resolveReferences(state);
- }
- }
-
- public final void resolveRoots(State state) {
- for (RootObj root: mRoots) {
- root.resolveReferences(state);
- }
- }
-}
diff --git a/hit/src/com/android/hit/HprofParser.java b/hit/src/com/android/hit/HprofParser.java
deleted file mode 100644
index 98fef1e..0000000
--- a/hit/src/com/android/hit/HprofParser.java
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.InputStream;
-import java.io.EOFException;
-import java.io.IOException;
-import java.util.HashMap;
-
-public class HprofParser
-{
- private static final int STRING_IN_UTF8 = 0x01;
- private static final int LOAD_CLASS = 0x02;
- private static final int UNLOAD_CLASS = 0x03; // unused
- private static final int STACK_FRAME = 0x04;
- private static final int STACK_TRACE = 0x05;
- private static final int ALLOC_SITES = 0x06; // unused
- private static final int HEAP_SUMMARY = 0x07;
- private static final int START_THREAD = 0x0a; // unused
- private static final int END_THREAD = 0x0b; // unused
- private static final int HEAP_DUMP = 0x0c;
- private static final int HEAP_DUMP_SEGMENT = 0x1c;
- private static final int HEAP_DUMP_END = 0x2c;
- private static final int CPU_SAMPLES = 0x0d; // unused
- private static final int CONTROL_SETTINGS = 0x0e; // unused
-
- private static final int ROOT_UNKNOWN = 0xff;
- private static final int ROOT_JNI_GLOBAL = 0x01;
- private static final int ROOT_JNI_LOCAL = 0x02;
- private static final int ROOT_JAVA_FRAME = 0x03;
- private static final int ROOT_NATIVE_STACK = 0x04;
- private static final int ROOT_STICKY_CLASS = 0x05;
- private static final int ROOT_THREAD_BLOCK = 0x06;
- private static final int ROOT_MONITOR_USED = 0x07;
- private static final int ROOT_THREAD_OBJECT = 0x08;
- private static final int ROOT_CLASS_DUMP = 0x20;
- private static final int ROOT_INSTANCE_DUMP = 0x21;
- private static final int ROOT_OBJECT_ARRAY_DUMP = 0x22;
- private static final int ROOT_PRIMITIVE_ARRAY_DUMP = 0x23;
-
- /**
- * Android format addition
- *
- * Specifies information about which heap certain objects came from.
- * When a sub-tag of this type appears in a HPROF_HEAP_DUMP or
- * HPROF_HEAP_DUMP_SEGMENT record, entries that follow it will be
- * associated with the specified heap. The HEAP_DUMP_INFO data is reset
- * at the end of the HEAP_DUMP[_SEGMENT]. Multiple HEAP_DUMP_INFO entries
- * may appear in a single HEAP_DUMP[_SEGMENT].
- *
- * Format:
- * u1: Tag value (0xFE)
- * u4: heap ID
- * ID: heap name string ID
- */
- private static final int ROOT_HEAP_DUMP_INFO = 0xfe;
- private static final int ROOT_INTERNED_STRING = 0x89;
- private static final int ROOT_FINALIZING = 0x8a;
- private static final int ROOT_DEBUGGER = 0x8b;
- private static final int ROOT_REFERENCE_CLEANUP = 0x8c;
- private static final int ROOT_VM_INTERNAL = 0x8d;
- private static final int ROOT_JNI_MONITOR = 0x8e;
- private static final int ROOT_UNREACHABLE = 0x90;
- private static final int ROOT_PRIMITIVE_ARRAY_NODATA= 0xc3;
-
- DataInputStream mInput;
- int mIdSize;
- State mState;
-
- byte[] mFieldBuffer = new byte[8];
-
- /*
- * These are only needed while parsing so are not kept as part of the
- * heap data.
- */
- HashMap<Long, String> mStrings = new HashMap<Long, String>();
- HashMap<Long, String> mClassNames = new HashMap<Long, String>();
-
- public HprofParser(DataInputStream in) {
- mInput = in;
- }
-
- public final State parse() {
- State state = new State();
- mState = state;
-
- try {
- String s = readNullTerminatedString();
- DataInputStream in = mInput;
-
- mIdSize = in.readInt();
- Types.setIdSize(mIdSize);
-
- in.readLong(); // Timestamp, ignored for now
-
- while (true) {
- int tag = in.readUnsignedByte();
- int timestamp = in.readInt();
- int length = in.readInt();
-
- switch (tag) {
- case STRING_IN_UTF8:
- loadString(length - 4);
- break;
-
- case LOAD_CLASS:
- loadClass();
- break;
-
- case STACK_FRAME:
- loadStackFrame();
- break;
-
- case STACK_TRACE:
- loadStackTrace();
- break;
-
- case HEAP_DUMP:
- loadHeapDump(length);
- mState.setToDefaultHeap();
- break;
-
- case HEAP_DUMP_SEGMENT:
- loadHeapDump(length);
- mState.setToDefaultHeap();
- break;
-
- default:
- skipFully(length);
- }
-
- }
- } catch (EOFException eof) {
- // this is fine
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- mState.resolveReferences();
-
- return state;
- }
-
- private String readNullTerminatedString() throws IOException {
- StringBuilder s = new StringBuilder();
- DataInputStream in = mInput;
-
- for (int c = in.read(); c != 0; c = in.read()) {
- s.append((char) c);
- }
-
- return s.toString();
- }
-
- private long readId() throws IOException {
- switch (mIdSize) {
- case 1: return mInput.readUnsignedByte();
- case 2: return mInput.readUnsignedShort();
- case 4: return ((long) mInput.readInt()) & 0x00000000ffffffffL;
- case 8: return mInput.readLong();
- }
-
- throw new IllegalArgumentException("ID Length must be 1, 2, 4, or 8");
- }
-
- private String readUTF8(int length) throws IOException {
- byte[] b = new byte[length];
-
- mInput.read(b);
-
- return new String(b, "utf-8");
- }
-
- private void loadString(int length) throws IOException {
- long id = readId();
- String string = readUTF8(length);
-
- mStrings.put(id, string);
- }
-
- private void loadClass() throws IOException {
- DataInputStream in = mInput;
- int serial = in.readInt();
- long id = readId();
- int stackTrace = in.readInt(); // unused
- String name = mStrings.get(readId());
-
- mClassNames.put(id, name);
- }
-
- private void loadStackFrame() throws IOException {
- long id = readId();
- String methodName = mStrings.get(readId());
- String methodSignature = mStrings.get(readId());
- String sourceFile = mStrings.get(readId());
- int serial = mInput.readInt();
- int lineNumber = mInput.readInt();
-
- StackFrame frame = new StackFrame(id, methodName, methodSignature,
- sourceFile, serial, lineNumber);
-
- mState.addStackFrame(frame);
- }
-
- private void loadStackTrace() throws IOException {
- int serialNumber = mInput.readInt();
- int threadSerialNumber = mInput.readInt();
- final int numFrames = mInput.readInt();
- StackFrame[] frames = new StackFrame[numFrames];
-
- for (int i = 0; i < numFrames; i++) {
- frames[i] = mState.getStackFrame(readId());
- }
-
- StackTrace trace = new StackTrace(serialNumber, threadSerialNumber,
- frames);
-
- mState.addStackTrace(trace);
- }
-
- private void loadHeapDump(int length) throws IOException {
- DataInputStream in = mInput;
-
- while (length > 0) {
- int tag = in.readUnsignedByte();
- length--;
-
- switch (tag) {
- case ROOT_UNKNOWN:
- length -= loadBasicObj(RootType.UNKNOWN);
- break;
-
- case ROOT_JNI_GLOBAL:
- length -= loadBasicObj(RootType.NATIVE_STATIC);
- readId(); // ignored
- length -= mIdSize;
- break;
-
- case ROOT_JNI_LOCAL:
- length -= loadJniLocal();
- break;
-
- case ROOT_JAVA_FRAME:
- length -= loadJavaFrame();
- break;
-
- case ROOT_NATIVE_STACK:
- length -= loadNativeStack();
- break;
-
- case ROOT_STICKY_CLASS:
- length -= loadBasicObj(RootType.SYSTEM_CLASS);
- break;
-
- case ROOT_THREAD_BLOCK:
- length -= loadThreadBlock();
- break;
-
- case ROOT_MONITOR_USED:
- length -= loadBasicObj(RootType.BUSY_MONITOR);
- break;
-
- case ROOT_THREAD_OBJECT:
- length -= loadThreadObject();
- break;
-
- case ROOT_CLASS_DUMP:
- length -= loadClassDump();
- break;
-
- case ROOT_INSTANCE_DUMP:
- length -= loadInstanceDump();
- break;
-
- case ROOT_OBJECT_ARRAY_DUMP:
- length -= loadObjectArrayDump();
- break;
-
- case ROOT_PRIMITIVE_ARRAY_DUMP:
- length -= loadPrimitiveArrayDump();
- break;
-
- case ROOT_PRIMITIVE_ARRAY_NODATA:
- System.err.println("+--- PRIMITIVE ARRAY NODATA DUMP");
- length -= loadPrimitiveArrayDump();
-
- throw new IllegalArgumentException(
- "Don't know how to load a nodata array");
-
- case ROOT_HEAP_DUMP_INFO:
- int heapId = mInput.readInt();
- long heapNameId = readId();
- String heapName = mStrings.get(heapNameId);
-
- mState.setHeapTo(heapId, heapName);
- length -= 4 + mIdSize;
- break;
-
- case ROOT_INTERNED_STRING:
- length -= loadBasicObj(RootType.INTERNED_STRING);
- break;
-
- case ROOT_FINALIZING:
- length -= loadBasicObj(RootType.FINALIZING);
- break;
-
- case ROOT_DEBUGGER:
- length -= loadBasicObj(RootType.DEBUGGER);
- break;
-
- case ROOT_REFERENCE_CLEANUP:
- length -= loadBasicObj(RootType.REFERENCE_CLEANUP);
- break;
-
- case ROOT_VM_INTERNAL:
- length -= loadBasicObj(RootType.VM_INTERNAL);
- break;
-
- case ROOT_JNI_MONITOR:
- length -= loadJniMonitor();
- break;
-
- case ROOT_UNREACHABLE:
- length -= loadBasicObj(RootType.UNREACHABLE);
- break;
-
- default:
- throw new IllegalArgumentException(
- "loadHeapDump loop with unknown tag " + tag
- + " with " + mInput.available()
- + " bytes possibly remaining");
- }
- }
- }
-
- private int loadJniLocal() throws IOException {
- long id = readId();
- int threadSerialNumber = mInput.readInt();
- int stackFrameNumber = mInput.readInt();
- ThreadObj thread = mState.getThread(threadSerialNumber);
- StackTrace trace = mState.getStackTraceAtDepth(thread.mStackTrace,
- stackFrameNumber);
- RootObj root = new RootObj(RootType.NATIVE_LOCAL, id,
- threadSerialNumber, trace);
-
- root.setHeap(mState.mCurrentHeap);
- mState.addRoot(root);
-
- return mIdSize + 4 + 4;
- }
-
- private int loadJavaFrame() throws IOException {
- long id = readId();
- int threadSerialNumber = mInput.readInt();
- int stackFrameNumber = mInput.readInt();
- ThreadObj thread = mState.getThread(threadSerialNumber);
- StackTrace trace = mState.getStackTraceAtDepth(thread.mStackTrace,
- stackFrameNumber);
- RootObj root = new RootObj(RootType.JAVA_LOCAL, id, threadSerialNumber,
- trace);
-
- root.setHeap(mState.mCurrentHeap);
- mState.addRoot(root);
-
- return mIdSize + 4 + 4;
- }
-
- private int loadNativeStack() throws IOException {
- long id = readId();
- int threadSerialNumber = mInput.readInt();
- ThreadObj thread = mState.getThread(threadSerialNumber);
- StackTrace trace = mState.getStackTrace(thread.mStackTrace);
- RootObj root = new RootObj(RootType.NATIVE_STACK, id,
- threadSerialNumber, trace);
-
- root.setHeap(mState.mCurrentHeap);
- mState.addRoot(root);
-
- return mIdSize + 4;
- }
-
- private int loadBasicObj(RootType type) throws IOException {
- long id = readId();
- RootObj root = new RootObj(type, id);
-
- root.setHeap(mState.mCurrentHeap);
- mState.addRoot(root);
-
- return mIdSize;
- }
-
- private int loadThreadBlock() throws IOException {
- long id = readId();
- int threadSerialNumber = mInput.readInt();
- ThreadObj thread = mState.getThread(threadSerialNumber);
- StackTrace stack = mState.getStackTrace(thread.mStackTrace);
- RootObj root = new RootObj(RootType.THREAD_BLOCK, id,
- threadSerialNumber, stack);
-
- root.setHeap(mState.mCurrentHeap);
- mState.addRoot(root);
-
- return mIdSize + 4;
- }
-
- private int loadThreadObject() throws IOException {
- long id = readId();
- int threadSerialNumber = mInput.readInt();
- int stackSerialNumber = mInput.readInt();
- ThreadObj thread = new ThreadObj(id, stackSerialNumber);
-
- mState.addThread(thread, threadSerialNumber);
-
- return mIdSize + 4 + 4;
- }
-
- private int loadClassDump() throws IOException {
- int bytesRead = 0;
- DataInputStream in = mInput;
- long id = readId();
- int stackSerialNumber = in.readInt();
- StackTrace stack = mState.getStackTrace(stackSerialNumber);
- long superClassId = readId();
- long classLoaderId = readId();
- long signersId = readId();
- long protectionDomainId = readId();
- long reserved1 = readId();
- long reserved2 = readId();
- int instanceSize = in.readInt();
-
- bytesRead = (7 * mIdSize) + 4 + 4;
-
- // Skip over the constant pool
- int numEntries = in.readUnsignedShort();
- bytesRead += 2;
-
- for (int i = 0; i < numEntries; i++) {
- in.readUnsignedShort();
- bytesRead += 2 + skipValue();
- }
-
- // Static fields
- numEntries = in.readUnsignedShort();
- bytesRead += 2;
-
- String[] staticFieldNames = new String[numEntries];
- int[] staticFieldTypes = new int[numEntries];
- ByteArrayOutputStream staticFieldValues = new ByteArrayOutputStream();
- byte[] buffer = mFieldBuffer;
-
- for (int i = 0; i < numEntries; i++) {
- staticFieldNames[i] = mStrings.get(readId());
-
- int fieldType = in.readByte();
- int fieldSize = Types.getTypeSize(fieldType);
- staticFieldTypes[i] = fieldType;
-
- in.readFully(buffer, 0, fieldSize);
- staticFieldValues.write(buffer, 0, fieldSize);
-
- bytesRead += mIdSize + 1 + fieldSize;
- }
-
- // Instance fields
- numEntries = in.readUnsignedShort();
- bytesRead += 2;
-
- String[] names = new String[numEntries];
- int[] types = new int[numEntries];
-
- for (int i = 0; i < numEntries; i++) {
- long fieldName = readId();
- int type = in.readUnsignedByte();
-
- names[i] = mStrings.get(fieldName);
- types[i] = type;
-
- bytesRead += mIdSize + 1;
- }
-
- ClassObj theClass = new ClassObj(id, stack, mClassNames.get(id));
-
- theClass.setStaticFieldNames(staticFieldNames);
- theClass.setStaticFieldTypes(staticFieldTypes);
- theClass.setStaticFieldValues(staticFieldValues.toByteArray());
-
- theClass.setSuperclassId(superClassId);
- theClass.setFieldNames(names);
- theClass.setFieldTypes(types);
- theClass.setSize(instanceSize);
-
- theClass.setHeap(mState.mCurrentHeap);
-
- mState.addClass(id, theClass);
-
- return bytesRead;
- }
-
- private int loadInstanceDump() throws IOException {
- long id = readId();
- int stackId = mInput.readInt();
- StackTrace stack = mState.getStackTrace(stackId);
- long classId = readId();
- int remaining = mInput.readInt();
- ClassInstance instance = new ClassInstance(id, stack, classId);
-
- instance.loadFieldData(mInput, remaining);
- instance.setHeap(mState.mCurrentHeap);
- mState.addInstance(id, instance);
-
- return mIdSize + 4 + mIdSize + 4 + remaining;
- }
-
- private int loadObjectArrayDump() throws IOException {
- long id = readId();
- int stackId = mInput.readInt();
- StackTrace stack = mState.getStackTrace(stackId);
- int numElements = mInput.readInt();
- long classId = readId();
- int totalBytes = numElements * mIdSize;
- byte[] data = new byte[totalBytes];
- String className = mClassNames.get(classId);
-
- mInput.readFully(data);
-
- ArrayInstance array = new ArrayInstance(id, stack, Types.OBJECT,
- numElements, data);
-
- array.mClassId = classId;
- array.setHeap(mState.mCurrentHeap);
- mState.addInstance(id, array);
-
- return mIdSize + 4 + 4 + mIdSize + totalBytes;
- }
-
- private int loadPrimitiveArrayDump() throws IOException {
- long id = readId();
- int stackId = mInput.readInt();
- StackTrace stack = mState.getStackTrace(stackId);
- int numElements = mInput.readInt();
- int type = mInput.readUnsignedByte();
- int size = Types.getTypeSize(type);
- int totalBytes = numElements * size;
- byte[] data = new byte[totalBytes];
-
- mInput.readFully(data);
-
- ArrayInstance array = new ArrayInstance(id, stack, type, numElements,
- data);
-
- array.setHeap(mState.mCurrentHeap);
- mState.addInstance(id, array);
-
- return mIdSize + 4 + 4 + 1 + totalBytes;
- }
-
- private int loadJniMonitor() throws IOException {
- long id = readId();
- int threadSerialNumber = mInput.readInt();
- int stackDepth = mInput.readInt();
- ThreadObj thread = mState.getThread(threadSerialNumber);
- StackTrace trace = mState.getStackTraceAtDepth(thread.mStackTrace,
- stackDepth);
- RootObj root = new RootObj(RootType.NATIVE_MONITOR, id,
- threadSerialNumber, trace);
-
- root.setHeap(mState.mCurrentHeap);
- mState.addRoot(root);
-
- return mIdSize + 4 + 4;
- }
-
- private int skipValue() throws IOException {
- int type = mInput.readUnsignedByte();
- int size = Types.getTypeSize(type);
-
- skipFully(size);
-
- return size + 1;
- }
-
- /*
- * BufferedInputStream will not skip(int) the entire requested number
- * of bytes if it extends past the current buffer boundary. So, this
- * routine is needed to actually skip over the requested number of bytes
- * using as many iterations as needed.
- */
- private void skipFully(long numBytes) throws IOException {
- while (numBytes > 0) {
- long skipped = mInput.skip(numBytes);
-
- numBytes -= skipped;
- }
- }
-}
diff --git a/hit/src/com/android/hit/Instance.java b/hit/src/com/android/hit/Instance.java
deleted file mode 100644
index 6afa2b2..0000000
--- a/hit/src/com/android/hit/Instance.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-
-public abstract class Instance {
- long mId;
-
- // Id of the ClassObj of which this object is an instance
- long mClassId;
-
- // The stack in which this object was allocated
- StackTrace mStack;
-
- // The heap in which this object was allocated (app, zygote, etc)
- Heap mHeap;
-
- // The size of this object
- int mSize;
-
- public interface Filter {
- public boolean accept(Instance instance);
- }
-
- // List of all objects that hold a live reference to this object
- private ArrayList<Instance> mParents;
-
- /*
- * After the whole HPROF file is read and parsed this method will be
- * called on all heap objects so that they can resolve their internal
- * object references.
- *
- * The super-State is passed in because some object references (such
- * as interned Strings and static class fields) may need to be searched
- * for in a heap other than the one this Instance is in.
- */
- public abstract void resolveReferences(State state);
-
- /*
- * Some operations require gathering all the objects in a given section
- * of the object graph. If non-null, the filter is applied to each
- * node in the graph to determine if it should be added to the result
- * set.
- */
- public abstract void visit(Set<Instance> resultSet, Filter filter);
-
- public void setSize(int size) {
- mSize = size;
- }
-
- public final int getCompositeSize() {
- HashSet<Instance> set = new HashSet<Instance>();
-
- visit(set, null);
-
- int size = 0;
-
- for (Instance instance: set) {
- size += instance.getSize();
- }
-
- return size;
- }
-
- // Returns the instrinsic size of a given object
- public int getSize() {
- return mSize;
- }
-
- public abstract String getTypeName();
-
- public void setHeap(Heap heap) {
- mHeap = heap;
- }
-
- // Add to the list of objects that have a hard reference to this Instance
- public void addParent(Instance parent) {
- if (mParents == null) {
- mParents = new ArrayList<Instance>();
- }
-
- mParents.add(parent);
- }
-
- public ArrayList<Instance> getParents() {
- if (mParents == null) {
- mParents = new ArrayList<Instance>();
- }
-
- return mParents;
- }
-
- /*
- * If this object has a reference to the object identified by id, return
- * a String describing the reference in detail.
- */
- public String describeReferenceTo(long id) {
- return "No reference to 0x" + Long.toHexString(id);
- }
-}
diff --git a/hit/src/com/android/hit/Main.java b/hit/src/com/android/hit/Main.java
deleted file mode 100644
index 4ed5c11..0000000
--- a/hit/src/com/android/hit/Main.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-import java.io.BufferedInputStream;
-import java.io.DataInputStream;
-import java.io.FileInputStream;
-import java.util.Map;
-import java.util.Set;
-
-public class Main
-{
- public static void main(String argv[]) {
- FileInputStream fis;
- BufferedInputStream bis;
- DataInputStream dis;
-
- try {
- fis = new FileInputStream(argv[0]);
- bis = new BufferedInputStream(fis);
- dis = new DataInputStream(bis);
-
- State state = (new HprofParser(dis)).parse();
-
- dis.close();
-
- testClassesQuery(state);
- testAllClassesQuery(state);
- testFindInstancesOf(state);
- testFindAllInstancesOf(state);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private static void testClassesQuery(State state) {
- String[] x = new String[] {
- "char[",
- "javax.",
- "org.xml.sax"
- };
-
- Map<String, Set<ClassObj>> someClasses = Queries.classes(state, x);
-
- for (String thePackage: someClasses.keySet()) {
- System.out.println("------------------- " + thePackage);
-
- Set<ClassObj> classes = someClasses.get(thePackage);
-
- for (ClassObj theClass: classes) {
- System.out.println(" " + theClass.mClassName);
- }
- }
- }
-
- private static void testAllClassesQuery(State state) {
- Map<String, Set<ClassObj>> allClasses = Queries.allClasses(state);
-
- for (String thePackage: allClasses.keySet()) {
- System.out.println("------------------- " + thePackage);
-
- Set<ClassObj> classes = allClasses.get(thePackage);
-
- for (ClassObj theClass: classes) {
- System.out.println(" " + theClass.mClassName);
- }
- }
- }
-
- private static void testFindInstancesOf(State state) {
- Instance[] instances = Queries.instancesOf(state, "java.lang.String");
-
- System.out.println("There are " + instances.length + " Strings.");
- }
-
- private static void testFindAllInstancesOf(State state) {
- Instance[] instances = Queries.allInstancesOf(state,
- "android.graphics.drawable.Drawable");
-
- System.out.println("There are " + instances.length
- + " instances of Drawables and its subclasses.");
- }
-}
diff --git a/hit/src/com/android/hit/Queries.java b/hit/src/com/android/hit/Queries.java
deleted file mode 100644
index 0dac796..0000000
--- a/hit/src/com/android/hit/Queries.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-
-public class Queries {
- /*
- * NOTES: Here's a list of the queries that can be done in hat and
- * how you'd perform a similar query here in hit:
- *
- * hat hit
- * ------------------------------------------------------------------------
- * allClasses classes
- * allClassesWithPlatform allClasses
- * class findClass
- * instances instancesOf
- * allInstances allInstancesOf
- * object findObject
- * showRoots getRoots
- * newInstances newInstances
- *
- * reachableFrom make a call to findObject to get the target
- * parent object, this will give you an Instance.
- * Then call visit(Set, Filter) on that to have
- * it build the set of objects in its subgraph.
- *
- * rootsTo make a call to findObject on the leaf node
- * in question, this will give you an Instance.
- * Instances have an ArrayList of all of the
- * parent objects that refer to it. You can
- * follow those parent links until you hit an
- * object whose parent is null or a ThreadObj.
- * You've not successfully traced the paths to
- * the roots.
- */
-
- private static final String DEFAULT_PACKAGE = "<default>";
-
- /*
- * Produce a collection of all classes, broken down by package.
- * The keys of the resultant map iterate in sorted package order.
- * The values of the map are the classes defined in each package.
- */
- public static Map<String, Set<ClassObj>> allClasses(State state) {
- return classes(state, null);
- }
-
- public static Map<String, Set<ClassObj>> classes(State state,
- String[] excludedPrefixes) {
- TreeMap<String, Set<ClassObj>> result =
- new TreeMap<String, Set<ClassObj>>();
-
- Set<ClassObj> classes = new TreeSet<ClassObj>();
-
- // Build a set of all classes across all heaps
- for (Heap heap: state.mHeaps.values()) {
- classes.addAll(heap.mClassesById.values());
- }
-
- // Filter it if needed
- if (excludedPrefixes != null) {
- final int N = excludedPrefixes.length;
- Iterator<ClassObj> iter = classes.iterator();
-
- while (iter.hasNext()) {
- ClassObj theClass = iter.next();
- String classPath = theClass.toString();
-
- for (int i = 0; i < N; i++) {
- if (classPath.startsWith(excludedPrefixes[i])) {
- iter.remove();
- break;
- }
- }
- }
- }
-
- // Now that we have a final list of classes, group them by package
- for (ClassObj theClass: classes) {
- String packageName = DEFAULT_PACKAGE;
- int lastDot = theClass.mClassName.lastIndexOf('.');
-
- if (lastDot != -1) {
- packageName = theClass.mClassName.substring(0, lastDot);
- }
-
- Set<ClassObj> classSet = result.get(packageName);
-
- if (classSet == null) {
- classSet = new TreeSet<ClassObj>();
- result.put(packageName, classSet);
- }
-
- classSet.add(theClass);
- }
-
- return result;
- }
-
- /*
- * It's sorta sad that this is a pass-through call, but it seems like
- * having all of the hat-like query methods in one place is a good thing
- * even if there is duplication of effort.
- */
- public static ClassObj findClass(State state, String name) {
- return state.findClass(name);
- }
-
- /*
- * Return an array of instances of the given class. This does not include
- * instances of subclasses.
- */
- public static Instance[] instancesOf(State state, String baseClassName) {
- ClassObj theClass = state.findClass(baseClassName);
-
- if (theClass == null) {
- throw new IllegalArgumentException("Class not found: "
- + baseClassName);
- }
-
- Instance[] instances = new Instance[theClass.mInstances.size()];
-
- return theClass.mInstances.toArray(instances);
- }
-
- /*
- * Return an array of instances of the given class. This includes
- * instances of subclasses.
- */
- public static Instance[] allInstancesOf(State state, String baseClassName) {
- ClassObj theClass = state.findClass(baseClassName);
-
- if (theClass == null) {
- throw new IllegalArgumentException("Class not found: "
- + baseClassName);
- }
-
- ArrayList<ClassObj> classList = new ArrayList<ClassObj>();
-
- classList.add(theClass);
- classList.addAll(traverseSubclasses(theClass));
-
- ArrayList<Instance> instanceList = new ArrayList<Instance>();
-
- for (ClassObj someClass: classList) {
- instanceList.addAll(someClass.mInstances);
- }
-
- Instance[] result = new Instance[instanceList.size()];
-
- instanceList.toArray(result);
-
- return result;
- }
-
- private static ArrayList<ClassObj> traverseSubclasses(ClassObj base) {
- ArrayList<ClassObj> result = new ArrayList<ClassObj>();
-
- for (ClassObj subclass: base.mSubclasses) {
- result.add(subclass);
- result.addAll(traverseSubclasses(subclass));
- }
-
- return result;
- }
-
- /*
- * Find a reference to an object based on its id. The id should be
- * in hexadecimal.
- */
- public static Instance findObject(State state, String id) {
- long id2 = Long.parseLong(id, 16);
-
- return state.findReference(id2);
- }
-
- public static Collection<RootObj> getRoots(State state) {
- HashSet<RootObj> result = new HashSet<RootObj>();
-
- for (Heap heap: state.mHeaps.values()) {
- result.addAll(heap.mRoots);
- }
-
- return result;
- }
-
- public static final Instance[] newInstances(State older, State newer) {
- ArrayList<Instance> resultList = new ArrayList<Instance>();
-
- for (Heap newHeap: newer.mHeaps.values()) {
- Heap oldHeap = older.getHeap(newHeap.mName);
-
- if (oldHeap == null) {
- continue;
- }
-
- for (Instance instance: newHeap.mInstances.values()) {
- Instance oldInstance = oldHeap.getInstance(instance.mId);
-
- /*
- * If this instance wasn't in the old heap, or was there,
- * but that ID was for an obj of a different type, then we have
- * a newly allocated object and we should report it in the
- * results.
- */
- if ((oldInstance == null)
- || (instance.mClassId != oldInstance.mClassId)) {
- resultList.add(instance);
- }
- }
- }
-
- Instance[] resultArray = new Instance[resultList.size()];
-
- return resultList.toArray(resultArray);
- }
-}
diff --git a/hit/src/com/android/hit/RootObj.java b/hit/src/com/android/hit/RootObj.java
deleted file mode 100644
index a9acd35..0000000
--- a/hit/src/com/android/hit/RootObj.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-import java.util.Set;
-
-public class RootObj extends Instance {
- RootType mType = RootType.UNKNOWN;
- int mIndex;
- int mThread;
-
- /*
- * These two fields are only used by roots that are static
- * fields of class objects
- */
- long mParent;
- String mComment;
-
- public RootObj(RootType type) {
- this(type, 0, 0, null);
- }
-
- public RootObj(RootType type, long id) {
- this(type, id, 0, null);
- }
-
- public RootObj(RootType type, long id, int thread, StackTrace stack) {
- mType = type;
- mId = id;
- mThread = thread;
- mStack = stack;
- }
-
- public final String getClassName(State state) {
- ClassObj theClass;
-
- if (mType == RootType.SYSTEM_CLASS) {
- theClass = state.findClass(mId);
- } else {
- Instance instance = state.findReference(mId);
-
- theClass = state.findClass(instance.mClassId);
- }
-
- if (theClass == null) {
- return "no class defined!!";
- }
-
- return theClass.mClassName;
- }
-
- @Override
- public final int getSize() {
- Instance instance = null;
-
- if (mType == RootType.SYSTEM_CLASS) {
- instance = mHeap.mState.findClass(mId);
- } else {
- instance = mHeap.mState.findReference(mId);
- }
-
- if (instance == null) {
- return 0;
- }
-
- return instance.getSize();
- }
-
- @Override
- public final void visit(Set<Instance> resultSet, Filter filter) {
- if (resultSet.contains(this)) {
- return;
- }
-
- if (filter != null) {
- if (filter.accept(this)) {
- resultSet.add(this);
- }
- } else {
- resultSet.add(this);
- }
- }
-
- @Override
- public final void resolveReferences(State state) {
- // Nothing to do here
- }
-
- @Override
- public final String getTypeName() {
- return "root " + mType.getName();
- }
-
- public final String toString() {
- return String.format("%s@0x08x", mType.getName(), mId);
- }
-}
diff --git a/hit/src/com/android/hit/RootType.java b/hit/src/com/android/hit/RootType.java
deleted file mode 100644
index 209ed1b..0000000
--- a/hit/src/com/android/hit/RootType.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-public enum RootType {
- UNREACHABLE (0, "unreachable object"),
- INVALID_TYPE (1, "invalid type"),
- INTERNED_STRING (2, "interned string"),
- UNKNOWN (3, "unknown"),
- SYSTEM_CLASS (4, "system class"),
- VM_INTERNAL (5, "vm internal"),
- DEBUGGER (6, "debugger"),
- NATIVE_LOCAL (7, "native local"),
- NATIVE_STATIC (8, "native static"),
- THREAD_BLOCK (9, "thread block"),
- BUSY_MONITOR (10, "busy monitor"),
- NATIVE_MONITOR (11, "native monitor"),
- REFERENCE_CLEANUP (12, "reference cleanup"),
- FINALIZING (13, "finalizing"),
- JAVA_LOCAL (14, "java local"),
- NATIVE_STACK (15, "native stack"),
- JAVA_STATIC (16, "java static");
-
- private final int mType;
- private final String mName;
-
- RootType(int type, String name) {
- mType = type;
- mName = name;
- }
-
- public final int getType() {
- return mType;
- }
-
- public final String getName() {
- return mName;
- }
-}
diff --git a/hit/src/com/android/hit/StackFrame.java b/hit/src/com/android/hit/StackFrame.java
deleted file mode 100644
index 2ae7f32..0000000
--- a/hit/src/com/android/hit/StackFrame.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-public class StackFrame {
- public static final int NO_LINE_NUMBER = 0;
- public static final int UNKNOWN_LOCATION = -1;
- public static final int COMPILED_METHOD = -2;
- public static final int NATIVE_METHOD = -3;
-
- long mId;
- String mMethodName;
- String mSignature;
- String mFilename;
- int mSerialNumber;
- int mLineNumber;
-
- public StackFrame(long id, String method, String sig, String file,
- int serial, int line) {
- mId = id;
- mMethodName = method;
- mSignature = sig;
- mFilename = file;
- mSerialNumber = serial;
- mLineNumber = line;
- }
-
- private final String lineNumberString() {
- switch (mLineNumber) {
- case NO_LINE_NUMBER: return "No line number";
- case UNKNOWN_LOCATION: return "Unknown line number";
- case COMPILED_METHOD: return "Compiled method";
- case NATIVE_METHOD: return "Native method";
-
- default: return String.valueOf(mLineNumber);
- }
- }
-
- public final String toString() {
- return mMethodName
- + mSignature.replace('/', '.')
- + " - "
- + mFilename + ":"
- + lineNumberString();
- }
-}
diff --git a/hit/src/com/android/hit/StackTrace.java b/hit/src/com/android/hit/StackTrace.java
deleted file mode 100644
index 53cb86d..0000000
--- a/hit/src/com/android/hit/StackTrace.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-public class StackTrace {
- int mSerialNumber;
- int mThreadSerialNumber;
- StackFrame[] mFrames;
-
- /*
- * For subsets of the stack frame we'll reference the parent list of frames
- * but keep track of its offset into the parent's list of stack frame ids.
- * This alleviates the need to constantly be duplicating subsections of the
- * list of stack frame ids.
- */
- StackTrace mParent = null;
- int mOffset = 0;
-
- private StackTrace() {
-
- }
-
- public StackTrace(int serial, int thread, StackFrame[] frames) {
- mSerialNumber = serial;
- mThreadSerialNumber = thread;
- mFrames = frames;
- }
-
- public final StackTrace fromDepth(int startingDepth) {
- StackTrace result = new StackTrace();
-
- if (mParent != null) {
- result.mParent = mParent;
- } else {
- result.mParent = this;
- }
-
- result.mOffset = startingDepth + mOffset;
-
- return result;
- }
-
- public final void dump() {
- final int N = mFrames.length;
-
- for (int i = 0; i < N; i++) {
- System.out.println(mFrames[i].toString());
- }
- }
-}
diff --git a/hit/src/com/android/hit/State.java b/hit/src/com/android/hit/State.java
deleted file mode 100644
index 96c944d..0000000
--- a/hit/src/com/android/hit/State.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/*
- * State is a snapshot of all of the heaps, and related meta-data, for
- * the runtime at a given instant.
- *
- * During parsing of the HPROF file HEAP_DUMP_INFO chunks change which heap
- * is being referenced.
- */
-public class State {
- HashMap<Integer, Heap> mHeaps;
- Heap mCurrentHeap;
-
- public State() {
- mHeaps = new HashMap<Integer, Heap>();
- setToDefaultHeap();
- }
-
- public Heap setToDefaultHeap() {
- return setHeapTo(0, "default");
- }
-
- public Heap setHeapTo(int id, String name) {
- Heap heap = mHeaps.get(id);
-
- if (heap == null) {
- heap = new Heap(name);
- heap.mState = this;
- mHeaps.put(id, heap);
- }
-
- mCurrentHeap = heap;
-
- return mCurrentHeap;
- }
-
- public Heap getHeap(int id) {
- return mHeaps.get(id);
- }
-
- public Heap getHeap(String name) {
- for (Heap heap: mHeaps.values()) {
- if (heap.mName.equals(name)) {
- return heap;
- }
- }
-
- return null;
- }
-
- public final void addStackFrame(StackFrame theFrame) {
- mCurrentHeap.addStackFrame(theFrame);
- }
-
- public final StackFrame getStackFrame(long id) {
- return mCurrentHeap.getStackFrame(id);
- }
-
- public final void addStackTrace(StackTrace theTrace) {
- mCurrentHeap.addStackTrace(theTrace);
- }
-
- public final StackTrace getStackTrace(int traceSerialNumber) {
- return mCurrentHeap.getStackTrace(traceSerialNumber);
- }
-
- public final StackTrace getStackTraceAtDepth(int traceSerialNumber,
- int depth) {
- return mCurrentHeap.getStackTraceAtDepth(traceSerialNumber, depth);
- }
-
- public final void addRoot(RootObj root) {
- mCurrentHeap.addRoot(root);
- }
-
- public final void addThread(ThreadObj thread, int serialNumber) {
- mCurrentHeap.addThread(thread, serialNumber);
- }
-
- public final ThreadObj getThread(int serialNumber) {
- return mCurrentHeap.getThread(serialNumber);
- }
-
- public final void addInstance(long id, Instance instance) {
- mCurrentHeap.addInstance(id, instance);
- }
-
- public final void addClass(long id, ClassObj theClass) {
- mCurrentHeap.addClass(id, theClass);
- }
-
- public final Instance findReference(long id) {
- for (Heap heap: mHeaps.values()) {
- Instance instance = heap.getInstance(id);
-
- if (instance != null) {
- return instance;
- }
- }
-
- // Couldn't find an instance of a class, look for a class object
- return findClass(id);
- }
-
- public final ClassObj findClass(long id) {
- for (Heap heap: mHeaps.values()) {
- ClassObj theClass = heap.getClass(id);
-
- if (theClass != null) {
- return theClass;
- }
- }
-
- return null;
- }
-
- public final ClassObj findClass(String name) {
- for (Heap heap: mHeaps.values()) {
- ClassObj theClass = heap.getClass(name);
-
- if (theClass != null) {
- return theClass;
- }
- }
-
- return null;
- }
-
- public final void dumpInstanceCounts() {
- for (Heap heap: mHeaps.values()) {
- System.out.println(
- "+------------------ instance counts for heap: " + heap.mName);
- heap.dumpInstanceCounts();
- }
- }
-
- public final void dumpSizes() {
- for (Heap heap: mHeaps.values()) {
- System.out.println(
- "+------------------ sizes for heap: " + heap.mName);
- heap.dumpSizes();
- }
- }
-
- public final void dumpSubclasses() {
- for (Heap heap: mHeaps.values()) {
- System.out.println(
- "+------------------ subclasses for heap: " + heap.mName);
- heap.dumpSubclasses();
- }
- }
-
- public final void resolveReferences() {
- for (Heap heap: mHeaps.values()) {
- heap.resolveInstanceRefs(this);
- heap.resolveClassStatics(this);
- heap.resolveRoots(this);
- }
- }
-}
diff --git a/hit/src/com/android/hit/ThreadObj.java b/hit/src/com/android/hit/ThreadObj.java
deleted file mode 100644
index 32a73f0..0000000
--- a/hit/src/com/android/hit/ThreadObj.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-public class ThreadObj {
- long mId;
- int mStackTrace;
-
- public ThreadObj(long id, int stackTrace) {
- mId = id;
- mStackTrace = stackTrace;
- }
-}
diff --git a/hit/src/com/android/hit/Types.java b/hit/src/com/android/hit/Types.java
deleted file mode 100644
index 62228ce..0000000
--- a/hit/src/com/android/hit/Types.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2008 Google Inc.
- *
- * 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.
- */
-
-package com.android.hit;
-
-public class Types {
- private static int mIdSize = 4;
-
- public static final int OBJECT = 2;
- public static final int BOOLEAN = 4;
- public static final int CHAR = 5;
- public static final int FLOAT = 6;
- public static final int DOUBLE = 7;
- public static final int BYTE = 8;
- public static final int SHORT = 9;
- public static final int INT = 10;
- public static final int LONG = 11;
-
- public static final void setIdSize(int size) {
- mIdSize = size;
- }
-
- public static final int getTypeSize(int type) {
- switch (type) {
- case '[': return mIdSize; // array object
- case 'L': return mIdSize; // object
- case 'Z': return 1; // boolean
- case 'C': return 2; // char
- case 'F': return 4; // float
- case 'D': return 8; // double
- case 'B': return 1; // byte
- case 'S': return 2; // short
- case 'I': return 4; // int
- case 'J': return 8; // long
-
- case OBJECT: return mIdSize;
- case BOOLEAN: return 1;
- case CHAR: return 2;
- case FLOAT: return 4;
- case DOUBLE: return 8;
- case BYTE: return 1;
- case SHORT: return 2;
- case INT: return 4;
- case LONG: return 8;
- }
-
- throw new IllegalArgumentException("Illegal type signature: " + type);
- }
-
- public static final String getTypeName(int type) {
- switch (type) {
- case '[': return "array";
- case 'L': return "object";
- case 'Z': return "boolean";
- case 'C': return "char";
- case 'F': return "float";
- case 'D': return "double";
- case 'B': return "byte";
- case 'S': return "short";
- case 'I': return "int";
- case 'J': return "long";
-
- case OBJECT: return "object";
- case BOOLEAN: return "boolean";
- case CHAR: return "char";
- case FLOAT: return "float";
- case DOUBLE: return "double";
- case BYTE: return "byte";
- case SHORT: return "short";
- case INT: return "int";
- case LONG: return "long";
- }
-
- throw new IllegalArgumentException("Illegal type signature: " + type);
- }
-}
diff --git a/hit/test/testparser b/hit/test/testparser
deleted file mode 100755
index a3a722e..0000000
--- a/hit/test/testparser
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-find ../src -name \*java | xargs javac -d build -Xlint:unchecked
-
-# debug launch line tha turns off the jit and runs a debug server
-#java -Djava.compiler=NONE -Xdebug -Xrunjdwp:transport=dt_socket,address=53635,server=y,suspend=y -cp build com.android.hit.Main ../samples/android.hprof
-
-java -cp build com.android.hit.Main ../samples/android.hprof
diff --git a/libdex/Android.mk b/libdex/Android.mk
index d07af63..15e7ba7 100644
--- a/libdex/Android.mk
+++ b/libdex/Android.mk
@@ -49,12 +49,14 @@
#LOCAL_CFLAGS += -UNDEBUG -DDEBUG=1
LOCAL_SRC_FILES := $(dex_src_files)
LOCAL_C_INCLUDES += $(dex_include_files)
+LOCAL_CPPFLAGS := -std=gnu++11
LOCAL_STATIC_LIBRARIES := liblog
LOCAL_WHOLE_STATIC_LIBRARIES := libziparchive
LOCAL_SHARED_LIBRARIES := libutils
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libdex
LOCAL_32_BIT_ONLY := true
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_STATIC_LIBRARY)
endif # !SDK_ONLY
@@ -68,8 +70,11 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(dex_src_files)
LOCAL_C_INCLUDES += $(dex_include_files)
+LOCAL_CPPFLAGS := -std=gnu++11
LOCAL_STATIC_LIBRARIES := liblog libutils
LOCAL_WHOLE_STATIC_LIBRARIES := libziparchive-host
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libdex
+LOCAL_32_BIT_ONLY := true
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/libdex/DexFile.h b/libdex/DexFile.h
index 7104005..e8ab319 100644
--- a/libdex/DexFile.h
+++ b/libdex/DexFile.h
@@ -33,7 +33,44 @@
#ifndef LIBDEX_DEXFILE_H_
#define LIBDEX_DEXFILE_H_
-#include "vm/Common.h" // basic type defs, e.g. u1/u2/u4/u8, and LOG
+#ifndef LOG_TAG
+# define LOG_TAG "libdex"
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <assert.h>
+#include "cutils/log.h"
+
+/*
+ * If "very verbose" logging is enabled, make it equivalent to ALOGV.
+ * Otherwise, make it disappear.
+ *
+ * Define this above the #include "Dalvik.h" to enable for only a
+ * single file.
+ */
+/* #define VERY_VERBOSE_LOG */
+#if defined(VERY_VERBOSE_LOG)
+# define LOGVV ALOGV
+# define IF_LOGVV() IF_ALOGV()
+#else
+# define LOGVV(...) ((void)0)
+# define IF_LOGVV() if (false)
+#endif
+
+/*
+ * These match the definitions in the VM specification.
+ */
+typedef uint8_t u1;
+typedef uint16_t u2;
+typedef uint32_t u4;
+typedef uint64_t u8;
+typedef int8_t s1;
+typedef int16_t s2;
+typedef int32_t s4;
+typedef int64_t s8;
+
#include "libdex/SysUtil.h"
/*
diff --git a/libdex/DexSwapVerify.cpp b/libdex/DexSwapVerify.cpp
index ff47ab5..7f18831 100644
--- a/libdex/DexSwapVerify.cpp
+++ b/libdex/DexSwapVerify.cpp
@@ -31,35 +31,9 @@
#include <stdlib.h>
#include <string.h>
-#ifndef __BYTE_ORDER
-# error "byte ordering not defined"
-#endif
-
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-# define SWAP2(_value) (_value)
-# define SWAP4(_value) (_value)
-# define SWAP8(_value) (_value)
-#else
-# define SWAP2(_value) endianSwapU2((_value))
-# define SWAP4(_value) endianSwapU4((_value))
-# define SWAP8(_value) endianSwapU8((_value))
-static u2 endianSwapU2(u2 value) {
- return (value >> 8) | (value << 8);
-}
-static u4 endianSwapU4(u4 value) {
- /* ABCD --> CDAB --> DCBA */
- value = (value >> 16) | (value << 16);
- return ((value & 0xff00ff00) >> 8) | ((value << 8) & 0xff00ff00);
-}
-static u8 endianSwapU8(u8 value) {
- /* ABCDEFGH --> EFGHABCD --> GHEFCDAB --> HGFEDCBA */
- value = (value >> 32) | (value << 32);
- value = ((value & 0xffff0000ffff0000ULL) >> 16) |
- ((value << 16) & 0xffff0000ffff0000ULL);
- return ((value & 0xff00ff00ff00ff00ULL) >> 8) |
- ((value << 8) & 0xff00ff00ff00ff00ULL);
-}
-#endif
+#define SWAP2(_value) (_value)
+#define SWAP4(_value) (_value)
+#define SWAP8(_value) (_value)
#define SWAP_FIELD2(_field) (_field) = SWAP2(_field)
#define SWAP_FIELD4(_field) (_field) = SWAP4(_field)
diff --git a/libdex/OptInvocation.cpp b/libdex/OptInvocation.cpp
index 031ec91..be7f70b 100644
--- a/libdex/OptInvocation.cpp
+++ b/libdex/OptInvocation.cpp
@@ -18,8 +18,6 @@
* Utility functions for dealing with optimized dex files.
*/
-#include "vm/DalvikVersion.h"
-
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
diff --git a/libdex/SysUtil.cpp b/libdex/SysUtil.cpp
index 825315e..5650be5 100644
--- a/libdex/SysUtil.cpp
+++ b/libdex/SysUtil.cpp
@@ -24,7 +24,7 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
-#ifdef HAVE_POSIX_FILEMAP
+#if !defined(__MINGW32__)
# include <sys/mman.h>
#endif
#include <limits.h>
@@ -40,7 +40,7 @@
*/
static void* sysCreateAnonShmem(size_t length)
{
-#ifdef HAVE_POSIX_FILEMAP
+#if !defined(__MINGW32__)
void* ptr;
ptr = mmap(NULL, length, PROT_READ | PROT_WRITE,
@@ -106,7 +106,7 @@
return 0;
}
-#ifndef HAVE_POSIX_FILEMAP
+#if defined(__MINGW32__)
int sysFakeMapFile(int fd, MemMapping* pMap)
{
/* No MMAP, just fake it by copying the bits.
@@ -149,7 +149,7 @@
*/
int sysMapFileInShmemWritableReadOnly(int fd, MemMapping* pMap)
{
-#ifdef HAVE_POSIX_FILEMAP
+#if !defined(__MINGW32__)
off_t start;
size_t length;
void* memPtr;
@@ -193,7 +193,7 @@
int sysMapFileSegmentInShmem(int fd, off_t start, size_t length,
MemMapping* pMap)
{
-#ifdef HAVE_POSIX_FILEMAP
+#if !defined(__MINGW32__)
size_t actualLength;
off_t actualStart;
int adjust;
@@ -239,7 +239,7 @@
int sysChangeMapAccess(void* addr, size_t length, int wantReadWrite,
MemMapping* pMap)
{
-#ifdef HAVE_POSIX_FILEMAP
+#if !defined(__MINGW32__)
/*
* Verify that "addr" is part of this mapping file.
*/
@@ -278,7 +278,7 @@
*/
void sysReleaseShmem(MemMapping* pMap)
{
-#ifdef HAVE_POSIX_FILEMAP
+#if !defined(__MINGW32__)
if (pMap->baseAddr == NULL && pMap->baseLength == 0)
return;
diff --git a/libdex/ZipArchive.h b/libdex/ZipArchive.h
index c4794ce..e293bf0 100644
--- a/libdex/ZipArchive.h
+++ b/libdex/ZipArchive.h
@@ -70,7 +70,7 @@
*/
DEX_INLINE int dexZipFindEntry(const ZipArchiveHandle pArchive,
const char* entryName, ZipEntry* data) {
- return FindEntry(pArchive, entryName, data);
+ return FindEntry(pArchive, ZipEntryName(entryName), data);
}
/*
diff --git a/libdex/sha1.cpp b/libdex/sha1.cpp
index 15a81cc..60c4d93 100644
--- a/libdex/sha1.cpp
+++ b/libdex/sha1.cpp
@@ -93,12 +93,9 @@
# include <unistd.h>
# include <stdlib.h>
//# include <endian.h>
-
-#include "DexFile.h" // want common byte ordering def
-
-# if __BYTE_ORDER == __LITTLE_ENDIAN
+//# if __BYTE_ORDER == __LITTLE_ENDIAN
# define X_LITTLE_ENDIAN
-# endif
+//# endif
#endif
#include <ctype.h>
diff --git a/tools/dmtracedump/Android.mk b/tools/dmtracedump/Android.mk
index 5d3146e..933f4e5 100644
--- a/tools/dmtracedump/Android.mk
+++ b/tools/dmtracedump/Android.mk
@@ -10,7 +10,6 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := TraceDump.c
LOCAL_CFLAGS += -O0 -g
-LOCAL_C_INCLUDES += dalvik/vm
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := dmtracedump
include $(BUILD_HOST_EXECUTABLE)
@@ -18,7 +17,6 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := CreateTestTrace.c
LOCAL_CFLAGS += -O0 -g
-LOCAL_C_INCLUDES += dalvik/vm
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := create_test_dmtrace
include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/dmtracedump/Profile.h b/tools/dmtracedump/Profile.h
new file mode 100644
index 0000000..efbedb3
--- /dev/null
+++ b/tools/dmtracedump/Profile.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/*
+ * Android's method call profiling goodies.
+ */
+#ifndef DALVIK_PROFILE_H_
+#define DALVIK_PROFILE_H_
+
+/*
+ * Enumeration for the two "action" bits.
+ */
+enum {
+ METHOD_TRACE_ENTER = 0x00, // method entry
+ METHOD_TRACE_EXIT = 0x01, // method exit
+ METHOD_TRACE_UNROLL = 0x02, // method exited by exception unrolling
+ // 0x03 currently unused
+};
+
+#define TOKEN_CHAR '*'
+
+/*
+ * Common definitions, shared with the dump tool.
+ */
+#define METHOD_ACTION_MASK 0x03 /* two bits */
+#define METHOD_ID(_method) ((_method) & (~METHOD_ACTION_MASK))
+#define METHOD_ACTION(_method) (((unsigned int)(_method)) & METHOD_ACTION_MASK)
+#define METHOD_COMBINE(_method, _action) ((_method) | (_action))
+
+#endif // DALVIK_PROFILE_H_
diff --git a/tools/hprof-conv/HprofConv.c b/tools/hprof-conv/HprofConv.c
index bd61e36..d37c12c 100644
--- a/tools/hprof-conv/HprofConv.c
+++ b/tools/hprof-conv/HprofConv.c
@@ -239,7 +239,7 @@
if (eofExpected && feof(in) && !ferror(in)) {
/* return without reporting an error */
} else {
- fprintf(stderr, "ERROR: read %d of %d bytes\n", actual, count);
+ fprintf(stderr, "ERROR: read %zu of %zu bytes\n", actual, count);
return -1;
}
}
@@ -262,7 +262,7 @@
actual = fwrite(pBuf->storage, 1, pBuf->curLen, out);
if (actual != pBuf->curLen) {
- fprintf(stderr, "ERROR: write %d of %d bytes\n", actual, pBuf->curLen);
+ fprintf(stderr, "ERROR: write %zu of %zu bytes\n", actual, pBuf->curLen);
return -1;
}
@@ -559,8 +559,8 @@
/* shouldn't get here */
default:
- fprintf(stderr, "ERROR: unexpected subtype 0x%02x at offset %d\n",
- subType, buf - origBuf);
+ fprintf(stderr, "ERROR: unexpected subtype 0x%02x at offset %zu\n",
+ subType, (size_t) (buf - origBuf));
goto bail;
}
diff --git a/vm/Common.h b/vm/Common.h
deleted file mode 100644
index af31b97..0000000
--- a/vm/Common.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * 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.
- */
-
-/*
- * Common defines for all Dalvik code.
- */
-#ifndef DALVIK_COMMON_H_
-#define DALVIK_COMMON_H_
-
-#ifndef LOG_TAG
-# define LOG_TAG "dalvikvm"
-#endif
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <assert.h>
-#include "cutils/log.h"
-
-#if defined(HAVE_ENDIAN_H)
-# include <endian.h>
-#else /*not HAVE_ENDIAN_H*/
-# define __BIG_ENDIAN 4321
-# define __LITTLE_ENDIAN 1234
-# if defined(HAVE_LITTLE_ENDIAN)
-# define __BYTE_ORDER __LITTLE_ENDIAN
-# else
-# define __BYTE_ORDER __BIG_ENDIAN
-# endif
-#endif /*not HAVE_ENDIAN_H*/
-
-#if !defined(NDEBUG) && defined(WITH_DALVIK_ASSERT)
-# undef assert
-# define assert(x) \
- ((x) ? ((void)0) : (ALOGE("ASSERT FAILED (%s:%d): %s", \
- __FILE__, __LINE__, #x), *(int*)39=39, (void)0) )
-#endif
-
-#define MIN(x,y) (((x) < (y)) ? (x) : (y))
-#define MAX(x,y) (((x) > (y)) ? (x) : (y))
-
-#define LIKELY(exp) (__builtin_expect((exp) != 0, true))
-#define UNLIKELY(exp) (__builtin_expect((exp) != 0, false))
-
-#define ALIGN_UP(x, n) (((size_t)(x) + (n) - 1) & ~((n) - 1))
-#define ALIGN_DOWN(x, n) ((size_t)(x) & -(n))
-#define ALIGN_UP_TO_PAGE_SIZE(p) ALIGN_UP(p, SYSTEM_PAGE_SIZE)
-#define ALIGN_DOWN_TO_PAGE_SIZE(p) ALIGN_DOWN(p, SYSTEM_PAGE_SIZE)
-
-#define CLZ(x) __builtin_clz(x)
-
-/*
- * If "very verbose" logging is enabled, make it equivalent to ALOGV.
- * Otherwise, make it disappear.
- *
- * Define this above the #include "Dalvik.h" to enable for only a
- * single file.
- */
-/* #define VERY_VERBOSE_LOG */
-#if defined(VERY_VERBOSE_LOG)
-# define LOGVV ALOGV
-# define IF_LOGVV() IF_ALOGV()
-#else
-# define LOGVV(...) ((void)0)
-# define IF_LOGVV() if (false)
-#endif
-
-
-/*
- * These match the definitions in the VM specification.
- */
-typedef uint8_t u1;
-typedef uint16_t u2;
-typedef uint32_t u4;
-typedef uint64_t u8;
-typedef int8_t s1;
-typedef int16_t s2;
-typedef int32_t s4;
-typedef int64_t s8;
-
-/*
- * Storage for primitive types and object references.
- *
- * Some parts of the code (notably object field access) assume that values
- * are "left aligned", i.e. given "JValue jv", "jv.i" and "*((s4*)&jv)"
- * yield the same result. This seems to be guaranteed by gcc on big- and
- * little-endian systems.
- */
-struct Object;
-
-union JValue {
-#if defined(HAVE_LITTLE_ENDIAN)
- u1 z;
- s1 b;
- u2 c;
- s2 s;
- s4 i;
- s8 j;
- float f;
- double d;
- Object* l;
-#endif
-#if defined(HAVE_BIG_ENDIAN)
- struct {
- u1 _z[3];
- u1 z;
- };
- struct {
- s1 _b[3];
- s1 b;
- };
- struct {
- u2 _c;
- u2 c;
- };
- struct {
- s2 _s;
- s2 s;
- };
- s4 i;
- s8 j;
- float f;
- double d;
- void* l;
-#endif
-};
-
-#define OFFSETOF_MEMBER(t, f) \
- (reinterpret_cast<char*>( \
- &reinterpret_cast<t*>(16)->f) - \
- reinterpret_cast<char*>(16))
-
-#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
-
-#endif // DALVIK_COMMON_H_
diff --git a/vm/DalvikVersion.h b/vm/DalvikVersion.h
deleted file mode 100644
index e71c839..0000000
--- a/vm/DalvikVersion.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * 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.
- */
-
-/*
- * Dalvik VM version info.
- */
-#ifndef DALVIK_VERSION_H_
-#define DALVIK_VERSION_H_
-
-/*
- * The version we show to tourists.
- */
-#define DALVIK_MAJOR_VERSION 1
-#define DALVIK_MINOR_VERSION 6
-#define DALVIK_BUG_VERSION 0
-
-/*
- * VM build number. This must change whenever something that affects the
- * way classes load changes, e.g. field ordering or vtable layout. Changing
- * this guarantees that the optimized form of the DEX file is regenerated.
- */
-#define DALVIK_VM_BUILD 27
-
-#endif // DALVIK_VERSION_H_
diff --git a/vm/Profile.h b/vm/Profile.h
deleted file mode 100644
index 9059181..0000000
--- a/vm/Profile.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * 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.
- */
-
-/*
- * Android's method call profiling goodies.
- */
-#ifndef DALVIK_PROFILE_H_
-#define DALVIK_PROFILE_H_
-
-#ifndef NOT_VM /* for utilities that sneakily include this file */
-
-#include <stdio.h>
-
-struct Thread; // extern
-
-
-/* boot init */
-bool dvmProfilingStartup(void);
-void dvmProfilingShutdown(void);
-
-/*
- * Method trace state. This is currently global. In theory we could make
- * most of this per-thread.
- */
-struct MethodTraceState {
- /* active state */
- pthread_mutex_t startStopLock;
- pthread_cond_t threadExitCond;
- FILE* traceFile;
- bool directToDdms;
- int bufferSize;
- int flags;
-
- int traceEnabled;
- u1* buf;
- volatile int curOffset;
- u8 startWhen;
- int overflow;
-
- int traceVersion;
- size_t recordSize;
-
- bool samplingEnabled;
- pthread_t samplingThreadHandle;
-};
-
-/*
- * Memory allocation profiler state. This is used both globally and
- * per-thread.
- *
- * If you add a field here, zero it out in dvmStartAllocCounting().
- */
-struct AllocProfState {
- bool enabled; // is allocation tracking enabled?
-
- int allocCount; // #of objects allocated
- int allocSize; // cumulative size of objects
-
- int failedAllocCount; // #of times an allocation failed
- int failedAllocSize; // cumulative size of failed allocations
-
- int freeCount; // #of objects freed
- int freeSize; // cumulative size of freed objects
-
- int gcCount; // #of times an allocation triggered a GC
-
- int classInitCount; // #of initialized classes
- u8 classInitTime; // cumulative time spent in class init (nsec)
-};
-
-
-/*
- * Start/stop method tracing.
- */
-void dvmMethodTraceStart(const char* traceFileName, int traceFd, int bufferSize,
- int flags, bool directToDdms, bool samplingEnabled, int intervalUs);
-void dvmMethodTraceStop(void);
-
-/*
- * Returns current method tracing mode.
- */
-enum TracingMode {
- TRACING_INACTIVE,
- METHOD_TRACING_ACTIVE,
- SAMPLE_PROFILING_ACTIVE,
-};
-TracingMode dvmGetMethodTracingMode(void);
-
-/*
- * Start/stop emulator tracing.
- */
-void dvmEmulatorTraceStart(void);
-void dvmEmulatorTraceStop(void);
-
-/*
- * Start/stop Dalvik instruction counting.
- */
-void dvmStartInstructionCounting();
-void dvmStopInstructionCounting();
-
-/*
- * Bit flags for dvmMethodTraceStart "flags" argument. These must match
- * the values in android.os.Debug.
- */
-enum {
- TRACE_ALLOC_COUNTS = 0x01,
-};
-
-/*
- * Call these when a method enters or exits.
- */
-#define TRACE_METHOD_ENTER(_self, _method) \
- do { \
- if (_self->interpBreak.ctl.subMode & kSubModeMethodTrace) { \
- u4 cpuClockDiff = 0; \
- u4 wallClockDiff = 0; \
- dvmMethodTraceReadClocks(_self, &cpuClockDiff, &wallClockDiff); \
- dvmMethodTraceAdd(_self, _method, METHOD_TRACE_ENTER, \
- cpuClockDiff, wallClockDiff); \
- } \
- if (_self->interpBreak.ctl.subMode & kSubModeEmulatorTrace) \
- dvmEmitEmulatorTrace(_method, METHOD_TRACE_ENTER); \
- } while(0);
-#define TRACE_METHOD_EXIT(_self, _method) \
- do { \
- if (_self->interpBreak.ctl.subMode & kSubModeMethodTrace) { \
- u4 cpuClockDiff = 0; \
- u4 wallClockDiff = 0; \
- dvmMethodTraceReadClocks(_self, &cpuClockDiff, &wallClockDiff); \
- dvmMethodTraceAdd(_self, _method, METHOD_TRACE_EXIT, \
- cpuClockDiff, wallClockDiff); \
- } \
- if (_self->interpBreak.ctl.subMode & kSubModeEmulatorTrace) \
- dvmEmitEmulatorTrace(_method, METHOD_TRACE_EXIT); \
- } while(0);
-#define TRACE_METHOD_UNROLL(_self, _method) \
- do { \
- if (_self->interpBreak.ctl.subMode & kSubModeMethodTrace) { \
- u4 cpuClockDiff = 0; \
- u4 wallClockDiff = 0; \
- dvmMethodTraceReadClocks(_self, &cpuClockDiff, &wallClockDiff); \
- dvmMethodTraceAdd(_self, _method, METHOD_TRACE_UNROLL, \
- cpuClockDiff, wallClockDiff); \
- } \
- if (_self->interpBreak.ctl.subMode & kSubModeEmulatorTrace) \
- dvmEmitEmulatorTrace(_method, METHOD_TRACE_UNROLL); \
- } while(0);
-
-void dvmMethodTraceReadClocks(Thread* self, u4* cpuClockDiff,
- u4* wallClockDiff);
-void dvmMethodTraceAdd(struct Thread* self, const Method* method, int action,
- u4 cpuClockDiff, u4 wallClockDiff);
-void dvmEmitEmulatorTrace(const Method* method, int action);
-
-void dvmMethodTraceGCBegin(void);
-void dvmMethodTraceGCEnd(void);
-void dvmMethodTraceClassPrepBegin(void);
-void dvmMethodTraceClassPrepEnd(void);
-
-extern "C" void dvmFastMethodTraceEnter(const Method* method, struct Thread* self);
-extern "C" void dvmFastMethodTraceExit(struct Thread* self);
-extern "C" void dvmFastNativeMethodTraceExit(const Method* method, struct Thread* self);
-
-/*
- * Start/stop alloc counting.
- */
-void dvmStartAllocCounting(void);
-void dvmStopAllocCounting(void);
-
-#endif
-
-
-/*
- * Enumeration for the two "action" bits.
- */
-enum {
- METHOD_TRACE_ENTER = 0x00, // method entry
- METHOD_TRACE_EXIT = 0x01, // method exit
- METHOD_TRACE_UNROLL = 0x02, // method exited by exception unrolling
- // 0x03 currently unused
-};
-
-#define TOKEN_CHAR '*'
-
-/*
- * Common definitions, shared with the dump tool.
- */
-#define METHOD_ACTION_MASK 0x03 /* two bits */
-#define METHOD_ID(_method) ((_method) & (~METHOD_ACTION_MASK))
-#define METHOD_ACTION(_method) (((unsigned int)(_method)) & METHOD_ACTION_MASK)
-#define METHOD_COMBINE(_method, _action) ((_method) | (_action))
-
-#endif // DALVIK_PROFILE_H_